Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b21334799a
commit
68ce709bef
|
|
@ -2655,7 +2655,6 @@ RSpec/FeatureCategory:
|
|||
- 'spec/lib/bitbucket/representation/issue_spec.rb'
|
||||
- 'spec/lib/bitbucket/representation/pull_request_comment_spec.rb'
|
||||
- 'spec/lib/bitbucket/representation/pull_request_spec.rb'
|
||||
- 'spec/lib/bitbucket/representation/repo_spec.rb'
|
||||
- 'spec/lib/bitbucket/representation/user_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/client_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/collection_spec.rb'
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -495,7 +495,7 @@ group :test do
|
|||
# Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527
|
||||
gem 'derailed_benchmarks', require: false # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.3.0', require: false # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.4.0', require: false # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
end
|
||||
|
||||
gem 'octokit', '~> 6.0' # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
{"name":"aes_key_wrap","version":"1.1.0","platform":"ruby","checksum":"b935f4756b37375895db45669e79dfcdc0f7901e12d4e08974d5540c8e0776a5"},
|
||||
{"name":"akismet","version":"3.0.0","platform":"ruby","checksum":"74991b8e3d3257eeea996b47069abb8da2006c84a144255123e8dffd1c86b230"},
|
||||
{"name":"aliyun-sdk","version":"0.8.0","platform":"ruby","checksum":"65915d3f9b528082253d1f9ad0e4d13d6b552933fe49251c68c6915cd4d75b9d"},
|
||||
{"name":"amatch","version":"0.4.1","platform":"ruby","checksum":"d3ff15226a2e627c72802e94579db829e5e10c96cf89d329494caec5889145f7"},
|
||||
{"name":"android_key_attestation","version":"0.3.0","platform":"ruby","checksum":"467eb01a99d2bb48ef9cf24cc13712669d7056cba5a52d009554ff037560570b"},
|
||||
{"name":"apollo_upload_server","version":"2.1.0","platform":"ruby","checksum":"e5f3c9dda0c2ca775d007072742b98d517dfd91a667111fedbcdc94dfabd904e"},
|
||||
{"name":"app_store_connect","version":"0.29.0","platform":"ruby","checksum":"01d7a923825a4221892099acb5a72f86f6ee7d8aa95815d3c459ba6816ea430f"},
|
||||
|
|
@ -219,7 +220,7 @@
|
|||
{"name":"gitlab-styles","version":"10.1.0","platform":"ruby","checksum":"f42745f5397d042fe24cf2d0eb56c995b37f9f43d8fb79b834d197a1cafdc84a"},
|
||||
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},
|
||||
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
|
||||
{"name":"gitlab_quality-test_tooling","version":"1.3.0","platform":"ruby","checksum":"0c932e0a98839c219ef21e2da336edb59ff48cc43cd06e22d780738715a4652e"},
|
||||
{"name":"gitlab_quality-test_tooling","version":"1.4.0","platform":"ruby","checksum":"0fdfb574138ac9228ccce5fc40687aa81dcb8158900ca26982e15c14797959cf"},
|
||||
{"name":"globalid","version":"1.1.0","platform":"ruby","checksum":"b337e1746f0c8cb0a6c918234b03a1ddeb4966206ce288fbb57779f59b2d154f"},
|
||||
{"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"},
|
||||
{"name":"google-apis-androidpublisher_v3","version":"0.34.0","platform":"ruby","checksum":"d7e1d7dd92f79c498fe2082222a1740d788e022e660c135564b3fd299cab5425"},
|
||||
|
|
@ -366,6 +367,7 @@
|
|||
{"name":"mixlib-log","version":"3.0.9","platform":"ruby","checksum":"fd6ca2c8075f8085065dffcee0805c5b3f88d643d5c954acdc3282f463a9ad58"},
|
||||
{"name":"mixlib-shellout","version":"3.2.5","platform":"ruby","checksum":"121a54005e52b6596a945f7bfc95bbcbd7d8ee7685cb3736dd3cef5ff46029bd"},
|
||||
{"name":"mixlib-shellout","version":"3.2.5","platform":"universal-mingw32","checksum":"c40ef5f34a68eec5e0cad13482497f6c3898a30cff1747517f2169d4fa4055e0"},
|
||||
{"name":"mize","version":"0.4.1","platform":"ruby","checksum":"55bcba0cf001cbff5a647a18172c4a885061ceec586395fb08ecbb98d039f627"},
|
||||
{"name":"msgpack","version":"1.5.4","platform":"java","checksum":"05b3bd16a65dddc64c878634b7ecb9cd613569ca3dd6e480d7295626a0a3f562"},
|
||||
{"name":"msgpack","version":"1.5.4","platform":"ruby","checksum":"a53db320fba40f58c07c5b66ed9fd4d73cbe8eba4cb28fe9e3218444341a4e09"},
|
||||
{"name":"multi_json","version":"1.14.1","platform":"ruby","checksum":"d971296c0eacea289d31e4a7ab7ac5eda97262c62bbc8c110de4f5e36425c577"},
|
||||
|
|
@ -457,6 +459,7 @@
|
|||
{"name":"prometheus-client-mmap","version":"0.28.1","platform":"ruby","checksum":"92fb3989a16927fb0cacfcb3ebc6c8ea5e4abf82e4aef22ab62c3c4b8f17e52a"},
|
||||
{"name":"prometheus-client-mmap","version":"0.28.1","platform":"x86_64-darwin","checksum":"66e7cad96ad581174edf4f1f52da141e5a15389ce3283fba7b4e3e5968dd46b7"},
|
||||
{"name":"prometheus-client-mmap","version":"0.28.1","platform":"x86_64-linux","checksum":"4d3e92a249b16e41ef3e55078537bca599659578c0f86e31d195429c6e5e1f3a"},
|
||||
{"name":"protocol","version":"2.0.0","platform":"ruby","checksum":"dcd7c509e53b8cd6284e965a2e2e71d5291ca9e2d50acfa3d7ee0561c0df16b9"},
|
||||
{"name":"pry","version":"0.14.2","platform":"java","checksum":"fd780670977ba04ff7ee32dabd4d02fe4bf02e977afe8809832d5dca1412862e"},
|
||||
{"name":"pry","version":"0.14.2","platform":"ruby","checksum":"c4fe54efedaca1d351280b45b8849af363184696fcac1c72e0415f9bdac4334d"},
|
||||
{"name":"pry-byebug","version":"3.10.1","platform":"ruby","checksum":"c8f975c32255bfdb29e151f5532130be64ff3d0042dc858d0907e849125581f8"},
|
||||
|
|
@ -555,6 +558,7 @@
|
|||
{"name":"ruby-saml","version":"1.15.0","platform":"ruby","checksum":"3a9dda2b448310f4f90d5cf0967d4b668530fa7994d2a4d9cbfdfa62e35f76a3"},
|
||||
{"name":"ruby-statistics","version":"3.0.0","platform":"ruby","checksum":"610301370346931cb701e3a8d3d3e28eb65681162cae6066c0c11abf20efdc81"},
|
||||
{"name":"ruby2_keywords","version":"0.0.5","platform":"ruby","checksum":"ffd13740c573b7301cf7a2e61fc857b2a8e3d3aff32545d6f8300d8bae10e3ef"},
|
||||
{"name":"ruby_parser","version":"3.20.3","platform":"ruby","checksum":"8d2289a695dc81ffddcdd5a56e80c9a109806bc0d0b1239a1c852b0c71251c49"},
|
||||
{"name":"rubyntlm","version":"0.6.3","platform":"ruby","checksum":"5b321456dba3130351f7451f8669f1afa83a0d26fd63cdec285b7b88e667102d"},
|
||||
{"name":"rubypants","version":"0.2.0","platform":"ruby","checksum":"f07e38eac793655a0323fe91946081052341b9e69807026fcf102346589eedee"},
|
||||
{"name":"rubyzip","version":"2.3.2","platform":"ruby","checksum":"3f57e3935dc2255c414484fbf8d673b4909d8a6a57007ed754dde39342d2373f"},
|
||||
|
|
@ -575,6 +579,7 @@
|
|||
{"name":"sentry-ruby","version":"5.8.0","platform":"ruby","checksum":"caeb121433be379fb94e991a45265a287b13a9a9083e7264f539752369d37110"},
|
||||
{"name":"sentry-sidekiq","version":"5.8.0","platform":"ruby","checksum":"90d1123d16a9fc5fd99dbad190b766dd189eaf9e2baddad641f1334e1877c779"},
|
||||
{"name":"set","version":"1.0.2","platform":"ruby","checksum":"02ffa4de1f2621495e05b72326040dd014d7abbcb02fea698bc600a389992c02"},
|
||||
{"name":"sexp_processor","version":"4.17.0","platform":"ruby","checksum":"4daa4874ce1838cd801c65e66ed5d4f140024404a3de7482c36d4ef2604dff6f"},
|
||||
{"name":"shellany","version":"0.0.1","platform":"ruby","checksum":"0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7"},
|
||||
{"name":"shoulda-matchers","version":"5.1.0","platform":"ruby","checksum":"a01d20589989e9653ab4a28c67d9db2b82bcf0a2496cf01d5e1a95a4aaaf5b07"},
|
||||
{"name":"sidekiq","version":"6.5.12","platform":"ruby","checksum":"b4f93b2204c42220d0b526a7b8e0c49b5f9da82c1ce1a05d2baf1e8f744c197f"},
|
||||
|
|
|
|||
15
Gemfile.lock
15
Gemfile.lock
|
|
@ -242,6 +242,9 @@ GEM
|
|||
aliyun-sdk (0.8.0)
|
||||
nokogiri (~> 1.6)
|
||||
rest-client (~> 2.0)
|
||||
amatch (0.4.1)
|
||||
mize
|
||||
tins (~> 1.0)
|
||||
android_key_attestation (0.3.0)
|
||||
apollo_upload_server (2.1.0)
|
||||
actionpack (>= 4.2)
|
||||
|
|
@ -692,8 +695,9 @@ GEM
|
|||
omniauth (>= 1.3, < 3)
|
||||
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
|
||||
rubyntlm (~> 0.5)
|
||||
gitlab_quality-test_tooling (1.3.0)
|
||||
gitlab_quality-test_tooling (1.4.0)
|
||||
activesupport (>= 6.1, < 7.2)
|
||||
amatch (~> 0.4.1)
|
||||
gitlab (~> 4.19)
|
||||
http (~> 5.0)
|
||||
nokogiri (~> 1.10)
|
||||
|
|
@ -1032,6 +1036,8 @@ GEM
|
|||
mixlib-log (3.0.9)
|
||||
mixlib-shellout (3.2.5)
|
||||
chef-utils
|
||||
mize (0.4.1)
|
||||
protocol (~> 2.0)
|
||||
msgpack (1.5.4)
|
||||
multi_json (1.14.1)
|
||||
multi_xml (0.6.0)
|
||||
|
|
@ -1222,6 +1228,8 @@ GEM
|
|||
unparser
|
||||
prometheus-client-mmap (0.28.1)
|
||||
rb_sys (~> 0.9)
|
||||
protocol (2.0.0)
|
||||
ruby_parser (~> 3.0)
|
||||
pry (0.14.2)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
|
|
@ -1436,6 +1444,8 @@ GEM
|
|||
rexml
|
||||
ruby-statistics (3.0.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
ruby_parser (3.20.3)
|
||||
sexp_processor (~> 4.16)
|
||||
rubyntlm (0.6.3)
|
||||
rubypants (0.2.0)
|
||||
rubyzip (2.3.2)
|
||||
|
|
@ -1480,6 +1490,7 @@ GEM
|
|||
sentry-ruby (~> 5.8.0)
|
||||
sidekiq (>= 3.0)
|
||||
set (1.0.2)
|
||||
sexp_processor (4.17.0)
|
||||
shellany (0.0.1)
|
||||
shoulda-matchers (5.1.0)
|
||||
activesupport (>= 5.2.0)
|
||||
|
|
@ -1837,7 +1848,7 @@ DEPENDENCIES
|
|||
gitlab-utils!
|
||||
gitlab_chronic_duration (~> 0.12)
|
||||
gitlab_omniauth-ldap (~> 2.2.0)
|
||||
gitlab_quality-test_tooling (~> 1.3.0)
|
||||
gitlab_quality-test_tooling (~> 1.4.0)
|
||||
gon (~> 6.4.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.34.0)
|
||||
google-apis-cloudbilling_v1 (~> 0.21.0)
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export default {
|
|||
data-testid="issue-sticky-header"
|
||||
>
|
||||
<div
|
||||
class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-gap-2 gl-mx-auto gl-px-5"
|
||||
class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-gap-2 gl-mx-auto"
|
||||
>
|
||||
<gl-badge :variant="statusVariant">
|
||||
<gl-icon :name="statusIcon" />
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ export default {
|
|||
:class="{ 'gl-visibility-hidden': !isStickyHeaderVisible }"
|
||||
>
|
||||
<div
|
||||
class="issue-sticky-header-text gl-display-flex gl-flex-direction-column gl-align-items-center gl-mx-auto gl-px-5 gl-w-full"
|
||||
:class="{ 'gl-max-w-container-xl': !isFluidLayout }"
|
||||
class="issue-sticky-header-text gl-display-flex gl-flex-direction-column gl-align-items-center gl-mx-auto gl-w-full"
|
||||
:class="{ 'container-limited': !isFluidLayout }"
|
||||
>
|
||||
<div class="gl-w-full gl-display-flex gl-align-items-baseline">
|
||||
<status-badge
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import { s__ } from '~/locale';
|
|||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export const CREATE_EXPERIMENT_HELP_PATH = helpPagePath(
|
||||
'user/project/ml/experiment_tracking/index.md',
|
||||
'user/project/ml/experiment_tracking/index',
|
||||
{
|
||||
anchor: 'tracking-new-experiments-and-trials',
|
||||
anchor: 'track-new-experiments-and-candidates',
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { s__ } from '~/locale';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export const METRIC_KEY_PREFIX = 'metric.';
|
||||
export const LIST_KEY_CREATED_AT = 'created_at';
|
||||
|
|
@ -13,9 +12,3 @@ export const BASE_SORT_FIELDS = Object.freeze([
|
|||
label: s__('MlExperimentTracking|Created at'),
|
||||
},
|
||||
]);
|
||||
export const CREATE_CANDIDATE_HELP_PATH = helpPagePath(
|
||||
'user/project/ml/experiment_tracking/index.md',
|
||||
{
|
||||
anchor: 'tracking-new-experiments-and-trials',
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,12 +10,8 @@ import KeysetPagination from '~/vue_shared/components/incubation/pagination.vue'
|
|||
import ModelExperimentsHeader from '~/ml/experiment_tracking/components/model_experiments_header.vue';
|
||||
import DeleteButton from '~/ml/experiment_tracking/components/delete_button.vue';
|
||||
|
||||
import {
|
||||
LIST_KEY_CREATED_AT,
|
||||
BASE_SORT_FIELDS,
|
||||
METRIC_KEY_PREFIX,
|
||||
CREATE_CANDIDATE_HELP_PATH,
|
||||
} from './constants';
|
||||
import { CREATE_EXPERIMENT_HELP_PATH as CREATE_CANDIDATE_HELP_PATH } from '../index/constants';
|
||||
import { LIST_KEY_CREATED_AT, BASE_SORT_FIELDS, METRIC_KEY_PREFIX } from './constants';
|
||||
import * as translations from './translations';
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ export default {
|
|||
:roles="pushAccessLevels.roles"
|
||||
:users="pushAccessLevels.users"
|
||||
:groups="pushAccessLevels.groups"
|
||||
data-qa-selector="allowed_to_push_content"
|
||||
data-testid="allowed-to-push-content"
|
||||
/>
|
||||
|
||||
<!-- Allowed to merge -->
|
||||
|
|
@ -198,7 +198,7 @@ export default {
|
|||
:roles="mergeAccessLevels.roles"
|
||||
:users="mergeAccessLevels.users"
|
||||
:groups="mergeAccessLevels.groups"
|
||||
data-qa-selector="allowed_to_merge_content"
|
||||
data-testid="allowed-to-merge-content"
|
||||
/>
|
||||
|
||||
<!-- Force push -->
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ export default {
|
|||
v-for="(item, index) in accessLevels"
|
||||
:key="index"
|
||||
data-testid="access-level"
|
||||
data-qa-selector="access_level_content"
|
||||
:data-qa-role="item.accessLevelDescription"
|
||||
>
|
||||
<span v-if="commaSeparateList && index > 0" data-testid="comma-separator">,</span>
|
||||
|
|
|
|||
|
|
@ -79,9 +79,7 @@ export default {
|
|||
class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
|
||||
data-testid="header"
|
||||
>
|
||||
<div
|
||||
class="issue-sticky-header-text gl-display-flex gl-align-items-baseline gl-mx-auto gl-px-5"
|
||||
>
|
||||
<div class="issue-sticky-header-text gl-display-flex gl-align-items-baseline gl-mx-auto">
|
||||
<gl-badge
|
||||
class="gl-white-space-nowrap gl-mr-3 gl-align-self-center"
|
||||
:variant="badgeVariant"
|
||||
|
|
|
|||
|
|
@ -901,7 +901,6 @@ table.code {
|
|||
|
||||
@media (max-width: map-get($grid-breakpoints, lg)-1) {
|
||||
.diffs .files {
|
||||
@include fixed-width-container;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,15 +30,6 @@
|
|||
max-width: $max-width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin for fixed width container
|
||||
*/
|
||||
@mixin fixed-width-container {
|
||||
max-width: $limited-layout-width - ($gl-padding * 2);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Base mixin for lists in GitLab
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
width: 100%;
|
||||
|
||||
.container-fluid {
|
||||
padding: 0 $gl-padding;
|
||||
padding: 0 $container-margin;
|
||||
|
||||
@include media-breakpoint-up(xl) {
|
||||
padding: 0 $container-margin-xl;
|
||||
}
|
||||
|
||||
&.container-blank {
|
||||
background: none;
|
||||
|
|
|
|||
|
|
@ -468,8 +468,10 @@ $content-wrapper-padding: 100px;
|
|||
$header-zindex: 1000;
|
||||
$zindex-dropdown-menu: 300;
|
||||
$ide-statusbar-height: 25px;
|
||||
$fixed-layout-width: 1280px;
|
||||
$limited-layout-width: 990px;
|
||||
$limited-layout-width: 1006px;
|
||||
$fixed-layout-width: 1296px;
|
||||
$container-margin: $gl-padding;
|
||||
$container-margin-xl: $gl-padding-24;
|
||||
$container-text-max-width: 540px;
|
||||
$border-radius-default: 4px;
|
||||
$border-radius-small: 2px;
|
||||
|
|
|
|||
|
|
@ -1,34 +1,5 @@
|
|||
@import 'mixins_and_variables_and_functions';
|
||||
|
||||
.limit-container-width {
|
||||
.flash-container,
|
||||
.detail-page-header,
|
||||
.page-content-header,
|
||||
.commit-box,
|
||||
.info-well,
|
||||
.commit-ci-menu,
|
||||
.files-changed-inner,
|
||||
.limited-header-width,
|
||||
.limited-width-notes {
|
||||
@include fixed-width-container;
|
||||
}
|
||||
|
||||
.issuable-details {
|
||||
.detail-page-description,
|
||||
.mr-source-target,
|
||||
.mr-state-widget,
|
||||
.merge-manually {
|
||||
@include fixed-width-container;
|
||||
}
|
||||
}
|
||||
|
||||
.merge-request-details {
|
||||
.emoji-list-container {
|
||||
@include fixed-width-container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-details {
|
||||
section {
|
||||
.issuable-discussion {
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ $tabs-holder-z-index: 250;
|
|||
.merge-request-tabs-container {
|
||||
&.is-merge-request {
|
||||
@include gl-mx-auto;
|
||||
max-width: $fixed-layout-width - ($gl-padding * 2);
|
||||
max-width: $fixed-layout-width - ($container-margin-xl * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1131,7 +1131,7 @@ $tabs-holder-z-index: 250;
|
|||
|
||||
.review-bar-content {
|
||||
max-width: $limited-layout-width;
|
||||
padding: 0 $gl-padding;
|
||||
padding: 0 $container-margin;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,6 +251,14 @@ ul.related-merge-requests > li gl-emoji {
|
|||
}
|
||||
}
|
||||
|
||||
.issue-sticky-header-text {
|
||||
padding: 0 $container-margin;
|
||||
|
||||
@include media-breakpoint-up(xl) {
|
||||
padding: 0 $container-margin-xl;
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-header-slide-enter-active,
|
||||
.issuable-header-slide-leave-active {
|
||||
@include gl-transition-medium;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ module Ci
|
|||
# if the setting is disabled any project is considered to be in scope.
|
||||
return true unless current_project.ci_outbound_job_token_scope_enabled?
|
||||
|
||||
if !accessed_project.private? &&
|
||||
Feature.enabled?(:restrict_ci_job_token_for_public_and_internal_projects, accessed_project)
|
||||
return true
|
||||
end
|
||||
|
||||
outbound_allowlist.includes?(accessed_project)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -599,7 +599,7 @@ class Integration < ApplicationRecord
|
|||
return if ::Gitlab::SilentMode.enabled?
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
Integrations::ExecuteWorker.perform_async(id, data)
|
||||
Integrations::ExecuteWorker.perform_async(id, data.deep_stringify_keys)
|
||||
end
|
||||
|
||||
# override if needed
|
||||
|
|
|
|||
|
|
@ -1234,17 +1234,14 @@ class MergeRequest < ApplicationRecord
|
|||
}
|
||||
end
|
||||
|
||||
def mergeable?(
|
||||
skip_ci_check: false, skip_discussions_check: false, skip_approved_check: false, check_mergeability_retry_lease: false,
|
||||
skip_draft_check: false, skip_rebase_check: false, skip_blocked_check: false)
|
||||
|
||||
return false unless mergeable_state?(
|
||||
skip_ci_check: skip_ci_check,
|
||||
skip_discussions_check: skip_discussions_check,
|
||||
skip_draft_check: skip_draft_check,
|
||||
skip_approved_check: skip_approved_check,
|
||||
skip_blocked_check: skip_blocked_check
|
||||
)
|
||||
# mergeable_state_check_params allows a hash of merge checks to skip or not
|
||||
# skip_ci_check
|
||||
# skip_discussions_check
|
||||
# skip_draft_check
|
||||
# skip_approved_check
|
||||
# skip_blocked_check
|
||||
def mergeable?(check_mergeability_retry_lease: false, skip_rebase_check: false, **mergeable_state_check_params)
|
||||
return false unless mergeable_state?(**mergeable_state_check_params)
|
||||
|
||||
check_mergeability(sync_retry_lease: check_mergeability_retry_lease)
|
||||
mergeable_git_state?(skip_rebase_check: skip_rebase_check)
|
||||
|
|
@ -1274,18 +1271,16 @@ class MergeRequest < ApplicationRecord
|
|||
mergeable_state_checks + mergeable_git_state_checks
|
||||
end
|
||||
|
||||
def mergeable_state?(
|
||||
skip_ci_check: false, skip_discussions_check: false, skip_approved_check: false,
|
||||
skip_draft_check: false, skip_blocked_check: false)
|
||||
# mergeable_state_check_params allows a hash of merge checks to skip or not
|
||||
# skip_ci_check
|
||||
# skip_discussions_check
|
||||
# skip_draft_check
|
||||
# skip_approved_check
|
||||
# skip_blocked_check
|
||||
def mergeable_state?(**mergeable_state_check_params)
|
||||
additional_checks = execute_merge_checks(
|
||||
self.class.mergeable_state_checks,
|
||||
params: {
|
||||
skip_ci_check: skip_ci_check,
|
||||
skip_discussions_check: skip_discussions_check,
|
||||
skip_approved_check: skip_approved_check,
|
||||
skip_draft_check: skip_draft_check,
|
||||
skip_blocked_check: skip_blocked_check
|
||||
}
|
||||
params: mergeable_state_check_params
|
||||
)
|
||||
additional_checks.success?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ class PagesDomain < ApplicationRecord
|
|||
|
||||
MAX_CERTIFICATE_KEY_LENGTH = 8192
|
||||
|
||||
X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19
|
||||
|
||||
enum certificate_source: { user_provided: 0, gitlab_provided: 1 }, _prefix: :certificate
|
||||
enum scope: { instance: 0, group: 1, project: 2 }, _prefix: :scope, _default: :project
|
||||
enum usage: { pages: 0, serverless: 1 }, _prefix: :usage, _default: :pages
|
||||
|
|
@ -122,15 +124,23 @@ class PagesDomain < ApplicationRecord
|
|||
x509.check_private_key(pkey)
|
||||
end
|
||||
|
||||
def has_intermediates?
|
||||
def has_valid_intermediates?
|
||||
return false unless x509
|
||||
|
||||
# self-signed certificates doesn't have the certificate chain
|
||||
# self-signed certificates don't have the certificate chain
|
||||
return true if x509.verify(x509.public_key)
|
||||
|
||||
store = OpenSSL::X509::Store.new
|
||||
store.set_default_paths
|
||||
|
||||
store.verify_callback = ->(is_valid, store_ctx) {
|
||||
# allow self signed certs, see https://gitlab.com/gitlab-org/gitlab/-/issues/356447
|
||||
return true if store_ctx.error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
|
||||
|
||||
self.errors.add(:certificate, store_ctx.error_string) unless is_valid
|
||||
is_valid
|
||||
}
|
||||
|
||||
store.verify(x509, untrusted_ca_certs_bundle)
|
||||
rescue OpenSSL::X509::StoreError
|
||||
false
|
||||
|
|
@ -260,9 +270,7 @@ class PagesDomain < ApplicationRecord
|
|||
end
|
||||
|
||||
def validate_intermediates
|
||||
unless has_intermediates?
|
||||
self.errors.add(:certificate, 'misses intermediates')
|
||||
end
|
||||
self.errors.add(:certificate, 'misses intermediates') unless has_valid_intermediates?
|
||||
end
|
||||
|
||||
def validate_pages_domain
|
||||
|
|
|
|||
|
|
@ -1241,6 +1241,10 @@ class Repository
|
|||
def get_patch_id(old_revision, new_revision)
|
||||
raw_repository.get_patch_id(old_revision, new_revision)
|
||||
rescue Gitlab::Git::CommandError, Gitlab::Git::Repository::NoRepository => e
|
||||
# This is expected when there are no differences between the old_revision and the new_revision.
|
||||
# It's not ideal, but is simpler to handle this here than making breaking changes to gitaly.
|
||||
return if e.message.match?(/no difference between old and new revision./)
|
||||
|
||||
Gitlab::ErrorTracking.track_exception(
|
||||
e,
|
||||
project_id: project.id,
|
||||
|
|
|
|||
|
|
@ -133,6 +133,29 @@ class ProjectPolicy < BasePolicy
|
|||
!@user&.from_ci_job_token? || @user.ci_job_token_scope.accessible?(project)
|
||||
end
|
||||
|
||||
desc "If the user is via CI job token and project container registry visibility allows access"
|
||||
condition(:job_token_container_registry) { job_token_access_allowed_to?(:container_registry) }
|
||||
|
||||
desc "If the user is via CI job token and project package registry visibility allows access"
|
||||
condition(:job_token_package_registry) { job_token_access_allowed_to?(:package_registry) }
|
||||
|
||||
desc "If the user is via CI job token and project ci/cd visibility allows access"
|
||||
condition(:job_token_builds) { job_token_access_allowed_to?(:builds) }
|
||||
|
||||
desc "If the user is via CI job token and project releases visibility allows access"
|
||||
condition(:job_token_releases) { job_token_access_allowed_to?(:releases) }
|
||||
|
||||
desc "If the user is via CI job token and project environment visibility allows access"
|
||||
condition(:job_token_environments) { job_token_access_allowed_to?(:environments) }
|
||||
|
||||
desc "If the project is either public or internal"
|
||||
condition(:public_or_internal) do
|
||||
project.public? || project.internal?
|
||||
end
|
||||
|
||||
with_scope :subject
|
||||
condition(:restrict_job_token_enabled) { Feature.enabled?(:restrict_ci_job_token_for_public_and_internal_projects, @subject) }
|
||||
|
||||
with_scope :subject
|
||||
condition(:forking_allowed) do
|
||||
@subject.feature_available?(:forking, @user)
|
||||
|
|
@ -680,8 +703,42 @@ class ProjectPolicy < BasePolicy
|
|||
enable :read_project_for_iids
|
||||
end
|
||||
|
||||
# If the project is private
|
||||
rule { ~public_project & ~internal_access & ~project_allowed_for_job_token }.prevent_all
|
||||
|
||||
# If this project is public or internal we want to prevent all aside from a few public policies
|
||||
rule { public_or_internal & ~project_allowed_for_job_token & restrict_job_token_enabled }.policy do
|
||||
prevent :guest_access
|
||||
prevent :public_access
|
||||
prevent :public_user_access
|
||||
prevent :reporter_access
|
||||
prevent :developer_access
|
||||
prevent :maintainer_access
|
||||
prevent :owner_access
|
||||
end
|
||||
|
||||
rule { public_or_internal & job_token_container_registry & restrict_job_token_enabled }.policy do
|
||||
enable :build_read_container_image
|
||||
enable :read_container_image
|
||||
end
|
||||
|
||||
rule { public_or_internal & job_token_package_registry & restrict_job_token_enabled }.policy do
|
||||
enable :read_package
|
||||
enable :read_project
|
||||
end
|
||||
|
||||
rule { public_or_internal & job_token_builds & restrict_job_token_enabled }.policy do
|
||||
enable :read_commit_status # this is additionally needed to download artifacts
|
||||
end
|
||||
|
||||
rule { public_or_internal & job_token_releases & restrict_job_token_enabled }.policy do
|
||||
enable :read_release
|
||||
end
|
||||
|
||||
rule { public_or_internal & job_token_environments & restrict_job_token_enabled }.policy do
|
||||
enable :read_environment
|
||||
end
|
||||
|
||||
rule { can?(:public_access) }.policy do
|
||||
enable :read_package
|
||||
enable :read_project
|
||||
|
|
@ -1008,6 +1065,20 @@ class ProjectPolicy < BasePolicy
|
|||
end
|
||||
end
|
||||
|
||||
def job_token_access_allowed_to?(feature)
|
||||
return false unless @user&.from_ci_job_token?
|
||||
return false unless project.project_feature
|
||||
|
||||
case project.project_feature.access_level(feature)
|
||||
when ProjectFeature::DISABLED
|
||||
false
|
||||
when ProjectFeature::PRIVATE
|
||||
@user.ci_job_token_scope.accessible?(project)
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def resource_access_token_feature_available?
|
||||
true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -61,15 +61,19 @@ module AutoMerge
|
|||
merge_request.can_be_merged_by?(current_user) &&
|
||||
merge_request.open? &&
|
||||
!merge_request.broken? &&
|
||||
(skip_draft_check(merge_request) || !merge_request.draft?) &&
|
||||
(skip_discussions_check(merge_request) || merge_request.mergeable_discussions_state?) &&
|
||||
(skip_blocked_check(merge_request) || !merge_request.merge_blocked_by_other_mrs?) &&
|
||||
overrideable_available_for_checks(merge_request) &&
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def overrideable_available_for_checks(merge_request)
|
||||
!merge_request.draft? &&
|
||||
merge_request.mergeable_discussions_state? &&
|
||||
!merge_request.merge_blocked_by_other_mrs?
|
||||
end
|
||||
|
||||
# Overridden in child classes
|
||||
def notify(merge_request)
|
||||
end
|
||||
|
|
@ -109,20 +113,5 @@ module AutoMerge
|
|||
def track_exception(error, merge_request)
|
||||
Gitlab::ErrorTracking.track_exception(error, merge_request_id: merge_request&.id)
|
||||
end
|
||||
|
||||
# Will skip the draft check or not when checking if strategy is available
|
||||
def skip_draft_check(merge_request)
|
||||
false
|
||||
end
|
||||
|
||||
# Will skip the blocked check or not when checking if strategy is available
|
||||
def skip_blocked_check(merge_request)
|
||||
false
|
||||
end
|
||||
|
||||
# Will skip the discussions check or not when checking if strategy is available
|
||||
def skip_discussions_check(merge_request)
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -110,10 +110,10 @@ class WebHookService
|
|||
break log_recursion_blocked if recursion_blocked?
|
||||
|
||||
params = {
|
||||
recursion_detection_request_uuid: Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid
|
||||
"recursion_detection_request_uuid" => Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid
|
||||
}.compact
|
||||
|
||||
WebHookWorker.perform_async(hook.id, data, hook_name, params)
|
||||
WebHookWorker.perform_async(hook.id, data.deep_stringify_keys, hook_name, params)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ class WebHookService
|
|||
def queue_log_execution_with_retry(log_data, category)
|
||||
retried = false
|
||||
begin
|
||||
::WebHooks::LogExecutionWorker.perform_async(hook.id, log_data, category, uniqueness_token)
|
||||
::WebHooks::LogExecutionWorker.perform_async(hook.id, log_data.deep_stringify_keys, category, uniqueness_token)
|
||||
rescue Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError
|
||||
raise if retried
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: restrict_ci_job_token_for_public_and_internal_projects
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135263
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/417172
|
||||
milestone: '16.6'
|
||||
type: development
|
||||
group: group::pipeline security
|
||||
default_enabled: false
|
||||
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377723
|
|||
milestone: '15.8'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddServiceAccessTokensExpirationApplicationSetting < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.6'
|
||||
|
||||
enable_lock_retries!
|
||||
|
||||
def change
|
||||
add_column :application_settings, :service_access_tokens_expiration_enforced, :boolean, default: true, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddServiceAccessTokensExpirationNamespaceSetting < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.6'
|
||||
|
||||
enable_lock_retries!
|
||||
|
||||
def change
|
||||
add_column :namespace_settings, :service_access_tokens_expiration_enforced, :boolean, default: true, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
2418c94e1e40f2765252f5c69dae7def898ed3c329fa5fc05d3b51ed812bb7c7
|
||||
|
|
@ -0,0 +1 @@
|
|||
b8ecc7e8ead4cddc7dad712c46fdff0d559da1697bd5d16c1130f2c71272b890
|
||||
|
|
@ -11867,6 +11867,7 @@ CREATE TABLE application_settings (
|
|||
encrypted_vertex_ai_access_token_iv bytea,
|
||||
project_jobs_api_rate_limit integer DEFAULT 600 NOT NULL,
|
||||
math_rendering_limits_enabled boolean DEFAULT true NOT NULL,
|
||||
service_access_tokens_expiration_enforced boolean DEFAULT true NOT NULL,
|
||||
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
|
||||
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
|
||||
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
|
||||
|
|
@ -19205,6 +19206,7 @@ CREATE TABLE namespace_settings (
|
|||
experiment_features_enabled boolean DEFAULT false NOT NULL,
|
||||
third_party_ai_features_enabled boolean DEFAULT true NOT NULL,
|
||||
default_branch_protection_defaults jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
service_access_tokens_expiration_enforced boolean DEFAULT true NOT NULL,
|
||||
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
|
||||
CONSTRAINT namespace_settings_unique_project_download_limit_alertlist_size CHECK ((cardinality(unique_project_download_limit_alertlist) <= 100)),
|
||||
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
|
||||
|
|
|
|||
|
|
@ -179,14 +179,16 @@ nodes. In this example, we exclude all import-related jobs from a Sidekiq node.
|
|||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
### Migrating from queue selectors to routing rules
|
||||
## Migrating from queue selectors to routing rules
|
||||
|
||||
We recommend GitLab deployments add more Sidekiq processes listening to all queues, as in the
|
||||
[Reference Architectures](../reference_architectures/index.md). For very large-scale deployments, we recommend
|
||||
[routing rules](#routing-rules) instead of [queue selectors](#queue-selectors-deprecated). We use routing rules on GitLab.com as
|
||||
it helps to lower the load on Redis.
|
||||
|
||||
To migrate from queue selectors to routing rules:
|
||||
### Single node setup
|
||||
|
||||
To migrate from queue selectors to routing rules in a [single node setup](../reference_architectures/index.md#standalone-non-ha):
|
||||
|
||||
1. Open `/etc/gitlab/gitlab.rb`.
|
||||
1. Set `sidekiq['queue_selector']` to `false`.
|
||||
|
|
@ -213,9 +215,11 @@ NOTE:
|
|||
It is important to run the Rake task immediately after reconfiguring GitLab.
|
||||
After reconfiguring GitLab, existing jobs are not processed until the Rake task starts to migrate the jobs.
|
||||
|
||||
#### Migration example
|
||||
|
||||
The following example better illustrates the migration process above:
|
||||
|
||||
1. Check the following content of `/etc/gitlab/gitlab.rb`:
|
||||
1. In `/etc/gitlab/gitlab.rb`, check the `urgency` queries in the `sidekiq['queue_groups']`. For example:
|
||||
|
||||
```ruby
|
||||
sidekiq['routing_rules'] = []
|
||||
|
|
@ -228,7 +232,7 @@ The following example better illustrates the migration process above:
|
|||
]
|
||||
```
|
||||
|
||||
1. Update `/etc/gitlab/gitlab.rb` to use routing rules:
|
||||
1. Use these same `urgency` queries to update `/etc/gitlab/gitlab.rb` to use routing rules:
|
||||
|
||||
```ruby
|
||||
sidekiq['min_concurrency'] = 20
|
||||
|
|
@ -270,6 +274,31 @@ in a queue group entry is 1, while `min_concurrency` is set to `0`, and `max_con
|
|||
concurrency is set to `2` instead. A concurrency of `2` might be too low in most cases, except for very highly-CPU
|
||||
bound tasks.
|
||||
|
||||
### Multiple node setup
|
||||
|
||||
For a multiple node setup:
|
||||
|
||||
- Reconfigure all GitLab Rails and Sidekiq nodes with the same `sidekiq['routing_rules']` setting.
|
||||
- Alternate between GitLab Rails and Sidekiq nodes as you update and reconfigure the nodes. This ensures the newly configured Sidekiq is ready to consume jobs from the new set of
|
||||
queues during the migration. Otherwise, the new jobs hang until the end of the migration.
|
||||
|
||||
Consider the following example of three GitLab Rails nodes and two Sidekiq nodes. To migrate from queue selectors to routing rules:
|
||||
|
||||
1. In Sidekiq 1, follow all steps but one in [single node setup](#single-node-setup).
|
||||
**Do not** run the Rake task to [migrate existing jobs](sidekiq_job_migration.md).
|
||||
1. Configure the external load balancer to remove Rails 1 from accepting traffic. This step ensures Rails 1 is not serving any request while the Rails process is restarting. For more information, see [issue 428794](https://gitlab.com/gitlab-org/gitlab/-/issues/428794#note_1619505870).
|
||||
1. In Rails 1, update `/etc/gitlab/gitlab.rb` to use the same `sidekiq['routing_rules']` setting as Sidekiq 1.
|
||||
Only `sidekiq['routing_rules']` is required in Rails nodes.
|
||||
1. Configure the external load balancer to register Rails 1 back.
|
||||
1. Repeat steps 1 to 4 for Sidekiq 2 and Rails 2.
|
||||
1. Repeat steps 2 to 4 for Rails 3.
|
||||
1. If there are more Sidekiq nodes than Rails nodes, follow step 1 on the remaining Sidekiq nodes.
|
||||
1. Run the Rake task to [migrate existing jobs](sidekiq_job_migration.md):
|
||||
|
||||
```shell
|
||||
sudo gitlab-rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule gitlab:sidekiq:migrate_jobs:queued
|
||||
```
|
||||
|
||||
<!--- end_remove -->
|
||||
|
||||
## Worker matching query
|
||||
|
|
|
|||
|
|
@ -506,6 +506,22 @@ This field returns a [connection](#connections). It accepts the
|
|||
four standard [pagination arguments](#connection-pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, `last: Int`.
|
||||
|
||||
### `Query.memberRole`
|
||||
|
||||
Finds a single custom role.
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.6.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Returns [`MemberRole`](#memberrole).
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="querymemberroleid"></a>`id` | [`MemberRoleID`](#memberroleid) | Global ID of the member role to look up. |
|
||||
|
||||
### `Query.memberRolePermissions`
|
||||
|
||||
List of all customizable permissions.
|
||||
|
|
@ -18106,7 +18122,6 @@ GPG signature for a signed commit.
|
|||
| <a id="groupid"></a>`id` | [`ID!`](#id) | ID of the namespace. |
|
||||
| <a id="groupistemporarystorageincreaseenabled"></a>`isTemporaryStorageIncreaseEnabled` | [`Boolean!`](#boolean) | Status of the temporary storage increase. |
|
||||
| <a id="grouplfsenabled"></a>`lfsEnabled` | [`Boolean`](#boolean) | Indicates if Large File Storage (LFS) is enabled for namespace. |
|
||||
| <a id="groupmemberroles"></a>`memberRoles` **{warning-solid}** | [`MemberRoleConnection`](#memberroleconnection) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Member roles available for the group. |
|
||||
| <a id="groupmentionsdisabled"></a>`mentionsDisabled` | [`Boolean`](#boolean) | Indicates if a group is disabled from getting mentioned. |
|
||||
| <a id="groupname"></a>`name` | [`String!`](#string) | Name of the namespace. |
|
||||
| <a id="grouppackagesettings"></a>`packageSettings` | [`PackageSettings`](#packagesettings) | Package settings for the namespace. |
|
||||
|
|
@ -18724,6 +18739,26 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| <a id="grouplabelsonlygrouplabels"></a>`onlyGroupLabels` | [`Boolean`](#boolean) | Include only group level labels. |
|
||||
| <a id="grouplabelssearchterm"></a>`searchTerm` | [`String`](#string) | Search term to find labels with. |
|
||||
|
||||
##### `Group.memberRoles`
|
||||
|
||||
Member roles available for the group.
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.5.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Returns [`MemberRoleConnection`](#memberroleconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#connection-pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, `last: Int`.
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="groupmemberrolesid"></a>`id` | [`MemberRoleID`](#memberroleid) | Global ID of the member role to look up. |
|
||||
|
||||
##### `Group.mergeRequestViolations`
|
||||
|
||||
Compliance violations reported on merge requests merged within the group.
|
||||
|
|
@ -22768,7 +22803,6 @@ Represents vulnerability finding of a security report on the pipeline.
|
|||
| <a id="projectlanguages"></a>`languages` | [`[RepositoryLanguage!]`](#repositorylanguage) | Programming languages used in the project. |
|
||||
| <a id="projectlastactivityat"></a>`lastActivityAt` | [`Time`](#time) | Timestamp of the project last activity. |
|
||||
| <a id="projectlfsenabled"></a>`lfsEnabled` | [`Boolean`](#boolean) | Indicates if the project has Large File Storage (LFS) enabled. |
|
||||
| <a id="projectmemberroles"></a>`memberRoles` **{warning-solid}** | [`MemberRoleConnection`](#memberroleconnection) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Member roles available for the group. |
|
||||
| <a id="projectmergecommittemplate"></a>`mergeCommitTemplate` | [`String`](#string) | Template used to create merge commit message in merge requests. |
|
||||
| <a id="projectmergerequestsdisablecommittersapproval"></a>`mergeRequestsDisableCommittersApproval` | [`Boolean!`](#boolean) | Indicates that committers of the given merge request cannot approve. |
|
||||
| <a id="projectmergerequestsenabled"></a>`mergeRequestsEnabled` | [`Boolean`](#boolean) | Indicates if Merge Requests are enabled for the current user. |
|
||||
|
|
@ -23645,6 +23679,26 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| <a id="projectlabelsincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include labels from ancestor groups. |
|
||||
| <a id="projectlabelssearchterm"></a>`searchTerm` | [`String`](#string) | Search term to find labels with. |
|
||||
|
||||
##### `Project.memberRoles`
|
||||
|
||||
Member roles available for the group.
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.5.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Returns [`MemberRoleConnection`](#memberroleconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#connection-pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, `last: Int`.
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="projectmemberrolesid"></a>`id` | [`MemberRoleID`](#memberroleid) | Global ID of the member role to look up. |
|
||||
|
||||
##### `Project.mergeRequest`
|
||||
|
||||
A single merge request of the project.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Example response:
|
|||
```json
|
||||
[
|
||||
{
|
||||
"extern_uid": "4",
|
||||
"extern_uid": "yrnZW46BrtBFqM7xDzE7dddd",
|
||||
"user_id": 48
|
||||
}
|
||||
]
|
||||
|
|
@ -67,14 +67,14 @@ Supported attributes:
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/saml/sydney_jones" --header "PRIVATE-TOKEN: <PRIVATE TOKEN>"
|
||||
curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/saml/yrnZW46BrtBFqM7xDzE7dddd" --header "PRIVATE-TOKEN: <PRIVATE TOKEN>"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"extern_uid": "4",
|
||||
"extern_uid": "yrnZW46BrtBFqM7xDzE7dddd",
|
||||
"user_id": 48
|
||||
}
|
||||
```
|
||||
|
|
@ -101,9 +101,9 @@ Supported attributes:
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --location --request PATCH "https://gitlab.example.com/api/v4/groups/33/saml/sydney_jones" \
|
||||
curl --location --request PATCH "https://gitlab.example.com/api/v4/groups/33/saml/yrnZW46BrtBFqM7xDzE7dddd" \
|
||||
--header "PRIVATE-TOKEN: <PRIVATE TOKEN>" \
|
||||
--form "extern_uid=sydney_jones_new"
|
||||
--form "extern_uid=be20d8dcc028677c931e04f387"
|
||||
```
|
||||
|
||||
## Delete a single SAML identity
|
||||
|
|
@ -124,7 +124,7 @@ Supported attributes:
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/33/saml/sydney_jones"
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/33/saml/be20d8dcc028677c931e04f387"
|
||||
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ Example response:
|
|||
```json
|
||||
[
|
||||
{
|
||||
"extern_uid": "4",
|
||||
"extern_uid": "be20d8dcc028677c931e04f387",
|
||||
"user_id": 48,
|
||||
"active": true
|
||||
}
|
||||
|
|
@ -85,14 +85,14 @@ Supported attributes:
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/scim/sydney_jones" --header "PRIVATE-TOKEN: <PRIVATE TOKEN>"
|
||||
curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/scim/be20d8dcc028677c931e04f387" --header "PRIVATE-TOKEN: <PRIVATE TOKEN>"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"extern_uid": "4",
|
||||
"extern_uid": "be20d8dcc028677c931e04f387",
|
||||
"user_id": 48,
|
||||
"active": true
|
||||
}
|
||||
|
|
@ -122,9 +122,9 @@ Parameters:
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --location --request PATCH "https://gitlab.example.com/api/v4/groups/33/scim/sydney_jones" \
|
||||
curl --location --request PATCH "https://gitlab.example.com/api/v4/groups/33/scim/be20d8dcc028677c931e04f387" \
|
||||
--header "PRIVATE-TOKEN: <PRIVATE TOKEN>" \
|
||||
--form "extern_uid=sydney_jones_new"
|
||||
--form "extern_uid=yrnZW46BrtBFqM7xDzE7dddd"
|
||||
```
|
||||
|
||||
## Delete a single SCIM identity
|
||||
|
|
@ -145,7 +145,7 @@ Supported attributes:
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --request DELETE --header "Content-Type: application/json" --header "Authorization: Bearer <your_access_token>" "https://gitlab.example.com/api/v4/groups/33/scim/sydney_jones"
|
||||
curl --request DELETE --header "Content-Type: application/json" --header "Authorization: Bearer <your_access_token>" "https://gitlab.example.com/api/v4/groups/33/scim/yrnZW46BrtBFqM7xDzE7dddd"
|
||||
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -70,9 +70,7 @@ tries to steal tokens from other jobs.
|
|||
|
||||
You can control what projects a CI/CD job token can access to increase the
|
||||
job token's security. A job token might give extra permissions that aren't necessary
|
||||
to access specific private resources. The job token scope only controls access
|
||||
to private projects. If an accessed project is public or internal, token scoping does
|
||||
not apply.
|
||||
to access specific private resources.
|
||||
|
||||
When enabled, and the job token is being used to access a different project:
|
||||
|
||||
|
|
@ -81,7 +79,7 @@ When enabled, and the job token is being used to access a different project:
|
|||
- The accessed project must have the project attempting to access it [added to the allowlist](#add-a-project-to-the-job-token-scope-allowlist).
|
||||
|
||||
If a job token is leaked, it could potentially be used to access private data
|
||||
to the job token's user. By limiting the job token access scope, private data cannot
|
||||
to the job token's user. By limiting the job token access scope, project data cannot
|
||||
be accessed unless projects are explicitly authorized.
|
||||
|
||||
There is a proposal to add more strategic control of the access permissions,
|
||||
|
|
@ -101,8 +99,7 @@ their `CI_JOB_TOKEN`.
|
|||
|
||||
For example, project `A` can add project `B` to the allowlist. CI/CD jobs
|
||||
in project `B` (the "allowed project") can now use their CI/CD job token to
|
||||
authenticate API calls to access project `A`. If project `A` is public or internal,
|
||||
the project can be accessed by project `B` without adding it to the allowlist.
|
||||
authenticate API calls to access project `A`.
|
||||
|
||||
By default, the allowlist of any project only includes itself.
|
||||
|
||||
|
|
@ -110,6 +107,32 @@ It is a security risk to disable this feature, so project maintainers or owners
|
|||
keep this setting enabled at all times. Add projects to the allowlist only when cross-project
|
||||
access is needed.
|
||||
|
||||
### Limit job token scope for public or internal projects
|
||||
|
||||
Projects can use a job token to authenticate with public or internal projects for
|
||||
the following actions without being added to the allowlist:
|
||||
|
||||
- Fetch artifacts
|
||||
- Access the container registry
|
||||
- Access the package registry
|
||||
- Access releases, deployments, and environments
|
||||
|
||||
To limit access to these actions to only the projects on the allowlist, set the visibility
|
||||
of each feature to be only accessible to project members:
|
||||
|
||||
Prerequisite:
|
||||
|
||||
- You must have the Maintainer role for the project.
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Visibility, project features, permissions**.
|
||||
1. Set the visibility to **Only project members** for the features you want to restrict access to.
|
||||
- The ability to fetch artifacts is controlled by the CI/CD visibility setting.
|
||||
1. Select **Save changes**.
|
||||
|
||||
Triggering pipelines and fetching Terraform plans is not affected by feature visibility.
|
||||
|
||||
### Disable the job token scope allowlist
|
||||
|
||||
> **Allow access to this project with a CI_JOB_TOKEN** setting [renamed to **Limit access _to_ this project**](https://gitlab.com/gitlab-org/gitlab/-/issues/411406) in GitLab 16.3.
|
||||
|
|
@ -181,9 +204,7 @@ limited only by the user's access permissions.
|
|||
|
||||
For example, when the setting is enabled, jobs in a pipeline in project `A` have
|
||||
a `CI_JOB_TOKEN` scope limited to project `A`. If the job needs to use the token
|
||||
to make an API request to a private project `B`, then `B` must be added to the allowlist for `A`.
|
||||
If project `B` is public or internal, you do not need to add
|
||||
`B` to the allowlist to grant access.
|
||||
to make an API request to project `B`, then `B` must be added to the allowlist for `A`.
|
||||
|
||||
### Configure the job token scope
|
||||
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ Now you're ready to push changes from the community fork to the main GitLab repo
|
|||
1. If you're happy with this merge request and want to start the review process, type
|
||||
`@gitlab-bot ready` in a comment and then select **Comment**.
|
||||
|
||||

|
||||

|
||||
|
||||
Someone from GitLab will look at your request and let you know what the next steps are.
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
|
|
@ -372,7 +372,11 @@ end
|
|||
### Unleash Proxy example
|
||||
|
||||
As of [Unleash Proxy](https://docs.getunleash.io/reference/unleash-proxy) version
|
||||
0.2, the proxy is compatible with feature flags. To run a Docker container to
|
||||
0.2, the proxy is compatible with feature flags.
|
||||
|
||||
You should use Unleash Proxy for production on GitLab.com. See the [performance note](#maximum-supported-clients-in-application-nodes) for details.
|
||||
|
||||
To run a Docker container to
|
||||
connect to your project's feature flags, run the following command:
|
||||
|
||||
```shell
|
||||
|
|
@ -418,10 +422,8 @@ Read [How it works](#how-it-works) section before diving into the details.
|
|||
|
||||
### Maximum supported clients in application nodes
|
||||
|
||||
GitLab accepts client requests as much as possible until it hits the [rate limiting](../security/rate_limits.md).
|
||||
At the moment, the feature flag API falls into **Unauthenticated traffic (from a given IP address)**
|
||||
in the [GitLab.com specific limits](../user/gitlab_com/index.md),
|
||||
so it's **500 requests per minute**.
|
||||
GitLab accepts as many client requests as possible until it hits the [rate limit](../security/rate_limits.md).
|
||||
The feature flag API is considered **Unauthenticated traffic (from a given IP address)**. For GitLab.com, see the [GitLab.com specific limits](../user/gitlab_com/index.md).
|
||||
|
||||
The polling rate is configurable in SDKs. Provided that all clients are requesting from the same IP:
|
||||
|
||||
|
|
@ -429,7 +431,8 @@ The polling rate is configurable in SDKs. Provided that all clients are requesti
|
|||
- Request once per 15 sec ... 125 clients can be supported.
|
||||
|
||||
For applications looking for more scalable solution, you should use [Unleash Proxy](#unleash-proxy-example).
|
||||
This proxy server sits between the server and clients. It requests to the server as a behalf of the client groups,
|
||||
On GitLab.com, you should use Unleash Proxy to reduce the chance of being rate limited across endpoints.
|
||||
This proxy server sits between the server and clients. It makes requests to the server on behalf of the client groups,
|
||||
so the number of outbound requests can be greatly reduced.
|
||||
|
||||
There is also an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/295472) to give more
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ a system alert notifies you of its successful addition.
|
|||
The issue's description is automatically edited to include the Zoom link, and a button
|
||||
appears right under the issue's title.
|
||||
|
||||

|
||||

|
||||
|
||||
You are only allowed to attach a single Zoom meeting to an issue. If you attempt
|
||||
to add a second Zoom meeting using the `/zoom` quick action, it doesn't work. You
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
|
|
@ -59,6 +59,10 @@ module Bitbucket
|
|||
end
|
||||
end
|
||||
|
||||
def default_branch
|
||||
raw.dig('mainbranch', 'name')
|
||||
end
|
||||
|
||||
def to_s
|
||||
full_name
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ module Gitlab
|
|||
|
||||
validate_repository_size!
|
||||
|
||||
set_default_branch
|
||||
update_clone_time
|
||||
end
|
||||
|
||||
|
|
@ -76,6 +77,16 @@ module Gitlab
|
|||
def validate_repository_size!
|
||||
# Defined in EE
|
||||
end
|
||||
|
||||
def set_default_branch
|
||||
default_branch = client.repo(project.import_source).default_branch
|
||||
|
||||
project.change_head(default_branch) if default_branch
|
||||
end
|
||||
|
||||
def client
|
||||
Bitbucket::Client.new(project.import_data.credentials)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ module Gitlab
|
|||
validations do
|
||||
validates :config, type: Hash, allowed_keys: ALLOWED_KEYS
|
||||
validates :key, alphanumeric: true
|
||||
validates :input_default, alphanumeric: true, allow_nil: true
|
||||
validates :input_description, alphanumeric: true, allow_nil: true
|
||||
validates :input_regex, type: String, allow_nil: true
|
||||
validates :input_type, allow_nil: true, allowed_values: Interpolation::Inputs.input_types
|
||||
|
|
|
|||
|
|
@ -5596,6 +5596,9 @@ msgstr ""
|
|||
msgid "Analytics|Event counts update hourly"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Events"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Failed to fetch data"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -5644,6 +5647,9 @@ msgstr ""
|
|||
msgid "Analytics|Previous month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Referer"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -6,23 +6,23 @@ module QA
|
|||
module Settings
|
||||
class BranchRulesDetails < Page::Base
|
||||
view 'app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue' do
|
||||
element :allowed_to_push_content
|
||||
element :allowed_to_merge_content
|
||||
element 'allowed-to-push-content'
|
||||
element 'allowed-to-merge-content'
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/projects/settings/branch_rules/components/view/protection_row.vue' do
|
||||
element :access_level_content
|
||||
element 'access-level'
|
||||
end
|
||||
|
||||
def has_allowed_to_push?(role)
|
||||
within_element(:allowed_to_push_content) do
|
||||
has_element?(:access_level_content, role: role)
|
||||
within_element('allowed-to-push-content') do
|
||||
has_element?('access-level', role: role)
|
||||
end
|
||||
end
|
||||
|
||||
def has_allowed_to_merge?(role)
|
||||
within_element(:allowed_to_merge_content) do
|
||||
has_element?(:access_level_content, role: role)
|
||||
within_element('allowed-to-merge-content') do
|
||||
has_element?('access-level', role: role)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -150,6 +150,87 @@ NVOFBkpdn627G190
|
|||
end
|
||||
end
|
||||
|
||||
trait :with_untrusted_root_ca_in_chain do
|
||||
# This contains
|
||||
# [Intermediate #2 (SHA-2)] 'CloudFlare Origin SSL Certificate Authority'
|
||||
# [Intermediate #1 (SHA-2)] 'CloudFlare Origin Certificate'
|
||||
certificate do
|
||||
'-----BEGIN CERTIFICATE-----
|
||||
MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB
|
||||
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
||||
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
|
||||
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy
|
||||
MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
|
||||
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
|
||||
Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh
|
||||
bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||
ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh
|
||||
bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0
|
||||
Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6
|
||||
ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51
|
||||
UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n
|
||||
c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY
|
||||
MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz
|
||||
30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
|
||||
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG
|
||||
BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv
|
||||
bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB
|
||||
AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E
|
||||
T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
|
||||
ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p
|
||||
mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/
|
||||
e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps
|
||||
P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY
|
||||
dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc
|
||||
2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG
|
||||
V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4
|
||||
HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX
|
||||
j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII
|
||||
0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap
|
||||
lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf
|
||||
+AZxAeKCINT+b72x
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
|
||||
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
||||
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
|
||||
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
|
||||
MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
|
||||
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
|
||||
Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
|
||||
dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
|
||||
6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
|
||||
pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
|
||||
9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
|
||||
/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
|
||||
Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
|
||||
+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
|
||||
qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
|
||||
SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
|
||||
u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
|
||||
Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
|
||||
crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
|
||||
FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
|
||||
/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
|
||||
wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
|
||||
4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
|
||||
2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
|
||||
FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
|
||||
CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
|
||||
boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
|
||||
jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
|
||||
S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
|
||||
QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
|
||||
0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
|
||||
NVOFBkpdn627G190
|
||||
-----END CERTIFICATE-----'
|
||||
end
|
||||
|
||||
key do
|
||||
File.read(Rails.root.join('spec/fixtures/', 'origin_cert_key.pem'))
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_trusted_expired_chain do
|
||||
# This contains
|
||||
# Let's Encrypt Authority X3
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
RSpec.describe Bitbucket::Representation::Repo do
|
||||
RSpec.describe Bitbucket::Representation::Repo, feature_category: :importers do
|
||||
describe '#has_wiki?' do
|
||||
it { expect(described_class.new({ 'has_wiki' => false }).has_wiki?).to be_falsey }
|
||||
it { expect(described_class.new({ 'has_wiki' => true }).has_wiki?).to be_truthy }
|
||||
|
|
@ -42,6 +42,11 @@ RSpec.describe Bitbucket::Representation::Repo do
|
|||
it { expect(described_class.new({ 'full_name' => 'ben/test' }).slug).to eq('test') }
|
||||
end
|
||||
|
||||
describe '#default_branch' do
|
||||
it { expect(described_class.new({ 'mainbranch' => { 'name' => 'master' } }).default_branch).to eq('master') }
|
||||
it { expect(described_class.new({}).default_branch).to eq(nil) }
|
||||
end
|
||||
|
||||
describe '#clone_url' do
|
||||
it 'builds url' do
|
||||
data = { 'links' => { 'clone' => [{ 'name' => 'https', 'href' => 'https://bibucket.org/test/test.git' }] } }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@ RSpec.describe Gitlab::BitbucketImport::Importers::RepositoryImporter, feature_c
|
|||
|
||||
subject(:importer) { described_class.new(project) }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(Bitbucket::Client) do |client|
|
||||
allow(client).to receive(:repo).and_return(Bitbucket::Representation::Repo.new(
|
||||
{ 'mainbranch' => { 'name' => 'develop' } }
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
context 'when repository is empty' do
|
||||
it 'imports the repository' do
|
||||
|
|
@ -17,6 +25,15 @@ RSpec.describe Gitlab::BitbucketImport::Importers::RepositoryImporter, feature_c
|
|||
|
||||
importer.execute
|
||||
end
|
||||
|
||||
it 'sets the default branch' do
|
||||
allow(project.repository).to receive(:import_repository)
|
||||
allow(project.repository).to receive(:fetch_as_mirror)
|
||||
|
||||
expect(project).to receive(:change_head).with('develop')
|
||||
|
||||
importer.execute
|
||||
end
|
||||
end
|
||||
|
||||
context 'when repository is not empty' do
|
||||
|
|
|
|||
|
|
@ -40,12 +40,24 @@ RSpec.describe Gitlab::Ci::Config::Header::Input, feature_category: :pipeline_co
|
|||
end
|
||||
end
|
||||
|
||||
context 'when has a default value' do
|
||||
context 'when has a string default value' do
|
||||
let(:input_hash) { { default: 'bar' } }
|
||||
|
||||
it_behaves_like 'a valid input'
|
||||
end
|
||||
|
||||
context 'when has a numeric default value' do
|
||||
let(:input_hash) { { default: 6.66 } }
|
||||
|
||||
it_behaves_like 'a valid input'
|
||||
end
|
||||
|
||||
context 'when has a boolean default value' do
|
||||
let(:input_hash) { { default: true } }
|
||||
|
||||
it_behaves_like 'a valid input'
|
||||
end
|
||||
|
||||
context 'when has a description value' do
|
||||
let(:input_hash) { { description: 'bar' } }
|
||||
|
||||
|
|
|
|||
|
|
@ -88,24 +88,6 @@ RSpec.describe Ci::JobToken::Scope, feature_category: :continuous_integration, f
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'enforces outbound scope only' do
|
||||
include_context 'with accessible and inaccessible projects'
|
||||
|
||||
where(:accessed_project, :result) do
|
||||
ref(:current_project) | true
|
||||
ref(:inbound_allowlist_project) | false
|
||||
ref(:unscoped_project1) | false
|
||||
ref(:unscoped_project2) | false
|
||||
ref(:outbound_allowlist_project) | true
|
||||
ref(:inbound_accessible_project) | false
|
||||
ref(:fully_accessible_project) | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq(result) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'accessible?' do
|
||||
subject { scope.accessible?(accessed_project) }
|
||||
|
||||
|
|
@ -121,6 +103,7 @@ RSpec.describe Ci::JobToken::Scope, feature_category: :continuous_integration, f
|
|||
ref(:outbound_allowlist_project) | false
|
||||
ref(:inbound_accessible_project) | false
|
||||
ref(:fully_accessible_project) | true
|
||||
ref(:unscoped_public_project) | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -147,6 +130,7 @@ RSpec.describe Ci::JobToken::Scope, feature_category: :continuous_integration, f
|
|||
ref(:outbound_allowlist_project) | false
|
||||
ref(:inbound_accessible_project) | true
|
||||
ref(:fully_accessible_project) | true
|
||||
ref(:unscoped_public_project) | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -160,7 +144,34 @@ RSpec.describe Ci::JobToken::Scope, feature_category: :continuous_integration, f
|
|||
current_project.update!(ci_outbound_job_token_scope_enabled: true)
|
||||
end
|
||||
|
||||
include_examples 'enforces outbound scope only'
|
||||
include_context 'with accessible and inaccessible projects'
|
||||
|
||||
where(:accessed_project, :result) do
|
||||
ref(:current_project) | true
|
||||
ref(:inbound_allowlist_project) | false
|
||||
ref(:unscoped_project1) | false
|
||||
ref(:unscoped_project2) | false
|
||||
ref(:outbound_allowlist_project) | true
|
||||
ref(:inbound_accessible_project) | false
|
||||
ref(:fully_accessible_project) | true
|
||||
ref(:unscoped_public_project) | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq(result) }
|
||||
end
|
||||
|
||||
context "with FF restrict_ci_job_token_for_public_and_internal_projects disabled" do
|
||||
before do
|
||||
stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false)
|
||||
end
|
||||
|
||||
let(:accessed_project) { unscoped_public_project }
|
||||
|
||||
it "restricts public and internal outbound projects not in allowlist" do
|
||||
is_expected.to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1327,6 +1327,7 @@ RSpec.describe Integration, feature_category: :integrations do
|
|||
describe '#async_execute' do
|
||||
let(:integration) { described_class.new(id: 123) }
|
||||
let(:data) { { object_kind: 'build' } }
|
||||
let(:serialized_data) { data.deep_stringify_keys }
|
||||
let(:supported_events) { %w[push build] }
|
||||
|
||||
subject(:async_execute) { integration.async_execute(data) }
|
||||
|
|
@ -1336,7 +1337,7 @@ RSpec.describe Integration, feature_category: :integrations do
|
|||
end
|
||||
|
||||
it 'queues a Integrations::ExecuteWorker' do
|
||||
expect(Integrations::ExecuteWorker).to receive(:perform_async).with(integration.id, data)
|
||||
expect(Integrations::ExecuteWorker).to receive(:perform_async).with(integration.id, serialized_data)
|
||||
|
||||
async_execute
|
||||
end
|
||||
|
|
|
|||
|
|
@ -288,8 +288,8 @@ RSpec.describe PagesDomain, feature_category: :pages do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#has_intermediates?' do
|
||||
subject { domain.has_intermediates? }
|
||||
describe '#has_valid_intermediates?' do
|
||||
subject { domain.has_valid_intermediates? }
|
||||
|
||||
context 'for self signed' do
|
||||
let(:domain) { build(:pages_domain) }
|
||||
|
|
@ -312,6 +312,14 @@ RSpec.describe PagesDomain, feature_category: :pages do
|
|||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'for chain with unknown root CA' do
|
||||
# In cases where users use an origin certificate the CA does not necessarily need to be in
|
||||
# the trust store, eg. in the case of Cloudflare Origin Certs.
|
||||
let(:domain) { build(:pages_domain, :with_untrusted_root_ca_in_chain) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#expired?' do
|
||||
|
|
|
|||
|
|
@ -3822,6 +3822,13 @@ RSpec.describe Repository, feature_category: :source_code_management do
|
|||
it 'returns nil' do
|
||||
expect(repository.get_patch_id('HEAD', 'HEAD')).to be_nil
|
||||
end
|
||||
|
||||
it 'does not report the exception' do
|
||||
expect(Gitlab::ErrorTracking)
|
||||
.not_to receive(:track_exception)
|
||||
|
||||
repository.get_patch_id('HEAD', 'HEAD')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a Gitlab::Git::CommandError is raised' do
|
||||
|
|
@ -3831,7 +3838,7 @@ RSpec.describe Repository, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(repository.get_patch_id('HEAD', 'HEAD')).to be_nil
|
||||
expect(repository.get_patch_id('HEAD~', 'HEAD')).to be_nil
|
||||
end
|
||||
|
||||
it 'reports the exception' do
|
||||
|
|
@ -3840,11 +3847,11 @@ RSpec.describe Repository, feature_category: :source_code_management do
|
|||
.with(
|
||||
instance_of(Gitlab::Git::CommandError),
|
||||
project_id: repository.project.id,
|
||||
old_revision: 'HEAD',
|
||||
old_revision: 'HEAD~',
|
||||
new_revision: 'HEAD'
|
||||
)
|
||||
|
||||
repository.get_patch_id('HEAD', 'HEAD')
|
||||
repository.get_patch_id('HEAD~', 'HEAD')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2564,72 +2564,153 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
describe 'when user is authenticated via CI_JOB_TOKEN', :request_store do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
|
||||
:private | :reporter | false | :same | true | true
|
||||
:private | :reporter | false | :same | false | true
|
||||
:private | :reporter | false | :different | true | false
|
||||
:private | :reporter | false | :different | false | true
|
||||
:private | :guest | false | :same | true | true
|
||||
:private | :guest | false | :same | false | true
|
||||
:private | :guest | false | :different | true | false
|
||||
:private | :guest | false | :different | false | true
|
||||
RSpec.shared_examples 'CI_JOB_TOKEN enforces the expected permissions' do
|
||||
with_them do
|
||||
let(:current_user) { public_send(user_role) }
|
||||
let(:project) { public_send("#{project_visibility}_project") }
|
||||
let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
|
||||
|
||||
:internal | :reporter | false | :same | true | true
|
||||
:internal | :reporter | true | :same | true | true
|
||||
:internal | :reporter | false | :same | false | true
|
||||
:internal | :reporter | false | :different | true | true
|
||||
:internal | :reporter | true | :different | true | false
|
||||
:internal | :reporter | false | :different | false | true
|
||||
:internal | :guest | false | :same | true | true
|
||||
:internal | :guest | true | :same | true | true
|
||||
:internal | :guest | false | :same | false | true
|
||||
:internal | :guest | false | :different | true | true
|
||||
:internal | :guest | true | :different | true | false
|
||||
:internal | :guest | false | :different | false | true
|
||||
let(:scope_project) do
|
||||
if scope_project_type == :same
|
||||
project
|
||||
else
|
||||
create(:project, :private)
|
||||
end
|
||||
end
|
||||
|
||||
:public | :reporter | false | :same | true | true
|
||||
:public | :reporter | false | :same | false | true
|
||||
:public | :reporter | false | :different | true | true
|
||||
:public | :reporter | false | :different | false | true
|
||||
:public | :guest | false | :same | true | true
|
||||
:public | :guest | false | :same | false | true
|
||||
:public | :guest | false | :different | true | true
|
||||
:public | :guest | false | :different | false | true
|
||||
before do
|
||||
current_user.set_ci_job_token_scope!(job)
|
||||
current_user.external = external_user
|
||||
project.update!(
|
||||
ci_outbound_job_token_scope_enabled: token_scope_enabled,
|
||||
ci_inbound_job_token_scope_enabled: token_scope_enabled
|
||||
)
|
||||
scope_project.update!(
|
||||
ci_outbound_job_token_scope_enabled: token_scope_enabled,
|
||||
ci_inbound_job_token_scope_enabled: token_scope_enabled
|
||||
)
|
||||
end
|
||||
|
||||
it "enforces the expected permissions" do
|
||||
if result
|
||||
is_expected.to be_allowed("#{user_role}_access".to_sym)
|
||||
else
|
||||
is_expected.to be_disallowed("#{user_role}_access".to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:current_user) { public_send(user_role) }
|
||||
let(:project) { public_send("#{project_visibility}_project") }
|
||||
let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
|
||||
# Remove project_visibility on FF restrict_ci_job_token_for_public_and_internal_projects cleanup
|
||||
where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
|
||||
:public | :reporter | false | :same | true | true
|
||||
:public | :reporter | true | :same | true | true
|
||||
:public | :reporter | false | :same | false | true
|
||||
:public | :reporter | false | :different | true | false
|
||||
:public | :reporter | true | :different | true | false
|
||||
:public | :reporter | false | :different | false | true
|
||||
:public | :guest | false | :same | true | true
|
||||
:public | :guest | true | :same | true | true
|
||||
:public | :guest | false | :same | false | true
|
||||
:public | :guest | false | :different | true | false
|
||||
:public | :guest | true | :different | true | false
|
||||
:public | :guest | false | :different | false | true
|
||||
end
|
||||
|
||||
let(:scope_project) do
|
||||
if scope_project_type == :same
|
||||
project
|
||||
else
|
||||
create(:project, :private)
|
||||
end
|
||||
include_examples "CI_JOB_TOKEN enforces the expected permissions"
|
||||
|
||||
context "when the project is public or internal and not on the allowlist" do
|
||||
where(:feature, :permissions) do
|
||||
:container_registry | [:build_read_container_image, :read_container_image]
|
||||
:package_registry | [:read_package, :read_project]
|
||||
:builds | [:read_commit_status]
|
||||
:releases | [:read_release]
|
||||
:environments | [:read_environment]
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:current_user) { developer }
|
||||
let(:project) { public_project }
|
||||
let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
|
||||
let_it_be(:scope_project) { create(:project, :private) }
|
||||
|
||||
before do
|
||||
current_user.set_ci_job_token_scope!(job)
|
||||
|
||||
scope_project.update!(ci_inbound_job_token_scope_enabled: true)
|
||||
end
|
||||
|
||||
it 'allows the permissions based on the feature access level' do
|
||||
project.project_feature.update!("#{feature}_access_level": ProjectFeature::ENABLED)
|
||||
|
||||
permissions.each { |p| expect_allowed(p) }
|
||||
end
|
||||
|
||||
it 'disallows the permissions if feature access level is restricted' do
|
||||
project.project_feature.update!("#{feature}_access_level": ProjectFeature::PRIVATE)
|
||||
|
||||
permissions.each { |p| expect_disallowed(p) }
|
||||
end
|
||||
|
||||
it 'disallows the permissions if feature access level is disabled' do
|
||||
project.project_feature.update!("#{feature}_access_level": ProjectFeature::DISABLED)
|
||||
|
||||
permissions.each { |p| expect_disallowed(p) }
|
||||
end
|
||||
|
||||
context "with restrict_ci_job_token_for_public_and_internal_projects disabled" do
|
||||
before do
|
||||
stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false)
|
||||
end
|
||||
|
||||
it 'allows all permissions for private' do
|
||||
project.project_feature.update!("#{feature}_access_level": ProjectFeature::PRIVATE)
|
||||
|
||||
permissions.each { |p| expect_allowed(p) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with FF restrict_ci_job_token_for_public_and_internal_projects disabled" do
|
||||
before do
|
||||
current_user.set_ci_job_token_scope!(job)
|
||||
current_user.external = external_user
|
||||
project.update!(
|
||||
ci_outbound_job_token_scope_enabled: token_scope_enabled,
|
||||
ci_inbound_job_token_scope_enabled: token_scope_enabled
|
||||
)
|
||||
scope_project.update!(
|
||||
ci_outbound_job_token_scope_enabled: token_scope_enabled,
|
||||
ci_inbound_job_token_scope_enabled: token_scope_enabled
|
||||
)
|
||||
stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false)
|
||||
end
|
||||
|
||||
it "enforces the expected permissions" do
|
||||
if result
|
||||
is_expected.to be_allowed("#{user_role}_access".to_sym)
|
||||
else
|
||||
is_expected.to be_disallowed("#{user_role}_access".to_sym)
|
||||
end
|
||||
where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
|
||||
:private | :reporter | false | :same | true | true
|
||||
:private | :reporter | false | :same | false | true
|
||||
:private | :reporter | false | :different | true | false
|
||||
:private | :reporter | false | :different | false | true
|
||||
:private | :guest | false | :same | true | true
|
||||
:private | :guest | false | :same | false | true
|
||||
:private | :guest | false | :different | true | false
|
||||
:private | :guest | false | :different | false | true
|
||||
|
||||
:internal | :reporter | false | :same | true | true
|
||||
:internal | :reporter | true | :same | true | true
|
||||
:internal | :reporter | false | :same | false | true
|
||||
:internal | :reporter | false | :different | true | true
|
||||
:internal | :reporter | true | :different | true | false
|
||||
:internal | :reporter | false | :different | false | true
|
||||
:internal | :guest | false | :same | true | true
|
||||
:internal | :guest | true | :same | true | true
|
||||
:internal | :guest | false | :same | false | true
|
||||
:internal | :guest | false | :different | true | true
|
||||
:internal | :guest | true | :different | true | false
|
||||
:internal | :guest | false | :different | false | true
|
||||
|
||||
:public | :reporter | false | :same | true | true
|
||||
:public | :reporter | false | :same | false | true
|
||||
:public | :reporter | false | :different | true | true
|
||||
:public | :reporter | false | :different | false | true
|
||||
:public | :guest | false | :same | true | true
|
||||
:public | :guest | false | :same | false | true
|
||||
:public | :guest | false | :different | true | true
|
||||
:public | :guest | false | :different | false | true
|
||||
end
|
||||
|
||||
include_examples "CI_JOB_TOKEN enforces the expected permissions"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ RSpec.describe API::NpmProjectPackages, feature_category: :package_registry do
|
|||
|
||||
context 'with a job token for a different user' do
|
||||
let_it_be(:other_user) { create(:user) }
|
||||
let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user) }
|
||||
let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user, project: project) }
|
||||
|
||||
let(:headers) { build_token_auth_header(other_job.token) }
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ RSpec.describe API::NpmProjectPackages, feature_category: :package_registry do
|
|||
|
||||
context 'with a job token for a different user' do
|
||||
let_it_be(:other_user) { create(:user) }
|
||||
let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user) }
|
||||
let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user, project: project) }
|
||||
|
||||
let(:headers) { build_token_auth_header(other_job.token) }
|
||||
|
||||
|
|
|
|||
|
|
@ -664,8 +664,7 @@ RSpec.describe 'Git LFS API and storage', feature_category: :source_code_managem
|
|||
context 'tries to push to other project' do
|
||||
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
|
||||
|
||||
# I'm not sure what this tests that is different from the previous test
|
||||
it_behaves_like 'LFS http 403 response'
|
||||
it_behaves_like 'LFS http 404 response'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1185,8 +1184,7 @@ RSpec.describe 'Git LFS API and storage', feature_category: :source_code_managem
|
|||
context 'tries to push to other project' do
|
||||
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
|
||||
|
||||
# I'm not sure what this tests that is different from the previous test
|
||||
it_behaves_like 'LFS http 403 response'
|
||||
it_behaves_like 'LFS http 404 response'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -309,26 +309,18 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
|
|||
|
||||
let(:merge_request) { create(:merge_request) }
|
||||
|
||||
where(:can_be_merged, :open, :broken, :discussions, :blocked, :draft, :skip_draft, :skip_blocked,
|
||||
:skip_discussions, :result) do
|
||||
true | true | false | true | false | false | false | false | false | true
|
||||
true | true | false | true | false | false | true | true | false | true
|
||||
true | true | false | true | false | true | true | false | false | true
|
||||
true | true | false | true | true | false | false | true | false | true
|
||||
true | true | false | false | false | false | false | false | true | true
|
||||
true | true | false | true | false | true | false | false | false | false
|
||||
false | true | false | true | false | false | false | false | false | false
|
||||
true | false | false | true | false | false | false | false | false | false
|
||||
true | true | true | true | false | false | false | false | false | false
|
||||
true | true | false | false | false | false | false | false | false | false
|
||||
true | true | false | true | true | false | false | false | false | false
|
||||
where(:can_be_merged, :open, :broken, :discussions, :blocked, :draft, :result) do
|
||||
true | true | false | true | false | false | true
|
||||
false | true | false | true | false | false | false
|
||||
true | false | false | true | false | false | false
|
||||
true | true | true | true | false | false | false
|
||||
true | true | false | false | false | false | false
|
||||
true | true | false | true | true | false | false
|
||||
true | true | false | true | false | true | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
allow(service).to receive(:skip_draft_check).and_return(skip_draft)
|
||||
allow(service).to receive(:skip_blocked_check).and_return(skip_blocked)
|
||||
allow(service).to receive(:skip_discussions_check).and_return(skip_discussions)
|
||||
allow(merge_request).to receive(:can_be_merged_by?).and_return(can_be_merged)
|
||||
allow(merge_request).to receive(:open?).and_return(open)
|
||||
allow(merge_request).to receive(:broken?).and_return(broken)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
{ before: 'oldrev', after: 'newrev', ref: 'ref' }
|
||||
end
|
||||
|
||||
let(:serialized_data) { data.deep_stringify_keys }
|
||||
|
||||
let(:service_instance) { described_class.new(project_hook, data, :push_hooks) }
|
||||
|
||||
describe '#initialize' do
|
||||
|
|
@ -426,7 +428,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data),
|
||||
hash_including(default_log_data.deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -456,7 +458,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
default_log_data.merge(
|
||||
response_body: 'Bad request',
|
||||
response_status: 400
|
||||
)
|
||||
).deep_stringify_keys
|
||||
),
|
||||
:failed,
|
||||
nil
|
||||
|
|
@ -480,7 +482,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
response_body: '',
|
||||
response_status: 'internal error',
|
||||
internal_error_message: 'Some HTTP Post error'
|
||||
)
|
||||
).deep_stringify_keys
|
||||
),
|
||||
:error,
|
||||
nil
|
||||
|
|
@ -499,7 +501,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data.merge(response_body: '')),
|
||||
hash_including(default_log_data.merge(response_body: '').deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -520,7 +522,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data.merge(response_body: stripped_body)),
|
||||
hash_including(default_log_data.merge(response_body: stripped_body).deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -553,7 +555,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data.merge(response_headers: expected_response_headers)),
|
||||
hash_including(default_log_data.merge(response_headers: expected_response_headers).deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -578,7 +580,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data.merge(response_headers: expected_response_headers)),
|
||||
hash_including(default_log_data.merge(response_headers: expected_response_headers).deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -596,7 +598,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data),
|
||||
hash_including(default_log_data.deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -607,7 +609,9 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
expect(WebHooks::LogExecutionWorker).to receive(:perform_async)
|
||||
.with(
|
||||
project_hook.id,
|
||||
hash_including(default_log_data.merge(request_data: WebHookLog::OVERSIZE_REQUEST_DATA)),
|
||||
hash_including(default_log_data.merge(
|
||||
request_data: WebHookLog::OVERSIZE_REQUEST_DATA
|
||||
).deep_stringify_keys),
|
||||
:ok,
|
||||
nil
|
||||
)
|
||||
|
|
@ -636,7 +640,9 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state,
|
|||
|
||||
describe '#async_execute' do
|
||||
def expect_to_perform_worker(hook)
|
||||
expect(WebHookWorker).to receive(:perform_async).with(hook.id, data, 'push_hooks', an_instance_of(Hash))
|
||||
expect(WebHookWorker).to receive(:perform_async).with(
|
||||
hook.id, serialized_data, 'push_hooks', an_instance_of(Hash)
|
||||
)
|
||||
end
|
||||
|
||||
def expect_to_rate_limit(hook, threshold:, throttled: false)
|
||||
|
|
|
|||
|
|
@ -16,12 +16,14 @@ end
|
|||
|
||||
RSpec.shared_context 'with inaccessible projects' do
|
||||
let_it_be(:inbound_allowlist_project) { create_project_in_allowlist(source_project, direction: :inbound) }
|
||||
|
||||
include_context 'with unscoped projects'
|
||||
end
|
||||
|
||||
RSpec.shared_context 'with unscoped projects' do
|
||||
let_it_be(:unscoped_project1) { create(:project) }
|
||||
let_it_be(:unscoped_project2) { create(:project) }
|
||||
let_it_be(:unscoped_public_project) { create(:project, :public) }
|
||||
|
||||
let_it_be(:link_out_of_scope) { create(:ci_job_token_project_scope_link, target_project: unscoped_project1) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'forwardable'
|
||||
require_relative 'suggestor'
|
||||
|
||||
module Tooling
|
||||
|
|
@ -14,11 +13,8 @@ module Tooling
|
|||
#
|
||||
# @see Suggestor
|
||||
class Suggestion
|
||||
extend Forwardable
|
||||
include ::Tooling::Danger::Suggestor
|
||||
|
||||
def_delegators :@context, :helper, :project_helper, :markdown
|
||||
|
||||
attr_reader :filename
|
||||
|
||||
def initialize(filename, context:)
|
||||
|
|
@ -34,6 +30,22 @@ module Tooling
|
|||
comment_text: self.class::SUGGESTION
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def helper(...)
|
||||
# Previously, we were using `forwardable` but it emitted a mysterious warning:
|
||||
# forwarding to private method Danger::Rubocop#helper
|
||||
@context.helper(...)
|
||||
end
|
||||
|
||||
def project_helper(...)
|
||||
@context.project_helper(...)
|
||||
end
|
||||
|
||||
def markdown(...)
|
||||
@context.markdown(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue