Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-06-10 21:12:46 +00:00
parent 0c84203069
commit f7f7703e1e
33 changed files with 554 additions and 207 deletions

View File

@ -282,7 +282,6 @@ export default {
'ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_modal.vue',
'ee/app/assets/javascripts/insights/components/insights_chart.vue',
'ee/app/assets/javascripts/invite_members/components/invite_modal_base.vue',
'ee/app/assets/javascripts/merge_requests/components/reviewers/approval_summary.vue',
'ee/app/assets/javascripts/oncall_schedules/components/add_edit_schedule_form.vue',
'ee/app/assets/javascripts/oncall_schedules/components/oncall_schedule.vue',
'ee/app/assets/javascripts/oncall_schedules/components/rotations/components/rotation_assignee.vue',

View File

@ -16,7 +16,7 @@ variables:
# Retry failed specs in separate process
QA_RETRY_FAILED_SPECS: "true"
# Helm chart ref used by test-on-cng pipeline
GITLAB_HELM_CHART_REF: "5613c3aaf1cacdc6df7e05b96de980be74742116"
GITLAB_HELM_CHART_REF: "dd78d0e357b90c54a7a7073f9d6ac18e8cc06161"
# Specific ref for cng-mirror project to trigger builds for
GITLAB_CNG_MIRROR_REF: "df7aafcccafdbab732a7cf757efb3b7b74c851dd"
# Makes sure some of the common scripts from pipeline-common use bundler to execute commands

View File

@ -1 +1 @@
41a9a2963eb4f08f2ba15667d005377f6127fa4d
e7ca9463ccd7a3a3001d3d7d3ac21408b9632f6e

View File

@ -138,6 +138,7 @@ export const initSharedAccessTokenApp = () => {
const {
accessTokenMaxDate,
accessTokenMinDate,
accessTokenAvailableScopes,
accessTokenName,
accessTokenDescription,
accessTokenScopes,
@ -152,6 +153,7 @@ export const initSharedAccessTokenApp = () => {
name: 'AccessTokensRoot',
pinia,
provide: {
accessTokenAvailableScopes: JSON.parse(accessTokenAvailableScopes),
accessTokenMaxDate,
accessTokenMinDate,
accessTokenCreate,

View File

@ -1,5 +1,6 @@
<script>
import { GlBadge } from '@gitlab/ui';
import { camelCase } from 'lodash';
import { QUERIES } from '../constants';
export default {
@ -30,7 +31,7 @@ export default {
query: QUERIES[query].countQuery,
variables,
manual: true,
context: { batchKey: `MergeRequestTabsCounts` },
context: { batchKey: `MergeRequestTabsCounts_${camelCase(this.title)}` },
result({ data }) {
if (data?.currentUser) {
this.count += data?.currentUser?.mergeRequests?.count ?? 0;

View File

@ -33,7 +33,7 @@ export default {
MaxExpirationDateMessage: () =>
import('ee_component/vue_shared/components/access_tokens/max_expiration_date_message.vue'),
},
inject: ['accessTokenMaxDate', 'accessTokenMinDate'],
inject: ['accessTokenMaxDate', 'accessTokenMinDate', 'accessTokenAvailableScopes'],
props: {
name: {
type: String,
@ -85,72 +85,6 @@ export default {
helpScopes: helpPagePath('user/profile/personal_access_tokens', {
anchor: 'personal-access-token-scopes',
}),
scopes: [
{
value: 'read_service_ping',
text: s__(
'AccessTokens|Grant access to download Service Ping payload via API when authenticated as an admin user.',
),
},
{
value: 'read_user',
text: s__(
'AccessTokens|Grants read-only access to your profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users.',
),
},
{
value: 'read_repository',
text: s__(
'AccessTokens|Grants read-only access to repositories on private projects using Git-over-HTTP or the Repository Files API.',
),
},
{
value: 'read_api',
text: s__(
'AccessTokens|Grants read access to the API, including all groups and projects, the container registry, and the package registry.',
),
},
{
value: 'self_rotate',
text: s__('AccessTokens|Grants permission for token to rotate itself.'),
},
{
value: 'write_repository',
text: s__(
'AccessTokens|Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API).',
),
},
{
value: 'api',
text: s__(
'AccessTokens|Grants complete read/write access to the API, including all groups and projects, the container registry, the dependency proxy, and the package registry.',
),
},
{
value: 'ai_features',
text: s__('AccessTokens|Grants access to GitLab Duo related API endpoints.'),
},
{ value: 'create_runner', text: s__('AccessTokens|Grants create access to the runners.') },
{ value: 'manage_runner', text: s__('AccessTokens|Grants access to manage the runners.') },
{
value: 'k8s_proxy',
text: s__(
'AccessTokens|Grants permission to perform Kubernetes API calls using the agent for Kubernetes.',
),
},
{
value: 'sudo',
text: s__(
'AccessTokens|Grants permission to perform API actions as any user in the system, when authenticated as an admin user.',
),
},
{
value: 'admin_mode',
text: s__(
'AccessTokens|Grants permission to perform API actions as an administrator, when Admin Mode is enabled.',
),
},
],
fields: {
name: {
label: s__('AccessTokens|Token name'),
@ -232,7 +166,7 @@ export default {
<template #input(scopes)="{ id, input, validation, value }">
<gl-form-checkbox-group :id="id" :state="validation.state" :checked="value" @input="input">
<gl-form-checkbox
v-for="scope in $options.scopes"
v-for="scope in accessTokenAvailableScopes"
:key="scope.value"
:value="scope.value"
:state="validation.state"

View File

@ -1,8 +1,8 @@
@import '../mixins_and_variables_and_functions';
.geo-replicable-item-grid {
grid-template-columns: 8ch 1fr auto;
grid-gap: 1rem;
grid-template-columns: max-content 1fr auto;
grid-gap: 0.5rem;
}
.geo-replicable-filter-grid {

View File

@ -35,10 +35,24 @@ module AccessTokensHelper
}.to_json
end
def personal_access_token_data(token)
def filter_sort_scopes(scopes, sources)
scopes.select { |scope| ::Gitlab::Auth::UI_SCOPES_ORDERED_BY_PERMISSION.include?(scope) }
.sort_by { |scope| ::Gitlab::Auth::UI_SCOPES_ORDERED_BY_PERMISSION.index(scope) }
.map do |value|
{
value: value,
text: t(value, scope: sources)
}
end
end
def personal_access_token_data(token, user = current_user)
sources = scope_description(:personal_access_token)
scopes = ::Gitlab::Auth.available_scopes_for(user)
{
access_token: {
**expires_at_field_data,
available_scopes: filter_sort_scopes(scopes, sources).to_json,
name: token[:name],
description: token[:description],
scopes: token[:scopes].to_json,

View File

@ -96,17 +96,18 @@ module CrossDatabaseModification
end
def gitlab_schema
case self.name
when 'ActiveRecord::Base', 'ApplicationRecord'
dbname, conn = Gitlab::Database.all_database_connections.find { |(_, conn)| conn.klass.name == self.name }
if conn
:"gitlab_#{dbname}"
# DB connections do not reference ApplicationRecord directly as they are used to apply load balancing,
# so instead we use the module to determine if we are in the main database
elsif self.name == 'ApplicationRecord'
:gitlab_main
when 'SecApplicationRecord'
:gitlab_sec
when 'Ci::ApplicationRecord'
:gitlab_ci
when 'PackageMetadata::ApplicationRecord'
elsif self.name == 'PackageMetadata::ApplicationRecord'
:gitlab_pm
else
Gitlab::Database::GitlabSchema.table_schema(table_name) if table_name
elsif table_name
Gitlab::Database::GitlabSchema.table_schema(table_name)
end
end
end

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
files = git.added_files + git.modified_files
finalize_batched_background_migration_validator.validate_migrations(files)

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
require_relative '../../tooling/danger/finalize_batched_background_migration_validator_helper'
module Danger
class FinalizeBatchedBackgroundMigrationValidator < ::Danger::Plugin
# Put the helper code somewhere it can be tested
include Tooling::Danger::FinalizeBatchedBackgroundMigrationValidatorHelper
end
end

View File

@ -0,0 +1,13 @@
---
table_name: workspace_tokens
classes:
- RemoteDevelopment::WorkspaceToken
feature_categories:
- workspaces
description: Stores the token associated with a workspace
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193071
milestone: '18.1'
gitlab_schema: gitlab_main_cell
sharding_key:
project_id: projects
table_size: small

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class CreateWorkspaceTokens < Gitlab::Database::Migration[2.3]
milestone '18.1'
# @return [void]
def change
create_table :workspace_tokens do |t|
t.references :workspace, foreign_key: { on_delete: :cascade }, null: false, index: { unique: true }
t.timestamps_with_timezone null: false
t.bigint :project_id, null: false, index: true
t.text :token_encrypted, limit: 512, null: false
t.check_constraint 'char_length(token_encrypted) <= 512'
end
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class AddProjectIdForeignKeyToWorkspaceTokens < Gitlab::Database::Migration[2.3]
disable_ddl_transaction!
milestone '18.1'
def up
add_concurrent_foreign_key :workspace_tokens, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :workspace_tokens, column: :project_id
end
end
end

View File

@ -0,0 +1 @@
00efa3926632481160d4c4e2bf87bbddd19a32cd52515534e65e4a4dcfe3ab29

View File

@ -0,0 +1 @@
d5096916ba707df9a6939c0703a2577fc8c244acd9a8c3304c0d83e697e149bb

View File

@ -26121,6 +26121,26 @@ CREATE SEQUENCE workspace_agentk_states_id_seq
ALTER SEQUENCE workspace_agentk_states_id_seq OWNED BY workspace_agentk_states.id;
CREATE TABLE workspace_tokens (
id bigint NOT NULL,
workspace_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
project_id bigint NOT NULL,
token_encrypted text NOT NULL,
CONSTRAINT check_35b32b26d3 CHECK ((char_length(token_encrypted) <= 512)),
CONSTRAINT chk_rails_78f4622c4e CHECK ((char_length(token_encrypted) <= 512))
);
CREATE SEQUENCE workspace_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE workspace_tokens_id_seq OWNED BY workspace_tokens.id;
CREATE TABLE workspace_variables (
id bigint NOT NULL,
workspace_id bigint NOT NULL,
@ -28354,6 +28374,8 @@ ALTER TABLE ONLY work_item_widget_definitions ALTER COLUMN id SET DEFAULT nextva
ALTER TABLE ONLY workspace_agentk_states ALTER COLUMN id SET DEFAULT nextval('workspace_agentk_states_id_seq'::regclass);
ALTER TABLE ONLY workspace_tokens ALTER COLUMN id SET DEFAULT nextval('workspace_tokens_id_seq'::regclass);
ALTER TABLE ONLY workspace_variables ALTER COLUMN id SET DEFAULT nextval('workspace_variables_id_seq'::regclass);
ALTER TABLE ONLY workspaces ALTER COLUMN id SET DEFAULT nextval('workspaces_id_seq'::regclass);
@ -31594,6 +31616,9 @@ ALTER TABLE ONLY work_item_widget_definitions
ALTER TABLE ONLY workspace_agentk_states
ADD CONSTRAINT workspace_agentk_states_pkey PRIMARY KEY (id);
ALTER TABLE ONLY workspace_tokens
ADD CONSTRAINT workspace_tokens_pkey PRIMARY KEY (id);
ALTER TABLE ONLY workspace_variables
ADD CONSTRAINT workspace_variables_pkey PRIMARY KEY (id);
@ -38226,6 +38251,10 @@ CREATE INDEX index_workspace_agentk_states_on_project_id ON workspace_agentk_sta
CREATE UNIQUE INDEX index_workspace_agentk_states_on_workspace_id ON workspace_agentk_states USING btree (workspace_id);
CREATE INDEX index_workspace_tokens_on_project_id ON workspace_tokens USING btree (project_id);
CREATE UNIQUE INDEX index_workspace_tokens_on_workspace_id ON workspace_tokens USING btree (workspace_id);
CREATE INDEX index_workspace_variables_on_project_id ON workspace_variables USING btree (project_id);
CREATE INDEX index_workspace_variables_on_workspace_id ON workspace_variables USING btree (workspace_id);
@ -42673,6 +42702,9 @@ ALTER TABLE ONLY merge_request_diffs
ALTER TABLE ONLY ml_candidates
ADD CONSTRAINT fk_56d6ed4d3d FOREIGN KEY (experiment_id) REFERENCES ml_experiments(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_tokens
ADD CONSTRAINT fk_5724f2499d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY projects_branch_rules_squash_options
ADD CONSTRAINT fk_574b8d531f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@ -44947,6 +44979,9 @@ ALTER TABLE ONLY work_item_parent_links
ALTER TABLE ONLY system_access_microsoft_graph_access_tokens
ADD CONSTRAINT fk_rails_604908851f FOREIGN KEY (system_access_microsoft_application_id) REFERENCES system_access_microsoft_applications(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_tokens
ADD CONSTRAINT fk_rails_60666321a4 FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_state_transitions
ADD CONSTRAINT fk_rails_60e4899648 FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;

View File

@ -1485,14 +1485,13 @@ background migration.
```ruby
class FinalizeBackfillRouteNamespaceId < Gitlab::Database::Migration[2.1]
MIGRATION = 'BackfillRouteNamespaceId'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
ensure_batched_background_migration_is_finished(
job_class_name: MIGRATION,
job_class_name: 'BackfillRouteNamespaceId',
table_name: :routes,
column_name: :id,
job_arguments: [],

View File

@ -115,10 +115,17 @@ consume system resources. You can use the following settings and configuration d
mattermost_external_url 'http://mattermost.example.com'
# Shut down GitLab services on the Mattermost server
alertmanager['enable'] = false
gitlab_exporter['enable'] = false
gitlab_kas['enable'] = false
gitlab_rails['enable'] = false
redis['enable'] = false
postgres_exporter['enable'] = false
grafana['enable'] = false
letsencrypt['enable'] = false
node_exporter['enable'] = false
postgres_exporter['enable'] = false
prometheus['enable'] = false
redis_exporter['enable'] = false
redis['enable'] = false
```
Then follow the appropriate steps in the [Authorize GitLab Mattermost section](#authorize-gitlab-mattermost). Last, to enable

View File

@ -37,21 +37,22 @@ Group items that are migrated to the destination GitLab instance include:
<!-- vale gitlab_base.OutdatedVersions = NO -->
| Group item | Introduced in |
|:---------------------|:----------------------------------------------------------------------------|
| Badges | [GitLab 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/292431) |
| Boards | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) |
| Board lists | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24863) |
| Epics <sup>1</sup> | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/250281) |
| Group labels <sup>2</sup> | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) |
| Iterations | [GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292428) |
| Iteration cadences | [GitLab 15.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96570) |
| Members <sup>3</sup> | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/299415) |
| Group milestones | [GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292427) |
| Namespace settings | [GitLab 14.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85128) |
| Release milestones | [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/339422) |
| Subgroups | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) |
| Uploads | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) |
| Group item | Introduced in |
| ------------------------- | ------------- |
| Badges | [GitLab 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/292431) |
| Board lists | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24863) |
| Boards | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) |
| Epics <sup>1</sup> | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/250281) |
| Group labels <sup>2</sup> | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) |
| Group milestones | [GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292427) |
| Iteration cadences | [GitLab 15.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96570) |
| Iterations | [GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292428) |
| Members <sup>3</sup> | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/299415) |
| Namespace settings | [GitLab 14.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85128) |
| Release milestones | [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/339422) |
| Subgroups | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) |
| Uploads | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) |
| Wikis | [GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/issues/345923) |
**Footnotes**:
@ -242,6 +243,7 @@ Some project items are excluded from migration because they:
from GitLab Self-Managed to GitLab.com or GitLab Dedicated
- Linked issues
- Merge request approval rules
- Wiki comments
{{< alert type="note" >}}

View File

@ -18,8 +18,8 @@ title: Test a new look for issues
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/9584) in GitLab 17.5 [with a flag](../../../administration/feature_flags.md) named `work_items_view_preference`. Disabled by default. This feature is in [beta](../../../policy/development_stages_support.md#beta).
- Feature flag named `work_items_view_preference` enabled on GitLab.com in GitLab 17.9 for a subset of users.
- Feature flag named `work_items_view_preference` [enabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184496) on GitLab.com, GitLab Self-Managed, and GitLab Dedicated in 17.10.
- **New look** toggle [hidden](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/182330) with feature flag named `work_item_view_for_issues`. Flag enabled on GitLab.com, GitLab Self-Managed, and GitLab Dedicated in 17.11.
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/482931) in GitLab 18.2. Feature flag `work_items_view_preference` removed.
- [Enabled on GitLab.com, GitLab Self-Managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/482931) in GitLab 17.11.
- [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/482931) to feature flag named `work_item_view_for_issues` in GitLab 18.1. Enabled on GitLab.com, GitLab Self-Managed, and GitLab Dedicated. Feature flag `work_items_view_preference` removed.
{{< /history >}}
@ -61,15 +61,6 @@ The new issues experience includes these improvements:
only exist in groups.
- **Development**: Merge requests, branches, and feature flags related to this item are shown in a single list.
## Toggle the new experience
When you view the Issues page or issue detail page, you can toggle the new experience.
To toggle the new issue look:
1. In the upper-right corner look for the **New look** badge.
1. Select the badge to toggle the experience on or off.
## Related topics
- [Test a new look for epics](../../group/epics/epic_work_items.md)

View File

@ -809,7 +809,7 @@ You can use the OR operator (**is one of: `||`**) when you [filter the list of i
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/464063) in GitLab 17.4 [with a flag](../../../administration/feature_flags.md) named `issues_list_drawer`. Disabled by default.
- In GitLab 17.11, if [the new look for issues](issue_work_items.md) is enabled, this feature is also enabled.
- In GitLab 17.11 and later, if [the new look for issues](issue_work_items.md) is enabled, this feature is also enabled.
{{< /history >}}

View File

@ -76,6 +76,31 @@ module Gitlab
# Default scopes for OAuth applications that don't define their own
DEFAULT_SCOPES = [API_SCOPE].freeze
# Scopes ordered by permission level, from lowest to highest.
# This is used to determine the order of scopes in the UI.
# If the scope is not present in this list, it won't appear in the UI.
UI_SCOPES_ORDERED_BY_PERMISSION = [
READ_SERVICE_PING_SCOPE,
READ_USER_SCOPE,
READ_REPOSITORY_SCOPE,
READ_OBSERVABILITY_SCOPE,
READ_VIRTUAL_REGISTRY_SCOPE,
READ_REGISTRY_SCOPE,
READ_API_SCOPE,
SELF_ROTATE_SCOPE,
WRITE_REPOSITORY_SCOPE,
WRITE_OBSERVABILITY_SCOPE,
WRITE_VIRTUAL_REGISTRY_SCOPE,
WRITE_REGISTRY_SCOPE,
API_SCOPE,
AI_FEATURES,
CREATE_RUNNER_SCOPE,
MANAGE_RUNNER_SCOPE,
K8S_PROXY_SCOPE,
ADMIN_MODE_SCOPE,
SUDO_SCOPE
].freeze
CI_JOB_USER = 'gitlab-ci-token'
class << self

View File

@ -3139,45 +3139,6 @@ msgstr ""
msgid "AccessTokens|Forces new personal, group, project and impersonation tokens to require an expiration date. Does not affect existing token expiration dates or personal access tokens for service accounts. This setting overrides the group-level %{link_start}service account token expiration%{link_end} setting."
msgstr ""
msgid "AccessTokens|Grant access to download Service Ping payload via API when authenticated as an admin user."
msgstr ""
msgid "AccessTokens|Grants access to GitLab Duo related API endpoints."
msgstr ""
msgid "AccessTokens|Grants access to manage the runners."
msgstr ""
msgid "AccessTokens|Grants complete read/write access to the API, including all groups and projects, the container registry, the dependency proxy, and the package registry."
msgstr ""
msgid "AccessTokens|Grants create access to the runners."
msgstr ""
msgid "AccessTokens|Grants permission for token to rotate itself."
msgstr ""
msgid "AccessTokens|Grants permission to perform API actions as an administrator, when Admin Mode is enabled."
msgstr ""
msgid "AccessTokens|Grants permission to perform API actions as any user in the system, when authenticated as an admin user."
msgstr ""
msgid "AccessTokens|Grants permission to perform Kubernetes API calls using the agent for Kubernetes."
msgstr ""
msgid "AccessTokens|Grants read access to the API, including all groups and projects, the container registry, and the package registry."
msgstr ""
msgid "AccessTokens|Grants read-only access to repositories on private projects using Git-over-HTTP or the Repository Files API."
msgstr ""
msgid "AccessTokens|Grants read-only access to your profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users."
msgstr ""
msgid "AccessTokens|Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API)."
msgstr ""
msgid "AccessTokens|How do I use DPoP?"
msgstr ""
@ -27851,6 +27812,9 @@ msgstr ""
msgid "Geo|Replication summary"
msgstr ""
msgid "Geo|Replication: %{status}"
msgstr ""
msgid "Geo|Repository synchronization concurrency limit"
msgstr ""

View File

@ -248,7 +248,7 @@
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.15.0",
"@gitlab/eslint-plugin": "20.7.1",
"@gitlab/eslint-plugin": "21.0.0",
"@gitlab/noop": "^1.0.1",
"@gitlab/stylelint-config": "6.2.2",
"@graphql-eslint/eslint-plugin": "4.4.0",

View File

@ -22,6 +22,11 @@ describe('AccessTokenForm', () => {
const accessTokenMaxDate = '2021-07-06';
const accessTokenMinDate = '2020-07-06';
const accessTokenAvailableScopes = [
{ value: 'read_service_ping', text: 'scope 1' },
{ value: 'read_user', text: 'scope 2' },
{ value: 'other', text: 'scope 3' },
];
const createComponent = (props = {}) => {
wrapper = mountExtended(AccessTokenForm, {
@ -29,6 +34,7 @@ describe('AccessTokenForm', () => {
provide: {
accessTokenMaxDate,
accessTokenMinDate,
accessTokenAvailableScopes,
},
propsData: {
...props,
@ -82,12 +88,10 @@ describe('AccessTokenForm', () => {
createComponent();
const checkboxes = findCheckboxes();
expect(checkboxes).toHaveLength(13);
expect(checkboxes).toHaveLength(3);
const checkbox = checkboxes.at(0);
expect(checkbox.find('input').element.value).toBe('read_service_ping');
expect(checkbox.find('label').text()).toContain(
'Grant access to download Service Ping payload via API when authenticated as an admin user.',
);
expect(checkbox.find('label').text()).toContain('scope 1');
});
describe('reset button', () => {

View File

@ -66,6 +66,17 @@ RSpec.describe AccessTokensHelper, feature_category: :system_access do
end
end
describe '#filter_sort_scopes' do
it 'excludes unknown scopes' do
expect(helper.filter_sort_scopes([:dummy], [:doorkeeper])).to match([])
end
it 'sort scopes' do
expect(helper.filter_sort_scopes([:sudo, :admin_mode],
[:doorkeeper])).to match([{ text: String, value: :admin_mode }, { text: String, value: :sudo }])
end
end
describe '#personal_access_token_data' do
before do
allow(helper).to receive_messages(
@ -77,10 +88,11 @@ RSpec.describe AccessTokensHelper, feature_category: :system_access do
it 'returns data for the PATs UI in the user settings' do
expect(helper.personal_access_token_data({ name: 'My token',
description: 'My description',
scopes: [:api, :sudo] })).to match(a_hash_including({
scopes: [:api, :sudo] }, 'dummy_user')).to match(a_hash_including({
access_token: {
max_date: '2022-03-02',
min_date: '2022-03-02',
available_scopes: '[]',
name: 'My token',
description: 'My description',
scopes: '["api","sudo"]',

View File

@ -46,14 +46,11 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
describe 'available_scopes' do
before do
stub_container_registry_config(enabled: true)
stub_config(dependency_proxy: { enabled: true })
end
it 'contains all non-default scopes' do
expect(subject.all_available_scopes).to match_array %i[
api read_user read_api read_repository read_service_ping write_repository read_registry write_registry
sudo admin_mode read_observability write_observability create_runner manage_runner k8s_proxy ai_features
self_rotate
]
expect(subject.all_available_scopes).to match_array(subject::UI_SCOPES_ORDERED_BY_PERMISSION)
end
it 'contains for non-admin user all non-default scopes without ADMIN access and without observability scopes' do
@ -61,7 +58,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(user)).to match_array %i[
api read_user read_api read_repository write_repository read_registry write_registry
create_runner manage_runner k8s_proxy ai_features self_rotate
create_runner manage_runner k8s_proxy ai_features self_rotate read_virtual_registry write_virtual_registry
]
end
@ -70,7 +67,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(user)).to match_array %i[
api read_user read_api read_repository read_service_ping write_repository read_registry write_registry
sudo admin_mode create_runner manage_runner k8s_proxy ai_features self_rotate
sudo admin_mode create_runner manage_runner k8s_proxy ai_features self_rotate read_virtual_registry write_virtual_registry
]
end
@ -88,7 +85,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(group)).to match_array %i[
api read_api read_repository write_repository read_registry write_registry
read_observability write_observability create_runner manage_runner k8s_proxy ai_features
self_rotate
self_rotate read_virtual_registry write_virtual_registry
]
end
@ -119,6 +116,8 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
write_observability
write_registry
write_repository
read_virtual_registry
write_virtual_registry
]
end
@ -135,7 +134,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(group)).to match_array %i[
api read_api read_repository write_repository read_registry write_registry create_runner manage_runner
k8s_proxy ai_features self_rotate
k8s_proxy ai_features self_rotate read_virtual_registry write_virtual_registry
]
end
@ -168,7 +167,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(group)).to match_array %i[
api read_api read_repository write_repository read_registry write_registry
read_observability write_observability create_runner manage_runner k8s_proxy ai_features
self_rotate
self_rotate read_virtual_registry write_virtual_registry
]
end
@ -177,7 +176,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(user)).to match_array %i[
api read_user read_api read_repository write_repository read_registry write_registry read_service_ping
sudo admin_mode create_runner manage_runner k8s_proxy ai_features self_rotate
sudo admin_mode create_runner manage_runner k8s_proxy ai_features self_rotate read_virtual_registry write_virtual_registry
]
end
@ -198,7 +197,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
expect(subject.available_scopes_for(other_group)).to match_array %i[
api read_api read_repository write_repository read_registry write_registry
create_runner manage_runner k8s_proxy ai_features
self_rotate
self_rotate read_virtual_registry write_virtual_registry
]
end
@ -253,10 +252,6 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
context 'when dependency proxy is enabled' do
let(:virtual_registry_scopes) { %i[read_virtual_registry write_virtual_registry] }
before do
stub_config(dependency_proxy: { enabled: true })
end
it 'contains all virtual registry related scopes' do
expect(subject.virtual_registry_scopes).to eq virtual_registry_scopes
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe CrossDatabaseModification do
RSpec.describe CrossDatabaseModification, feature_category: 'database' do
describe '.transaction' do
it 'adds the current gitlab schema to gitlab_transactions_stack', :aggregate_failures do
ApplicationRecord.transaction do

View File

@ -13,6 +13,7 @@
- Security::VulnerabilityElasticSearchFinder # Reason: The finder deals with Elasticsearch records and not DB records
- Security::VulnerabilityElasticIdentifierNamesFinder # Reason: The finder deals with Elasticsearch records and not DB records
- Security::VulnerabilityElasticCountBySeverityFinder # Reason: The finder deals with Elasticsearch records and not DB records
- Security::VulnerabilityElasticCountOverTimeFinder # Reason: The finder deals with Elasticsearch records and not DB records
# Temporary excludes (aka TODOs)
# For example:

View File

@ -0,0 +1,255 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'gitlab/dangerfiles/spec_helper'
require_relative '../../../tooling/danger/finalize_batched_background_migration_validator_helper'
require_relative '../../../tooling/danger/project_helper'
RSpec.describe Tooling::Danger::FinalizeBatchedBackgroundMigrationValidatorHelper, feature_category: :database do
include_context "with dangerfile"
let(:fake_project_helper) { instance_double(Tooling::Danger::ProjectHelper) }
let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
let(:valid_file_path) { 'db/post_migrate/20230101000000_finalize_migration.rb' }
let(:invalid_file_path) { 'app/models/user.rb' }
let(:helper) { fake_danger.new(helper: fake_project_helper) }
describe '#validate_migrations' do
context 'when no post migrate files are present' do
it 'returns early' do
expect(helper).not_to receive(:display_errors)
helper.validate_migrations([invalid_file_path])
end
end
context 'when post migrate files are present' do
before do
allow(File).to receive(:read).and_call_original
allow(File).to receive(:read).with(valid_file_path).and_return(file_content)
end
context 'with no ensure_batched_background_migration_is_finished call' do
let(:file_content) do
<<~RUBY
class QueueMigration < Gitlab::Database::Migration[2.2]
def up
queue_batched_background_migration(
)
end
end
RUBY
end
it 'does not report any errors' do
expect(helper).to receive(:display_errors).with([])
helper.validate_migrations([valid_file_path])
end
end
context 'with valid content' do
let(:file_content) do
<<~RUBY
class FinalizeMigration < Gitlab::Database::Migration[2.2]
def up
ensure_batched_background_migration_is_finished(
job_class_name: 'MigrationClass',
table_name: :users,
column_name: :id,
job_arguments: []
)
end
end
RUBY
end
it 'does not report any errors' do
expect(helper).to receive(:display_errors).with([])
helper.validate_migrations([valid_file_path])
end
end
context 'with a constant instead of string for job_class_name' do
let(:file_content) do
<<~RUBY
class FinalizeMigration < Gitlab::Database::Migration[2.2]
def up
ensure_batched_background_migration_is_finished(
job_class_name: MyMigrationClass,
table_name: :users,
column_name: :id,
job_arguments: []
)
end
end
RUBY
end
it 'reports an error about job_class_name' do
expect(helper).to receive(:display_errors) do |errors|
expect(errors.length).to eq(1)
expect(errors.first[:message]).to include('The value of job_class_name should be a string in PascalCase')
end
helper.validate_migrations([valid_file_path])
end
end
context 'with multiple ensure_batched_background_migration_is_finished calls' do
let(:file_content) do
<<~RUBY
class FinalizeMigration < Gitlab::Database::Migration[2.2]
def up
first_finalize_migration
second_finalize_migration
end
def first_finalize_migration
ensure_batched_background_migration_is_finished(
job_class_name: 'MigrationClass1',
table_name: :users,
column_name: :id,
job_arguments: []
)
end
def second_finalize_migration
ensure_batched_background_migration_is_finished(
job_class_name: 'MigrationClass2',
table_name: :projects,
column_name: :id,
job_arguments: []
)
end
end
RUBY
end
it 'reports an error about multiple migrations' do
expect(helper).to receive(:display_errors) do |errors|
expect(errors.length).to eq(1)
expect(errors.first[:message]).to include('There should only be one finalize batched background migration')
end
helper.validate_migrations([valid_file_path])
end
end
context 'with multiple errors' do
let(:file_content) do
<<~RUBY
class FinalizeMigration < Gitlab::Database::Migration[2.2]
def up
first_finalize_migration
second_finalize_migration
end
def first_finalize_migration
ensure_batched_background_migration_is_finished(
job_class_name: MigrationClass1,
table_name: :users,
column_name: :id,
job_arguments: []
)
end
def second_finalize_migration
ensure_batched_background_migration_is_finished(
job_class_name: MigrationClass2,
table_name: :projects,
column_name: :id,
job_arguments: []
)
end
end
RUBY
end
it 'reports both errors' do
expect(helper).to receive(:display_errors) do |errors|
expect(errors.length).to eq(2)
expect(errors.pluck(:message)).to include(
a_string_matching('There should only be one finalize batched background migration'),
a_string_matching('The value of job_class_name should be a string in PascalCase')
)
end
helper.validate_migrations([valid_file_path])
end
end
end
end
describe '#validate_job_class_name_format' do
it 'returns nil when job_class_name is a string' do
file_content = <<~RUBY
ensure_batched_background_migration_is_finished(
job_class_name: "MigrationClass",
table_name: :users
)
RUBY
expect(helper.validate_job_class_name_format(valid_file_path, file_content)).to be_nil
end
it 'returns an error when job_class_name value is a constant' do
file_content = <<~RUBY
ensure_batched_background_migration_is_finished(
job_class_name: MigrationClass,
table_name: :users
)
RUBY
result = helper.validate_job_class_name_format(valid_file_path, file_content)
expect(result).to be_a(Hash)
expect(result[:message]).to include('The value of job_class_name should be a string in PascalCase')
end
end
describe '#validate_migration_count' do
it 'returns nil when exactly one migration is present' do
file_content = <<~RUBY
ensure_batched_background_migration_is_finished(
job_class_name: 'MigrationClass',
table_name: :users
)
RUBY
expect(helper.validate_migration_count(valid_file_path, file_content)).to be_nil
end
it 'returns an error when multiple migrations are present' do
file_content = <<~RUBY
ensure_batched_background_migration_is_finished(job_class_name: 'First')
ensure_batched_background_migration_is_finished(job_class_name: 'Second')
RUBY
result = helper.validate_migration_count(valid_file_path, file_content)
expect(result).to be_a(Hash)
expect(result[:message]).to include('There should only be one finalize batched background migration')
end
end
describe '#display_errors' do
it 'returns nil when no errors are present' do
expect(helper.display_errors([])).to be_nil
end
it 'calls fail with formatted error messages when errors are present' do
errors = [
{ file: 'file1.rb', message: 'Error 1' },
{ file: 'file2.rb', message: 'Error 2' }
]
expected_messages = [
'**file1.rb**: Error 1',
'**file2.rb**: Error 2'
]
expect(helper).to receive(:fail).with(expected_messages)
helper.display_errors(errors)
end
end
end

View File

@ -0,0 +1,61 @@
# frozen_string_literal: true
module Tooling
module Danger
module FinalizeBatchedBackgroundMigrationValidatorHelper
POST_MIGRATE_PATH = [
'db/post_migrate',
'ee/db/geo/post_migrate',
'ee/db/embedding/post_migrate'
].freeze
def validate_migrations(changed_files)
post_migrate_migrations = changed_files.select { |f| f.match?(%r{^(?:#{POST_MIGRATE_PATH.join('|')})/.+$}) }
return if post_migrate_migrations.empty?
errors = []
post_migrate_migrations.each do |file_path|
file_content = File.read(file_path)
# Check only finalize batched background migration files
next unless file_content.include?('ensure_batched_background_migration_is_finished')
errors << validate_job_class_name_format(file_path, file_content)
errors << validate_migration_count(file_path, file_content)
end
display_errors(errors.compact)
end
def validate_job_class_name_format(file_path, file_content)
return unless file_content.include?('job_class_name')
return if file_content.match?(/job_class_name:[ \t]*["'][A-Za-z0-9]+["']/)
{ file: file_path,
message: "The value of job_class_name should be a string in PascalCase e.g 'FinalizeMigrationClass' " }
end
def validate_migration_count(file_path, file_content)
occurrences = file_content.scan(/ensure_batched_background_migration_is_finished/).count
return unless occurrences != 1
{ file: file_path, message: "There should only be one finalize batched background migration per class" }
end
def display_errors(errors)
return if errors.empty?
failure_messages = errors.map do |error|
"**#{error[:file]}**: #{error[:message]}"
end
return unless failure_messages.any?
fail(failure_messages)
end
end
end
end

View File

@ -1404,13 +1404,13 @@
vue-resizable "1.3.4"
vue-runtime-helpers "^1.1.2"
"@gitlab/eslint-plugin@20.7.1":
version "20.7.1"
resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-20.7.1.tgz#89dfb95bf6ffec50bd7d9bace42622634a529cf0"
integrity sha512-BSB5SC86ITaauEab0HMWLTiaA1QgFlwz5keoO8YQ0JSjPaKusVOGDYDoxQHtZVuRBVfYQi0Cwf5dSWiHJWAeEw==
"@gitlab/eslint-plugin@21.0.0":
version "21.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-21.0.0.tgz#293913ba721534f7074dd88f515cfa6e7f8b6682"
integrity sha512-ag2q6NltsDBaTwIjpZgUvIYtp/WcHaJoq/wVGFJPywCT56N3qFgvF3tHNoHOOxfq/IliNipUTGpEXXD7Kwwslw==
dependencies:
"@typescript-eslint/eslint-plugin" "^7.14.1"
eslint-config-airbnb-base "^15.0.0"
confusing-browser-globals "^1.0.11"
eslint-config-prettier "^9.1.0"
eslint-plugin-import "^2.29.1"
eslint-plugin-jest "^28.6.0"
@ -5621,10 +5621,10 @@ config-chain@^1.1.13:
ini "^1.3.4"
proto-list "~1.2.1"
confusing-browser-globals@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59"
integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==
confusing-browser-globals@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==
connect-history-api-fallback@^2.0.0:
version "2.0.0"
@ -7122,7 +7122,7 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
es-abstract@^1.19.1, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2:
es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2:
version "1.23.3"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0"
integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==
@ -7418,16 +7418,6 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
eslint-config-airbnb-base@^15.0.0:
version "15.0.0"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236"
integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==
dependencies:
confusing-browser-globals "^1.0.10"
object.assign "^4.1.2"
object.entries "^1.1.5"
semver "^6.3.0"
eslint-config-prettier@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"
@ -11625,7 +11615,7 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
object.assign@^4.1.2, object.assign@^4.1.5:
object.assign@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0"
integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==
@ -11635,15 +11625,6 @@ object.assign@^4.1.2, object.assign@^4.1.5:
has-symbols "^1.0.3"
object-keys "^1.1.1"
object.entries@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861"
integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.3"
es-abstract "^1.19.1"
object.fromentries@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65"