Skip to content

Commit d170c7e

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent 3bfb19d commit d170c7e

File tree

146 files changed

+879
-350
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

146 files changed

+879
-350
lines changed

.gitlab-ci.yml

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ default:
3535
.default-branch-incident-variables: &default-branch-incident-variables
3636
CREATE_INCIDENT_FOR_PIPELINE_FAILURE: "true"
3737
NOTIFY_PIPELINE_FAILURE_CHANNEL: "master-broken"
38+
BROKEN_BRANCH_INCIDENTS_PROJECT: "gitlab-org/quality/engineering-productivity/master-broken-incidents"
39+
BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN: "${BROKEN_MASTER_INCIDENTS_PROJECT_TOKEN}"
3840

3941
workflow:
4042
name: '$PIPELINE_NAME'
@@ -107,6 +109,9 @@ workflow:
107109
<<: *ruby2-variables
108110
NOTIFY_PIPELINE_FAILURE_CHANNEL: "releases"
109111
PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline'
112+
CREATE_INCIDENT_FOR_PIPELINE_FAILURE: "true"
113+
BROKEN_BRANCH_INCIDENTS_PROJECT: "gitlab-org/release/tasks"
114+
BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN: "${BROKEN_STABLE_INCIDENTS_PROJECT_TOKEN}"
110115
- if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/'
111116
variables:
112117
<<: *ruby2-variables

.gitlab/ci/notify.gitlab-ci.yml

+7-6
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ notify-pipeline-failure:
4343
- .notify:rules:notify-pipeline-failure
4444
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}
4545
variables:
46-
BROKEN_MASTER_INCIDENTS_PROJECT: "gitlab-org/quality/engineering-productivity/master-broken-incidents"
47-
BROKEN_MASTER_INCIDENT_JSON: "${CI_PROJECT_DIR}/incident.json"
46+
INCIDENT_PROJECT: "#{BROKEN_BRANCH_INCIDENTS_PROJECT}"
47+
BROKEN_BRANCH_PROJECT_TOKEN: "${BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN}"
48+
INCIDENT_JSON: "${CI_PROJECT_DIR}/incident.json"
4849
SLACK_CHANNEL: "${NOTIFY_PIPELINE_FAILURE_CHANNEL}"
4950
FAILED_PIPELINE_SLACK_MESSAGE_FILE: "${CI_PROJECT_DIR}/failed_pipeline_slack_message.json"
5051
before_script:
@@ -54,17 +55,17 @@ notify-pipeline-failure:
5455
script:
5556
- |
5657
if [[ "${CREATE_INCIDENT_FOR_PIPELINE_FAILURE}" == "true" ]]; then
57-
scripts/create-pipeline-failure-incident.rb -p ${BROKEN_MASTER_INCIDENTS_PROJECT} -f ${BROKEN_MASTER_INCIDENT_JSON} -t ${BROKEN_MASTER_INCIDENTS_PROJECT_TOKEN};
58-
echosuccess "Created incident $(jq '.web_url' ${BROKEN_MASTER_INCIDENT_JSON})";
58+
scripts/create-pipeline-failure-incident.rb -p ${INCIDENT_PROJECT} -f ${INCIDENT_JSON} -t ${BROKEN_BRANCH_PROJECT_TOKEN};
59+
echosuccess "Created incident $(jq '.web_url' ${INCIDENT_JSON})";
5960
fi
6061
- |
61-
scripts/generate-failed-pipeline-slack-message.rb -i ${BROKEN_MASTER_INCIDENT_JSON} -f ${FAILED_PIPELINE_SLACK_MESSAGE_FILE};
62+
scripts/generate-failed-pipeline-slack-message.rb -i ${INCIDENT_JSON} -f ${FAILED_PIPELINE_SLACK_MESSAGE_FILE};
6263
curl -X POST -H 'Content-Type: application/json' --data @${FAILED_PIPELINE_SLACK_MESSAGE_FILE} "$CI_SLACK_WEBHOOK_URL" ||
6364
scripts/slack ${SLACK_CHANNEL} "☠️ Broken pipeline notification failed! ☠️ See ${CI_JOB_URL}" ci_failing "Failed pipeline reporter"
6465
6566
artifacts:
6667
paths:
67-
- ${BROKEN_MASTER_INCIDENT_JSON}
68+
- ${INCIDENT_JSON}
6869
- ${FAILED_PIPELINE_SLACK_MESSAGE_FILE}
6970
when: always
7071
expire_in: 2 days

