Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitleaksignore2
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue26
-rw-r--r--app/assets/javascripts/lib/utils/secret_detection.js4
-rw-r--r--app/models/ci/build.rb12
-rw-r--r--config/feature_flags/beta/prefix_ci_build_tokens.yml9
-rw-r--r--config/gitleaks.toml2
-rw-r--r--doc/api/jobs.md11
-rw-r--r--doc/development/pipelines/index.md20
-rw-r--r--doc/security/token_overview.md2
-rw-r--r--lib/api/ci/pipelines.rb2
-rw-r--r--lib/api/entities/ci/job.rb1
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/job.json6
-rw-r--r--spec/frontend/boards/board_list_spec.js83
-rw-r--r--spec/frontend/lib/utils/secret_detection_spec.js4
-rw-r--r--spec/models/ci/build_spec.rb56
-rw-r--r--spec/requests/api/ci/jobs_spec.rb1
16 files changed, 194 insertions, 47 deletions
diff --git a/.gitleaksignore b/.gitleaksignore
index d52f10ebdc4..9ff1dcb3a70 100644
--- a/.gitleaksignore
+++ b/.gitleaksignore
@@ -1,3 +1,5 @@
afedb913baf4203aa688421873fdb9f94649578e:doc/api/users.md:generic-api-key:2201
spec/frontend/lib/utils/secret_detection_spec.js:generic-api-key:34
spec/frontend/lib/utils/secret_detection_spec.js:generic-api-key:35
+spec/frontend/lib/utils/secret_detection_spec.js:generic-api-key:38
+spec/frontend/lib/utils/secret_detection_spec.js:generic-api-key:39 \ No newline at end of file
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 8a5c6882e56..58c20c0da91 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -3,6 +3,7 @@ import { GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import Draggable from 'vuedraggable';
import { STATUS_CLOSED } from '~/issues/constants';
import { sprintf, __, s__ } from '~/locale';
+import { ESC_KEY_CODE } from '~/lib/utils/keycodes';
import { defaultSortableOptions, DRAG_DELAY } from '~/sortable/constants';
import { sortableStart, sortableEnd } from '~/sortable/utils';
import Tracking from '~/tracking';
@@ -82,6 +83,7 @@ export default {
toList: {},
addItemToListInProgress: false,
updateIssueOrderInProgress: false,
+ dragCancelled: false,
};
},
apollo: {
@@ -307,6 +309,11 @@ export default {
return;
}
+ // Reset dragCancelled flag
+ this.dragCancelled = false;
+ // Attach listener to detect `ESC` key press to cancel drag.
+ document.addEventListener('keyup', this.handleKeyUp.bind(this));
+
sortableStart();
this.track('drag_card', { label: 'board' });
},
@@ -323,6 +330,11 @@ export default {
return;
}
+ // Detach listener as soon as drag ends.
+ document.removeEventListener('keyup', this.handleKeyUp.bind(this));
+ // Drag was cancelled, prevent reordering.
+ if (this.dragCancelled) return;
+
sortableEnd();
let newIndex = originalNewIndex;
let { children } = to;
@@ -375,6 +387,20 @@ export default {
this.updateIssueOrderInProgress = false;
});
},
+ /**
+ * This implementation is needed to support `Esc` key press to cancel drag.
+ * It matches with what we already shipped in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119311
+ */
+ handleKeyUp(e) {
+ if (e.keyCode === ESC_KEY_CODE) {
+ this.dragCancelled = true;
+ // Sortable.js internally listens for `mouseup` event on document
+ // to register drop event, see https://github.com/SortableJS/Sortable/blob/master/src/Sortable.js#L625
+ // We need to manually trigger it to simulate cancel behaviour as VueDraggable doesn't
+ // natively support it, see https://github.com/SortableJS/Vue.Draggable/issues/968.
+ document.dispatchEvent(new Event('mouseup'));
+ }
+ },
isItemInTheList(itemIid) {
const items = this.toList?.[`${this.issuableType}s`]?.nodes || [];
return items.some((item) => item.iid === itemIid);
diff --git a/app/assets/javascripts/lib/utils/secret_detection.js b/app/assets/javascripts/lib/utils/secret_detection.js
index 92edd286c76..dad4af004cc 100644
--- a/app/assets/javascripts/lib/utils/secret_detection.js
+++ b/app/assets/javascripts/lib/utils/secret_detection.js
@@ -36,6 +36,10 @@ export const containsSensitiveToken = (message) => {
name: 'GitLab SCIM OAuth Access Token',
regex: `glsoat-[0-9a-zA-Z_-]{20}`,
},
+ {
+ name: 'GitLab CI Build (Job) Token',
+ regex: `glcbt-[0-9a-zA-Z]{1,5}_[0-9a-zA-Z_-]{20}`,
+ },
];
for (const rule of sensitiveDataPatterns) {
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index e56f3d2536c..23185548554 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -42,6 +42,8 @@ module Ci
DEPLOYMENT_NAMES = %w[deploy release rollout].freeze
+ TOKEN_PREFIX = 'glcbt-'
+
has_one :pending_state, class_name: 'Ci::BuildPendingState', foreign_key: :build_id, inverse_of: :build
has_one :queuing_entry, class_name: 'Ci::PendingBuild', foreign_key: :build_id, inverse_of: :build
has_one :runtime_metadata, class_name: 'Ci::RunningBuild', foreign_key: :build_id, inverse_of: :build
@@ -204,7 +206,7 @@ module Ci
add_authentication_token_field :token,
encrypted: :required,
- format_with_prefix: :partition_id_prefix_in_16_bit_encode
+ format_with_prefix: :prefix_and_partition_for_token
after_save :stick_build_if_status_changed
@@ -1232,6 +1234,14 @@ module Ci
def partition_id_prefix_in_16_bit_encode
"#{partition_id.to_s(16)}_"
end
+
+ def prefix_and_partition_for_token
+ if Feature.enabled?(:prefix_ci_build_tokens, project, type: :beta)
+ TOKEN_PREFIX + partition_id_prefix_in_16_bit_encode
+ else
+ partition_id_prefix_in_16_bit_encode
+ end
+ end
end
end
diff --git a/config/feature_flags/beta/prefix_ci_build_tokens.yml b/config/feature_flags/beta/prefix_ci_build_tokens.yml
new file mode 100644
index 00000000000..ed0838b36bd
--- /dev/null
+++ b/config/feature_flags/beta/prefix_ci_build_tokens.yml
@@ -0,0 +1,9 @@
+---
+name: prefix_ci_build_tokens
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/426137
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140159
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17299
+milestone: '16.8'
+group: group::pipeline security
+type: beta
+default_enabled: false
diff --git a/config/gitleaks.toml b/config/gitleaks.toml
index 0983a34ca71..d0d140c8414 100644
--- a/config/gitleaks.toml
+++ b/config/gitleaks.toml
@@ -14,6 +14,8 @@ path = "/gitleaks.toml"
"glpat-cgyKc1k_AsnEpmP-5fRL",
"gldt-cgyKc1k_AsnEpmP-5fRL",
"glsoat-cgyKc1k_AsnEpmP-5fRL",
+ "glcbt-FFFF_cgyKc1k_AsnEpmP-5fRL",
+ "glcbt-1_cgyKc1k_AsnEpmP-5fRL",
# spec/frontend/lib/utils/secret_detection_spec.js
"GlPat-abcdefghijklmnopqrstuvwxyz",
# doc/development/sec/token_revocation_api.md
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 739d5426082..886f209520d 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -46,6 +46,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.802Z",
"started_at": "2015-12-24T17:54:27.722Z",
@@ -115,6 +116,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.727Z",
"started_at": "2015-12-24T17:54:24.729Z",
@@ -209,6 +211,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.727Z",
"started_at": "2015-12-24T17:54:24.729Z",
@@ -269,6 +272,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.802Z",
"started_at": "2015-12-24T17:54:27.722Z",
@@ -363,6 +367,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.802Z",
"started_at": "2015-12-24T17:54:27.722Z",
@@ -450,6 +455,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.880Z",
"started_at": "2015-12-24T17:54:30.733Z",
@@ -600,6 +606,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.880Z",
"started_at": "2015-12-24T17:54:30.733Z",
@@ -705,6 +712,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2016-01-11T10:13:33.506Z",
"started_at": "2016-01-11T10:14:09.526Z",
@@ -759,6 +767,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2016-01-11T10:13:33.506Z",
"started_at": null,
@@ -817,6 +826,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"download_url": null,
"id": 1,
@@ -899,6 +909,7 @@ Example response:
"title": "Test the CI integration."
},
"coverage": null,
+ "archived": false,
"allow_failure": false,
"created_at": "2016-01-11T10:13:33.506Z",
"started_at": null,
diff --git a/doc/development/pipelines/index.md b/doc/development/pipelines/index.md
index cdcaae6a35e..072fb6382b4 100644
--- a/doc/development/pipelines/index.md
+++ b/doc/development/pipelines/index.md
@@ -750,28 +750,29 @@ graph LR
### Backend pipeline
-[Reference pipeline](https://gitlab.com/gitlab-org/gitlab/-/pipelines/433316063).
+[Reference pipeline](https://gitlab.com/gitlab-org/gitlab/-/pipelines/1118782302).
```mermaid
graph RL;
classDef criticalPath fill:#f66;
- 1-3["compile-test-assets (5.5 minutes)"];
- class 1-3 criticalPath;
+ 1-1["clone-gitlab-repo (1 minute)"];
+ 1-3["compile-test-assets (3 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
- 1-6["setup-test-env (3.6 minutes)"];
+ 1-6["setup-test-env (4 minutes)"];
+ class 1-6 criticalPath;
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
- 1-14["retrieve-tests-metadata"];
+ 1-14["retrieve-tests-metadata (50 seconds)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
- 1-15["detect-tests"];
+ 1-15["detect-tests (1 minute)"];
click 1-15 "https://app.periscopedata.com/app/gitlab/652085/EP---Jobs-Durations?widget=10113603&udv=1005715"
- 2_5-1["rspec & db jobs (24 minutes)"];
+ 2_5-1["rspec & db jobs (30~50 minutes)"];
class 2_5-1 criticalPath;
click 2_5-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations"
- 2_5-1 --> 1-3 & 1-6 & 1-14 & 1-15;
+ 2_5-1 --> 1-1 & 1-3 & 1-6 & 1-14 & 1-15;
- ac-1["rspec:artifact-collector (2 minutes)<br/>(workaround for 'needs' limitation)"];
+ ac-1["rspec:artifact-collector (30 seconds)<br/>(workaround for 'needs' limitation)"];
class ac-1 criticalPath;
ac-1 --> 2_5-1;
@@ -784,7 +785,6 @@ graph RL;
class 4_3-1 criticalPath;
click 4_3-1 "https://app.periscopedata.com/app/gitlab/652085/EP---Jobs-Durations?widget=13446492&udv=1005715"
4_3-1 --> 3_2-1;
-
```
### Review app pipeline
diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md
index 4498ee893a7..9cd445ed47b 100644
--- a/doc/security/token_overview.md
+++ b/doc/security/token_overview.md
@@ -238,7 +238,7 @@ The following tables show the prefixes for each type of token where applicable.
| Deploy key | Not applicable. |
| Runner registration token | Not applicable. |
| Runner authentication token | `glrt-` |
-| Job token | Not applicable. |
+| CI/CD Job token | `glcbt-` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/426137) in GitLab 16.8 behind a feature flag named `prefix_ci_build_tokens`. Disabled by default.) |
| Trigger token | `glptt-` |
| Legacy runner registration token | GR1348941 |
| Feed token | `glft-` |
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index b5123ab49dc..f369fc5e183 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -183,7 +183,7 @@ module API
.new(current_user: current_user, pipeline: pipeline, params: params)
.execute
- builds = builds.with_preloads
+ builds = builds.with_preloads.preload(:metadata) # rubocop:disable CodeReuse/ActiveRecord -- preload job.archived?
present paginate(builds), with: Entities::Ci::Job
end
diff --git a/lib/api/entities/ci/job.rb b/lib/api/entities/ci/job.rb
index d9e6b7eed75..2f748d28abf 100644
--- a/lib/api/entities/ci/job.rb
+++ b/lib/api/entities/ci/job.rb
@@ -12,6 +12,7 @@ module API
expose :runner, with: ::API::Entities::Ci::Runner
expose :artifacts_expire_at,
documentation: { type: 'dateTime', example: '2016-01-19T09:05:50.355Z' }
+ expose :archived?, as: :archived, documentation: { type: 'boolean', example: false }
expose(
:tag_list,
diff --git a/spec/fixtures/api/schemas/public_api/v4/job.json b/spec/fixtures/api/schemas/public_api/v4/job.json
index 6265fbcff69..3a0c69786e9 100644
--- a/spec/fixtures/api/schemas/public_api/v4/job.json
+++ b/spec/fixtures/api/schemas/public_api/v4/job.json
@@ -22,7 +22,8 @@
"artifacts_expire_at",
"tag_list",
"runner",
- "project"
+ "project",
+ "archived"
],
"properties": {
"id": { "type": "integer" },
@@ -70,7 +71,8 @@
},
"project": {
"ci_job_token_scope_enabled": { "type": "boolean" }
- }
+ },
+ "archived": { "type": "boolean" }
},
"additionalProperties":false
}
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 8d59cb2692e..ad5804f6eb7 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -5,6 +5,7 @@ import { DraggableItemTypes, ListType } from 'ee_else_ce/boards/constants';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import waitForPromises from 'helpers/wait_for_promises';
import createComponent from 'jest/boards/board_list_helper';
+import { ESC_KEY_CODE } from '~/lib/utils/keycodes';
import BoardCard from '~/boards/components/board_card.vue';
import eventHub from '~/boards/eventhub';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
@@ -203,9 +204,38 @@ describe('Board list component', () => {
expect(document.body.classList.contains('is-dragging')).toBe(true);
});
+
+ it('attaches `keyup` event listener on document', async () => {
+ jest.spyOn(document, 'addEventListener');
+ findDraggable().vm.$emit('start', {
+ item: {
+ dataset: {
+ draggableItemType: DraggableItemTypes.card,
+ },
+ },
+ });
+ await nextTick();
+
+ expect(document.addEventListener).toHaveBeenCalledWith('keyup', expect.any(Function));
+ });
});
describe('handleDragOnEnd', () => {
+ const getDragEndParam = (draggableItemType) => ({
+ oldIndex: 1,
+ newIndex: 0,
+ item: {
+ dataset: {
+ draggableItemType,
+ itemId: mockIssues[0].id,
+ itemIid: mockIssues[0].iid,
+ itemPath: mockIssues[0].referencePath,
+ },
+ },
+ to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
+ from: { dataset: { listId: 'gid://gitlab/List/2' } },
+ });
+
beforeEach(() => {
startDrag();
});
@@ -213,42 +243,39 @@ describe('Board list component', () => {
it('removes class `is-dragging` from document body', () => {
document.body.classList.add('is-dragging');
- endDrag({
- oldIndex: 1,
- newIndex: 0,
- item: {
- dataset: {
- draggableItemType: DraggableItemTypes.card,
- itemId: mockIssues[0].id,
- itemIid: mockIssues[0].iid,
- itemPath: mockIssues[0].referencePath,
- },
- },
- to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
- from: { dataset: { listId: 'gid://gitlab/List/2' } },
- });
+ endDrag(getDragEndParam(DraggableItemTypes.card));
expect(document.body.classList.contains('is-dragging')).toBe(false);
});
it(`should not handle the event if the dragged item is not a "${DraggableItemTypes.card}"`, () => {
- endDrag({
- oldIndex: 1,
- newIndex: 0,
- item: {
- dataset: {
- draggableItemType: DraggableItemTypes.list,
- itemId: mockIssues[0].id,
- itemIid: mockIssues[0].iid,
- itemPath: mockIssues[0].referencePath,
- },
- },
- to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
- from: { dataset: { listId: 'gid://gitlab/List/2' } },
- });
+ endDrag(getDragEndParam(DraggableItemTypes.list));
expect(document.body.classList.contains('is-dragging')).toBe(true);
});
+
+ it('detaches `keyup` event listener on document', async () => {
+ jest.spyOn(document, 'removeEventListener');
+
+ findDraggable().vm.$emit('end', getDragEndParam(DraggableItemTypes.card));
+ await nextTick();
+
+ expect(document.removeEventListener).toHaveBeenCalledWith('keyup', expect.any(Function));
+ });
+ });
+
+ describe('handleKeyUp', () => {
+ it('dispatches `mouseup` event when Escape key is pressed', () => {
+ jest.spyOn(document, 'dispatchEvent');
+
+ document.dispatchEvent(
+ new Event('keyup', {
+ keyCode: ESC_KEY_CODE,
+ }),
+ );
+
+ expect(document.dispatchEvent).toHaveBeenCalledWith(new Event('mouseup'));
+ });
});
});
diff --git a/spec/frontend/lib/utils/secret_detection_spec.js b/spec/frontend/lib/utils/secret_detection_spec.js
index 0d1bf1abbaa..b97827208d6 100644
--- a/spec/frontend/lib/utils/secret_detection_spec.js
+++ b/spec/frontend/lib/utils/secret_detection_spec.js
@@ -14,6 +14,8 @@ describe('containsSensitiveToken', () => {
'1234567890',
'!@#$%^&*()_+',
'https://example.com',
+ 'Some tokens are prefixed with glpat- or glcbt-, for example.',
+ 'glpat-FAKE',
];
it.each(nonSensitiveMessages)('returns false for message: %s', (message) => {
@@ -33,6 +35,8 @@ describe('containsSensitiveToken', () => {
'glpat-1234567890 and feed_token=ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'token: gldt-cgyKc1k_AsnEpmP-5fRL',
'curl "https://gitlab.example.com/api/v4/groups/33/scim/identities" --header "PRIVATE-TOKEN: glsoat-cgyKc1k_AsnEpmP-5fRL',
+ 'CI_JOB_TOKEN=glcbt-FFFF_cgyKc1k_AsnEpmP-5fRL',
+ 'Use this secret job token: glcbt-1_cgyKc1k_AsnEpmP-5fRL',
];
it.each(sensitiveMessages)('returns true for message: %s', (message) => {
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 18c7e57d464..af3f54c5f0a 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -5507,10 +5507,11 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
stub_current_partition_id
end
- it 'includes partition_id as a token prefix' do
- prefix = ci_build.token.split('_').first.to_i(16)
+ it 'includes partition_id in the token prefix' do
+ prefix = ci_build.token.match(/^glcbt-([\h]+)_/)
+ partition_prefix = prefix[1].to_i(16)
- expect(prefix).to eq(ci_testing_partition_id)
+ expect(partition_prefix).to eq(ci_testing_partition_id)
end
end
@@ -5648,7 +5649,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
it 'generates a token' do
expect { ci_build.enqueue }
- .to change { ci_build.token }.from(nil).to(a_string_starting_with(partition_id_prefix_in_16_bit_encode))
+ .to change { ci_build.token }.from(nil).to(a_string_starting_with("glcbt-#{partition_id_prefix_in_16_bit_encode}"))
end
end
@@ -5665,4 +5666,51 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
end
end
end
+
+ describe '#prefix_and_partition_for_token' do
+ # 100.to_s(16) -> 64
+ let(:ci_build) { described_class.new(partition_id: 100) }
+
+ shared_examples 'partition prefix' do
+ it 'is prefixed with partition_id' do
+ ci_build.ensure_token
+ expect(ci_build.token).to match(/^64_[\w-]{20}$/)
+ end
+ end
+
+ shared_examples 'static and partition prefixes' do
+ it 'is prefixed with static string and partition id' do
+ ci_build.ensure_token
+ expect(ci_build.token).to match(/^glcbt-64_[\w-]{20}$/)
+ end
+ end
+
+ it_behaves_like 'static and partition prefixes'
+
+ context 'when feature flag is globally disabled' do
+ before do
+ stub_feature_flags(prefix_ci_build_tokens: false)
+ end
+
+ it_behaves_like 'partition prefix'
+
+ context 'when enabled for a different project' do
+ let_it_be(:project) { create(:project) }
+
+ before do
+ stub_feature_flags(prefix_ci_build_tokens: project)
+ end
+
+ it_behaves_like 'partition prefix'
+ end
+
+ context 'when enabled for the project' do
+ before do
+ stub_feature_flags(prefix_ci_build_tokens: ci_build.project)
+ end
+
+ it_behaves_like 'static and partition prefixes'
+ end
+ end
+ end
end
diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb
index 382aabd45a1..941aa3734a3 100644
--- a/spec/requests/api/ci/jobs_spec.rb
+++ b/spec/requests/api/ci/jobs_spec.rb
@@ -70,6 +70,7 @@ RSpec.describe API::Ci::Jobs, feature_category: :continuous_integration do
expect(json_response['artifacts']).to be_an Array
expect(json_response['artifacts']).to be_empty
expect(json_response['web_url']).to be_present
+ expect(json_response['archived']).to eq(jobx.archived?)
end
end