Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7bbc9509dc
commit
a300f4d5c7
|
@ -1,20 +1,6 @@
|
|||
---
|
||||
Cop/StaticTranslationDefinition:
|
||||
Exclude:
|
||||
- 'app/models/application_setting.rb'
|
||||
- 'app/models/diff_viewer/image.rb'
|
||||
- 'app/models/diff_viewer/rich.rb'
|
||||
- 'app/models/diff_viewer/simple.rb'
|
||||
- 'app/models/group_group_link.rb'
|
||||
- 'app/models/jira_import_state.rb'
|
||||
- 'app/models/member.rb'
|
||||
- 'app/models/project.rb'
|
||||
- 'app/models/project_group_link.rb'
|
||||
- 'app/models/user.rb'
|
||||
- 'app/models/users/banned_user.rb'
|
||||
- 'ee/app/models/allowed_email_domain.rb'
|
||||
- 'ee/app/models/dast/site_profile_secret_variable.rb'
|
||||
- 'ee/app/models/group_merge_request_approval_setting.rb'
|
||||
- 'ee/app/models/incident_management/escalation_policy.rb'
|
||||
- 'ee/app/models/incident_management/escalation_rule.rb'
|
||||
- 'ee/app/models/vulnerabilities/read.rb'
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -424,7 +424,7 @@ group :development, :test do
|
|||
|
||||
gem 'sigdump', '~> 0.2.4', require: 'sigdump/setup'
|
||||
|
||||
gem 'pact', '~> 1.12'
|
||||
gem 'pact', '~> 1.63'
|
||||
end
|
||||
|
||||
group :development, :test, :danger do
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
{"name":"ethon","version":"0.15.0","platform":"ruby","checksum":"0809805a035bc10f54162ca99f15ded49e428e0488bcfe1c08c821e18261a74d"},
|
||||
{"name":"excon","version":"0.90.0","platform":"ruby","checksum":"01beac0f20652b12de95aef931f72bcb82ffb009e1c34c42a5cf5df93f4070ae"},
|
||||
{"name":"execjs","version":"2.8.1","platform":"ruby","checksum":"6d939919cfd81bcc4d6556f322c3995a70cfe4289ea0bd3b1f999b489c323088"},
|
||||
{"name":"expgen","version":"0.1.1","platform":"ruby","checksum":"4e6a0f65b210a201d6045debb3e62a24e33251a49f81a11b067d303a60d3a239"},
|
||||
{"name":"expression_parser","version":"0.9.0","platform":"ruby","checksum":"2b56db3cffc48c3337f4f29f5bc2374c86e7ba29acb40269c74bb55af9f868a4"},
|
||||
{"name":"extended-markdown-filter","version":"0.6.0","platform":"ruby","checksum":"46844b5740b1703a0e0674e31a17c83d1244a3198abb3aae51cad1eb152eb19e"},
|
||||
{"name":"factory_bot","version":"6.2.0","platform":"ruby","checksum":"d181902cdda531cf6cef036001b3a700a7b5e04bac63976864530120b2ac7d13"},
|
||||
|
@ -398,9 +399,9 @@
|
|||
{"name":"org-ruby","version":"0.9.12","platform":"ruby","checksum":"93cbec3a4470cb9dca6a4a98dc276a6434ea9d9e7bc2d42ea33c3aedd5d1c974"},
|
||||
{"name":"orm_adapter","version":"0.5.0","platform":"ruby","checksum":"aa5d0be5d540cbb46d3a93e88061f4ece6a25f6e97d6a47122beb84fe595e9b9"},
|
||||
{"name":"os","version":"1.1.1","platform":"ruby","checksum":"3db1fbc14ab8ea99b69ed8e353c894613e1b35e665fffb90414996cf8989d489"},
|
||||
{"name":"pact","version":"1.59.0","platform":"ruby","checksum":"6272cea35e4ee809493fadcba9800d4a24c262ef0778a0d1ba5d9a9b3f61fc59"},
|
||||
{"name":"pact-mock_service","version":"3.6.2","platform":"ruby","checksum":"cc91229484ae428b6eb3a6673c178046cbf6610ee6536ca6cbac060b6071f547"},
|
||||
{"name":"pact-support","version":"1.15.1","platform":"ruby","checksum":"c364596fe9fe78c4f93028013262d5d97867a680fa6acc35dda946447cdf1d1f"},
|
||||
{"name":"pact","version":"1.63.0","platform":"ruby","checksum":"cc2991ed242bf182c6a4abadfd492b2923d09a9b3ed24578126cc056921cb151"},
|
||||
{"name":"pact-mock_service","version":"3.10.0","platform":"ruby","checksum":"898ec3b8d96f1934d15941c701ca7d5fef5ccff32022d9a196fb82073cd95e27"},
|
||||
{"name":"pact-support","version":"1.18.1","platform":"ruby","checksum":"4a25961c8b1c4132e433a8eaa838b1e6914c6d3aae48eee705b9860a5e8b0476"},
|
||||
{"name":"parallel","version":"1.22.1","platform":"ruby","checksum":"ebdf1f0c51f182df38522f70ba770214940bef998cdb6e00f36492b29699761f"},
|
||||
{"name":"parser","version":"3.1.2.1","platform":"ruby","checksum":"57e49821b52d5fe7baffaca44ed77e9754688c9bbc68443b5293a722fdb161e0"},
|
||||
{"name":"parslet","version":"1.8.2","platform":"ruby","checksum":"08d1ab3721cd3f175bfbee8788b2ddff71f92038f2d69bd65454c22bb9fbd98a"},
|
||||
|
@ -438,7 +439,7 @@
|
|||
{"name":"rack-oauth2","version":"1.21.3","platform":"ruby","checksum":"4e72a79dd6a866692e84422a552b27c38a5a1918ded06661e04910f2bbe676ba"},
|
||||
{"name":"rack-protection","version":"2.2.2","platform":"ruby","checksum":"fd41414dbabbec274af0bdb1f72a48504449de4d979782c9af38cbb5dfff3299"},
|
||||
{"name":"rack-proxy","version":"0.7.4","platform":"ruby","checksum":"a8bb373583d8a3165d8caf5af5fd7c32c9e8a91b983fbc531efa0e3d6617d2d4"},
|
||||
{"name":"rack-test","version":"1.1.0","platform":"ruby","checksum":"154161f40f162b1c009a655b7b0c5de3a3102cc6d7d2e94b64e1f46ace800866"},
|
||||
{"name":"rack-test","version":"2.0.2","platform":"ruby","checksum":"adadd0e957f63a34199a9fdf905a920a0b0a50795735095b4ac4bd3c13385466"},
|
||||
{"name":"rack-timeout","version":"0.6.3","platform":"ruby","checksum":"1754892eacc124d405e7f1145731ec9b7421ebd1bee5d51ddc18b72c204d0ab3"},
|
||||
{"name":"rails","version":"6.1.6.1","platform":"ruby","checksum":"17024921a3913fb341f584542b06adf6bb12977a8b92d5fce093c3996c963686"},
|
||||
{"name":"rails-controller-testing","version":"1.0.5","platform":"ruby","checksum":"741448db59366073e86fc965ba403f881c636b79a2c39a48d0486f2607182e94"},
|
||||
|
@ -448,7 +449,6 @@
|
|||
{"name":"railties","version":"6.1.6.1","platform":"ruby","checksum":"bafecdf2dcbe4ea44e1ab7081fd797aa87ae9bbcd0f3a4372b662a1b93949733"},
|
||||
{"name":"rainbow","version":"3.1.1","platform":"ruby","checksum":"039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a"},
|
||||
{"name":"rake","version":"13.0.6","platform":"ruby","checksum":"5ce4bf5037b4196c24ac62834d8db1ce175470391026bd9e557d669beeb19097"},
|
||||
{"name":"randexp","version":"0.1.7","platform":"ruby","checksum":"3026510ecf6a8e8642b9b96fa44bb41af6d24058023b7df77cf280f08e14e4c8"},
|
||||
{"name":"rb-fsevent","version":"0.11.2","platform":"ruby","checksum":"43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe"},
|
||||
{"name":"rb-inotify","version":"0.10.1","platform":"ruby","checksum":"050062d4f31d307cca52c3f6a7f4b946df8de25fc4bd373e1a5142e41034a7ca"},
|
||||
{"name":"rbtrace","version":"0.4.14","platform":"ruby","checksum":"162bbf89cecabfc4f09c869b655f6f3a679c4870ebb7cbdcadf7393a81cc1769"},
|
||||
|
@ -586,7 +586,7 @@
|
|||
{"name":"timecop","version":"0.9.1","platform":"ruby","checksum":"374b543f0961dbd487e96d09ac812d4fdfeb603ec705bbff241ba060d0a9f534"},
|
||||
{"name":"timeliness","version":"0.3.10","platform":"ruby","checksum":"c357233ce19dc53148e8b29dfddde134689f18f52b32928e9dfe12ebcf4a773f"},
|
||||
{"name":"timfel-krb5-auth","version":"0.8.3","platform":"ruby","checksum":"ab388c9d747fa3cd95baf2cc1c03253e372d8c680adcc543670f4f099854bb80"},
|
||||
{"name":"tins","version":"1.31.0","platform":"ruby","checksum":"20b5ea997dc046358fd05f15d39636bd7946798591b9c5741cc41f69853c7894"},
|
||||
{"name":"tins","version":"1.31.1","platform":"ruby","checksum":"51c4a347c25c630d310cbc2c040ffb84e266c8227f2ade881f1130ee4f9fbecf"},
|
||||
{"name":"toml-rb","version":"2.0.1","platform":"ruby","checksum":"5016c6c77ac72bca5fe67c372722bdfdd4479a6fe1a1c4ff2a486e247849b274"},
|
||||
{"name":"tomlrb","version":"1.3.0","platform":"ruby","checksum":"68666bf53fa70ba686a48a7435ce7e086f5227c58c4c993bd9792f4760f2a503"},
|
||||
{"name":"tpm-key_attestation","version":"0.9.0","platform":"ruby","checksum":"e469ad9111a68dab4d04596e1c0621d7c877c2e3e247f765af3c04f1adf2b8cd"},
|
||||
|
|
31
Gemfile.lock
31
Gemfile.lock
|
@ -420,6 +420,8 @@ GEM
|
|||
ffi (>= 1.15.0)
|
||||
excon (0.90.0)
|
||||
execjs (2.8.1)
|
||||
expgen (0.1.1)
|
||||
parslet
|
||||
expression_parser (0.9.0)
|
||||
extended-markdown-filter (0.6.0)
|
||||
html-pipeline (~> 2.0)
|
||||
|
@ -999,29 +1001,29 @@ GEM
|
|||
rubypants (~> 0.2)
|
||||
orm_adapter (0.5.0)
|
||||
os (1.1.1)
|
||||
pact (1.59.0)
|
||||
pact (1.63.0)
|
||||
pact-mock_service (~> 3.0, >= 3.3.1)
|
||||
pact-support (~> 1.15)
|
||||
rack-test (>= 0.6.3, < 2.0.0)
|
||||
pact-support (~> 1.16, >= 1.16.9)
|
||||
rack-test (>= 0.6.3, < 3.0.0)
|
||||
rspec (~> 3.0)
|
||||
term-ansicolor (~> 1.0)
|
||||
thor (>= 0.20, < 2.0)
|
||||
webrick (~> 1.3)
|
||||
pact-mock_service (3.6.2)
|
||||
pact-mock_service (3.10.0)
|
||||
filelock (~> 1.1)
|
||||
find_a_port (~> 1.0.1)
|
||||
json
|
||||
pact-support (~> 1.12, >= 1.12.0)
|
||||
pact-support (~> 1.16, >= 1.16.4)
|
||||
rack (~> 2.0)
|
||||
rspec (>= 2.14)
|
||||
term-ansicolor (~> 1.0)
|
||||
thor (>= 0.19, < 2.0)
|
||||
webrick (~> 1.3)
|
||||
pact-support (1.15.1)
|
||||
awesome_print (~> 1.1)
|
||||
randexp (~> 0.1.7)
|
||||
rspec (>= 2.14)
|
||||
term-ansicolor (~> 1.0)
|
||||
pact-support (1.18.1)
|
||||
awesome_print (~> 1.9)
|
||||
diff-lcs (~> 1.4)
|
||||
expgen (~> 0.1)
|
||||
rainbow (~> 3.1.1)
|
||||
parallel (1.22.1)
|
||||
parser (3.1.2.1)
|
||||
ast (~> 2.4.1)
|
||||
|
@ -1087,8 +1089,8 @@ GEM
|
|||
rack
|
||||
rack-proxy (0.7.4)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-test (2.0.2)
|
||||
rack (>= 1.3)
|
||||
rack-timeout (0.6.3)
|
||||
rails (6.1.6.1)
|
||||
actioncable (= 6.1.6.1)
|
||||
|
@ -1125,7 +1127,6 @@ GEM
|
|||
thor (~> 1.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
randexp (0.1.7)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
|
@ -1415,7 +1416,7 @@ GEM
|
|||
timecop (0.9.1)
|
||||
timeliness (0.3.10)
|
||||
timfel-krb5-auth (0.8.3)
|
||||
tins (1.31.0)
|
||||
tins (1.31.1)
|
||||
sync
|
||||
toml-rb (2.0.1)
|
||||
citrus (~> 3.0, > 3.0)
|
||||
|
@ -1725,7 +1726,7 @@ DEPENDENCIES
|
|||
omniauth_crowd (~> 2.4.0)!
|
||||
openssl (= 2.2.1)
|
||||
org-ruby (~> 0.9.12)
|
||||
pact (~> 1.12)
|
||||
pact (~> 1.63)
|
||||
parallel (~> 1.19)
|
||||
parslet (~> 1.8)
|
||||
peek (~> 1.1)
|
||||
|
|
|
@ -472,7 +472,7 @@ export default {
|
|||
fetchData(toggleTree = true) {
|
||||
this.fetchDiffFilesMeta()
|
||||
.then(({ real_size = 0 }) => {
|
||||
this.diffFilesLength = parseInt(real_size, 10);
|
||||
this.diffFilesLength = parseInt(real_size, 10) || 0;
|
||||
if (toggleTree) {
|
||||
this.setTreeDisplay();
|
||||
}
|
||||
|
|
|
@ -19,34 +19,35 @@ export default {
|
|||
components: { GlTabs, GlTab, GroupsApp, GlSearchBoxByType, GlSorting, GlSortingItem },
|
||||
inject: ['endpoints', 'initialSort'],
|
||||
data() {
|
||||
const tabs = [
|
||||
{
|
||||
title: this.$options.i18n[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
|
||||
key: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
|
||||
renderEmptyState: true,
|
||||
lazy: this.$route.name !== ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
|
||||
service: new GroupsService(this.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
|
||||
store: new GroupsStore({ showSchemaMarkup: true }),
|
||||
},
|
||||
{
|
||||
title: this.$options.i18n[ACTIVE_TAB_SHARED],
|
||||
key: ACTIVE_TAB_SHARED,
|
||||
renderEmptyState: false,
|
||||
lazy: this.$route.name !== ACTIVE_TAB_SHARED,
|
||||
service: new GroupsService(this.endpoints[ACTIVE_TAB_SHARED]),
|
||||
store: new GroupsStore(),
|
||||
},
|
||||
{
|
||||
title: this.$options.i18n[ACTIVE_TAB_ARCHIVED],
|
||||
key: ACTIVE_TAB_ARCHIVED,
|
||||
renderEmptyState: false,
|
||||
lazy: this.$route.name !== ACTIVE_TAB_ARCHIVED,
|
||||
service: new GroupsService(this.endpoints[ACTIVE_TAB_ARCHIVED]),
|
||||
store: new GroupsStore(),
|
||||
},
|
||||
];
|
||||
return {
|
||||
tabs: [
|
||||
{
|
||||
title: this.$options.i18n[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
|
||||
key: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
|
||||
renderEmptyState: true,
|
||||
lazy: false,
|
||||
service: new GroupsService(this.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
|
||||
store: new GroupsStore({ showSchemaMarkup: true }),
|
||||
},
|
||||
{
|
||||
title: this.$options.i18n[ACTIVE_TAB_SHARED],
|
||||
key: ACTIVE_TAB_SHARED,
|
||||
renderEmptyState: false,
|
||||
lazy: true,
|
||||
service: new GroupsService(this.endpoints[ACTIVE_TAB_SHARED]),
|
||||
store: new GroupsStore(),
|
||||
},
|
||||
{
|
||||
title: this.$options.i18n[ACTIVE_TAB_ARCHIVED],
|
||||
key: ACTIVE_TAB_ARCHIVED,
|
||||
renderEmptyState: false,
|
||||
lazy: true,
|
||||
service: new GroupsService(this.endpoints[ACTIVE_TAB_ARCHIVED]),
|
||||
store: new GroupsStore(),
|
||||
},
|
||||
],
|
||||
activeTabIndex: 0,
|
||||
tabs,
|
||||
activeTabIndex: tabs.findIndex((tab) => tab.key === this.$route.name),
|
||||
sort: SORTING_ITEM_NAME,
|
||||
isAscending: true,
|
||||
search: '',
|
||||
|
@ -75,14 +76,6 @@ export default {
|
|||
) || SORTING_ITEM_NAME;
|
||||
this.sort = sort;
|
||||
this.isAscending = sort.asc === sortQueryStringValue;
|
||||
|
||||
const activeTabIndex = this.tabs.findIndex((tab) => tab.key === this.$route.name);
|
||||
|
||||
if (activeTabIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeTabIndex = activeTabIndex;
|
||||
},
|
||||
methods: {
|
||||
handleTabInput(tabIndex) {
|
||||
|
|
|
@ -57,7 +57,7 @@ export default {
|
|||
this.status = res.data.severity;
|
||||
|
||||
this.track('rendered_version_badge', {
|
||||
label: this.status,
|
||||
label: this.title,
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -66,19 +66,24 @@ export default {
|
|||
this.status = null;
|
||||
});
|
||||
},
|
||||
onClick() {
|
||||
this.track('click_version_badge', { label: this.title });
|
||||
},
|
||||
},
|
||||
UPGRADE_DOCS_URL,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-badge
|
||||
v-if="status"
|
||||
:href="$options.UPGRADE_DOCS_URL"
|
||||
class="version-check-badge"
|
||||
:variant="status"
|
||||
:size="size"
|
||||
@click="track('click_version_badge', { label: status })"
|
||||
>{{ title }}</gl-badge
|
||||
>
|
||||
<!-- TODO: remove the span element once bootstrap-vue is updated to version 2.21.1 -->
|
||||
<!-- TODO: https://github.com/bootstrap-vue/bootstrap-vue/issues/6219 -->
|
||||
<span v-if="status" data-testid="badge-click-wrapper" @click="onClick">
|
||||
<gl-badge
|
||||
:href="$options.UPGRADE_DOCS_URL"
|
||||
class="version-check-badge"
|
||||
:variant="status"
|
||||
:size="size"
|
||||
>{{ title }}</gl-badge
|
||||
>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -25,12 +25,21 @@ module Mutations
|
|||
def resolve(id:)
|
||||
job = authorized_find!(id: id)
|
||||
|
||||
result = ::Ci::JobArtifacts::DestroyBatchService.new(job.job_artifacts, pick_up_at: Time.current).execute
|
||||
{
|
||||
job: job,
|
||||
destroyed_artifacts_count: result[:destroyed_artifacts_count],
|
||||
errors: Array(result[:errors])
|
||||
}
|
||||
result = ::Ci::JobArtifacts::DeleteService.new(job).execute
|
||||
|
||||
if result.success?
|
||||
{
|
||||
job: job,
|
||||
destroyed_artifacts_count: result.payload[:destroyed_artifacts_count],
|
||||
errors: Array(result.payload[:errors])
|
||||
}
|
||||
else
|
||||
{
|
||||
job: job,
|
||||
destroyed_artifacts_count: 0,
|
||||
errors: Array(result.message)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -120,7 +120,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
if: :help_page_support_url_column_exists?
|
||||
|
||||
validates :help_page_documentation_base_url,
|
||||
length: { maximum: 255, message: _("is too long (maximum is %{count} characters)") },
|
||||
length: { maximum: 255, message: N_("is too long (maximum is %{count} characters)") },
|
||||
allow_blank: true,
|
||||
addressable_url: true
|
||||
|
||||
|
@ -148,7 +148,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
if: :akismet_enabled
|
||||
|
||||
validates :spam_check_api_key,
|
||||
length: { maximum: 2000, message: _('is too long (maximum is %{count} characters)') },
|
||||
length: { maximum: 2000, message: N_('is too long (maximum is %{count} characters)') },
|
||||
allow_blank: true
|
||||
|
||||
validates :unique_ips_limit_per_user,
|
||||
|
@ -228,7 +228,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
validates :default_artifacts_expire_in, presence: true, duration: true
|
||||
|
||||
validates :container_expiration_policies_enable_historic_entries,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
validates :container_registry_token_expire_delay,
|
||||
presence: true,
|
||||
|
@ -320,8 +320,8 @@ class ApplicationSetting < ApplicationRecord
|
|||
|
||||
validates :personal_access_token_prefix,
|
||||
format: { with: %r{\A[a-zA-Z0-9_+=/@:.-]+\z},
|
||||
message: _("can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'") },
|
||||
length: { maximum: 20, message: _('is too long (maximum is %{count} characters)') },
|
||||
message: N_("can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'") },
|
||||
length: { maximum: 20, message: N_('is too long (maximum is %{count} characters)') },
|
||||
allow_blank: true
|
||||
|
||||
validates :commit_email_hostname, format: { with: /\A[^@]+\z/ }
|
||||
|
@ -369,7 +369,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
|
||||
validates :email_restrictions, untrusted_regexp: true
|
||||
|
||||
validates :hashed_storage_enabled, inclusion: { in: [true], message: _("Hashed storage can't be disabled anymore for new projects") }
|
||||
validates :hashed_storage_enabled, inclusion: { in: [true], message: N_("Hashed storage can't be disabled anymore for new projects") }
|
||||
|
||||
validates :container_registry_delete_tags_service_timeout,
|
||||
:container_registry_cleanup_tags_service_max_list_size,
|
||||
|
@ -377,7 +377,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
|
||||
validates :container_registry_expiration_policies_caching,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
validates :container_registry_import_max_tags_count,
|
||||
:container_registry_import_max_retries,
|
||||
|
@ -404,11 +404,11 @@ class ApplicationSetting < ApplicationRecord
|
|||
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
|
||||
validates :invisible_captcha_enabled,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
validates :invitation_flow_enforcement, :can_create_group,
|
||||
allow_nil: false,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
Gitlab::SSHPublicKey.supported_types.each do |type|
|
||||
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
|
||||
|
@ -513,11 +513,11 @@ class ApplicationSetting < ApplicationRecord
|
|||
rsa_key: true, allow_nil: true
|
||||
|
||||
validates :rate_limiting_response_text,
|
||||
length: { maximum: 255, message: _('is too long (maximum is %{count} characters)') },
|
||||
length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
|
||||
allow_blank: true
|
||||
|
||||
validates :jira_connect_application_key,
|
||||
length: { maximum: 255, message: _('is too long (maximum is %{count} characters)') },
|
||||
length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
|
||||
allow_blank: true
|
||||
|
||||
with_options(presence: true, numericality: { only_integer: true, greater_than: 0 }) do
|
||||
|
@ -561,7 +561,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
allow_nil: false
|
||||
|
||||
validates :admin_mode,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
validates :external_pipeline_validation_service_url,
|
||||
addressable_url: true, allow_blank: true
|
||||
|
@ -574,7 +574,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
inclusion: { in: ApplicationSetting.whats_new_variants.keys }
|
||||
|
||||
validates :floc_enabled,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
enum sidekiq_job_limiter_mode: {
|
||||
Gitlab::SidekiqMiddleware::SizeLimiter::Validator::TRACK_MODE => 0,
|
||||
|
@ -589,7 +589,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
|
||||
validates :sentry_enabled,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
validates :sentry_dsn,
|
||||
addressable_url: true, presence: true, length: { maximum: 255 },
|
||||
if: :sentry_enabled?
|
||||
|
@ -601,7 +601,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
if: :sentry_enabled?
|
||||
|
||||
validates :error_tracking_enabled,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
validates :error_tracking_api_url,
|
||||
presence: true,
|
||||
addressable_url: true,
|
||||
|
@ -670,7 +670,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
attr_encrypted :jitsu_administrator_password, encryption_options_base_32_aes_256_gcm
|
||||
|
||||
validates :disable_feed_token,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
inclusion: { in: [true, false], message: N_('must be a boolean value') }
|
||||
|
||||
before_validation :ensure_uuid!
|
||||
before_validation :coerce_repository_storages_weighted, if: :repository_storages_weighted_changed?
|
||||
|
|
|
@ -23,7 +23,7 @@ module Ci
|
|||
|
||||
def includes?(target_project)
|
||||
# if the setting is disabled any project is considered to be in scope.
|
||||
return true unless source_project.ci_job_token_scope_enabled?
|
||||
return true unless source_project.ci_outbound_job_token_scope_enabled?
|
||||
|
||||
target_project.id == source_project.id ||
|
||||
Ci::JobToken::ProjectScopeLink.from_project(source_project).to_project(target_project).exists?
|
||||
|
|
|
@ -8,7 +8,7 @@ class GroupGroupLink < ApplicationRecord
|
|||
|
||||
validates :shared_group, presence: true
|
||||
validates :shared_group_id, uniqueness: { scope: [:shared_with_group_id],
|
||||
message: _('The group has already been shared with this group') }
|
||||
message: N_('The group has already been shared with this group') }
|
||||
validates :shared_with_group, presence: true
|
||||
validates :group_access, inclusion: { in: Gitlab::Access.all_values },
|
||||
presence: true
|
||||
|
|
|
@ -21,6 +21,11 @@ module IncidentManagement
|
|||
validates :note, presence: true, length: { maximum: 10_000 }
|
||||
validates :note_html, length: { maximum: 10_000 }
|
||||
|
||||
has_many :timeline_event_tag_links, class_name: 'IncidentManagement::TimelineEventTagLink'
|
||||
has_many :timeline_event_tags,
|
||||
class_name: 'IncidentManagement::TimelineEventTag',
|
||||
through: :timeline_event_tag_links
|
||||
|
||||
scope :order_occurred_at_asc_id_asc, -> { reorder(occurred_at: :asc, id: :asc) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module IncidentManagement
|
||||
class TimelineEventTag < ApplicationRecord
|
||||
self.table_name = 'incident_management_timeline_event_tags'
|
||||
|
||||
belongs_to :project, inverse_of: :incident_management_timeline_event_tags
|
||||
|
||||
has_many :timeline_event_tag_links,
|
||||
class_name: 'IncidentManagement::TimelineEventTagLink'
|
||||
|
||||
has_many :timeline_events,
|
||||
class_name: 'IncidentManagement::TimelineEvent',
|
||||
through: :timeline_event_tag_links
|
||||
|
||||
validates :name, presence: true, format: { with: /\A[^,]+\z/ }
|
||||
validates :name, uniqueness: { scope: :project_id }
|
||||
validates :name, length: { maximum: 255 }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module IncidentManagement
|
||||
class TimelineEventTagLink < ApplicationRecord
|
||||
self.table_name = 'incident_management_timeline_event_tag_links'
|
||||
|
||||
belongs_to :timeline_event_tag, class_name: 'IncidentManagement::TimelineEventTag'
|
||||
|
||||
belongs_to :timeline_event, class_name: 'IncidentManagement::TimelineEvent'
|
||||
end
|
||||
end
|
|
@ -24,7 +24,7 @@ class JiraImportState < ApplicationRecord
|
|||
|
||||
validates :project, uniqueness: {
|
||||
conditions: -> { where.not(status: STATUSES.values_at(:failed, :finished)) },
|
||||
message: _('Cannot have multiple Jira imports running at the same time')
|
||||
message: N_('Cannot have multiple Jira imports running at the same time')
|
||||
}
|
||||
|
||||
before_save :ensure_error_message_size
|
||||
|
|
|
@ -55,7 +55,7 @@ class Member < ApplicationRecord
|
|||
validate :signup_email_valid?, on: :create, if: ->(member) { member.invite_email.present? }
|
||||
validates :user_id,
|
||||
uniqueness: {
|
||||
message: _('project bots cannot be added to other groups / projects')
|
||||
message: N_('project bots cannot be added to other groups / projects')
|
||||
},
|
||||
if: :project_bot?
|
||||
validate :access_level_inclusion
|
||||
|
|
|
@ -262,6 +262,7 @@ class Project < ApplicationRecord
|
|||
has_many :source_of_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
|
||||
has_many :issues
|
||||
has_many :incident_management_issuable_escalation_statuses, through: :issues, inverse_of: :project, class_name: 'IncidentManagement::IssuableEscalationStatus'
|
||||
has_many :incident_management_timeline_event_tags, inverse_of: :project, class_name: 'IncidentManagement::TimelineEventTag'
|
||||
has_many :labels, class_name: 'ProjectLabel'
|
||||
has_many :integrations
|
||||
has_many :events
|
||||
|
@ -476,7 +477,7 @@ class Project < ApplicationRecord
|
|||
delegate :dashboard_timezone, to: :metrics_setting, allow_nil: true, prefix: true
|
||||
delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :forward_deployment_enabled, :forward_deployment_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :job_token_scope_enabled, :job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :job_token_scope_enabled, :job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci_outbound, allow_nil: true
|
||||
delegate :inbound_job_token_scope_enabled, :inbound_job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :keep_latest_artifact, :keep_latest_artifact=, to: :ci_cd_settings, allow_nil: true
|
||||
delegate :opt_in_jwt, :opt_in_jwt=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
|
@ -503,7 +504,7 @@ class Project < ApplicationRecord
|
|||
validates :description, length: { maximum: 2000 }, allow_blank: true
|
||||
validates :ci_config_path,
|
||||
format: { without: %r{(\.{2}|\A/)},
|
||||
message: _('cannot include leading slash or directory traversal.') },
|
||||
message: N_('cannot include leading slash or directory traversal.') },
|
||||
length: { maximum: 255 },
|
||||
allow_blank: true
|
||||
validates :name,
|
||||
|
@ -699,13 +700,13 @@ class Project < ApplicationRecord
|
|||
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
|
||||
|
||||
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
|
||||
default: 3600, error_message: _('Maximum job timeout has a value which could not be accepted')
|
||||
default: 3600, error_message: N_('Maximum job timeout has a value which could not be accepted')
|
||||
|
||||
validates :build_timeout, allow_nil: true,
|
||||
numericality: { greater_than_or_equal_to: 10.minutes,
|
||||
less_than: MAX_BUILD_TIMEOUT,
|
||||
only_integer: true,
|
||||
message: _('needs to be between 10 minutes and 1 month') }
|
||||
message: N_('needs to be between 10 minutes and 1 month') }
|
||||
|
||||
# Used by Projects::CleanupService to hold a map of rewritten object IDs
|
||||
mount_uploader :bfg_object_map, AttachmentUploader
|
||||
|
@ -2896,7 +2897,7 @@ class Project < ApplicationRecord
|
|||
ci_cd_settings.allow_fork_pipelines_to_run_in_parent_project?
|
||||
end
|
||||
|
||||
def ci_job_token_scope_enabled?
|
||||
def ci_outbound_job_token_scope_enabled?
|
||||
return false unless ci_cd_settings
|
||||
|
||||
ci_cd_settings.job_token_scope_enabled?
|
||||
|
|
|
@ -9,7 +9,7 @@ class ProjectGroupLink < ApplicationRecord
|
|||
|
||||
validates :project_id, presence: true
|
||||
validates :group, presence: true
|
||||
validates :group_id, uniqueness: { scope: [:project_id], message: _("already shared with this group") }
|
||||
validates :group_id, uniqueness: { scope: [:project_id], message: N_("already shared with this group") }
|
||||
validates :group_access, presence: true
|
||||
validates :group_access, inclusion: { in: Gitlab::Access.values }, presence: true
|
||||
validate :different_group
|
||||
|
|
|
@ -286,10 +286,10 @@ class User < ApplicationRecord
|
|||
validate :check_username_format, if: :username_changed?
|
||||
|
||||
validates :theme_id, allow_nil: true, inclusion: { in: Gitlab::Themes.valid_ids,
|
||||
message: _("%{placeholder} is not a valid theme") % { placeholder: '%{value}' } }
|
||||
message: ->(*) { _("%{placeholder} is not a valid theme") % { placeholder: '%{value}' } } }
|
||||
|
||||
validates :color_scheme_id, allow_nil: true, inclusion: { in: Gitlab::ColorSchemes.valid_ids,
|
||||
message: _("%{placeholder} is not a valid color scheme") % { placeholder: '%{value}' } }
|
||||
message: ->(*) { _("%{placeholder} is not a valid color scheme") % { placeholder: '%{value}' } } }
|
||||
|
||||
validates :website_url, allow_blank: true, url: true, if: :website_url_changed?
|
||||
|
||||
|
|
|
@ -7,6 +7,6 @@ module Users
|
|||
belongs_to :user
|
||||
|
||||
validates :user, presence: true
|
||||
validates :user_id, uniqueness: { message: _("banned user already exists") }
|
||||
validates :user_id, uniqueness: { message: N_("banned user already exists") }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,13 +15,23 @@ module Ci
|
|||
method: 'Ci::JobArtifacts::DeleteService#execute',
|
||||
project_id: build.project_id
|
||||
)
|
||||
return ServiceResponse.error(
|
||||
message: 'Action temporarily disabled. The project this job belongs to is undergoing stats refresh.',
|
||||
reason: :project_stats_refresh
|
||||
)
|
||||
end
|
||||
|
||||
# fix_expire_at is false because in this case we want to explicitly delete the job artifacts
|
||||
# this flag is a workaround that will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/355833
|
||||
Ci::JobArtifacts::DestroyBatchService.new(build.job_artifacts.erasable, fix_expire_at: false).execute
|
||||
result = Ci::JobArtifacts::DestroyBatchService.new(build.job_artifacts.erasable).execute
|
||||
|
||||
ServiceResponse.success
|
||||
if result.fetch(:status) == :success
|
||||
ServiceResponse.success(payload:
|
||||
{
|
||||
destroyed_artifacts_count: result.fetch(:destroyed_artifacts_count),
|
||||
statistics_updates: result.fetch(:statistics_updates)
|
||||
})
|
||||
else
|
||||
ServiceResponse.error(message: result.fetch(:message))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -9,5 +9,5 @@
|
|||
= label_tag :password
|
||||
= password_field_tag :password, nil, disabled: true, class: "form-control gl-form-input bottom", title: title
|
||||
.form-group
|
||||
= button_tag _("Sign in"), disabled: true, class: "btn gl-button btn-confirm", type: "button", title: title
|
||||
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm, disabled: true, button_options: { title: title }) do
|
||||
= _("Sign in")
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
%input.js-add-list{ type: "checkbox", name: "add_list", checked: add_list }
|
||||
%span= _('Add list')
|
||||
.clearfix
|
||||
%button.gl-button.btn.btn-confirm.float-left.js-new-label-btn{ type: "button" }
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'float-left js-new-label-btn' }) do
|
||||
= _('Create')
|
||||
%button.gl-button.btn.btn-default.float-right.js-cancel-label-btn{ type: "button" }
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'float-right js-cancel-label-btn' }) do
|
||||
= _('Cancel')
|
||||
|
|
|
@ -10,6 +10,7 @@ module Ci
|
|||
idempotent!
|
||||
deduplicate :until_executed
|
||||
urgency :high
|
||||
loggable_arguments 1
|
||||
|
||||
def perform(pipeline_id, auto_canceled_by_pipeline_id)
|
||||
::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
data_category: optional
|
||||
key_path: redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_monthly
|
||||
description: A monthly count of packages published to the registry using a deploy
|
||||
description: A monthly count of unique users who published packages to the registry using a deploy
|
||||
token
|
||||
product_section: ops
|
||||
product_stage: package
|
||||
|
@ -11,8 +11,11 @@ value_type: number
|
|||
status: active
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
instrumentation_class: RedisHLLMetric
|
||||
instrumentation_class: AggregatedMetric
|
||||
options:
|
||||
aggregate:
|
||||
operator: OR
|
||||
attribute: user_id
|
||||
events:
|
||||
- i_package_composer_deploy_token
|
||||
- i_package_conan_deploy_token
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
data_category: optional
|
||||
key_path: redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_weekly
|
||||
description: A weekly count of packages published to the registry using a deploy token
|
||||
description: A weekly count of unique users who published packages to the registry using a deploy
|
||||
token
|
||||
product_section: ops
|
||||
product_stage: package
|
||||
product_group: package
|
||||
|
@ -10,8 +11,11 @@ value_type: number
|
|||
status: active
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
instrumentation_class: RedisHLLMetric
|
||||
instrumentation_class: AggregatedMetric
|
||||
options:
|
||||
aggregate:
|
||||
operator: OR
|
||||
attribute: user_id
|
||||
events:
|
||||
- i_package_composer_deploy_token
|
||||
- i_package_conan_deploy_token
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
table_name: incident_management_timeline_event_tag_links
|
||||
classes:
|
||||
- IncidentManagement::TimelineEventTagLink
|
||||
feature_categories:
|
||||
- incident_management
|
||||
description: Persists links between timeline event tags and timeline events.
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100271
|
||||
milestone: '15.6'
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
table_name: incident_management_timeline_event_tags
|
||||
classes:
|
||||
- IncidentManagement::TimelineEventTag
|
||||
feature_categories:
|
||||
- incident_management
|
||||
description: Persists tags for timeline events in a project.
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100271
|
||||
milestone: '15.6'
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateIncidentManagementTimelineEventTags < Gitlab::Database::Migration[2.0]
|
||||
enable_lock_retries!
|
||||
|
||||
def up
|
||||
create_table :incident_management_timeline_event_tags do |t|
|
||||
t.timestamps_with_timezone null: false
|
||||
t.references :project, null: false, index: false, foreign_key: { on_delete: :cascade }
|
||||
t.text :name, limit: 255, null: false
|
||||
|
||||
t.index [:project_id, :name], unique: true, name: 'index_im_timeline_event_tags_name_project_id'
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :incident_management_timeline_event_tags
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateIncidentManagementTimelineEventTagLinks < Gitlab::Database::Migration[2.0]
|
||||
enable_lock_retries!
|
||||
|
||||
def up
|
||||
create_table :incident_management_timeline_event_tag_links do |t|
|
||||
t.references :timeline_event,
|
||||
null: false,
|
||||
index: { name: 'index_im_timeline_event_id' },
|
||||
foreign_key: { to_table: :incident_management_timeline_events, column: :timeline_event_id, on_delete: :cascade }
|
||||
|
||||
t.references :timeline_event_tag,
|
||||
null: false,
|
||||
index: false,
|
||||
foreign_key: {
|
||||
to_table: :incident_management_timeline_event_tags,
|
||||
column: :timeline_event_tag_id,
|
||||
on_delete: :cascade
|
||||
}
|
||||
|
||||
t.index [:timeline_event_tag_id, :timeline_event_id],
|
||||
unique: true,
|
||||
name: 'index_im_timeline_event_tags_on_tag_id_and_event_id'
|
||||
|
||||
t.datetime_with_timezone :created_at, null: false
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :incident_management_timeline_event_tag_links
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MembersRemoveMemberNamespaceIdNotNullConstraint < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
CONSTRAINT_NAME = 'check_508774aac0'
|
||||
|
||||
def up
|
||||
remove_not_null_constraint :members, :member_namespace_id, constraint_name: CONSTRAINT_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_not_null_constraint :members, :member_namespace_id, validate: false, constraint_name: CONSTRAINT_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
6b90dfb738c597a45ecaae792e97e1ae0decb93779ecc35fbc2fbaedafb5b9d1
|
|
@ -0,0 +1 @@
|
|||
ab93968543b6aec0bc304a2c0dc051f63a29b4765df11432fba45325e5e75e55
|
|
@ -0,0 +1 @@
|
|||
25030e3ba7c6632fa86100c2db320d1e0c431f992e2b3e333a98e7e03bd31a49
|
|
@ -16411,6 +16411,40 @@ CREATE SEQUENCE incident_management_pending_issue_escalations_id_seq
|
|||
|
||||
ALTER SEQUENCE incident_management_pending_issue_escalations_id_seq OWNED BY incident_management_pending_issue_escalations.id;
|
||||
|
||||
CREATE TABLE incident_management_timeline_event_tag_links (
|
||||
id bigint NOT NULL,
|
||||
timeline_event_id bigint NOT NULL,
|
||||
timeline_event_tag_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE incident_management_timeline_event_tag_links_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE incident_management_timeline_event_tag_links_id_seq OWNED BY incident_management_timeline_event_tag_links.id;
|
||||
|
||||
CREATE TABLE incident_management_timeline_event_tags (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
project_id bigint NOT NULL,
|
||||
name text NOT NULL,
|
||||
CONSTRAINT check_8717184e2c CHECK ((char_length(name) <= 255))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE incident_management_timeline_event_tags_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE incident_management_timeline_event_tags_id_seq OWNED BY incident_management_timeline_event_tags.id;
|
||||
|
||||
CREATE TABLE incident_management_timeline_events (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
|
@ -23743,6 +23777,10 @@ ALTER TABLE ONLY incident_management_pending_alert_escalations ALTER COLUMN id S
|
|||
|
||||
ALTER TABLE ONLY incident_management_pending_issue_escalations ALTER COLUMN id SET DEFAULT nextval('incident_management_pending_issue_escalations_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tag_links ALTER COLUMN id SET DEFAULT nextval('incident_management_timeline_event_tag_links_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tags ALTER COLUMN id SET DEFAULT nextval('incident_management_timeline_event_tags_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_events ALTER COLUMN id SET DEFAULT nextval('incident_management_timeline_events_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY index_statuses ALTER COLUMN id SET DEFAULT nextval('index_statuses_id_seq'::regclass);
|
||||
|
@ -25102,9 +25140,6 @@ ALTER TABLE ONLY chat_teams
|
|||
ALTER TABLE vulnerability_scanners
|
||||
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
|
||||
|
||||
ALTER TABLE members
|
||||
ADD CONSTRAINT check_508774aac0 CHECK ((member_namespace_id IS NOT NULL)) NOT VALID;
|
||||
|
||||
ALTER TABLE sprints
|
||||
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
|
||||
|
||||
|
@ -25702,6 +25737,12 @@ ALTER TABLE ONLY incident_management_pending_alert_escalations
|
|||
ALTER TABLE ONLY incident_management_pending_issue_escalations
|
||||
ADD CONSTRAINT incident_management_pending_issue_escalations_pkey PRIMARY KEY (id, process_at);
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tag_links
|
||||
ADD CONSTRAINT incident_management_timeline_event_tag_links_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tags
|
||||
ADD CONSTRAINT incident_management_timeline_event_tags_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_events
|
||||
ADD CONSTRAINT incident_management_timeline_events_pkey PRIMARY KEY (id);
|
||||
|
||||
|
@ -29054,6 +29095,12 @@ CREATE INDEX index_im_issuable_escalation_statuses_on_policy_id ON incident_mana
|
|||
|
||||
CREATE UNIQUE INDEX index_im_oncall_schedules_on_project_id_and_iid ON incident_management_oncall_schedules USING btree (project_id, iid);
|
||||
|
||||
CREATE INDEX index_im_timeline_event_id ON incident_management_timeline_event_tag_links USING btree (timeline_event_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_im_timeline_event_tags_name_project_id ON incident_management_timeline_event_tags USING btree (project_id, name);
|
||||
|
||||
CREATE UNIQUE INDEX index_im_timeline_event_tags_on_tag_id_and_event_id ON incident_management_timeline_event_tag_links USING btree (timeline_event_tag_id, timeline_event_id);
|
||||
|
||||
CREATE INDEX index_im_timeline_events_author_id ON incident_management_timeline_events USING btree (author_id);
|
||||
|
||||
CREATE INDEX index_im_timeline_events_issue_id ON incident_management_timeline_events USING btree (issue_id);
|
||||
|
@ -33925,6 +33972,9 @@ ALTER TABLE ONLY issue_user_mentions
|
|||
ALTER TABLE ONLY merge_request_assignees
|
||||
ADD CONSTRAINT fk_rails_579d375628 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tag_links
|
||||
ADD CONSTRAINT fk_rails_57baccd7f9 FOREIGN KEY (timeline_event_id) REFERENCES incident_management_timeline_events(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY packages_debian_project_architectures
|
||||
ADD CONSTRAINT fk_rails_5808663adf FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
|
||||
|
||||
|
@ -34129,6 +34179,9 @@ ALTER TABLE ONLY group_crm_settings
|
|||
ALTER TABLE ONLY clusters_applications_ingress
|
||||
ADD CONSTRAINT fk_rails_753a7b41c1 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tag_links
|
||||
ADD CONSTRAINT fk_rails_753b8b6ee3 FOREIGN KEY (timeline_event_tag_id) REFERENCES incident_management_timeline_event_tags(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY release_links
|
||||
ADD CONSTRAINT fk_rails_753be7ae29 FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
|
||||
|
||||
|
@ -34756,6 +34809,9 @@ ALTER TABLE ONLY deployment_merge_requests
|
|||
ALTER TABLE ONLY packages_debian_group_component_files
|
||||
ADD CONSTRAINT fk_rails_dd262386e9 FOREIGN KEY (component_id) REFERENCES packages_debian_group_components(id) ON DELETE RESTRICT;
|
||||
|
||||
ALTER TABLE ONLY incident_management_timeline_event_tags
|
||||
ADD CONSTRAINT fk_rails_dd5c91484e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY user_callouts
|
||||
ADD CONSTRAINT fk_rails_ddfdd80f3d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ module API
|
|||
|
||||
expose :project do
|
||||
expose :ci_job_token_scope_enabled do |job|
|
||||
job.project.ci_job_token_scope_enabled?
|
||||
job.project.ci_outbound_job_token_scope_enabled?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,7 +104,7 @@ module API
|
|||
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
|
||||
expose :ci_default_git_depth
|
||||
expose :ci_forward_deployment_enabled
|
||||
expose :ci_job_token_scope_enabled
|
||||
expose(:ci_job_token_scope_enabled) { |p, _| p.ci_outbound_job_token_scope_enabled? }
|
||||
expose :ci_separated_caches
|
||||
expose :ci_opt_in_jwt
|
||||
expose :ci_allow_fork_pipelines_to_run_in_parent_project
|
||||
|
|
|
@ -20,8 +20,6 @@ module API
|
|||
use :pagination
|
||||
use :event_filter_params
|
||||
use :sort_params
|
||||
optional :scope, type: String, desc: 'Include all events across a user\'s projects',
|
||||
documentation: { example: 'all' }
|
||||
end
|
||||
|
||||
get do
|
||||
|
|
|
@ -6,7 +6,7 @@ module API
|
|||
extend Grape::API::Helpers
|
||||
|
||||
params :event_filter_params do
|
||||
optional :action, type: String, values: Event.actions.keys, desc: 'Event action to filter on'
|
||||
optional :action, type: String, values: Event.actions, desc: 'Event action to filter on'
|
||||
optional :target_type, type: String, values: Event.target_types, desc: 'Event target type to filter on'
|
||||
optional :before, type: Date, desc: 'Include only events created before this date'
|
||||
optional :after, type: Date, desc: 'Include only events created after this date'
|
||||
|
|
|
@ -264,6 +264,8 @@ incident_management_oncall_shifts: :gitlab_main
|
|||
incident_management_pending_alert_escalations: :gitlab_main
|
||||
incident_management_pending_issue_escalations: :gitlab_main
|
||||
incident_management_timeline_events: :gitlab_main
|
||||
incident_management_timeline_event_tags: :gitlab_main
|
||||
incident_management_timeline_event_tag_links: :gitlab_main
|
||||
index_statuses: :gitlab_main
|
||||
in_product_marketing_emails: :gitlab_main
|
||||
insights: :gitlab_main
|
||||
|
|
|
@ -34,6 +34,7 @@ module Gitlab
|
|||
|
||||
alias_method :parse!, :parse
|
||||
alias_method :load, :parse
|
||||
alias_method :decode, :parse
|
||||
|
||||
# Restricted method for converting a Ruby object to JSON. If you
|
||||
# need to pass options to this, you should use `.generate` instead,
|
||||
|
@ -56,6 +57,8 @@ module Gitlab
|
|||
adapter_generate(object, opts)
|
||||
end
|
||||
|
||||
alias_method :encode, :generate
|
||||
|
||||
# Generates JSON for an object and makes it look purdy
|
||||
#
|
||||
# The Oj variant in this looks seriously weird but these are the settings
|
||||
|
|
|
@ -16,7 +16,7 @@ gem 'rspec-retry', '~> 0.6.1', require: 'rspec/retry'
|
|||
gem 'rspec_junit_formatter', '~> 0.6.0'
|
||||
gem 'faker', '~> 2.23'
|
||||
gem 'knapsack', '~> 4.0'
|
||||
gem 'parallel_tests', '~> 2.32'
|
||||
gem 'parallel_tests', '~> 3.13'
|
||||
gem 'rotp', '~> 6.2.0'
|
||||
gem 'timecop', '~> 0.9.5'
|
||||
gem 'parallel', '~> 1.19'
|
||||
|
|
|
@ -185,7 +185,7 @@ GEM
|
|||
oj (3.13.21)
|
||||
os (1.1.4)
|
||||
parallel (1.19.2)
|
||||
parallel_tests (2.32.0)
|
||||
parallel_tests (3.13.0)
|
||||
parallel
|
||||
parser (3.1.2.1)
|
||||
ast (~> 2.4.1)
|
||||
|
@ -316,7 +316,7 @@ DEPENDENCIES
|
|||
nokogiri (~> 1.13, >= 1.13.8)
|
||||
octokit (~> 5.6.1)
|
||||
parallel (~> 1.19)
|
||||
parallel_tests (~> 2.32)
|
||||
parallel_tests (~> 3.13)
|
||||
pry-byebug (~> 3.5.1)
|
||||
rainbow (~> 3.0.0)
|
||||
rake (~> 13)
|
||||
|
|
|
@ -11,7 +11,7 @@ end
|
|||
|
||||
desc "Initialize GitLab with an access token"
|
||||
task :initialize_gitlab_auth, [:address] do |_, args|
|
||||
QA::Tools::InitializeGitLabAuth.new(args).run
|
||||
QA::Tools::InitializeGitlabAuth.new(args).run
|
||||
end
|
||||
|
||||
desc "Generate Performance Testdata"
|
||||
|
@ -46,7 +46,7 @@ task generate_data_and_run_load_test: [:generate_perf_testdata, :run_artillery_l
|
|||
|
||||
desc "Deletes test ssh keys a user"
|
||||
task :delete_test_ssh_keys, [:title_portion, :delete_before, :dry_run] do |_, args|
|
||||
QA::Tools::DeleteTestSSHKeys.new(args).run
|
||||
QA::Tools::DeleteTestSshKeys.new(args).run
|
||||
end
|
||||
|
||||
desc "Deletes projects directly under the provided group"
|
||||
|
|
17
qa/qa.rb
17
qa/qa.rb
|
@ -30,6 +30,22 @@ module QA
|
|||
loader.ignore("#{root}/specs/features")
|
||||
loader.ignore("#{root}/specs/spec_helper.rb")
|
||||
|
||||
# we need to eager load scenario classes
|
||||
# zeitwerk does not have option to configure what to eager load, so all exceptions have to be defined
|
||||
loader.do_not_eager_load("#{root}/ce")
|
||||
loader.do_not_eager_load("#{root}/ee")
|
||||
loader.do_not_eager_load("#{root}/flow")
|
||||
loader.do_not_eager_load("#{root}/git")
|
||||
loader.do_not_eager_load("#{root}/mobile")
|
||||
loader.do_not_eager_load("#{root}/page")
|
||||
loader.do_not_eager_load("#{root}/resource")
|
||||
loader.do_not_eager_load("#{root}/runtime")
|
||||
loader.do_not_eager_load("#{root}/service")
|
||||
loader.do_not_eager_load("#{root}/specs")
|
||||
loader.do_not_eager_load("#{root}/support")
|
||||
loader.do_not_eager_load("#{root}/tools")
|
||||
loader.do_not_eager_load("#{root}/vendor")
|
||||
|
||||
loader.inflector.inflect(
|
||||
"ce" => "CE",
|
||||
"ee" => "EE",
|
||||
|
@ -74,6 +90,7 @@ module QA
|
|||
end
|
||||
|
||||
loader.setup
|
||||
loader.eager_load
|
||||
end
|
||||
|
||||
# Custom warning processing
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Scenario
|
||||
module Test
|
||||
# This class exists for back-compatibility so that gitlab-qa can continue
|
||||
# to call Test::Instance instead of Test::Instance::All until at least
|
||||
# the current latest GitLab version has the Test::Instance::All class.
|
||||
# As of Aug, 22nd 2018. Only GitLab >= 11.3 has this class.
|
||||
module Instance
|
||||
include Bootable
|
||||
|
||||
def self.perform(*args)
|
||||
self.tap do |scenario|
|
||||
yield scenario if block_given?
|
||||
break scenario.do_perform(*args)
|
||||
end
|
||||
end
|
||||
|
||||
def self.do_perform(address, *rspec_options)
|
||||
Runtime::Scenario.define(:gitlab_address, address)
|
||||
|
||||
##
|
||||
# Perform before hooks, which are different for CE and EE
|
||||
#
|
||||
Runtime::Release.perform_before_hooks
|
||||
|
||||
Specs::Runner.perform do |specs|
|
||||
specs.tty = true
|
||||
specs.options = rspec_options if rspec_options.any?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,20 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Scenario
|
||||
module Test
|
||||
module Integration
|
||||
class Github < Test::Instance::All
|
||||
tags :github
|
||||
|
||||
def perform(address, *rspec_options)
|
||||
# This test suite requires a GitHub personal access token
|
||||
Runtime::Env.require_github_access_token!
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,20 +5,24 @@ require 'deprecation_toolkit/rspec'
|
|||
require 'concurrent/utility/monotonic_time'
|
||||
require 'active_support/gem_version'
|
||||
|
||||
module QaDeprecationToolkitEnv
|
||||
# Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
|
||||
# rubocop:disable Layout/LineLength
|
||||
def self.kwargs_warning
|
||||
%r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z}
|
||||
end
|
||||
# rubocop:enable Layout/LineLength
|
||||
module QA
|
||||
module Specs
|
||||
class QaDeprecationToolkitEnv
|
||||
# Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
|
||||
# rubocop:disable Layout/LineLength
|
||||
def self.kwargs_warning
|
||||
%r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z}
|
||||
end
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
def self.configure!
|
||||
# Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7
|
||||
Warning[:deprecated] = true
|
||||
def self.configure!
|
||||
# Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7
|
||||
Warning[:deprecated] = true
|
||||
|
||||
DeprecationToolkit::Configuration.test_runner = :rspec
|
||||
DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
|
||||
DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning]
|
||||
DeprecationToolkit::Configuration.test_runner = :rspec
|
||||
DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
|
||||
DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
require_relative '../../qa'
|
||||
|
||||
require_relative 'qa_deprecation_toolkit_env'
|
||||
QaDeprecationToolkitEnv.configure!
|
||||
QA::Specs::QaDeprecationToolkitEnv.configure!
|
||||
|
||||
Knapsack::Adapters::RSpecAdapter.bind if QA::Runtime::Env.knapsack?
|
||||
|
||||
|
|
|
@ -10,42 +10,11 @@ module QA
|
|||
class NonEmptySuites
|
||||
include Helpers
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
SCENARIOS = [
|
||||
{ klass: "Test::Instance::All" },
|
||||
{ klass: "Test::Instance::Smoke" },
|
||||
{ klass: "Test::Instance::Reliable" },
|
||||
{ klass: "Test::Instance::ReviewBlocking" },
|
||||
{ klass: "Test::Instance::ReviewNonBlocking" },
|
||||
{ klass: "Test::Instance::CloudActivation" },
|
||||
{ klass: "Test::Instance::Integrations" },
|
||||
{ klass: "Test::Instance::Jira" },
|
||||
{ klass: "Test::Instance::LargeSetup" },
|
||||
{ klass: "Test::Instance::Metrics" },
|
||||
{ klass: "Test::Instance::ObjectStorage" },
|
||||
{ klass: "Test::Instance::Packages" },
|
||||
{ klass: "Test::Instance::RepositoryStorage" },
|
||||
{ klass: "Test::Integration::ServicePingDisabled" },
|
||||
{ klass: "Test::Integration::LDAPNoTLS" },
|
||||
{ klass: "Test::Integration::LDAPTLS" },
|
||||
{ klass: "Test::Integration::LDAPNoServer" },
|
||||
{ klass: "Test::Integration::InstanceSAML" },
|
||||
{ klass: "Test::Integration::RegistryWithCDN" },
|
||||
{ klass: "Test::Integration::RegistryTLS" },
|
||||
{ klass: "Test::Integration::Registry" },
|
||||
{ klass: "Test::Integration::SMTP" },
|
||||
{ klass: "QA::EE::Scenario::Test::Integration::Elasticsearch" },
|
||||
{ klass: "QA::EE::Scenario::Test::Integration::GroupSAML" },
|
||||
{
|
||||
klass: "QA::EE::Scenario::Test::Geo",
|
||||
args: "--primary-address http://dummy1.test --primary-name gitlab-primary --secondary-address http://dummy2.test --secondary-name gitlab-secondary --without-setup"
|
||||
},
|
||||
{
|
||||
klass: "Test::Integration::Mattermost",
|
||||
args: "--mattermost-address http://mattermost.test"
|
||||
}
|
||||
# @return [Array] scenarios that never run in package-and-test pipeline
|
||||
IGNORED_SCENARIOS = [
|
||||
"QA::EE::Scenario::Test::Geo",
|
||||
"QA::Scenario::Test::Instance::Airgapped"
|
||||
].freeze
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
def initialize(qa_tests)
|
||||
@qa_tests = qa_tests
|
||||
|
@ -56,38 +25,58 @@ module QA
|
|||
# @return [String]
|
||||
def fetch
|
||||
logger.info("Checking for runnable suites")
|
||||
scenarios = SCENARIOS.each_with_object([]) do |scenario, runnable_scenarios|
|
||||
logger.info(" fetching runnable specs for '#{scenario[:klass]}'")
|
||||
scenarios.each_with_object([]) do |scenario, runnable_scenarios|
|
||||
logger.info(" fetching runnable specs for '#{scenario}'")
|
||||
next logger.info(" scenario is in ignore list, skipping") if IGNORED_SCENARIOS.include?(scenario)
|
||||
|
||||
out, err, status = run_command(**scenario)
|
||||
out, err, status = run_command(scenario)
|
||||
|
||||
unless status.success?
|
||||
logger.error(" example count failed!\n#{err}")
|
||||
logger.error(" example count failed!\n#{err}")
|
||||
next
|
||||
end
|
||||
|
||||
count = out.split("\n").last.to_i
|
||||
logger.info(" found #{count} examples to run")
|
||||
runnable_scenarios << scenario[:klass] if count > 0
|
||||
end
|
||||
|
||||
scenarios.join(",")
|
||||
runnable_scenarios << scenario if count > 0
|
||||
end.join(",")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :qa_tests
|
||||
|
||||
# Get all defined scenarios
|
||||
#
|
||||
# @return [Array<String>]
|
||||
def scenarios
|
||||
foss_scenarios = scenario_classes(QA::Scenario::Test)
|
||||
return foss_scenarios unless QA.const_defined?("QA::EE")
|
||||
|
||||
foss_scenarios + scenario_classes(QA::EE::Scenario::Test)
|
||||
end
|
||||
|
||||
# Fetch scenario classes recursively
|
||||
#
|
||||
# @param [Module] mod
|
||||
# @return [Array<String>]
|
||||
def scenario_classes(mod)
|
||||
mod.constants.map do |const|
|
||||
c = mod.const_get(const, false)
|
||||
next c.to_s if c.is_a?(Class)
|
||||
|
||||
scenario_classes(c)
|
||||
end.flatten
|
||||
end
|
||||
|
||||
# Run scenario count command
|
||||
#
|
||||
# @param [String] klass
|
||||
# @param [String] args
|
||||
# @return [String]
|
||||
def run_command(klass:, args: nil)
|
||||
def run_command(klass)
|
||||
cmd = ["bundle exec bin/qa"]
|
||||
cmd << klass
|
||||
cmd << "--count-examples-only --address http://dummy1.test"
|
||||
cmd << args if args
|
||||
cmd << "-- #{qa_tests}" unless qa_tests.blank?
|
||||
|
||||
Open3.capture3(cmd.join(" "))
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
module QA
|
||||
module Tools
|
||||
class DeleteTestSSHKeys
|
||||
class DeleteTestSshKeys
|
||||
include Support::API
|
||||
|
||||
ITEMS_PER_PAGE = '100'
|
||||
|
|
|
@ -6,7 +6,7 @@ module QA
|
|||
# Also creates a personal access token
|
||||
# @example
|
||||
# $ bundle exec rake 'initialize_gitlab_auth[http://gitlab.test]'
|
||||
class InitializeGitLabAuth
|
||||
class InitializeGitlabAuth
|
||||
attr_reader :address
|
||||
|
||||
def initialize(address:)
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe QA::Scenario::Test::Integration::Github do
|
||||
describe '#perform' do
|
||||
let(:env) { spy('Runtime::Env', knapsack?: false, dry_run: false) }
|
||||
|
||||
before do
|
||||
stub_const('QA::Runtime::Env', env)
|
||||
end
|
||||
|
||||
it_behaves_like 'a QA scenario class' do
|
||||
let(:tags) { [:github] }
|
||||
|
||||
it 'requires a GitHub access token' do
|
||||
subject.perform(args)
|
||||
|
||||
expect(env).to have_received(:require_github_access_token!)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,11 +9,11 @@ RSpec.describe QA::Tools::Ci::NonEmptySuites do
|
|||
allow(Gitlab::QA::TestLogger).to receive(:logger).and_return(Logger.new(StringIO.new))
|
||||
allow(Open3).to receive(:capture3).and_return(["output\n0", "", status])
|
||||
allow(Open3).to receive(:capture3)
|
||||
.with("bundle exec bin/qa Test::Instance::All --count-examples-only --address http://dummy1.test")
|
||||
.with("bundle exec bin/qa QA::Scenario::Test::Instance::All --count-examples-only --address http://dummy1.test")
|
||||
.and_return(["output\n1", "", status])
|
||||
end
|
||||
|
||||
it "returns runnable test suites" do
|
||||
expect(non_empty_suites.fetch).to eq("Test::Instance::All")
|
||||
expect(non_empty_suites.fetch).to eq("QA::Scenario::Test::Instance::All")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :incident_management_timeline_event_tag_link, class: 'IncidentManagement::TimelineEventTagLink' do
|
||||
association :timeline_event_tag, factory: :incident_management_timeline_event_tag
|
||||
association :timeline_event, factory: :incident_management_timeline_event
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :incident_management_timeline_event_tag, class: 'IncidentManagement::TimelineEventTag' do
|
||||
project
|
||||
name { 'Start time' }
|
||||
end
|
||||
end
|
|
@ -54,7 +54,7 @@ FactoryBot.define do
|
|||
import_last_error { nil }
|
||||
forward_deployment_enabled { nil }
|
||||
restrict_user_defined_variables { nil }
|
||||
ci_job_token_scope_enabled { nil }
|
||||
ci_outbound_job_token_scope_enabled { nil }
|
||||
ci_inbound_job_token_scope_enabled { nil }
|
||||
runner_token_expiration_interval { nil }
|
||||
runner_token_expiration_interval_human_readable { nil }
|
||||
|
@ -113,7 +113,7 @@ FactoryBot.define do
|
|||
project.merge_trains_enabled = evaluator.merge_trains_enabled unless evaluator.merge_trains_enabled.nil?
|
||||
project.keep_latest_artifact = evaluator.keep_latest_artifact unless evaluator.keep_latest_artifact.nil?
|
||||
project.restrict_user_defined_variables = evaluator.restrict_user_defined_variables unless evaluator.restrict_user_defined_variables.nil?
|
||||
project.ci_job_token_scope_enabled = evaluator.ci_job_token_scope_enabled unless evaluator.ci_job_token_scope_enabled.nil?
|
||||
project.ci_outbound_job_token_scope_enabled = evaluator.ci_outbound_job_token_scope_enabled unless evaluator.ci_outbound_job_token_scope_enabled.nil?
|
||||
project.ci_inbound_job_token_scope_enabled = evaluator.ci_inbound_job_token_scope_enabled unless evaluator.ci_inbound_job_token_scope_enabled.nil?
|
||||
project.runner_token_expiration_interval = evaluator.runner_token_expiration_interval unless evaluator.runner_token_expiration_interval.nil?
|
||||
project.runner_token_expiration_interval_human_readable = evaluator.runner_token_expiration_interval_human_readable unless evaluator.runner_token_expiration_interval_human_readable.nil?
|
||||
|
|
|
@ -152,6 +152,30 @@ describe('diffs/components/app', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('fetch diff with no changes', () => {
|
||||
beforeEach(() => {
|
||||
const fetchResolver = () => {
|
||||
store.state.diffs.retrievingBatches = false;
|
||||
return Promise.resolve({ real_size: null });
|
||||
};
|
||||
|
||||
createComponent();
|
||||
jest.spyOn(wrapper.vm, 'fetchDiffFilesMeta').mockImplementation(fetchResolver);
|
||||
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('diff counter to be 0 after fetch', async () => {
|
||||
expect(wrapper.vm.diffFilesLength).toEqual(0);
|
||||
wrapper.vm.fetchData(false);
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
|
||||
expect(wrapper.vm.diffFilesLength).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('codequality diff', () => {
|
||||
it('does not fetch code quality data on FOSS', async () => {
|
||||
createComponent();
|
||||
|
|
|
@ -141,6 +141,14 @@ describe('OverviewTabs', () => {
|
|||
expect(tabPanel.vm.$attrs.lazy).toBe(false);
|
||||
});
|
||||
|
||||
it('sets `lazy` prop to `false` for initially active tab and `true` for all other tabs', async () => {
|
||||
await createComponent({ route: { name: ACTIVE_TAB_SHARED, params: { group: 'foo/bar' } } });
|
||||
|
||||
expect(findTabPanels().at(0).vm.$attrs.lazy).toBe(true);
|
||||
expect(findTabPanels().at(1).vm.$attrs.lazy).toBe(false);
|
||||
expect(findTabPanels().at(2).vm.$attrs.lazy).toBe(true);
|
||||
});
|
||||
|
||||
describe.each([
|
||||
[
|
||||
{ name: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS, params: { group: 'foo/bar/baz' } },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlBadge } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { mockTracking } from 'helpers/tracking_helper';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
@ -27,7 +27,7 @@ describe('GitlabVersionCheck', () => {
|
|||
mock = new MockAdapter(axios);
|
||||
mock.onGet().replyOnce(response.code, response.res);
|
||||
|
||||
wrapper = shallowMount(GitlabVersionCheck);
|
||||
wrapper = shallowMountExtended(GitlabVersionCheck);
|
||||
};
|
||||
|
||||
const dummyGon = {
|
||||
|
@ -42,6 +42,7 @@ describe('GitlabVersionCheck', () => {
|
|||
window.gon = originalGon;
|
||||
});
|
||||
|
||||
const findGlBadgeClickWrapper = () => wrapper.findByTestId('badge-click-wrapper');
|
||||
const findGlBadge = () => wrapper.findComponent(GlBadge);
|
||||
|
||||
describe.each`
|
||||
|
@ -81,7 +82,8 @@ describe('GitlabVersionCheck', () => {
|
|||
await waitForPromises(); // Ensure we wrap up the axios call
|
||||
});
|
||||
|
||||
it(`does${renders ? '' : ' not'} render GlBadge`, () => {
|
||||
it(`does${renders ? '' : ' not'} render Badge Click Wrapper and GlBadge`, () => {
|
||||
expect(findGlBadgeClickWrapper().exists()).toBe(renders);
|
||||
expect(findGlBadge().exists()).toBe(renders);
|
||||
});
|
||||
});
|
||||
|
@ -110,9 +112,9 @@ describe('GitlabVersionCheck', () => {
|
|||
expect(findGlBadge().attributes('variant')).toBe(expectedUI.variant);
|
||||
});
|
||||
|
||||
it(`tracks rendered_version_badge with status ${expectedUI.variant}`, () => {
|
||||
it(`tracks rendered_version_badge with label ${expectedUI.title}`, () => {
|
||||
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'rendered_version_badge', {
|
||||
label: expectedUI.variant,
|
||||
label: expectedUI.title,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -120,11 +122,11 @@ describe('GitlabVersionCheck', () => {
|
|||
expect(findGlBadge().attributes('href')).toBe(UPGRADE_DOCS_URL);
|
||||
});
|
||||
|
||||
it(`tracks click_version_badge with status ${expectedUI.variant} when badge is clicked`, async () => {
|
||||
await findGlBadge().vm.$emit('click');
|
||||
it(`tracks click_version_badge with label ${expectedUI.title} when badge is clicked`, async () => {
|
||||
await findGlBadgeClickWrapper().trigger('click');
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_version_badge', {
|
||||
label: expectedUI.variant,
|
||||
label: expectedUI.title,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject do
|
|||
|
||||
describe '#resolve' do
|
||||
let_it_be(:project) do
|
||||
create(:project, ci_job_token_scope_enabled: true).tap(&:save!)
|
||||
create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!)
|
||||
end
|
||||
|
||||
let_it_be(:target_project) { create(:project) }
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe Mutations::Ci::JobTokenScope::RemoveProject do
|
|||
end
|
||||
|
||||
describe '#resolve' do
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:target_project) { create(:project) }
|
||||
|
||||
let_it_be(:link) do
|
||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
|
|||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
|
||||
specify do
|
||||
expect(described_class).to have_nullable_graphql_type(::Types::Ci::JobTokenScopeType)
|
||||
|
@ -21,7 +21,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
|
|||
end
|
||||
|
||||
it 'returns the same project in the allow list of projects for the Ci Job Token when scope is not enabled' do
|
||||
allow(project).to receive(:ci_job_token_scope_enabled?).and_return(false)
|
||||
allow(project).to receive(:ci_outbound_job_token_scope_enabled?).and_return(false)
|
||||
|
||||
expect(resolve_scope.all_projects).to contain_exactly(project)
|
||||
end
|
||||
|
@ -40,7 +40,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
|
|||
|
||||
context 'when job token scope is disabled' do
|
||||
before do
|
||||
project.update!(ci_job_token_scope_enabled: false)
|
||||
project.update!(ci_outbound_job_token_scope_enabled: false)
|
||||
end
|
||||
|
||||
it 'resolves projects' do
|
||||
|
|
|
@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiJobTokenScopeType'] do
|
|||
end
|
||||
|
||||
describe 'query' do
|
||||
let(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
let(:query) do
|
||||
|
|
|
@ -61,6 +61,8 @@ issues:
|
|||
- requirement
|
||||
- incident_management_issuable_escalation_status
|
||||
- incident_management_timeline_events
|
||||
- incident_management_timeline_event_tags
|
||||
- incident_management_timeline_event_links
|
||||
- pending_escalations
|
||||
- customer_relations_contacts
|
||||
- issue_customer_relations_contacts
|
||||
|
@ -622,6 +624,7 @@ project:
|
|||
- incident_management_oncall_rotations
|
||||
- incident_management_escalation_policies
|
||||
- incident_management_issuable_escalation_statuses
|
||||
- incident_management_timeline_event_tags
|
||||
- debian_distributions
|
||||
- merge_request_metrics
|
||||
- security_orchestration_policy_configuration
|
||||
|
|
|
@ -8,6 +8,12 @@ RSpec.describe Gitlab::Json do
|
|||
end
|
||||
|
||||
describe ".parse" do
|
||||
it "is aliased" do
|
||||
[:parse!, :load, :decode].each do |method|
|
||||
expect(described_class.method(method)).to eq(described_class.method(:parse))
|
||||
end
|
||||
end
|
||||
|
||||
context "legacy_mode is disabled by default" do
|
||||
it "parses an object" do
|
||||
expect(subject.parse('{ "foo": "bar" }')).to eq({ "foo" => "bar" })
|
||||
|
@ -178,6 +184,10 @@ RSpec.describe Gitlab::Json do
|
|||
{ test: true, "foo.bar" => "baz", is_json: 1, some: [1, 2, 3] }
|
||||
end
|
||||
|
||||
it "is aliased" do
|
||||
expect(described_class.method(:encode)).to eq(described_class.method(:generate))
|
||||
end
|
||||
|
||||
it "generates JSON" do
|
||||
expected_string = <<~STR.chomp
|
||||
{"test":true,"foo.bar":"baz","is_json":1,"some":[1,2,3]}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::JobToken::Scope do
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
|
||||
let(:scope) { described_class.new(project) }
|
||||
|
||||
|
@ -53,7 +53,7 @@ RSpec.describe Ci::JobToken::Scope do
|
|||
|
||||
context 'when project scope setting is disabled' do
|
||||
before do
|
||||
project.ci_job_token_scope_enabled = false
|
||||
project.ci_outbound_job_token_scope_enabled = false
|
||||
end
|
||||
|
||||
it 'considers any project to be part of the scope' do
|
||||
|
|
|
@ -13,6 +13,12 @@ RSpec.describe IncidentManagement::TimelineEvent do
|
|||
it { is_expected.to belong_to(:incident) }
|
||||
it { is_expected.to belong_to(:updated_by_user) }
|
||||
it { is_expected.to belong_to(:promoted_from_note) }
|
||||
it { is_expected.to have_many(:timeline_event_tag_links).class_name('IncidentManagement::TimelineEventTagLink') }
|
||||
|
||||
it do
|
||||
is_expected.to have_many(:timeline_event_tags)
|
||||
.class_name('IncidentManagement::TimelineEventTag').through(:timeline_event_tag_links)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe IncidentManagement::TimelineEventTagLink do
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:timeline_event) }
|
||||
it { is_expected.to belong_to(:timeline_event_tag) }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe IncidentManagement::TimelineEventTag do
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to have_many(:timeline_event_tag_links).class_name('IncidentManagement::TimelineEventTagLink') }
|
||||
|
||||
it {
|
||||
is_expected.to have_many(:timeline_events)
|
||||
.class_name('IncidentManagement::TimelineEvent').through(:timeline_event_tag_links)
|
||||
}
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
subject { build(:incident_management_timeline_event_tag) }
|
||||
|
||||
it { is_expected.to validate_presence_of(:name) }
|
||||
it { is_expected.to validate_length_of(:name).is_at_most(255) }
|
||||
it { is_expected.to validate_uniqueness_of(:name).scoped_to([:project_id]) }
|
||||
|
||||
it { is_expected.to allow_value('Test tag 1').for(:name) }
|
||||
it { is_expected.not_to allow_value('Test tag, 1').for(:name) }
|
||||
it { is_expected.not_to allow_value('').for(:name) }
|
||||
it { is_expected.not_to allow_value('s' * 256).for(:name) }
|
||||
end
|
||||
end
|
|
@ -149,6 +149,7 @@ RSpec.describe Project, factory_default: :keep do
|
|||
it { is_expected.to have_one(:build_artifacts_size_refresh).class_name('Projects::BuildArtifactsSizeRefresh') }
|
||||
it { is_expected.to have_many(:project_callouts).class_name('Users::ProjectCallout').with_foreign_key(:project_id) }
|
||||
it { is_expected.to have_many(:pipeline_metadata).class_name('Ci::PipelineMetadata') }
|
||||
it { is_expected.to have_many(:incident_management_timeline_event_tags).class_name('IncidentManagement::TimelineEventTag') }
|
||||
|
||||
# GitLab Pages
|
||||
it { is_expected.to have_many(:pages_domains) }
|
||||
|
@ -845,6 +846,8 @@ RSpec.describe Project, factory_default: :keep do
|
|||
end
|
||||
|
||||
describe 'delegation' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
[:add_guest, :add_reporter, :add_developer, :add_maintainer, :add_member, :add_members].each do |method|
|
||||
it { is_expected.to delegate_method(method).to(:team) }
|
||||
end
|
||||
|
@ -887,8 +890,24 @@ RSpec.describe Project, factory_default: :keep do
|
|||
end
|
||||
|
||||
include_examples 'ci_cd_settings delegation' do
|
||||
# Skip attributes defined in EE code
|
||||
let(:attributes_with_prefix) do
|
||||
{
|
||||
'group_runners_enabled' => '',
|
||||
'default_git_depth' => 'ci_',
|
||||
'forward_deployment_enabled' => 'ci_',
|
||||
'keep_latest_artifact' => '',
|
||||
'restrict_user_defined_variables' => '',
|
||||
'runner_token_expiration_interval' => '',
|
||||
'separated_caches' => 'ci_',
|
||||
'opt_in_jwt' => 'ci_',
|
||||
'allow_fork_pipelines_to_run_in_parent_project' => 'ci_',
|
||||
'inbound_job_token_scope_enabled' => 'ci_',
|
||||
'job_token_scope_enabled' => 'ci_outbound_'
|
||||
}
|
||||
end
|
||||
|
||||
let(:exclude_attributes) do
|
||||
# Skip attributes defined in EE code
|
||||
%w(
|
||||
merge_pipelines_enabled
|
||||
merge_trains_enabled
|
||||
|
@ -909,8 +928,8 @@ RSpec.describe Project, factory_default: :keep do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#ci_job_token_scope_enabled?' do
|
||||
it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
|
||||
describe '#ci_outbound_job_token_scope_enabled?' do
|
||||
it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_outbound_' do
|
||||
let(:delegated_method) { :job_token_scope_enabled? }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2437,7 +2437,7 @@ RSpec.describe ProjectPolicy do
|
|||
before do
|
||||
current_user.set_ci_job_token_scope!(job)
|
||||
current_user.external = external_user
|
||||
scope_project.update!(ci_job_token_scope_enabled: token_scope_enabled)
|
||||
scope_project.update!(ci_outbound_job_token_scope_enabled: token_scope_enabled)
|
||||
end
|
||||
|
||||
it "enforces the expected permissions" do
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'JobArtifactsDestroy' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:job) { create(:ci_build) }
|
||||
|
||||
let(:mutation) do
|
||||
variables = {
|
||||
id: job.to_global_id.to_s
|
||||
}
|
||||
graphql_mutation(:job_artifacts_destroy, variables, <<~FIELDS)
|
||||
job {
|
||||
name
|
||||
}
|
||||
destroyedArtifactsCount
|
||||
errors
|
||||
FIELDS
|
||||
end
|
||||
|
||||
before do
|
||||
create(:ci_job_artifact, :archive, job: job)
|
||||
create(:ci_job_artifact, :junit, job: job)
|
||||
end
|
||||
|
||||
context 'when the user is not allowed to destroy the job artifacts' do
|
||||
it 'returns an error' do
|
||||
post_graphql_mutation(mutation, current_user: user)
|
||||
|
||||
expect(graphql_errors).not_to be_empty
|
||||
expect(job.reload.job_artifacts.count).to be(2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user is allowed to destroy the job artifacts' do
|
||||
before do
|
||||
job.project.add_maintainer(user)
|
||||
end
|
||||
|
||||
it 'destroys the job artifacts and returns the expected data' do
|
||||
expected_data = {
|
||||
'jobArtifactsDestroy' => {
|
||||
'errors' => [],
|
||||
'destroyedArtifactsCount' => 2,
|
||||
'job' => {
|
||||
'name' => job.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post_graphql_mutation(mutation, current_user: user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(graphql_data).to eq(expected_data)
|
||||
expect(job.reload.job_artifacts.count).to be(0)
|
||||
end
|
||||
|
||||
context 'when the the project this job belongs to is undergoing stats refresh' do
|
||||
it 'destroys no artifacts and returns the correct error' do
|
||||
allow_next_found_instance_of(Project) do |project|
|
||||
allow(project).to receive(:refreshing_build_artifacts_size?).and_return(true)
|
||||
end
|
||||
|
||||
expected_data = {
|
||||
'jobArtifactsDestroy' => {
|
||||
'errors' => ['Action temporarily disabled. The project this job belongs to is undergoing stats refresh.'],
|
||||
'destroyedArtifactsCount' => 0,
|
||||
'job' => {
|
||||
'name' => job.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post_graphql_mutation(mutation, current_user: user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(graphql_data).to eq(expected_data)
|
||||
expect(job.reload.job_artifacts.count).to be(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
RSpec.describe 'CiJobTokenScopeAddProject' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:target_project) { create(:project) }
|
||||
|
||||
let(:variables) do
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
RSpec.describe 'CiJobTokenScopeRemoveProject' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:target_project) { create(:project) }
|
||||
|
||||
let_it_be(:link) do
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate' do
|
|||
let_it_be(:project) do
|
||||
create(:project,
|
||||
keep_latest_artifact: true,
|
||||
ci_job_token_scope_enabled: true,
|
||||
ci_outbound_job_token_scope_enabled: true,
|
||||
ci_inbound_job_token_scope_enabled: true
|
||||
).tap(&:save!)
|
||||
end
|
||||
|
@ -66,7 +66,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate' do
|
|||
project.reload
|
||||
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(project.ci_job_token_scope_enabled).to eq(false)
|
||||
expect(project.ci_outbound_job_token_scope_enabled).to eq(false)
|
||||
end
|
||||
|
||||
it 'does not update job_token_scope_enabled if not specified' do
|
||||
|
@ -77,7 +77,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate' do
|
|||
project.reload
|
||||
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(project.ci_job_token_scope_enabled).to eq(true)
|
||||
expect(project.ci_outbound_job_token_scope_enabled).to eq(true)
|
||||
end
|
||||
|
||||
describe 'inbound_job_token_scope_enabled' do
|
||||
|
|
|
@ -14,6 +14,7 @@ RSpec.describe Ci::JobArtifacts::DeleteService do
|
|||
result = service.execute
|
||||
|
||||
expect(result).to be_success
|
||||
expect(result[:destroyed_artifacts_count]).to be(2)
|
||||
end
|
||||
|
||||
it 'deletes erasable artifacts' do
|
||||
|
@ -24,7 +25,7 @@ RSpec.describe Ci::JobArtifacts::DeleteService do
|
|||
expect { service.execute }.not_to change { build.has_trace? }.from(true)
|
||||
end
|
||||
|
||||
context 'when project is undergoing statistics refresh' do
|
||||
context 'when project is undergoing stats refresh' do
|
||||
before do
|
||||
allow(build.project).to receive(:refreshing_build_artifacts_size?).and_return(true)
|
||||
end
|
||||
|
@ -36,6 +37,30 @@ RSpec.describe Ci::JobArtifacts::DeleteService do
|
|||
|
||||
service.execute
|
||||
end
|
||||
|
||||
it 'returns an error response with the correct message and reason' do
|
||||
result = service.execute
|
||||
|
||||
expect(result).to be_error
|
||||
expect(result[:message]).to be('Action temporarily disabled. ' \
|
||||
'The project this job belongs to is undergoing stats refresh.')
|
||||
expect(result[:reason]).to be(:project_stats_refresh)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an error response is received from DestroyBatchService' do
|
||||
before do
|
||||
allow_next_instance_of(Ci::JobArtifacts::DestroyBatchService) do |service|
|
||||
allow(service).to receive(:execute).and_return({ status: :error, message: 'something went wrong' })
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns an error response with the correct message' do
|
||||
result = service.execute
|
||||
|
||||
expect(result).to be_error
|
||||
expect(result[:message]).to be('something went wrong')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
RSpec.describe Ci::JobTokenScope::AddProjectService do
|
||||
let(:service) { described_class.new(project, current_user) }
|
||||
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:target_project) { create(:project) }
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
RSpec.describe Ci::JobTokenScope::RemoveProjectService do
|
||||
let(:service) { described_class.new(project, current_user) }
|
||||
|
||||
let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
|
||||
let_it_be(:target_project) { create(:project) }
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
|
|
|
@ -5,12 +5,14 @@ RSpec.shared_examples 'ci_cd_settings delegation' do
|
|||
|
||||
context 'when ci_cd_settings is destroyed but project is not' do
|
||||
it 'allows methods delegated to ci_cd_settings to be nil', :aggregate_failures do
|
||||
project = create(:project)
|
||||
attributes = project.ci_cd_settings.attributes.keys - %w(id project_id) - exclude_attributes
|
||||
|
||||
expect(attributes).to match_array(attributes_with_prefix.keys)
|
||||
|
||||
project.ci_cd_settings.destroy!
|
||||
project.reload
|
||||
attributes.each do |attr|
|
||||
method = project.respond_to?("ci_#{attr}") ? "ci_#{attr}" : attr
|
||||
attributes_with_prefix.each do |attr, prefix|
|
||||
method = "#{prefix}#{attr}"
|
||||
expect(project.send(method)).to be_nil, "#{attr} was not nil"
|
||||
end
|
||||
end
|
||||
|
@ -20,8 +22,6 @@ end
|
|||
RSpec.shared_examples 'a ci_cd_settings predicate method' do |prefix: ''|
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
context 'when ci_cd_settings is nil' do
|
||||
before do
|
||||
allow(project).to receive(:ci_cd_settings).and_return(nil)
|
||||
|
|
Loading…
Reference in New Issue