.gitlab/ci/rules.gitlab-ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2096,7 +2096,7 @@
20962096
changes: *code-patterns
20972097
when: manual
20982098
allow_failure: true
2099-
- <<: *if-dot-com-gitlab-org-schedule
2099+
- <<: *if-dot-com-ee-schedule-default-branch-maintenance
21002100
allow_failure: true
21012101

21022102
.review:rules:review-k8s-resources-count-checks:

.rubocop_todo/performance/string_include.yml

-13
This file was deleted.

GITALY_SERVER_VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4e200026c03189abe2c60b071204340c4af5cf35
1+
6eb7389db0d54ef9ba3622eb7d1412f71e9deb2f

app/assets/javascripts/graphql_shared/issuable_client.js

+24
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.grap
66
import createDefaultClient from '~/lib/graphql';
77
import typeDefs from '~/work_items/graphql/typedefs.graphql';
88
import { WIDGET_TYPE_NOTES } from '~/work_items/constants';
9+
import getWorkItemLinksQuery from '~/work_items/graphql/work_item_links.query.graphql';
10+
import { findHierarchyWidgetChildren } from '~/work_items/utils';
911

1012
export const config = {
1113
typeDefs,
@@ -143,6 +145,28 @@ export const config = {
143145

144146
export const resolvers = {
145147
Mutation: {
148+
addHierarchyChild: (_, { id, workItem }, { cache }) => {
149+
const queryArgs = { query: getWorkItemLinksQuery, variables: { id } };
150+
const sourceData = cache.readQuery(queryArgs);
151+
152+
const data = produce(sourceData, (draftState) => {
153+
findHierarchyWidgetChildren(draftState.workItem).push(workItem);
154+
});
155+
156+
cache.writeQuery({ ...queryArgs, data });
157+
},
158+
removeHierarchyChild: (_, { id, workItem }, { cache }) => {
159+
const queryArgs = { query: getWorkItemLinksQuery, variables: { id } };
160+
const sourceData = cache.readQuery(queryArgs);
161+
162+
const data = produce(sourceData, (draftState) => {
163+
const hierarchyChildren = findHierarchyWidgetChildren(draftState.workItem);
164+
const index = hierarchyChildren.findIndex((child) => child.id === workItem.id);
165+
hierarchyChildren.splice(index, 1);
166+
});
167+
168+
cache.writeQuery({ ...queryArgs, data });
169+
},
146170
updateIssueState: (_, { issueType = undefined, isDirty = false }, { cache }) => {
147171
const sourceData = cache.readQuery({ query: getIssueStateQuery });
148172
const data = produce(sourceData, (draftData) => {

app/assets/javascripts/issues/show/graphql.js

-9
This file was deleted.

app/assets/javascripts/issues/show/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import Vue from 'vue';
22
import { mapGetters } from 'vuex';
33
import errorTrackingStore from '~/error_tracking/store';
4+
import { apolloProvider } from '~/graphql_shared/issuable_client';
45
import { parseBoolean } from '~/lib/utils/common_utils';
56
import { scrollToTargetOnResize } from '~/lib/utils/resize_observer';
67
import IssueApp from './components/app.vue';
78
import HeaderActions from './components/header_actions.vue';
89
import IncidentTabs from './components/incidents/incident_tabs.vue';
910
import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
1011
import { INCIDENT_TYPE, issueState } from './constants';
11-
import apolloProvider from './graphql';
1212
import getIssueStateQuery from './queries/get_issue_state.query.graphql';
1313

1414
const bootstrapApollo = (state = {}) => {

app/assets/javascripts/related_issues/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Vue from 'vue';
2-
import apolloProvider from '~/issues/show/graphql';
2+
import { apolloProvider } from '~/graphql_shared/issuable_client';
33
import { parseBoolean } from '~/lib/utils/common_utils';
44
import RelatedIssuesRoot from './components/related_issues_root.vue';
55

app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue

+25-36
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script>
22
import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
3-
import { produce } from 'immer';
43
import { isEmpty } from 'lodash';
54
import { s__ } from '~/locale';
65
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
@@ -18,6 +17,8 @@ import {
1817
WORK_ITEM_STATUS_TEXT,
1918
} from '../../constants';
2019
import getWorkItemLinksQuery from '../../graphql/work_item_links.query.graphql';
20+
import addHierarchyChildMutation from '../../graphql/add_hierarchy_child.mutation.graphql';
21+
import removeHierarchyChildMutation from '../../graphql/remove_hierarchy_child.mutation.graphql';
2122
import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql';
2223
import workItemQuery from '../../graphql/work_item.query.graphql';
2324
import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql';
@@ -177,10 +178,6 @@ export default {
177178
hideAddForm() {
178179
this.isShownAddForm = false;
179180
},
180-
addChild(child) {
181-
const { defaultClient: client } = this.$apollo.provider.clients;
182-
this.toggleChildFromCache(child, child.id, client);
183-
},
184181
openChild(child, e) {
185182
if (isMetaKey(e)) {
186183
return;
@@ -194,9 +191,8 @@ export default {
194191
this.activeChild = {};
195192
this.updateWorkItemIdUrlQuery();
196193
},
197-
handleWorkItemDeleted(childId) {
198-
const { defaultClient: client } = this.$apollo.provider.clients;
199-
this.toggleChildFromCache(null, childId, client);
194+
handleWorkItemDeleted(child) {
195+
this.removeHierarchyChild(child);
200196
this.activeToast = this.$toast.show(s__('WorkItem|Task deleted'));
201197
},
202198
updateWorkItemIdUrlQuery({ id, iid } = {}) {
@@ -205,38 +201,31 @@ export default {
205201
: { work_item_id: getIdFromGraphQLId(id) };
206202
updateHistory({ url: setUrlParams(params), replace: true });
207203
},
208-
toggleChildFromCache(workItem, childId, store) {
209-
const sourceData = store.readQuery({
210-
query: getWorkItemLinksQuery,
211-
variables: { id: this.issuableGid },
212-
});
213-
214-
const newData = produce(sourceData, (draftState) => {
215-
const widgetHierarchy = draftState.workItem.widgets.find(
216-
(widget) => widget.type === WIDGET_TYPE_HIERARCHY,
217-
);
218-
219-
const index = widgetHierarchy.children.nodes.findIndex((child) => child.id === childId);
220-
221-
if (index >= 0) {
222-
widgetHierarchy.children.nodes.splice(index, 1);
223-
} else {
224-
widgetHierarchy.children.nodes.push(workItem);
225-
}
204+
async addHierarchyChild(workItem) {
205+
return this.$apollo.mutate({
206+
mutation: addHierarchyChildMutation,
207+
variables: { id: this.issuableGid, workItem },
226208
});
227-
228-
store.writeQuery({
229-
query: getWorkItemLinksQuery,
230-
variables: { id: this.issuableGid },
231-
data: newData,
209+
},
210+
async removeHierarchyChild(workItem) {
211+
return this.$apollo.mutate({
212+
mutation: removeHierarchyChildMutation,
213+
variables: { id: this.issuableGid, workItem },
232214
});
233215
},
234216
async updateWorkItem(workItem, childId, parentId) {
235-
return this.$apollo.mutate({
217+
const response = await this.$apollo.mutate({
236218
mutation: updateWorkItemMutation,
237219
variables: { input: { id: childId, hierarchyWidget: { parentId } } },
238-
update: (store) => this.toggleChildFromCache(workItem, childId, store),
239220
});
221+
222+
if (parentId === null) {
223+
await this.removeHierarchyChild(workItem);
224+
} else {
225+
await this.addHierarchyChild(workItem);
226+
}
227+
228+
return response;
240229
},
241230
async undoChildRemoval(workItem, childId) {
242231
const { data } = await this.updateWorkItem(workItem, childId, this.issuableGid);
@@ -246,7 +235,7 @@ export default {
246235
}
247236
},
248237
async removeChild(childId) {
249-
const { data } = await this.updateWorkItem(null, childId, null);
238+
const { data } = await this.updateWorkItem({ id: childId }, childId, null);
250239
251240
if (data.workItemUpdate.errors.length === 0) {
252241
this.activeToast = this.$toast.show(s__('WorkItem|Child removed'), {
@@ -365,7 +354,7 @@ export default {
365354
:form-type="formType"
366355
:parent-work-item-type="workItem.workItemType.name"
367356
@cancel="hideAddForm"
368-
@addWorkItemChild="addChild"
357+
@addWorkItemChild="addHierarchyChild"
369358
/>
370359
<work-item-link-child
371360
v-for="child in children"
@@ -384,7 +373,7 @@ export default {
384373
:work-item-id="activeChild.id"
385374
:work-item-iid="activeChild.iid"
386375
@close="closeModal"
387-
@workItemDeleted="handleWorkItemDeleted(activeChild.id)"
376+
@workItemDeleted="handleWorkItemDeleted(activeChild)"
388377
/>
389378
</template>
390379
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mutation addHierarchyChild($id: WorkItemID!, $workItem: WorkItem!) {
2+
addHierarchyChild(id: $id, workItem: $workItem) @client
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mutation removeHierarchyChild($id: WorkItemID!, $workItem: WorkItem!) {
2+
removeHierarchyChild(id: $id, workItem: $workItem) @client
3+
}

app/assets/javascripts/work_items/utils.js

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { WIDGET_TYPE_HIERARCHY } from '~/work_items/constants';
12
import workItemQuery from './graphql/work_item.query.graphql';
23
import workItemByIidQuery from './graphql/work_item_by_iid.query.graphql';
34
import workItemNotesIdQuery from './graphql/work_item_notes.query.graphql';
@@ -10,3 +11,6 @@ export function getWorkItemQuery(isFetchedByIid) {
1011
export function getWorkItemNotesQuery(isFetchedByIid) {
1112
return isFetchedByIid ? workItemNotesByIidQuery : workItemNotesIdQuery;
1213
}
14+
15+
export const findHierarchyWidgetChildren = (workItem) =>
16+
workItem.widgets.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY).children.nodes;

app/models/concerns/sensitive_serializable_hash.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ def serializable_hash(options = nil)
2424

2525
options[:except].concat self.class.attributes_exempt_from_serializable_hash
2626

27-
if self.class.respond_to?(:encrypted_attributes)
28-
options[:except].concat self.class.encrypted_attributes.keys
27+
if self.class.respond_to?(:attr_encrypted_attributes)
28+
options[:except].concat self.class.attr_encrypted_attributes.keys
2929

3030
# Per https://github.com/attr-encrypted/attr_encrypted/blob/a96693e9a2a25f4f910bf915e29b0f364f277032/lib/attr_encrypted.rb#L413
31-
options[:except].concat self.class.encrypted_attributes.values.map { |v| v[:attribute] }
32-
options[:except].concat self.class.encrypted_attributes.values.map { |v| "#{v[:attribute]}_iv" }
31+
options[:except].concat self.class.attr_encrypted_attributes.values.map { |v| v[:attribute] }
32+
options[:except].concat self.class.attr_encrypted_attributes.values.map { |v| "#{v[:attribute]}_iv" }
3333
end
3434

3535
super(options)

app/models/deploy_key.rb

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class DeployKey < Key
1212
has_many :deploy_keys_projects_with_write_access, -> { with_write_access }, class_name: "DeployKeysProject", inverse_of: :deploy_key
1313
has_many :projects_with_write_access, -> { includes(:route) }, class_name: 'Project', through: :deploy_keys_projects_with_write_access, source: :project
1414
has_many :protected_branch_push_access_levels, class_name: '::ProtectedBranch::PushAccessLevel', inverse_of: :deploy_key
15+
has_many :protected_tag_create_access_levels, class_name: '::ProtectedTag::CreateAccessLevel', inverse_of: :deploy_key
1516

1617
scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where(deploy_keys_projects: { project_id: projects }) }
1718
scope :with_write_access, -> { joins(:deploy_keys_projects).merge(DeployKeysProject.with_write_access) }

app/models/grafana_integration.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def reset_token
4545
end
4646

4747
def token
48-
decrypt(:token, encrypted_token)
48+
attr_decrypt(:token, encrypted_token)
4949
end
5050

5151
def check_token_changes

app/models/integration.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,9 @@ def to_database_hash
493493

494494
def reencrypt_properties
495495
unless properties.nil? || properties.empty?
496-
alg = self.class.encrypted_attributes[:properties][:algorithm]
496+
alg = self.class.attr_encrypted_attributes[:properties][:algorithm]
497497
iv = generate_iv(alg)
498-
ep = self.class.encrypt(:properties, properties, { iv: iv })
498+
ep = self.class.attr_encrypt(:properties, properties, { iv: iv })
499499
end
500500

501501
{ 'encrypted_properties' => ep, 'encrypted_properties_iv' => iv }

app/models/protected_tag/create_access_level.rb

+34
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,43 @@ class ProtectedTag::CreateAccessLevel < ApplicationRecord
44
include Importable
55
include ProtectedTagAccess
66

7+
belongs_to :deploy_key
8+
9+
validates :access_level, uniqueness: { scope: :protected_tag_id, if: :role?,
10+
conditions: -> { where(user_id: nil, group_id: nil, deploy_key_id: nil) } }
11+
validates :deploy_key_id, uniqueness: { scope: :protected_tag_id, allow_nil: true }
12+
validate :validate_deploy_key_membership
13+
14+
def type
15+
if deploy_key.present?
16+
:deploy_key
17+
else
18+
super
19+
end
20+
end
21+
722
def check_access(user)
823
return false if access_level == Gitlab::Access::NO_ACCESS
924

25+
if user && deploy_key.present?
26+
return user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user)
27+
end
28+
1029
super
1130
end
31+
32+
private
33+
34+
def validate_deploy_key_membership
35+
return unless deploy_key
36+
37+
return if project.deploy_keys_projects.where(deploy_key: deploy_key).exists?
38+
39+
errors.add(:deploy_key, 'is not enabled for this project')
40+
end
41+
42+
def enabled_deploy_key_for_user?(deploy_key, user)
43+
deploy_key.user_id == user.id &&
44+
DeployKey.with_write_access_for_project(protected_tag.project, deploy_key: deploy_key).any?
45+
end
1246
end

app/models/snippet_repository.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def invalid_path_error?(err)
121121

122122
def invalid_signature_error?(err)
123123
err.is_a?(ArgumentError) &&
124-
err.message.downcase.match?(/failed to parse signature/)
124+
err.message.downcase.include?('failed to parse signature')
125125
end
126126

127127
def only_rename_action?(action)

0 commit comments

Comments
 (0)