Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
e4a0b94a64
commit
cdd826bc3a
|
@ -7,6 +7,26 @@
|
||||||
* feature development should use the Feature Request template.
|
* feature development should use the Feature Request template.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
If you are a community contributor:
|
||||||
|
|
||||||
|
1. To work on an issue, type `@gl-docsteam I would like to work on this issue.`
|
||||||
|
in a comment. A technical writer
|
||||||
|
will assign the issue to you. Do not work on the issue before it is assigned to you.
|
||||||
|
If someone has already chosen the issue, pick another or view docs [in the docs directory](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc)
|
||||||
|
and open a merge request for any page you feel can be improved.
|
||||||
|
1. Create a merge request for the issue. If this is for a Hackathon, do not create the merge request
|
||||||
|
before the Hackathon has started or it will not be counted towards the Hackathon. If you were not
|
||||||
|
assigned the issue, do not create a merge request. It will not be accepted.
|
||||||
|
1. Copy the link to this issue and add it to the merge request's description, which will link
|
||||||
|
the merge request and the issue together.
|
||||||
|
1. After your merge request is accepted and merged, close this issue.
|
||||||
|
|
||||||
|
If you notice things you'd like to fix that are not part of the issue, open separate merge requests for those issues.
|
||||||
|
|
||||||
|
We're sorry for all the rules but we want everyone to have a good experience, and it can be hard when we get an influx of contributions.
|
||||||
|
|
||||||
|
Thank you again for contributing to the GitLab documentation!
|
||||||
|
|
||||||
## Identified documentation issue
|
## Identified documentation issue
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
@ -19,19 +39,6 @@
|
||||||
* the opportunities for contributors.
|
* the opportunities for contributors.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Process
|
|
||||||
|
|
||||||
If you, as a contributor, decide to take this work on, assign this issue to yourself, and create one or more linked
|
|
||||||
merge requests that resolve this issue. Be sure to close this issue after all linked merge requests are completed.
|
|
||||||
|
|
||||||
The work for this issue should involve only what's listed in the previous section. If you identify other work that
|
|
||||||
needs to be done, create separate, unlinked MRs as needed to address those items.
|
|
||||||
|
|
||||||
When using automated test results for identified work, use this issue to work only on the listed lines. For
|
|
||||||
example, if the tests list several lines that show the word "admin" as needing to possibly be "administrator,"
|
|
||||||
do not modify other parts of the page that may also include "admin," as the testing may have excluded those lines
|
|
||||||
(for example, they may be part of the **Admin Area** of GitLab).
|
|
||||||
|
|
||||||
## Additional information
|
## Additional information
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -146,25 +146,6 @@ Performance/CollectionLiteralInLoop:
|
||||||
Performance/ConstantRegexp:
|
Performance/ConstantRegexp:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 14
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: SafeMultiline.
|
|
||||||
Performance/DeletePrefix:
|
|
||||||
Exclude:
|
|
||||||
- 'app/helpers/submodule_helper.rb'
|
|
||||||
- 'app/workers/concerns/application_worker.rb'
|
|
||||||
- 'ee/lib/gitlab/geo/git_ssh_proxy.rb'
|
|
||||||
- 'lib/banzai/filter/repository_link_filter.rb'
|
|
||||||
- 'lib/gitlab/auth/ldap/dn.rb'
|
|
||||||
- 'lib/gitlab/gfm/uploads_rewriter.rb'
|
|
||||||
- 'lib/gitlab/git/ref.rb'
|
|
||||||
- 'lib/gitlab/project_template.rb'
|
|
||||||
- 'lib/gitlab/setup_helper.rb'
|
|
||||||
- 'lib/gitlab/time_tracking_formatter.rb'
|
|
||||||
- 'spec/controllers/projects/artifacts_controller_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/gfm/uploads_rewriter_spec.rb'
|
|
||||||
- 'spec/support/helpers/test_env.rb'
|
|
||||||
|
|
||||||
# Offense count: 121
|
# Offense count: 121
|
||||||
Performance/MethodObjectAsBlock:
|
Performance/MethodObjectAsBlock:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -398,22 +379,6 @@ Rails/WhereExists:
|
||||||
Style/AccessorGrouping:
|
Style/AccessorGrouping:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 11
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/ArrayCoercion:
|
|
||||||
Exclude:
|
|
||||||
- 'app/controllers/admin/ci/variables_controller.rb'
|
|
||||||
- 'app/controllers/groups/variables_controller.rb'
|
|
||||||
- 'app/controllers/projects/variables_controller.rb'
|
|
||||||
- 'db/migrate/20190620105427_change_null_private_profile_to_false.rb'
|
|
||||||
- 'db/post_migrate/20190812070645_migrate_private_profile_nulls.rb'
|
|
||||||
- 'db/post_migrate/20200311130802_schedule_populate_user_highest_roles_table.rb'
|
|
||||||
- 'db/post_migrate/20200805152108_migrate_null_external_diff_store_to_local_value.rb'
|
|
||||||
- 'db/post_migrate/20200806173633_migrate_null_package_files_file_store_to_local_value.rb'
|
|
||||||
- 'ee/app/services/geo/repository_verification_secondary_service.rb'
|
|
||||||
- 'ee/lib/ee/banzai/pipeline/gfm_pipeline.rb'
|
|
||||||
- 'spec/support/helpers/lfs_http_helpers.rb'
|
|
||||||
|
|
||||||
# Offense count: 188
|
# Offense count: 188
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
@ -433,20 +398,6 @@ Style/BisectedAttrAccessor:
|
||||||
Style/CaseLikeIf:
|
Style/CaseLikeIf:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 13
|
|
||||||
Style/CombinableLoops:
|
|
||||||
Exclude:
|
|
||||||
- 'ee/db/fixtures/development/30_customizable_cycle_analytics.rb'
|
|
||||||
- 'ee/lib/gitlab/audit/events/preloader.rb'
|
|
||||||
- 'ee/spec/finders/snippets_finder_spec.rb'
|
|
||||||
- 'ee/spec/lib/ee/gitlab/background_migration/remove_duplicate_cs_findings_spec.rb'
|
|
||||||
- 'spec/features/merge_request/user_suggests_changes_on_diff_spec.rb'
|
|
||||||
- 'spec/finders/packages/group_packages_finder_spec.rb'
|
|
||||||
- 'spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb'
|
|
||||||
- 'spec/migrations/cleanup_optimistic_locking_nulls_spec.rb'
|
|
||||||
- 'spec/requests/api/members_spec.rb'
|
|
||||||
- 'spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb'
|
|
||||||
|
|
||||||
# Offense count: 5
|
# Offense count: 5
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/EachWithObject:
|
Style/EachWithObject:
|
||||||
|
@ -471,13 +422,6 @@ Style/EmptyElse:
|
||||||
Style/EmptyMethod:
|
Style/EmptyMethod:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/ExpandPathArguments:
|
|
||||||
Exclude:
|
|
||||||
- 'cable/config.ru'
|
|
||||||
- 'config.ru'
|
|
||||||
|
|
||||||
# Offense count: 118
|
# Offense count: 118
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/ExplicitBlockArgument:
|
Style/ExplicitBlockArgument:
|
||||||
|
|
|
@ -878,7 +878,6 @@ RSpec/VerifiedDoubles:
|
||||||
- spec/models/design_management/design_at_version_spec.rb
|
- spec/models/design_management/design_at_version_spec.rb
|
||||||
- spec/models/diff_viewer/image_spec.rb
|
- spec/models/diff_viewer/image_spec.rb
|
||||||
- spec/models/environment_spec.rb
|
- spec/models/environment_spec.rb
|
||||||
- spec/models/error_tracking/project_error_tracking_setting_spec.rb
|
|
||||||
- spec/models/event_spec.rb
|
- spec/models/event_spec.rb
|
||||||
- spec/models/external_issue_spec.rb
|
- spec/models/external_issue_spec.rb
|
||||||
- spec/models/hooks/web_hook_spec.rb
|
- spec/models/hooks/web_hook_spec.rb
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
Style/ArrayCoercion:
|
||||||
|
Exclude:
|
||||||
|
- 'app/controllers/admin/ci/variables_controller.rb'
|
||||||
|
- 'app/controllers/groups/variables_controller.rb'
|
||||||
|
- 'app/controllers/projects/variables_controller.rb'
|
||||||
|
- 'ee/app/services/geo/repository_verification_secondary_service.rb'
|
||||||
|
- 'ee/lib/ee/banzai/pipeline/gfm_pipeline.rb'
|
||||||
|
- 'spec/support/helpers/lfs_http_helpers.rb'
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
Style/CombinableLoops:
|
||||||
|
Exclude:
|
||||||
|
- 'ee/db/fixtures/development/30_customizable_cycle_analytics.rb'
|
||||||
|
- 'ee/lib/gitlab/audit/events/preloader.rb'
|
||||||
|
- 'ee/spec/finders/snippets_finder_spec.rb'
|
||||||
|
- 'spec/features/merge_request/user_suggests_changes_on_diff_spec.rb'
|
||||||
|
- 'spec/finders/packages/group_packages_finder_spec.rb'
|
||||||
|
- 'spec/requests/api/members_spec.rb'
|
||||||
|
- 'spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb'
|
|
@ -8,7 +8,6 @@ Style/OpenStructUse:
|
||||||
- ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb
|
- ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb
|
||||||
- ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
|
- ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
|
||||||
- lib/gitlab/testing/request_inspector_middleware.rb
|
- lib/gitlab/testing/request_inspector_middleware.rb
|
||||||
- spec/factories/go_module_versions.rb
|
|
||||||
- spec/factories/wiki_pages.rb
|
- spec/factories/wiki_pages.rb
|
||||||
- spec/graphql/mutations/branches/create_spec.rb
|
- spec/graphql/mutations/branches/create_spec.rb
|
||||||
- spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
|
- spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
|
||||||
|
|
|
@ -37,7 +37,7 @@ export default {
|
||||||
anchor: 'update-the-agent-version',
|
anchor: 'update-the-agent-version',
|
||||||
}),
|
}),
|
||||||
configHelpLink: helpPagePath('user/clusters/agent/install/index', {
|
configHelpLink: helpPagePath('user/clusters/agent/install/index', {
|
||||||
anchor: 'create-an-agent-without-configuration-file',
|
anchor: 'create-an-agent-configuration-file',
|
||||||
}),
|
}),
|
||||||
inject: ['gitlabVersion'],
|
inject: ['gitlabVersion'],
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -31,7 +31,7 @@ export default {
|
||||||
EVENT_LABEL_MODAL,
|
EVENT_LABEL_MODAL,
|
||||||
enableKasPath: helpPagePath('administration/clusters/kas'),
|
enableKasPath: helpPagePath('administration/clusters/kas'),
|
||||||
registerAgentPath: helpPagePath('user/clusters/agent/install/index', {
|
registerAgentPath: helpPagePath('user/clusters/agent/install/index', {
|
||||||
anchor: 'register-an-agent-with-gitlab',
|
anchor: 'register-the-agent-with-gitlab',
|
||||||
}),
|
}),
|
||||||
components: {
|
components: {
|
||||||
AvailableAgentsDropdown,
|
AvailableAgentsDropdown,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import {
|
import {
|
||||||
GlCollapse,
|
GlCollapse,
|
||||||
GlDropdown,
|
GlDropdown,
|
||||||
|
GlBadge,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlLink,
|
GlLink,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
|
@ -26,6 +27,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
GlCollapse,
|
GlCollapse,
|
||||||
GlDropdown,
|
GlDropdown,
|
||||||
|
GlBadge,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlLink,
|
GlLink,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
|
@ -74,6 +76,7 @@ export default {
|
||||||
'Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}',
|
'Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}',
|
||||||
),
|
),
|
||||||
autoStopIn: s__('Environment|Auto stop %{time}'),
|
autoStopIn: s__('Environment|Auto stop %{time}'),
|
||||||
|
tierTooltip: s__('Environment|Deployment tier'),
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return { visible: false };
|
return { visible: false };
|
||||||
|
@ -100,6 +103,9 @@ export default {
|
||||||
hasDeployment() {
|
hasDeployment() {
|
||||||
return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment);
|
return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment);
|
||||||
},
|
},
|
||||||
|
tier() {
|
||||||
|
return this.lastDeployment?.tierInYaml;
|
||||||
|
},
|
||||||
hasOpenedAlert() {
|
hasOpenedAlert() {
|
||||||
return this.environment?.hasOpenedAlert;
|
return this.environment?.hasOpenedAlert;
|
||||||
},
|
},
|
||||||
|
@ -206,6 +212,13 @@ export default {
|
||||||
>
|
>
|
||||||
{{ displayName }}
|
{{ displayName }}
|
||||||
</gl-link>
|
</gl-link>
|
||||||
|
<gl-badge
|
||||||
|
v-if="tier"
|
||||||
|
v-gl-tooltip
|
||||||
|
:title="$options.i18n.tierTooltip"
|
||||||
|
class="gl-ml-3 gl-font-monospace"
|
||||||
|
>{{ tier }}</gl-badge
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="gl-display-flex gl-align-items-center">
|
<div class="gl-display-flex gl-align-items-center">
|
||||||
<p v-if="canShowAutoStopDate" class="gl-font-sm gl-text-gray-700 gl-mr-5 gl-mb-0">
|
<p v-if="canShowAutoStopDate" class="gl-font-sm gl-text-gray-700 gl-mr-5 gl-mb-0">
|
||||||
|
|
|
@ -24,7 +24,7 @@ const mapNestedEnvironment = (env) => ({
|
||||||
__typename: 'NestedLocalEnvironment',
|
__typename: 'NestedLocalEnvironment',
|
||||||
});
|
});
|
||||||
const mapEnvironment = (env) => ({
|
const mapEnvironment = (env) => ({
|
||||||
...convertObjectPropsToCamelCase(env),
|
...convertObjectPropsToCamelCase(env, { deep: true }),
|
||||||
__typename: 'LocalEnvironment',
|
__typename: 'LocalEnvironment',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlLink, GlIcon, GlTooltipDirective } from '@gitlab/ui';
|
import { GlLink, GlIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||||
|
import { IssuableStatus } from '~/issues/constants';
|
||||||
import {
|
import {
|
||||||
dateInWords,
|
dateInWords,
|
||||||
getTimeRemainingInWords,
|
getTimeRemainingInWords,
|
||||||
|
@ -41,7 +42,10 @@ export default {
|
||||||
return this.issue.dueDate && dateInWords(newDateAsLocaleTime(this.issue.dueDate), true);
|
return this.issue.dueDate && dateInWords(newDateAsLocaleTime(this.issue.dueDate), true);
|
||||||
},
|
},
|
||||||
showDueDateInRed() {
|
showDueDateInRed() {
|
||||||
return isInPast(newDateAsLocaleTime(this.issue.dueDate)) && !this.issue.closedAt;
|
return (
|
||||||
|
isInPast(newDateAsLocaleTime(this.issue.dueDate)) &&
|
||||||
|
this.issue.state !== IssuableStatus.Closed
|
||||||
|
);
|
||||||
},
|
},
|
||||||
timeEstimate() {
|
timeEstimate() {
|
||||||
return this.issue.humanTimeEstimate || this.issue.timeStats?.humanTimeEstimate;
|
return this.issue.humanTimeEstimate || this.issue.timeStats?.humanTimeEstimate;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { ITEM_TYPE } from '~/groups/constants';
|
import { ITEM_TYPE } from '~/groups/constants';
|
||||||
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
|
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
|
||||||
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
|
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
|
||||||
|
import { IssuableStatus } from '~/issues/constants';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import { scrollUp } from '~/lib/utils/scroll_utils';
|
import { scrollUp } from '~/lib/utils/scroll_utils';
|
||||||
import { getParameterByName, joinPaths } from '~/lib/utils/url_utility';
|
import { getParameterByName, joinPaths } from '~/lib/utils/url_utility';
|
||||||
|
@ -480,10 +481,10 @@ export default {
|
||||||
return `${this.exportCsvPath}${window.location.search}`;
|
return `${this.exportCsvPath}${window.location.search}`;
|
||||||
},
|
},
|
||||||
getStatus(issue) {
|
getStatus(issue) {
|
||||||
if (issue.closedAt && issue.moved) {
|
if (issue.state === IssuableStatus.Closed && issue.moved) {
|
||||||
return this.$options.i18n.closedMoved;
|
return this.$options.i18n.closedMoved;
|
||||||
}
|
}
|
||||||
if (issue.closedAt) {
|
if (issue.state === IssuableStatus.Closed) {
|
||||||
return this.$options.i18n.closed;
|
return this.$options.i18n.closed;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -2,7 +2,6 @@ fragment IssueFragment on Issue {
|
||||||
__typename
|
__typename
|
||||||
id
|
id
|
||||||
iid
|
iid
|
||||||
closedAt
|
|
||||||
confidential
|
confidential
|
||||||
createdAt
|
createdAt
|
||||||
downvotes
|
downvotes
|
||||||
|
@ -11,6 +10,7 @@ fragment IssueFragment on Issue {
|
||||||
humanTimeEstimate
|
humanTimeEstimate
|
||||||
mergeRequestsCount
|
mergeRequestsCount
|
||||||
moved
|
moved
|
||||||
|
state
|
||||||
title
|
title
|
||||||
updatedAt
|
updatedAt
|
||||||
upvotes
|
upvotes
|
||||||
|
|
|
@ -124,7 +124,7 @@ MergeRequest.prototype.submitNoteForm = function (form, $button) {
|
||||||
|
|
||||||
MergeRequest.decreaseCounter = function (by = 1) {
|
MergeRequest.decreaseCounter = function (by = 1) {
|
||||||
const $el = $('.js-merge-counter');
|
const $el = $('.js-merge-counter');
|
||||||
const count = Math.max(parseInt($el.text().replace(/[^\d]/, ''), 10) - by, 0);
|
const count = Math.max(parseInt($el.first().text().replace(/[^\d]/, ''), 10) - by, 0);
|
||||||
|
|
||||||
$el.text(addDelimiter(count));
|
$el.text(addDelimiter(count));
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,6 +29,8 @@ module IssuableLink
|
||||||
validate :check_self_relation
|
validate :check_self_relation
|
||||||
validate :check_opposite_relation
|
validate :check_opposite_relation
|
||||||
|
|
||||||
|
scope :for_source_or_target, ->(issuable) { where(source: issuable).or(where(target: issuable)) }
|
||||||
|
|
||||||
enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1 }
|
enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1 }
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -380,6 +380,12 @@ class Deployment < ApplicationRecord
|
||||||
status == params[:status]
|
status == params[:status]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tier_in_yaml
|
||||||
|
return unless deployable
|
||||||
|
|
||||||
|
deployable.environment_deployment_tier
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def update_status!(status)
|
def update_status!(status)
|
||||||
|
|
|
@ -135,7 +135,7 @@ module ErrorTracking
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_issue(opts = {} )
|
def update_issue(opts = {})
|
||||||
handle_exceptions do
|
handle_exceptions do
|
||||||
{ updated: sentry_client.update_issue(opts) }
|
{ updated: sentry_client.update_issue(opts) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,6 +23,7 @@ class DeploymentEntity < Grape::Entity
|
||||||
expose :tag
|
expose :tag
|
||||||
expose :last?
|
expose :last?
|
||||||
expose :last?, as: :is_last
|
expose :last?, as: :is_last
|
||||||
|
expose :tier_in_yaml
|
||||||
|
|
||||||
expose :deployed_by, as: :user, using: UserEntity
|
expose :deployed_by, as: :user, using: UserEntity
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ module ContainerRegistry
|
||||||
Gitlab::ErrorTracking.log_exception(e, next_aborted_repository_id: next_aborted_repository&.id)
|
Gitlab::ErrorTracking.log_exception(e, next_aborted_repository_id: next_aborted_repository&.id)
|
||||||
|
|
||||||
true
|
true
|
||||||
|
ensure
|
||||||
|
log_repository_migration_state(next_aborted_repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_next_migration
|
def handle_next_migration
|
||||||
|
@ -59,6 +61,8 @@ module ContainerRegistry
|
||||||
next_repository&.abort_import
|
next_repository&.abort_import
|
||||||
|
|
||||||
false
|
false
|
||||||
|
ensure
|
||||||
|
log_repository_migration_state(next_repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_count_too_high?
|
def tag_count_too_high?
|
||||||
|
@ -151,6 +155,12 @@ module ContainerRegistry
|
||||||
log_extra_metadata_on_done(:container_repository_path, repository&.path)
|
log_extra_metadata_on_done(:container_repository_path, repository&.path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_repository_migration_state(repository)
|
||||||
|
return unless repository
|
||||||
|
|
||||||
|
log_extra_metadata_on_done(:container_repository_migration_state, repository.migration_state)
|
||||||
|
end
|
||||||
|
|
||||||
# used by ExclusiveLeaseGuard
|
# used by ExclusiveLeaseGuard
|
||||||
def lease_key
|
def lease_key
|
||||||
'container_registry:migration:enqueuer_worker'
|
'container_registry:migration:enqueuer_worker'
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# This file is used by Rack-based servers to start the application.
|
# This file is used by Rack-based servers to start the application.
|
||||||
|
|
||||||
require ::File.expand_path('../config/environment', __FILE__)
|
require ::File.expand_path('config/environment', __dir__)
|
||||||
|
|
||||||
warmup do |app|
|
warmup do |app|
|
||||||
client = Rack::MockRequest.new(app)
|
client = Rack::MockRequest.new(app)
|
||||||
|
|
|
@ -2484,8 +2484,10 @@ Use `changes` in pipelines with the following refs:
|
||||||
- Paths to files.
|
- Paths to files.
|
||||||
- Wildcard paths for single directories, for example `path/to/directory/*`, or a directory
|
- Wildcard paths for single directories, for example `path/to/directory/*`, or a directory
|
||||||
and all its subdirectories, for example `path/to/directory/**/*`.
|
and all its subdirectories, for example `path/to/directory/**/*`.
|
||||||
- Wildcard ([glob](https://en.wikipedia.org/wiki/Glob_(programming))) paths for all
|
- Wildcard [glob](https://en.wikipedia.org/wiki/Glob_(programming)) paths for all
|
||||||
files with the same extension or multiple extensions, for example `*.md` or `path/to/directory/*.{rb,py,sh}`.
|
files with the same extension or multiple extensions, for example `*.md` or `path/to/directory/*.{rb,py,sh}`.
|
||||||
|
See the [Ruby `fnmatch` documentation](https://docs.ruby-lang.org/en/master/File.html#method-c-fnmatch)
|
||||||
|
for the supported syntax list.
|
||||||
- Wildcard paths to files in the root directory, or all directories, wrapped in double quotes.
|
- Wildcard paths to files in the root directory, or all directories, wrapped in double quotes.
|
||||||
For example `"*.json"` or `"**/*.json"`.
|
For example `"*.json"` or `"**/*.json"`.
|
||||||
|
|
||||||
|
|
|
@ -91,20 +91,25 @@ The API fuzzing configuration form helps you create or modify your project's API
|
||||||
configuration. The form lets you choose values for the most common API fuzzing options and builds
|
configuration. The form lets you choose values for the most common API fuzzing options and builds
|
||||||
a YAML snippet that you can paste in your GitLab CI/CD configuration.
|
a YAML snippet that you can paste in your GitLab CI/CD configuration.
|
||||||
|
|
||||||
#### Configure Web API fuzzing with the configuration form
|
#### Configure Web API fuzzing in the UI
|
||||||
|
|
||||||
To generate an API Fuzzing configuration snippet:
|
To generate an API Fuzzing configuration snippet:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Projects** and find your project.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||||
1. In the **API Fuzzing** row, select **Configure**.
|
1. In the **API Fuzzing** row, select **Enable API Fuzzing**.
|
||||||
1. Complete the form as needed. Read below for more information on available configuration options.
|
1. Complete the fields. For details see [Available CI/CD variables](#available-cicd-variables).
|
||||||
1. Select **Generate code snippet**.
|
1. Select **Generate code snippet**.
|
||||||
A modal opens with the YAML snippet corresponding to the options you've selected in the form.
|
A modal opens with the YAML snippet corresponding to the options you've selected in the form.
|
||||||
1. Choose one of the following actions:
|
1. Do one of the following:
|
||||||
1. To copy the snippet to your clipboard and be redirected to your project's `.gitlab-ci.yml` file,
|
1. To copy the snippet to your clipboard, select **Copy code only**.
|
||||||
where you can paste the YAML configuration, select **Copy code and open `.gitlab-ci.yml` file**.
|
1. To add the snippet to your project's `.gitlab-ci.yml` file, select
|
||||||
1. To copy the snippet to your clipboard and close the modal, select **Copy code only**.
|
**Copy code and open `.gitlab-ci.yml` file**. The Pipeline Editor opens.
|
||||||
|
1. Paste the snippet into the `.gitlab-ci.yml` file.
|
||||||
|
1. Select the **Lint** tab to confirm the edited `.gitlab-ci.yml` file is valid.
|
||||||
|
1. Select the **Edit** tab, then select **Commit changes**.
|
||||||
|
|
||||||
|
When the snippet is committed to the `.gitlab-ci.yml` file, pipelines include an API Fuzzing job.
|
||||||
|
|
||||||
### OpenAPI Specification
|
### OpenAPI Specification
|
||||||
|
|
||||||
|
|
|
@ -278,7 +278,8 @@ page.
|
||||||
You can enable or configure DAST settings using the UI. The generated settings are formatted so they
|
You can enable or configure DAST settings using the UI. The generated settings are formatted so they
|
||||||
can be conveniently pasted into the `.gitlab-ci.yml` file.
|
can be conveniently pasted into the `.gitlab-ci.yml` file.
|
||||||
|
|
||||||
1. From the project's home page, go to **Security & Compliance > Configuration**.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
|
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||||
1. In the **Dynamic Application Security Testing (DAST)** section, select **Enable DAST** or
|
1. In the **Dynamic Application Security Testing (DAST)** section, select **Enable DAST** or
|
||||||
**Configure DAST**.
|
**Configure DAST**.
|
||||||
1. Select the desired **Scanner profile**, or select **Create scanner profile** and save a
|
1. Select the desired **Scanner profile**, or select **Create scanner profile** and save a
|
||||||
|
@ -288,12 +289,14 @@ can be conveniently pasted into the `.gitlab-ci.yml` file.
|
||||||
1. Select **Generate code snippet**. A modal opens with the YAML snippet corresponding to the
|
1. Select **Generate code snippet**. A modal opens with the YAML snippet corresponding to the
|
||||||
options you selected.
|
options you selected.
|
||||||
1. Do one of the following:
|
1. Do one of the following:
|
||||||
1. Select **Copy code only** to copy the snippet to your clipboard.
|
1. To copy the snippet to your clipboard, select **Copy code only**.
|
||||||
1. Select **Copy code and open `.gitlab-ci.yml` file** to copy the snippet to your clipboard. The
|
1. To add the snippet to your project's `.gitlab-ci.yml` file, select
|
||||||
CI/CD Editor then opens.
|
**Copy code and open `.gitlab-ci.yml` file**. The Pipeline Editor opens.
|
||||||
1. Paste the snippet into the `.gitlab-ci.yml` file.
|
1. Paste the snippet into the `.gitlab-ci.yml` file.
|
||||||
1. Select the **Lint** tab to confirm the edited `.gitlab-ci.yml` file is valid.
|
1. Select the **Lint** tab to confirm the edited `.gitlab-ci.yml` file is valid.
|
||||||
1. Select **Commit changes**.
|
1. Select the **Edit** tab, then select **Commit changes**.
|
||||||
|
|
||||||
|
When the snippet is committed to the `.gitlab-ci.yml` file, pipelines include a DAST job.
|
||||||
|
|
||||||
#### Crawling web applications dependent on JavaScript
|
#### Crawling web applications dependent on JavaScript
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,9 @@ the body generation is limited to these body types:
|
||||||
- `application/json`
|
- `application/json`
|
||||||
- `application/xml`
|
- `application/xml`
|
||||||
|
|
||||||
Follow these steps to configure DAST API in GitLab with an OpenAPI specification:
|
To configure DAST API scanning with an OpenAPI specification:
|
||||||
|
|
||||||
1. To use DAST API, you must [include](../../../ci/yaml/index.md#includetemplate)
|
1. To use DAST API scanning, [include](../../../ci/yaml/index.md#includetemplate)
|
||||||
the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
|
the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
|
||||||
that's provided as part of your GitLab installation. Add the following to your
|
that's provided as part of your GitLab installation. Add the following to your
|
||||||
`.gitlab-ci.yml` file:
|
`.gitlab-ci.yml` file:
|
||||||
|
@ -182,8 +182,7 @@ WARNING:
|
||||||
HAR files may contain sensitive information such as authentication tokens, API keys, and session
|
HAR files may contain sensitive information such as authentication tokens, API keys, and session
|
||||||
cookies. We recommend that you review the HAR file contents before adding them to a repository.
|
cookies. We recommend that you review the HAR file contents before adding them to a repository.
|
||||||
|
|
||||||
Follow these steps to configure DAST API to use a HAR file that provides information about the
|
To configure DAST API scanning to use a HAR file:
|
||||||
target API to test:
|
|
||||||
|
|
||||||
1. To use DAST API, you must [include](../../../ci/yaml/index.md#includetemplate)
|
1. To use DAST API, you must [include](../../../ci/yaml/index.md#includetemplate)
|
||||||
the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
|
the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
|
||||||
|
@ -282,8 +281,7 @@ Postman Collection files may contain sensitive information such as authenticatio
|
||||||
and session cookies. We recommend that you review the Postman Collection file contents before adding
|
and session cookies. We recommend that you review the Postman Collection file contents before adding
|
||||||
them to a repository.
|
them to a repository.
|
||||||
|
|
||||||
Follow these steps to configure DAST API to use a Postman Collection file that provides
|
To configure DAST API scanning to use a Postman Collection file:
|
||||||
information about the target API to test:
|
|
||||||
|
|
||||||
1. To use DAST API, you must [include](../../../ci/yaml/index.md#includetemplate)
|
1. To use DAST API, you must [include](../../../ci/yaml/index.md#includetemplate)
|
||||||
the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
|
the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
|
||||||
|
|
|
@ -508,19 +508,18 @@ always take the latest dependency scanning artifact available.
|
||||||
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/282533) in GitLab 14.1.
|
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/282533) in GitLab 14.1.
|
||||||
> - [Feature flag sec_dependency_scanning_ui_enable removed](https://gitlab.com/gitlab-org/gitlab/-/issues/326005) in GitLab 14.2.
|
> - [Feature flag sec_dependency_scanning_ui_enable removed](https://gitlab.com/gitlab-org/gitlab/-/issues/326005) in GitLab 14.2.
|
||||||
|
|
||||||
To enable Dependency Scanning in a project, you can create a merge request
|
To enable Dependency Scanning in a project, you can create a merge request:
|
||||||
from the Security Configuration page.
|
|
||||||
|
|
||||||
1. In the project where you want to enable Dependency Scanning, navigate to
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
**Security & Compliance > Configuration**.
|
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||||
1. In the **Dependency Scanning** row, select **Configure with a merge request**.
|
1. In the **Dependency Scanning** row, select **Configure with a merge request**.
|
||||||
|
1. Review and merge the merge request to enable Dependency Scanning.
|
||||||
|
|
||||||
This automatically creates a merge request with the changes necessary to enable Dependency Scanning
|
Pipelines now include a dependency scanning job.
|
||||||
that you can review and merge to complete the configuration.
|
|
||||||
|
|
||||||
### Customizing the dependency scanning settings
|
### Customizing the dependency scanning settings
|
||||||
|
|
||||||
The dependency scanning settings can be changed through [CI/CD variables](#available-cicd-variables) by using the
|
The Dependency Scanning settings can be changed through [CI/CD variables](#available-cicd-variables) by using the
|
||||||
[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`.
|
[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`.
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
|
|
@ -93,15 +93,14 @@ that you can download and analyze.
|
||||||
|
|
||||||
### Enable IaC Scanning via an automatic merge request
|
### Enable IaC Scanning via an automatic merge request
|
||||||
|
|
||||||
To enable IaC Scanning in a project, you can create a merge request
|
To enable IaC Scanning in a project, you can create a merge request:
|
||||||
from the Security Configuration page:
|
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Projects** and find your project.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||||
1. In the **Infrastructure as Code (IaC) Scanning** row, select **Configure with a merge request**.
|
1. In the **Infrastructure as Code (IaC) Scanning** row, select **Configure with a merge request**.
|
||||||
|
1. Review and merge the merge request to enable IaC Scanning.
|
||||||
|
|
||||||
This automatically creates a merge request with the changes necessary to enable IaC Scanning
|
Pipelines now include an IaC job.
|
||||||
that you can review and merge to complete the configuration.
|
|
||||||
|
|
||||||
## Reports JSON format
|
## Reports JSON format
|
||||||
|
|
||||||
|
|
|
@ -190,56 +190,57 @@ always take the latest SAST artifact available.
|
||||||
### Configure SAST in the UI
|
### Configure SAST in the UI
|
||||||
|
|
||||||
You can enable and configure SAST in the UI, either with default settings, or with customizations.
|
You can enable and configure SAST in the UI, either with default settings, or with customizations.
|
||||||
Use the method that best meets your needs.
|
The method you can use depends on your GitLab license tier.
|
||||||
|
|
||||||
- [Configure SAST in the UI with default settings](#configure-sast-in-the-ui-with-default-settings)
|
- [Configure SAST in the UI with default settings](#configure-sast-in-the-ui-with-default-settings).
|
||||||
- [Configure SAST in the UI with customizations](#configure-sast-in-the-ui-with-customizations)
|
- [Configure SAST in the UI with customizations](#configure-sast-in-the-ui-with-customizations). **(ULTIMATE)**
|
||||||
|
|
||||||
### Configure SAST in the UI with default settings
|
### Configure SAST in the UI with default settings
|
||||||
|
|
||||||
> [Introduced](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#security-configuration-page-for-all-users) in GitLab 13.9
|
> [Introduced](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#security-configuration-page-for-all-users) in GitLab 13.9
|
||||||
|
|
||||||
To enable and configure SAST with default settings:
|
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Projects** and find your project.
|
|
||||||
1. On the left sidebar, select **Security & Compliance** > **Configuration**.
|
|
||||||
1. In the SAST section, select `Enable via MR`.
|
|
||||||
1. Review the draft MR that enables SAST with the default recommended settings in the
|
|
||||||
`.gitlab-ci.yml` file.
|
|
||||||
1. Merge the MR to enable SAST. You should see SAST jobs run in that MR's pipeline.
|
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
The configuration tool works best with no existing `.gitlab-ci.yml` file, or with a minimal
|
The configuration tool works best with no existing `.gitlab-ci.yml` file, or with a minimal
|
||||||
configuration file. If you have a complex GitLab configuration file it may not be parsed
|
configuration file. If you have a complex GitLab configuration file it may not be parsed
|
||||||
successfully, and an error may occur.
|
successfully, and an error may occur.
|
||||||
|
|
||||||
|
To enable and configure SAST with default settings:
|
||||||
|
|
||||||
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
|
1. On the left sidebar, select **Security & Compliance** > **Configuration**.
|
||||||
|
1. In the SAST section, select **Configure with a merge request**.
|
||||||
|
1. Review and merge the merge request to enable SAST.
|
||||||
|
|
||||||
|
Pipelines now include a SAST job.
|
||||||
|
|
||||||
### Configure SAST in the UI with customizations **(ULTIMATE)**
|
### Configure SAST in the UI with customizations **(ULTIMATE)**
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3659) in GitLab 13.3.
|
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3659) in GitLab 13.3.
|
||||||
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in GitLab 13.4.
|
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in GitLab 13.4.
|
||||||
> - [Improved](https://gitlab.com/groups/gitlab-org/-/epics/3635) in GitLab 13.5.
|
> - [Improved](https://gitlab.com/groups/gitlab-org/-/epics/3635) in GitLab 13.5.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
The configuration tool works best with no existing `.gitlab-ci.yml` file, or with a minimal
|
||||||
|
configuration file. If you have a complex GitLab configuration file it may not be parsed
|
||||||
|
successfully, and an error may occur.
|
||||||
|
|
||||||
To enable and configure SAST with customizations:
|
To enable and configure SAST with customizations:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Projects** and find your project.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||||
1. If the project does not have a `.gitlab-ci.yml` file, select **Enable** in the Static Application
|
1. If the project does not have a `.gitlab-ci.yml` file, select **Enable SAST** in the Static
|
||||||
Security Testing (SAST) row, otherwise select **Configure**.
|
Application Security Testing (SAST) row, otherwise select **Configure SAST**.
|
||||||
1. Enter the custom SAST values.
|
1. Enter the custom SAST values.
|
||||||
|
|
||||||
Custom values are stored in the `.gitlab-ci.yml` file. For CI/CD variables not in the SAST
|
Custom values are stored in the `.gitlab-ci.yml` file. For CI/CD variables not in the SAST
|
||||||
Configuration page, their values are left unchanged. Default values are inherited from the GitLab
|
Configuration page, their values are inherited from the GitLab SAST template.
|
||||||
SAST template.
|
|
||||||
|
|
||||||
1. Optionally, expand the **SAST analyzers** section, select individual
|
1. Optionally, expand the **SAST analyzers** section, select individual
|
||||||
[SAST analyzers](analyzers.md) and enter custom analyzer values.
|
[SAST analyzers](analyzers.md) and enter custom analyzer values.
|
||||||
1. Select **Create Merge Request**.
|
1. Select **Create Merge Request**.
|
||||||
1. Review and merge the merge request.
|
1. Review and merge the merge request.
|
||||||
|
|
||||||
NOTE:
|
Pipelines now include a SAST job.
|
||||||
The configuration tool works best with no existing `.gitlab-ci.yml` file, or with a minimal
|
|
||||||
configuration file. If you have a complex GitLab configuration file it may not be parsed
|
|
||||||
successfully, and an error may occur.
|
|
||||||
|
|
||||||
### Overriding SAST jobs
|
### Overriding SAST jobs
|
||||||
|
|
||||||
|
|
|
@ -112,20 +112,19 @@ always take the latest Secret Detection artifact available.
|
||||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4496) in GitLab 13.11, deployed behind a feature flag, enabled by default.
|
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4496) in GitLab 13.11, deployed behind a feature flag, enabled by default.
|
||||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/329886) in GitLab 14.1.
|
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/329886) in GitLab 14.1.
|
||||||
|
|
||||||
To enable Secret Detection in a project, you can create a merge request
|
|
||||||
from the Security Configuration page.
|
|
||||||
|
|
||||||
1. In the project where you want to enable Secret Detection, go to
|
|
||||||
**Security & Compliance > Configuration**.
|
|
||||||
1. In the **Secret Detection** row, select **Configure with a merge request**.
|
|
||||||
|
|
||||||
This automatically creates a merge request with the changes necessary to enable Secret Detection
|
|
||||||
that you can review and merge to complete the configuration.
|
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
The configuration tool works best with no existing `.gitlab-ci.yml` file, or with a minimal
|
This method works best with no existing `.gitlab-ci.yml` file, or with a minimal configuration
|
||||||
configuration file. If you have a complex GitLab configuration file it may not be parsed
|
file. If you have a complex GitLab configuration file it may not be parsed successfully, and an
|
||||||
successfully, and an error may occur.
|
error may occur.
|
||||||
|
|
||||||
|
To enable Secret Detection in a project, you can create a merge request:
|
||||||
|
|
||||||
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
|
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||||
|
1. In the **Secret Detection** row, select **Configure with a merge request**.
|
||||||
|
1. Review and merge the merge request to enable Secret Detection.
|
||||||
|
|
||||||
|
Pipelines now include a Secret Detection job.
|
||||||
|
|
||||||
### Customizing settings
|
### Customizing settings
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ Creating a file is optional but is needed if:
|
||||||
- You use [a GitOps workflow](../gitops.md#gitops-configuration-reference) and you want a more advanced configuration.
|
- You use [a GitOps workflow](../gitops.md#gitops-configuration-reference) and you want a more advanced configuration.
|
||||||
- You use a GitLab CI/CD workflow. In that workflow, you must [authorize the agent](../ci_cd_tunnel.md#authorize-the-agent).
|
- You use a GitLab CI/CD workflow. In that workflow, you must [authorize the agent](../ci_cd_tunnel.md#authorize-the-agent).
|
||||||
|
|
||||||
|
If you do not create an agent configuration file, you can use the CI/CD workflow in the project where the agent is registered only.
|
||||||
|
|
||||||
To create an agent configuration file, go to the GitLab project. In the repository, create a file called `config.yaml` at this path:
|
To create an agent configuration file, go to the GitLab project. In the repository, create a file called `config.yaml` at this path:
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
|
|
|
@ -67,14 +67,16 @@ module API
|
||||||
requires :issue_link_id, type: Integer, desc: 'The ID of an issue link'
|
requires :issue_link_id, type: Integer, desc: 'The ID of an issue link'
|
||||||
end
|
end
|
||||||
delete ':id/issues/:issue_iid/links/:issue_link_id' do
|
delete ':id/issues/:issue_iid/links/:issue_link_id' do
|
||||||
issue_link = IssueLink.find(declared_params[:issue_link_id])
|
issue = find_project_issue(params[:issue_iid])
|
||||||
|
issue_link = IssueLink
|
||||||
|
.for_source_or_target(issue)
|
||||||
|
.find(declared_params[:issue_link_id])
|
||||||
|
|
||||||
find_project_issue(params[:issue_iid])
|
|
||||||
find_project_issue(issue_link.target.iid.to_s, issue_link.target.project_id.to_s)
|
find_project_issue(issue_link.target.iid.to_s, issue_link.target.project_id.to_s)
|
||||||
|
|
||||||
result = ::IssueLinks::DestroyService
|
result = ::IssueLinks::DestroyService
|
||||||
.new(issue_link, current_user)
|
.new(issue_link, current_user)
|
||||||
.execute
|
.execute
|
||||||
|
|
||||||
if result[:status] == :success
|
if result[:status] == :success
|
||||||
present issue_link, with: Entities::IssueLink
|
present issue_link, with: Entities::IssueLink
|
||||||
|
|
|
@ -52,9 +52,9 @@ module Gitlab
|
||||||
WHERE cte_id = id
|
WHERE cte_id = id
|
||||||
SQL
|
SQL
|
||||||
end
|
end
|
||||||
|
|
||||||
mark_job_as_succeeded(start_id, end_id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mark_job_as_succeeded(start_id, end_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -4,11 +4,13 @@ module Gitlab
|
||||||
module Database
|
module Database
|
||||||
module EachDatabase
|
module EachDatabase
|
||||||
class << self
|
class << self
|
||||||
def each_database_connection(only: nil)
|
def each_database_connection(only: nil, include_shared: true)
|
||||||
selected_names = Array.wrap(only)
|
selected_names = Array.wrap(only)
|
||||||
base_models = select_base_models(selected_names)
|
base_models = select_base_models(selected_names)
|
||||||
|
|
||||||
base_models.each_pair do |connection_name, model|
|
base_models.each_pair do |connection_name, model|
|
||||||
|
next if !include_shared && Gitlab::Database.db_config_share_with(model.connection_db_config)
|
||||||
|
|
||||||
connection = model.connection
|
connection = model.connection
|
||||||
|
|
||||||
with_shared_connection(connection, connection_name) do
|
with_shared_connection(connection, connection_name) do
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace :gitlab do
|
||||||
begin
|
begin
|
||||||
ActiveRecord::Base.establish_connection(db_config) # rubocop: disable Database/EstablishConnection
|
ActiveRecord::Base.establish_connection(db_config) # rubocop: disable Database/EstablishConnection
|
||||||
ActiveRecord::Base.connection.select_one("SELECT system_identifier, current_database() FROM pg_control_system()")
|
ActiveRecord::Base.connection.select_one("SELECT system_identifier, current_database() FROM pg_control_system()")
|
||||||
rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad
|
rescue ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad
|
||||||
end
|
end
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace :gitlab do
|
||||||
AND pid <> pg_backend_pid();
|
AND pid <> pg_backend_pid();
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
Gitlab::Database::EachDatabase.each_database_connection do |connection|
|
Gitlab::Database::EachDatabase.each_database_connection(include_shared: false) do |connection|
|
||||||
connection.execute(cmd)
|
connection.execute(cmd)
|
||||||
rescue ActiveRecord::NoDatabaseError
|
rescue ActiveRecord::NoDatabaseError
|
||||||
end
|
end
|
||||||
|
|
|
@ -7402,6 +7402,9 @@ msgstr ""
|
||||||
msgid "Child epic doesn't exist."
|
msgid "Child epic doesn't exist."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Child issues and epics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Chinese language support using"
|
msgid "Chinese language support using"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -14395,6 +14398,9 @@ msgstr ""
|
||||||
msgid "Environment|Auto stop %{time}"
|
msgid "Environment|Auto stop %{time}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Environment|Deployment tier"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Epic"
|
msgid "Epic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -14419,9 +14425,6 @@ msgstr ""
|
||||||
msgid "Epics Roadmap"
|
msgid "Epics Roadmap"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Epics and Issues"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
|
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -15413,6 +15416,9 @@ msgstr ""
|
||||||
msgid "Failed to load"
|
msgid "Failed to load"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Failed to load Roadmap"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Failed to load assignees."
|
msgid "Failed to load assignees."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -32148,6 +32154,9 @@ msgstr ""
|
||||||
msgid "Roadmap settings"
|
msgid "Roadmap settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Roadmap view"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Role"
|
msgid "Role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -75,11 +75,10 @@ module QA
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def has_imported_project?(gh_project_name, wait: QA::Support::WaitForRequests::DEFAULT_MAX_WAIT_TIME)
|
def has_imported_project?(gh_project_name, wait: QA::Support::WaitForRequests::DEFAULT_MAX_WAIT_TIME)
|
||||||
within_element(:project_import_row, source_project: gh_project_name, skip_finished_loading_check: true) do
|
within_element(:project_import_row, source_project: gh_project_name, skip_finished_loading_check: true) do
|
||||||
# TODO: remove retrier with reload:true once https://gitlab.com/gitlab-org/gitlab/-/issues/292861 is fixed
|
|
||||||
wait_until(
|
wait_until(
|
||||||
max_duration: wait,
|
max_duration: wait,
|
||||||
sleep_interval: 5,
|
sleep_interval: 5,
|
||||||
reload: true,
|
reload: false,
|
||||||
skip_finished_loading_check_on_refresh: true
|
skip_finished_loading_check_on_refresh: true
|
||||||
) do
|
) do
|
||||||
has_element?(:import_status_indicator, text: "Complete")
|
has_element?(:import_status_indicator, text: "Complete")
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Package', :orchestrated, :skip_live_env do
|
RSpec.describe 'Package', :orchestrated, :skip_live_env do
|
||||||
describe 'Self-managed Container Registry' do
|
describe 'Self-managed Container Registry' do
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
|
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api! do |project|
|
||||||
project.name = 'project-with-registry'
|
project.name = 'project-with-registry'
|
||||||
|
@ -110,9 +112,9 @@ module QA
|
||||||
let(:auth_token) do
|
let(:auth_token) do
|
||||||
case authentication_token_type
|
case authentication_token_type
|
||||||
when :personal_access_token
|
when :personal_access_token
|
||||||
"\"#{personal_access_token}\""
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: project)
|
||||||
when :project_deploy_token
|
when :project_deploy_token
|
||||||
"\"#{project_deploy_token.token}\""
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project)
|
||||||
when :ci_job_token
|
when :ci_job_token
|
||||||
'$CI_JOB_TOKEN'
|
'$CI_JOB_TOKEN'
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ module QA
|
||||||
describe 'Helm Registry' do
|
describe 'Helm Registry' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
using RSpec::Parameterized::TableSyntax
|
||||||
include Runtime::Fixtures
|
include Runtime::Fixtures
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
include_context 'packages registry qa scenario'
|
include_context 'packages registry qa scenario'
|
||||||
|
|
||||||
let(:package_name) { "gitlab_qa_helm-#{SecureRandom.hex(8)}" }
|
let(:package_name) { "gitlab_qa_helm-#{SecureRandom.hex(8)}" }
|
||||||
|
@ -32,11 +33,13 @@ module QA
|
||||||
let(:access_token) do
|
let(:access_token) do
|
||||||
case authentication_token_type
|
case authentication_token_type
|
||||||
when :personal_access_token
|
when :personal_access_token
|
||||||
personal_access_token
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: package_project)
|
||||||
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: client_project)
|
||||||
when :ci_job_token
|
when :ci_job_token
|
||||||
'${CI_JOB_TOKEN}'
|
'${CI_JOB_TOKEN}'
|
||||||
when :project_deploy_token
|
when :project_deploy_token
|
||||||
project_deploy_token.token
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: package_project)
|
||||||
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: client_project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ module QA
|
||||||
describe 'npm instance level endpoint' do
|
describe 'npm instance level endpoint' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
using RSpec::Parameterized::TableSyntax
|
||||||
include Runtime::Fixtures
|
include Runtime::Fixtures
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
|
|
||||||
let!(:registry_scope) { Runtime::Namespace.sandbox_name }
|
let!(:registry_scope) { Runtime::Namespace.sandbox_name }
|
||||||
let!(:personal_access_token) do
|
let!(:personal_access_token) do
|
||||||
|
@ -78,11 +79,13 @@ module QA
|
||||||
let(:auth_token) do
|
let(:auth_token) do
|
||||||
case authentication_token_type
|
case authentication_token_type
|
||||||
when :personal_access_token
|
when :personal_access_token
|
||||||
"\"#{personal_access_token}\""
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: project)
|
||||||
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: another_project)
|
||||||
when :ci_job_token
|
when :ci_job_token
|
||||||
'${CI_JOB_TOKEN}'
|
'${CI_JOB_TOKEN}'
|
||||||
when :project_deploy_token
|
when :project_deploy_token
|
||||||
"\"#{project_deploy_token.token}\""
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project)
|
||||||
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: another_project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ module QA
|
||||||
describe 'npm project level endpoint' do
|
describe 'npm project level endpoint' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
using RSpec::Parameterized::TableSyntax
|
||||||
include Runtime::Fixtures
|
include Runtime::Fixtures
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
|
|
||||||
let!(:registry_scope) { Runtime::Namespace.sandbox_name }
|
let!(:registry_scope) { Runtime::Namespace.sandbox_name }
|
||||||
let!(:personal_access_token) do
|
let!(:personal_access_token) do
|
||||||
|
@ -69,11 +70,11 @@ module QA
|
||||||
let(:auth_token) do
|
let(:auth_token) do
|
||||||
case authentication_token_type
|
case authentication_token_type
|
||||||
when :personal_access_token
|
when :personal_access_token
|
||||||
"\"#{personal_access_token}\""
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: project)
|
||||||
when :ci_job_token
|
when :ci_job_token
|
||||||
'${CI_JOB_TOKEN}'
|
'${CI_JOB_TOKEN}'
|
||||||
when :project_deploy_token
|
when :project_deploy_token
|
||||||
"\"#{project_deploy_token.token}\""
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ module QA
|
||||||
describe 'NuGet group level endpoint' do
|
describe 'NuGet group level endpoint' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
using RSpec::Parameterized::TableSyntax
|
||||||
include Runtime::Fixtures
|
include Runtime::Fixtures
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
|
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api! do |project|
|
||||||
|
@ -61,6 +62,8 @@ module QA
|
||||||
after do
|
after do
|
||||||
runner.remove_via_api!
|
runner.remove_via_api!
|
||||||
package.remove_via_api!
|
package.remove_via_api!
|
||||||
|
project.remove_via_api!
|
||||||
|
another_project.remove_via_api!
|
||||||
end
|
end
|
||||||
|
|
||||||
where(:case_name, :authentication_token_type, :token_name, :testcase) do
|
where(:case_name, :authentication_token_type, :token_name, :testcase) do
|
||||||
|
@ -73,11 +76,13 @@ module QA
|
||||||
let(:auth_token_password) do
|
let(:auth_token_password) do
|
||||||
case authentication_token_type
|
case authentication_token_type
|
||||||
when :personal_access_token
|
when :personal_access_token
|
||||||
"\"#{personal_access_token.token}\""
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token.token, project: project)
|
||||||
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token.token, project: another_project)
|
||||||
when :ci_job_token
|
when :ci_job_token
|
||||||
'${CI_JOB_TOKEN}'
|
'${CI_JOB_TOKEN}'
|
||||||
when :group_deploy_token
|
when :group_deploy_token
|
||||||
"\"#{group_deploy_token.token}\""
|
use_ci_variable(name: 'GROUP_DEPLOY_TOKEN', value: group_deploy_token.token, project: project)
|
||||||
|
use_ci_variable(name: 'GROUP_DEPLOY_TOKEN', value: group_deploy_token.token, project: another_project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
|
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
|
||||||
describe 'NuGet project level endpoint' do
|
describe 'NuGet project level endpoint' do
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
|
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api! do |project|
|
||||||
project.name = 'nuget-package-project'
|
project.name = 'nuget-package-project'
|
||||||
|
@ -77,11 +79,11 @@ module QA
|
||||||
let(:auth_token_password) do
|
let(:auth_token_password) do
|
||||||
case authentication_token_type
|
case authentication_token_type
|
||||||
when :personal_access_token
|
when :personal_access_token
|
||||||
"\"#{personal_access_token.token}\""
|
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token.token, project: project)
|
||||||
when :ci_job_token
|
when :ci_job_token
|
||||||
'${CI_JOB_TOKEN}'
|
'${CI_JOB_TOKEN}'
|
||||||
when :project_deploy_token
|
when :project_deploy_token
|
||||||
"\"#{project_deploy_token.token}\""
|
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ module QA
|
||||||
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
|
RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
|
||||||
describe 'PyPI Repository' do
|
describe 'PyPI Repository' do
|
||||||
include Runtime::Fixtures
|
include Runtime::Fixtures
|
||||||
|
include Support::Helpers::MaskToken
|
||||||
|
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api! do |project|
|
||||||
|
@ -30,7 +31,7 @@ module QA
|
||||||
let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
|
let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
|
||||||
let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
|
let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
|
||||||
let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
|
let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
|
||||||
let(:personal_access_token) { Runtime::Env.personal_access_token }
|
let(:personal_access_token) { use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module QA
|
||||||
|
module Support
|
||||||
|
module Helpers
|
||||||
|
module MaskToken
|
||||||
|
def use_ci_variable(name:, value:, project:)
|
||||||
|
Resource::CiVariable.fabricate_via_api! do |ci_variable|
|
||||||
|
ci_variable.project = project
|
||||||
|
ci_variable.key = name
|
||||||
|
ci_variable.value = value
|
||||||
|
ci_variable.protected = true
|
||||||
|
end
|
||||||
|
"$#{name}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,12 +5,10 @@ FactoryBot.define do
|
||||||
skip_create
|
skip_create
|
||||||
|
|
||||||
initialize_with do
|
initialize_with do
|
||||||
p = attributes[:params]
|
s = Packages::SemVer.parse(semver, prefixed: true)
|
||||||
s = Packages::SemVer.parse(p.semver, prefixed: true)
|
raise ArgumentError, "invalid sematic version: #{semver.inspect}" if !s && semver
|
||||||
|
|
||||||
raise ArgumentError, "invalid sematic version: '#{p.semver}'" if !s && p.semver
|
new(mod, type, commit, name: name, semver: s, ref: ref)
|
||||||
|
|
||||||
new(p.mod, p.type, p.commit, name: p.name, semver: s, ref: p.ref)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
mod { association(:go_module) }
|
mod { association(:go_module) }
|
||||||
|
@ -20,8 +18,6 @@ FactoryBot.define do
|
||||||
semver { nil }
|
semver { nil }
|
||||||
ref { nil }
|
ref { nil }
|
||||||
|
|
||||||
params { OpenStruct.new(mod: mod, type: type, commit: commit, name: name, semver: semver, ref: ref) }
|
|
||||||
|
|
||||||
trait :tagged do
|
trait :tagged do
|
||||||
ref { mod.project.repository.find_tag(name) }
|
ref { mod.project.repository.find_tag(name) }
|
||||||
commit { ref.dereferenced_target }
|
commit { ref.dereferenced_target }
|
||||||
|
@ -36,8 +32,8 @@ FactoryBot.define do
|
||||||
.max_by(&:to_s)
|
.max_by(&:to_s)
|
||||||
.to_s
|
.to_s
|
||||||
end
|
end
|
||||||
|
type { :ref }
|
||||||
params { OpenStruct.new(mod: mod, type: :ref, commit: commit, semver: name, ref: ref) }
|
semver { name }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ RSpec.describe "User merges a merge request", :js do
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples "fast forward merge a merge request" do
|
shared_examples "fast forward merge a merge request" do
|
||||||
it "merges a merge request", :sidekiq_might_not_need_inline do
|
it "merges a merge request", :sidekiq_inline do
|
||||||
expect(page).to have_content("Fast-forward merge without a merge commit").and have_button("Merge")
|
expect(page).to have_content("Fast-forward merge without a merge commit").and have_button("Merge")
|
||||||
|
|
||||||
page.within(".mr-state-widget") do
|
page.within(".mr-state-widget") do
|
||||||
|
@ -42,4 +42,23 @@ RSpec.describe "User merges a merge request", :js do
|
||||||
it_behaves_like "fast forward merge a merge request"
|
it_behaves_like "fast forward merge a merge request"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'sidebar merge requests counter' do
|
||||||
|
let(:project) { create(:project, :public, :repository) }
|
||||||
|
let!(:merge_request) { create(:merge_request, source_project: project) }
|
||||||
|
|
||||||
|
it 'decrements the open MR count', :sidekiq_inline do
|
||||||
|
create(:merge_request, source_project: project, source_branch: 'branch-1')
|
||||||
|
|
||||||
|
visit(merge_request_path(merge_request))
|
||||||
|
|
||||||
|
expect(page).to have_css('.js-merge-counter', text: '2')
|
||||||
|
|
||||||
|
page.within(".mr-state-widget") do
|
||||||
|
click_button("Merge")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_css('.js-merge-counter', text: '1')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ import timeagoMixin from '~/vue_shared/mixins/timeago';
|
||||||
import { clusterAgents, connectedTimeNow, connectedTimeInactive } from './mock_data';
|
import { clusterAgents, connectedTimeNow, connectedTimeInactive } from './mock_data';
|
||||||
|
|
||||||
const defaultConfigHelpUrl =
|
const defaultConfigHelpUrl =
|
||||||
'/help/user/clusters/agent/install/index#create-an-agent-without-configuration-file';
|
'/help/user/clusters/agent/install/index#create-an-agent-configuration-file';
|
||||||
|
|
||||||
const provideData = {
|
const provideData = {
|
||||||
gitlabVersion: '14.8',
|
gitlabVersion: '14.8',
|
||||||
|
|
|
@ -543,6 +543,7 @@ export const resolvedEnvironment = {
|
||||||
externalUrl: 'https://example.org',
|
externalUrl: 'https://example.org',
|
||||||
environmentType: 'review',
|
environmentType: 'review',
|
||||||
nameWithoutType: 'hello',
|
nameWithoutType: 'hello',
|
||||||
|
tier: 'development',
|
||||||
lastDeployment: {
|
lastDeployment: {
|
||||||
id: 78,
|
id: 78,
|
||||||
iid: 24,
|
iid: 24,
|
||||||
|
@ -551,6 +552,7 @@ export const resolvedEnvironment = {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
createdAt: '2022-01-07T15:47:27.415Z',
|
createdAt: '2022-01-07T15:47:27.415Z',
|
||||||
deployedAt: '2022-01-07T15:47:32.450Z',
|
deployedAt: '2022-01-07T15:47:32.450Z',
|
||||||
|
tierInYaml: 'staging',
|
||||||
tag: false,
|
tag: false,
|
||||||
isLast: true,
|
isLast: true,
|
||||||
user: {
|
user: {
|
||||||
|
|
|
@ -73,6 +73,34 @@ describe('~/environments/components/new_environment_item.vue', () => {
|
||||||
expect(name.text()).toHaveLength(80);
|
expect(name.text()).toHaveLength(80);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('tier', () => {
|
||||||
|
it('displays the tier of the environment when defined in yaml', () => {
|
||||||
|
wrapper = createWrapper({ apolloProvider: createApolloProvider() });
|
||||||
|
|
||||||
|
const tier = wrapper.findByTitle(s__('Environment|Deployment tier'));
|
||||||
|
|
||||||
|
expect(tier.text()).toBe(resolvedEnvironment.lastDeployment.tierInYaml);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display the tier if not defined in yaml', () => {
|
||||||
|
const environment = {
|
||||||
|
...resolvedEnvironment,
|
||||||
|
lastDeployment: {
|
||||||
|
...resolvedEnvironment.lastDeployment,
|
||||||
|
tierInYaml: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
wrapper = createWrapper({
|
||||||
|
propsData: { environment },
|
||||||
|
apolloProvider: createApolloProvider(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const tier = wrapper.findByTitle(s__('Environment|Deployment tier'));
|
||||||
|
|
||||||
|
expect(tier.exists()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('url', () => {
|
describe('url', () => {
|
||||||
it('shows a link for the url if one is present', () => {
|
it('shows a link for the url if one is present', () => {
|
||||||
wrapper = createWrapper({ apolloProvider: createApolloProvider() });
|
wrapper = createWrapper({ apolloProvider: createApolloProvider() });
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { GlIcon, GlLink } from '@gitlab/ui';
|
import { GlIcon, GlLink } from '@gitlab/ui';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import { useFakeDate } from 'helpers/fake_date';
|
import { useFakeDate } from 'helpers/fake_date';
|
||||||
|
import { IssuableStatus } from '~/issues/constants';
|
||||||
import IssueCardTimeInfo from '~/issues/list/components/issue_card_time_info.vue';
|
import IssueCardTimeInfo from '~/issues/list/components/issue_card_time_info.vue';
|
||||||
|
|
||||||
describe('CE IssueCardTimeInfo component', () => {
|
describe('CE IssueCardTimeInfo component', () => {
|
||||||
|
@ -24,7 +25,7 @@ describe('CE IssueCardTimeInfo component', () => {
|
||||||
const findDueDate = () => wrapper.find('[data-testid="issuable-due-date"]');
|
const findDueDate = () => wrapper.find('[data-testid="issuable-due-date"]');
|
||||||
|
|
||||||
const mountComponent = ({
|
const mountComponent = ({
|
||||||
closedAt = null,
|
state = IssuableStatus.Open,
|
||||||
dueDate = issue.dueDate,
|
dueDate = issue.dueDate,
|
||||||
milestoneDueDate = issue.milestone.dueDate,
|
milestoneDueDate = issue.milestone.dueDate,
|
||||||
milestoneStartDate = issue.milestone.startDate,
|
milestoneStartDate = issue.milestone.startDate,
|
||||||
|
@ -38,7 +39,7 @@ describe('CE IssueCardTimeInfo component', () => {
|
||||||
dueDate: milestoneDueDate,
|
dueDate: milestoneDueDate,
|
||||||
startDate: milestoneStartDate,
|
startDate: milestoneStartDate,
|
||||||
},
|
},
|
||||||
closedAt,
|
state,
|
||||||
dueDate,
|
dueDate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -101,7 +102,7 @@ describe('CE IssueCardTimeInfo component', () => {
|
||||||
it('does not render in red', () => {
|
it('does not render in red', () => {
|
||||||
wrapper = mountComponent({
|
wrapper = mountComponent({
|
||||||
dueDate: '2020-10-10',
|
dueDate: '2020-10-10',
|
||||||
closedAt: '2020-09-05T13:06:25Z',
|
state: IssuableStatus.Closed,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(findDueDate().classes()).not.toContain('gl-text-red-500');
|
expect(findDueDate().classes()).not.toContain('gl-text-red-500');
|
||||||
|
|
|
@ -21,7 +21,6 @@ export const getIssuesQueryResponse = {
|
||||||
__typename: 'Issue',
|
__typename: 'Issue',
|
||||||
id: 'gid://gitlab/Issue/123456',
|
id: 'gid://gitlab/Issue/123456',
|
||||||
iid: '789',
|
iid: '789',
|
||||||
closedAt: null,
|
|
||||||
confidential: false,
|
confidential: false,
|
||||||
createdAt: '2021-05-22T04:08:01Z',
|
createdAt: '2021-05-22T04:08:01Z',
|
||||||
downvotes: 2,
|
downvotes: 2,
|
||||||
|
@ -30,6 +29,7 @@ export const getIssuesQueryResponse = {
|
||||||
humanTimeEstimate: null,
|
humanTimeEstimate: null,
|
||||||
mergeRequestsCount: false,
|
mergeRequestsCount: false,
|
||||||
moved: false,
|
moved: false,
|
||||||
|
state: 'opened',
|
||||||
title: 'Issue title',
|
title: 'Issue title',
|
||||||
updatedAt: '2021-05-22T04:08:01Z',
|
updatedAt: '2021-05-22T04:08:01Z',
|
||||||
upvotes: 3,
|
upvotes: 3,
|
||||||
|
|
|
@ -39,6 +39,14 @@ RSpec.describe Gitlab::BackgroundMigration::EncryptStaticObjectToken do
|
||||||
expect(new_state[user_with_encrypted_token.id]).to match_array([nil, 'encrypted'])
|
expect(new_state[user_with_encrypted_token.id]).to match_array([nil, 'encrypted'])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when id range does not include existing user ids' do
|
||||||
|
let(:arguments) { [non_existing_record_id, non_existing_record_id.succ] }
|
||||||
|
|
||||||
|
it_behaves_like 'marks background migration job records' do
|
||||||
|
subject { described_class.new }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_user!(name:, token: nil, encrypted_token: nil)
|
def create_user!(name:, token: nil, encrypted_token: nil)
|
||||||
|
|
|
@ -58,6 +58,15 @@ RSpec.describe Gitlab::Database::EachDatabase do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when shared connections are not included' do
|
||||||
|
it 'only yields the unshared connections' do
|
||||||
|
expect(Gitlab::Database).to receive(:db_config_share_with).twice.and_return(nil, 'main')
|
||||||
|
|
||||||
|
expect { |b| described_class.each_database_connection(include_shared: false, &b) }
|
||||||
|
.to yield_successive_args([ActiveRecord::Base.connection, 'main'])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.each_model_connection' do
|
describe '.each_model_connection' do
|
||||||
|
|
|
@ -1055,6 +1055,40 @@ RSpec.describe Deployment do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#tier_in_yaml' do
|
||||||
|
context 'when deployable is nil' do
|
||||||
|
before do
|
||||||
|
subject.deployable = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns nil' do
|
||||||
|
expect(subject.tier_in_yaml).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when deployable is present' do
|
||||||
|
context 'when tier is specified' do
|
||||||
|
let(:deployable) { create(:ci_build, :success, :environment_with_deployment_tier) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.deployable = deployable
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the tier' do
|
||||||
|
expect(subject.tier_in_yaml).to eq('testing')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when tier is not specified' do
|
||||||
|
let(:deployable) { create(:ci_build, :success) }
|
||||||
|
|
||||||
|
it 'returns nil' do
|
||||||
|
expect(subject.tier_in_yaml).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '.fast_destroy_all' do
|
describe '.fast_destroy_all' do
|
||||||
it 'cleans path_refs for destroyed environments' do
|
it 'cleans path_refs for destroyed environments' do
|
||||||
project = create(:project, :repository)
|
project = create(:project, :repository)
|
||||||
|
|
|
@ -8,6 +8,8 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
|
|
||||||
let_it_be(:project) { create(:project) }
|
let_it_be(:project) { create(:project) }
|
||||||
|
|
||||||
|
let(:sentry_client) { instance_double(ErrorTracking::SentryClient) }
|
||||||
|
|
||||||
subject(:setting) { build(:project_error_tracking_setting, project: project) }
|
subject(:setting) { build(:project_error_tracking_setting, project: project) }
|
||||||
|
|
||||||
describe 'Associations' do
|
describe 'Associations' do
|
||||||
|
@ -48,7 +50,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
expect(subject.errors.messages[:project]).to include('is a required field')
|
expect(subject.errors.messages[:project]).to include('is a required field')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'presence validations' do
|
describe 'presence validations' do
|
||||||
using RSpec::Parameterized::TableSyntax
|
using RSpec::Parameterized::TableSyntax
|
||||||
|
|
||||||
valid_api_url = 'http://example.com/api/0/projects/org-slug/proj-slug/'
|
valid_api_url = 'http://example.com/api/0/projects/org-slug/proj-slug/'
|
||||||
|
@ -83,12 +85,12 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
describe 'after_save :create_client_key!' do
|
describe 'after_save :create_client_key!' do
|
||||||
subject { build(:project_error_tracking_setting, :integrated, project: project) }
|
subject { build(:project_error_tracking_setting, :integrated, project: project) }
|
||||||
|
|
||||||
context 'no client key yet' do
|
context 'without client key' do
|
||||||
it 'creates a new client key' do
|
it 'creates a new client key' do
|
||||||
expect { subject.save! }.to change { ErrorTracking::ClientKey.count }.by(1)
|
expect { subject.save! }.to change { ErrorTracking::ClientKey.count }.by(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'sentry backend' do
|
context 'with sentry backend' do
|
||||||
before do
|
before do
|
||||||
subject.integrated = false
|
subject.integrated = false
|
||||||
end
|
end
|
||||||
|
@ -98,7 +100,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'feature disabled' do
|
context 'when feature disabled' do
|
||||||
before do
|
before do
|
||||||
subject.enabled = false
|
subject.enabled = false
|
||||||
end
|
end
|
||||||
|
@ -109,7 +111,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'client key already exists' do
|
context 'when client key already exists' do
|
||||||
let!(:client_key) { create(:error_tracking_client_key, project: project) }
|
let!(:client_key) { create(:error_tracking_client_key, project: project) }
|
||||||
|
|
||||||
it 'does not create a new client key' do
|
it 'does not create a new client key' do
|
||||||
|
@ -122,13 +124,13 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
describe '.extract_sentry_external_url' do
|
describe '.extract_sentry_external_url' do
|
||||||
subject { described_class.extract_sentry_external_url(sentry_url) }
|
subject { described_class.extract_sentry_external_url(sentry_url) }
|
||||||
|
|
||||||
describe 'when passing a URL' do
|
context 'when passing a URL' do
|
||||||
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
|
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
|
||||||
|
|
||||||
it { is_expected.to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project') }
|
it { is_expected.to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project') }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'when passing nil' do
|
context 'when passing nil' do
|
||||||
let(:sentry_url) { nil }
|
let(:sentry_url) { nil }
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
|
@ -159,23 +161,15 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
|
|
||||||
describe '#list_sentry_issues' do
|
describe '#list_sentry_issues' do
|
||||||
let(:issues) { [:list, :of, :issues] }
|
let(:issues) { [:list, :of, :issues] }
|
||||||
|
let(:result) { subject.list_sentry_issues(**opts) }
|
||||||
let(:opts) do
|
let(:opts) { { issue_status: 'unresolved', limit: 10 } }
|
||||||
{ issue_status: 'unresolved', limit: 10 }
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:result) do
|
|
||||||
subject.list_sentry_issues(**opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when cached' do
|
context 'when cached' do
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_reactive_cache(subject, issues, opts)
|
stub_reactive_cache(subject, issues, opts)
|
||||||
synchronous_reactive_cache(subject)
|
synchronous_reactive_cache(subject)
|
||||||
|
|
||||||
expect(subject).to receive(:sentry_client).and_return(sentry_client)
|
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns cached issues' do
|
it 'returns cached issues' do
|
||||||
|
@ -195,8 +189,6 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when sentry client raises ErrorTracking::SentryClient::Error' do
|
context 'when sentry client raises ErrorTracking::SentryClient::Error' do
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
synchronous_reactive_cache(subject)
|
synchronous_reactive_cache(subject)
|
||||||
|
|
||||||
|
@ -214,14 +206,13 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when sentry client raises ErrorTracking::SentryClient::MissingKeysError' do
|
context 'when sentry client raises ErrorTracking::SentryClient::MissingKeysError' do
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
synchronous_reactive_cache(subject)
|
synchronous_reactive_cache(subject)
|
||||||
|
|
||||||
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
||||||
allow(sentry_client).to receive(:list_issues).with(opts)
|
allow(sentry_client).to receive(:list_issues).with(opts)
|
||||||
.and_raise(ErrorTracking::SentryClient::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
|
.and_raise(ErrorTracking::SentryClient::MissingKeysError,
|
||||||
|
'Sentry API response is missing keys. key not found: "id"')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns error' do
|
it 'returns error' do
|
||||||
|
@ -233,8 +224,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when sentry client raises ErrorTracking::SentryClient::ResponseInvalidSizeError' do
|
context 'when sentry client raises ErrorTracking::SentryClient::ResponseInvalidSizeError' do
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
let(:error_msg) { "Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}." }
|
||||||
let(:error_msg) {"Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}."}
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
synchronous_reactive_cache(subject)
|
synchronous_reactive_cache(subject)
|
||||||
|
@ -253,8 +243,6 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when sentry client raises StandardError' do
|
context 'when sentry client raises StandardError' do
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
synchronous_reactive_cache(subject)
|
synchronous_reactive_cache(subject)
|
||||||
|
|
||||||
|
@ -270,7 +258,6 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
|
|
||||||
describe '#list_sentry_projects' do
|
describe '#list_sentry_projects' do
|
||||||
let(:projects) { [:list, :of, :projects] }
|
let(:projects) { [:list, :of, :projects] }
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
|
||||||
|
|
||||||
it 'calls sentry client' do
|
it 'calls sentry client' do
|
||||||
expect(subject).to receive(:sentry_client).and_return(sentry_client)
|
expect(subject).to receive(:sentry_client).and_return(sentry_client)
|
||||||
|
@ -284,19 +271,17 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
|
|
||||||
describe '#issue_details' do
|
describe '#issue_details' do
|
||||||
let(:issue) { build(:error_tracking_sentry_detailed_error) }
|
let(:issue) { build(:error_tracking_sentry_detailed_error) }
|
||||||
let(:sentry_client) { double('sentry_client', issue_details: issue) }
|
|
||||||
let(:commit_id) { issue.first_release_version }
|
let(:commit_id) { issue.first_release_version }
|
||||||
|
let(:result) { subject.issue_details(opts) }
|
||||||
let(:result) do
|
let(:opts) { { issue_id: 1 } }
|
||||||
subject.issue_details
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when cached' do
|
context 'when cached' do
|
||||||
before do
|
before do
|
||||||
stub_reactive_cache(subject, issue, {})
|
stub_reactive_cache(subject, issue, {})
|
||||||
synchronous_reactive_cache(subject)
|
synchronous_reactive_cache(subject)
|
||||||
|
|
||||||
expect(subject).to receive(:sentry_client).and_return(sentry_client)
|
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
||||||
|
allow(sentry_client).to receive(:issue_details).with(opts).and_return(issue)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(result).to eq(issue: issue) }
|
it { expect(result).to eq(issue: issue) }
|
||||||
|
@ -314,15 +299,15 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when repo commit matches first relase version' do
|
context 'when repo commit matches first relase version' do
|
||||||
let(:commit) { double('commit', id: commit_id) }
|
let(:commit) { instance_double(Commit, id: commit_id) }
|
||||||
let(:repository) { double('repository', commit: commit) }
|
let(:repository) { instance_double(Repository, commit: commit) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
expect(project).to receive(:repository).and_return(repository)
|
allow(project).to receive(:repository).and_return(repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(result[:issue].gitlab_commit).to eq(commit_id) }
|
it { expect(result[:issue].gitlab_commit).to eq(commit_id) }
|
||||||
it { expect(result[:issue].gitlab_commit_path).to eq("/#{project.namespace.path}/#{project.path}/-/commit/#{commit_id}") }
|
it { expect(result[:issue].gitlab_commit_path).to eq(project_commit_path(project, commit_id)) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -333,19 +318,15 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#update_issue' do
|
describe '#update_issue' do
|
||||||
let(:opts) do
|
let(:result) { subject.update_issue(**opts) }
|
||||||
{ status: 'resolved' }
|
let(:opts) { { issue_id: 1, params: {} } }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:result) do
|
context 'when sentry response is successful' do
|
||||||
subject.update_issue(**opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:sentry_client) { spy(:sentry_client) }
|
|
||||||
|
|
||||||
context 'successful call to sentry' do
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
|
||||||
allow(sentry_client).to receive(:update_issue).with(opts).and_return(true)
|
allow(sentry_client).to receive(:update_issue).with(opts).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -354,9 +335,8 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'sentry raises an error' do
|
context 'when sentry raises an error' do
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:sentry_client).and_return(sentry_client)
|
|
||||||
allow(sentry_client).to receive(:update_issue).with(opts).and_raise(StandardError)
|
allow(sentry_client).to receive(:update_issue).with(opts).and_raise(StandardError)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -366,7 +346,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'slugs' do
|
describe 'slugs' do
|
||||||
shared_examples_for 'slug from api_url' do |method, slug|
|
shared_examples_for 'slug from api_url' do |method, slug|
|
||||||
context 'when api_url is correct' do
|
context 'when api_url is correct' do
|
||||||
before do
|
before do
|
||||||
|
@ -393,9 +373,9 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
it_behaves_like 'slug from api_url', :organization_slug, 'org-slug'
|
it_behaves_like 'slug from api_url', :organization_slug, 'org-slug'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'names from api_url' do
|
describe 'names from api_url' do
|
||||||
shared_examples_for 'name from api_url' do |name, titleized_slug|
|
shared_examples_for 'name from api_url' do |name, titleized_slug|
|
||||||
context 'name is present in DB' do
|
context 'when name is present in DB' do
|
||||||
it 'returns name from DB' do
|
it 'returns name from DB' do
|
||||||
subject[name] = 'Sentry name'
|
subject[name] = 'Sentry name'
|
||||||
subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug'
|
subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug'
|
||||||
|
@ -404,7 +384,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'name is null in DB' do
|
context 'when name is null in DB' do
|
||||||
it 'titleizes and returns slug from api_url' do
|
it 'titleizes and returns slug from api_url' do
|
||||||
subject[name] = nil
|
subject[name] = nil
|
||||||
subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug'
|
subject.api_url = 'http://gitlab.com/api/0/projects/org-slug/project-slug'
|
||||||
|
|
|
@ -205,16 +205,30 @@ RSpec.describe API::IssueLinks do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user has ability to delete the issue link' do
|
context 'when user has ability to delete the issue link' do
|
||||||
it 'returns 200' do
|
let_it_be(:target_issue) { create(:issue, project: project) }
|
||||||
target_issue = create(:issue, project: project)
|
|
||||||
issue_link = create(:issue_link, source: issue, target: target_issue)
|
before do
|
||||||
project.add_reporter(user)
|
project.add_reporter(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns 200' do
|
||||||
|
issue_link = create(:issue_link, source: issue, target: target_issue)
|
||||||
|
|
||||||
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
|
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
expect(response).to match_response_schema('public_api/v4/issue_link')
|
expect(response).to match_response_schema('public_api/v4/issue_link')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns 404 when the issue link does not belong to the specified issue' do
|
||||||
|
other_issue = create(:issue, project: project)
|
||||||
|
issue_link = create(:issue_link, source: other_issue, target: target_issue)
|
||||||
|
|
||||||
|
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:not_found)
|
||||||
|
expect(json_response['message']).to eq('404 Not found')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe DeploymentEntity do
|
||||||
let(:project) { create(:project, :repository) }
|
let(:project) { create(:project, :repository) }
|
||||||
let(:request) { double('request') }
|
let(:request) { double('request') }
|
||||||
let(:deployment) { create(:deployment, deployable: build, project: project) }
|
let(:deployment) { create(:deployment, deployable: build, project: project) }
|
||||||
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
|
let(:build) { create(:ci_build, :manual, :environment_with_deployment_tier, pipeline: pipeline) }
|
||||||
let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
|
let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
|
||||||
let(:entity) { described_class.new(deployment, request: request) }
|
let(:entity) { described_class.new(deployment, request: request) }
|
||||||
|
|
||||||
|
@ -46,6 +46,10 @@ RSpec.describe DeploymentEntity do
|
||||||
expect(subject).to include(:is_last)
|
expect(subject).to include(:is_last)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'exposes deployment tier in yaml' do
|
||||||
|
expect(subject).to include(:tier_in_yaml)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when deployable is nil' do
|
context 'when deployable is nil' do
|
||||||
let(:entity) { described_class.new(deployment, request: request, deployment_details: false) }
|
let(:entity) { described_class.new(deployment, request: request, deployment_details: false) }
|
||||||
let(:deployment) { create(:deployment, deployable: nil, project: project) }
|
let(:deployment) { create(:deployment, deployable: nil, project: project) }
|
||||||
|
|
|
@ -237,6 +237,7 @@ RSpec.configure do |config|
|
||||||
# Enable all features by default for testing
|
# Enable all features by default for testing
|
||||||
# Reset any changes in after hook.
|
# Reset any changes in after hook.
|
||||||
stub_all_feature_flags
|
stub_all_feature_flags
|
||||||
|
stub_feature_flags(main_branch_over_master: false)
|
||||||
|
|
||||||
TestEnv.seed_db
|
TestEnv.seed_db
|
||||||
end
|
end
|
||||||
|
|
|
@ -55,6 +55,19 @@ RSpec.shared_examples 'issuable link' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'scopes' do
|
||||||
|
describe '.for_source_or_target' do
|
||||||
|
it 'returns only links where id is either source or target id' do
|
||||||
|
link1 = create(issuable_link_factory, source: issuable_link.source)
|
||||||
|
link2 = create(issuable_link_factory, target: issuable_link.source)
|
||||||
|
# unrelated link, should not be included in result list
|
||||||
|
create(issuable_link_factory) # rubocop: disable Rails/SaveBang
|
||||||
|
|
||||||
|
expect(described_class.for_source_or_target(issuable_link.source_id)).to match_array([issuable_link, link1, link2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '.link_type' do
|
describe '.link_type' do
|
||||||
it { is_expected.to define_enum_for(:link_type).with_values(relates_to: 0, blocks: 1) }
|
it { is_expected.to define_enum_for(:link_type).with_values(relates_to: 0, blocks: 1) }
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,18 @@ RSpec.describe 'gitlab:db:validate_config', :silence_stdout do
|
||||||
expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr
|
expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr
|
||||||
expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error
|
expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when finding the initializer fails' do
|
||||||
|
where(:raised_error) { [ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad] }
|
||||||
|
with_them do
|
||||||
|
it "does not raise an error for #{params[:raised_error]}" do
|
||||||
|
allow(ActiveRecord::Base.connection).to receive(:select_one).and_raise(raised_error) # rubocop: disable Database/MultipleDatabases
|
||||||
|
|
||||||
|
expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr
|
||||||
|
expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples 'raises an error' do |match|
|
shared_examples 'raises an error' do |match|
|
||||||
|
|
|
@ -22,7 +22,11 @@ RSpec.describe 'gitlab:setup namespace rake tasks', :silence_stdout do
|
||||||
let(:server_service1) { double(:server_service) }
|
let(:server_service1) { double(:server_service) }
|
||||||
let(:server_service2) { double(:server_service) }
|
let(:server_service2) { double(:server_service) }
|
||||||
|
|
||||||
let(:connections) { Gitlab::Database.database_base_models.values.map(&:connection) }
|
let(:connections) do
|
||||||
|
Gitlab::Database.database_base_models.values.filter_map do |model|
|
||||||
|
model.connection if Gitlab::Database.db_config_share_with(model.connection_db_config).nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(Gitlab).to receive_message_chain('config.repositories.storages').and_return(storages)
|
allow(Gitlab).to receive_message_chain('config.repositories.storages').and_return(storages)
|
||||||
|
@ -119,6 +123,10 @@ RSpec.describe 'gitlab:setup namespace rake tasks', :silence_stdout do
|
||||||
end
|
end
|
||||||
|
|
||||||
def expect_connections_to_be_terminated
|
def expect_connections_to_be_terminated
|
||||||
|
expect(Gitlab::Database::EachDatabase).to receive(:each_database_connection)
|
||||||
|
.with(include_shared: false)
|
||||||
|
.and_call_original
|
||||||
|
|
||||||
expect(connections).to all(receive(:execute).with(/SELECT pg_terminate_backend/))
|
expect(connections).to all(receive(:execute).with(/SELECT pg_terminate_backend/))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
|
||||||
expect_log_extra_metadata(
|
expect_log_extra_metadata(
|
||||||
import_type: 'next',
|
import_type: 'next',
|
||||||
container_repository_id: container_repository.id,
|
container_repository_id: container_repository.id,
|
||||||
container_repository_path: container_repository.path
|
container_repository_path: container_repository.path,
|
||||||
|
container_repository_migration_state: 'pre_importing'
|
||||||
)
|
)
|
||||||
|
|
||||||
subject
|
subject
|
||||||
|
@ -135,7 +136,8 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
|
||||||
expect_log_extra_metadata(
|
expect_log_extra_metadata(
|
||||||
import_type: 'retry',
|
import_type: 'retry',
|
||||||
container_repository_id: aborted_repository.id,
|
container_repository_id: aborted_repository.id,
|
||||||
container_repository_path: aborted_repository.path
|
container_repository_path: aborted_repository.path,
|
||||||
|
container_repository_migration_state: 'importing'
|
||||||
)
|
)
|
||||||
|
|
||||||
subject
|
subject
|
||||||
|
@ -158,7 +160,8 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
|
||||||
expect_log_extra_metadata(
|
expect_log_extra_metadata(
|
||||||
import_type: 'retry',
|
import_type: 'retry',
|
||||||
container_repository_id: aborted_repository.id,
|
container_repository_id: aborted_repository.id,
|
||||||
container_repository_path: aborted_repository.path
|
container_repository_path: aborted_repository.path,
|
||||||
|
container_repository_migration_state: 'import_aborted'
|
||||||
)
|
)
|
||||||
|
|
||||||
subject
|
subject
|
||||||
|
@ -189,6 +192,7 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
|
||||||
import_type: 'next',
|
import_type: 'next',
|
||||||
container_repository_id: container_repository.id,
|
container_repository_id: container_repository.id,
|
||||||
container_repository_path: container_repository.path,
|
container_repository_path: container_repository.path,
|
||||||
|
container_repository_migration_state: 'import_skipped',
|
||||||
tags_count_too_high: true,
|
tags_count_too_high: true,
|
||||||
max_tags_count_setting: 2
|
max_tags_count_setting: 2
|
||||||
)
|
)
|
||||||
|
@ -212,7 +216,8 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
|
||||||
expect_log_extra_metadata(
|
expect_log_extra_metadata(
|
||||||
import_type: 'next',
|
import_type: 'next',
|
||||||
container_repository_id: container_repository.id,
|
container_repository_id: container_repository.id,
|
||||||
container_repository_path: container_repository.path
|
container_repository_path: container_repository.path,
|
||||||
|
container_repository_migration_state: 'import_aborted'
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
|
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
|
||||||
|
|
Loading…
Reference in New Issue