Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
2ef2c32853
commit
47970fc5b7
|
|
@ -1 +1 @@
|
|||
6dc57705f4d70c87ea803faa572e5bb844cbc569
|
||||
dd5a7ec67062bdb145fa2f66385a9bea72ccce1f
|
||||
|
|
|
|||
|
|
@ -47,7 +47,10 @@ module MergeRequests
|
|||
delegate :project, :author_id, :changed_paths, to: :merge_request
|
||||
|
||||
def contains_locked_lfs_files?
|
||||
project.lfs_file_locks.for_paths(changed_paths.map(&:path)).not_for_users(author_id).exists?
|
||||
return false unless project.lfs_file_locks.exists?
|
||||
|
||||
paths = changed_paths.map(&:path).uniq
|
||||
project.lfs_file_locks.for_paths(paths).not_for_users(author_id).exists?
|
||||
end
|
||||
|
||||
def check_inactive?
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
.syntax-theme.row
|
||||
- Gitlab::ColorSchemes.each do |scheme|
|
||||
%label.col-6.col-sm-4.col-md-3.col-lg-auto.gl-mb-5
|
||||
.preview= image_tag "#{scheme.css_class}-scheme-preview.png"
|
||||
.preview= image_tag "#{scheme.css_class}-scheme-preview.png", alt: "#{scheme.css_class}-scheme-preview.png"
|
||||
= f.gitlab_ui_radio_component :color_scheme_id, scheme.id,
|
||||
scheme.name,
|
||||
radio_options: { checked: user_color_schema_id == scheme.id }
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@ ci_group_variables:
|
|||
- table: namespaces
|
||||
column: group_id
|
||||
on_delete: async_delete
|
||||
ci_instance_runner_monthly_usages:
|
||||
- table: namespaces
|
||||
column: root_namespace_id
|
||||
on_delete: async_delete
|
||||
- table: projects
|
||||
column: project_id
|
||||
on_delete: async_nullify
|
||||
ci_job_token_authorizations:
|
||||
- table: projects
|
||||
column: origin_project_id
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
table_name: ci_gitlab_hosted_runner_monthly_usages
|
||||
classes:
|
||||
- Ci::Minutes::GitlabHostedRunnerMonthlyUsage
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
description: Per month CI usage data at the runner and project level meant to store
|
||||
GitLab hosted runners data on Dedicated installations only.
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/171336
|
||||
milestone: '17.9'
|
||||
gitlab_schema: gitlab_ci
|
||||
exempt_from_sharding: true
|
||||
notes: Exempted from sharding because Dedicated only.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
table_name: ci_instance_runner_monthly_usages
|
||||
classes:
|
||||
- Ci::Minutes::InstanceRunnerMonthlyUsage
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
description: Per month CI usage data at the runner and project level meant to store
|
||||
instance runner usage except hosted runners on dedicated
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/171336
|
||||
milestone: '17.9'
|
||||
gitlab_schema: gitlab_ci
|
||||
sharding_key:
|
||||
# The table entries belong to a namespace/group only
|
||||
# We don't shard on projects because the usage is recorded as caused by a project but shouldn't move with that project
|
||||
# the usage should stay with it's root namespace even if the project moves
|
||||
root_namespace_id: namespaces
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateCiInstanceRunnerMonthlyUsages < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
# rubocop:disable Migration/EnsureFactoryForTable -- False Positive
|
||||
create_table :ci_instance_runner_monthly_usages do |t|
|
||||
# 8 bytes
|
||||
t.references :runner,
|
||||
type: :bigint, index: false, null: true,
|
||||
foreign_key: { to_table: :ci_runners, on_delete: :nullify }
|
||||
t.bigint :runner_duration_seconds, null: false, default: 0
|
||||
t.bigint :project_id, null: true
|
||||
t.bigint :root_namespace_id, null: false
|
||||
t.timestamps_with_timezone null: false
|
||||
# 4 bytes
|
||||
t.date :billing_month, null: false
|
||||
t.integer :notification_level, null: false, default: 100
|
||||
# variables bytes
|
||||
t.decimal :compute_minutes_used, precision: 18, scale: 4, null: false, default: 0.0
|
||||
end
|
||||
|
||||
add_index :ci_instance_runner_monthly_usages, [:root_namespace_id, :billing_month],
|
||||
name: 'index_ci_instance_runner_monthly_usages_on_namespace_and_month'
|
||||
|
||||
add_index :ci_instance_runner_monthly_usages, [:project_id, :billing_month],
|
||||
name: 'index_ci_instance_runner_monthly_usages_on_project_and_month'
|
||||
|
||||
add_index :ci_instance_runner_monthly_usages,
|
||||
[:runner_id, :billing_month, :root_namespace_id, :project_id],
|
||||
name: 'idx_instance_runner_usage_unique',
|
||||
unique: true
|
||||
|
||||
add_check_constraint(
|
||||
:ci_instance_runner_monthly_usages,
|
||||
"(billing_month = date_trunc('month', billing_month::timestamp with time zone))",
|
||||
'ci_instance_runner_monthly_usages_year_month_constraint'
|
||||
)
|
||||
# rubocop:enable Migration/EnsureFactoryForTable -- False Positive
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :ci_instance_runner_monthly_usages if table_exists? :ci_instance_runner_monthly_usages
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Dedicated only
|
||||
class CreateCiGitlabHostedRunnerMonthlyUsages < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.9'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
# rubocop:disable Migration/EnsureFactoryForTable -- False Positive
|
||||
create_table :ci_gitlab_hosted_runner_monthly_usages do |t|
|
||||
# 8 bytes
|
||||
t.references :runner,
|
||||
type: :bigint, index: false, null: false
|
||||
t.bigint :runner_duration_seconds, null: false, default: 0
|
||||
t.bigint :project_id, null: false
|
||||
t.bigint :root_namespace_id, null: false
|
||||
t.timestamps_with_timezone null: false
|
||||
# 4 bytes
|
||||
t.date :billing_month, null: false
|
||||
t.integer :notification_level, null: false, default: 100
|
||||
# variables bytes
|
||||
t.decimal :compute_minutes_used, precision: 18, scale: 4, null: false, default: 0.0
|
||||
end
|
||||
|
||||
add_index :ci_gitlab_hosted_runner_monthly_usages, [:root_namespace_id, :billing_month],
|
||||
name: 'idx_hosted_runner_usage_on_namespace_billing_month'
|
||||
|
||||
add_index :ci_gitlab_hosted_runner_monthly_usages, [:project_id, :billing_month],
|
||||
name: 'idx_hosted_runner_usage_on_project_billing_month'
|
||||
|
||||
add_index :ci_gitlab_hosted_runner_monthly_usages,
|
||||
[:runner_id, :billing_month, :root_namespace_id, :project_id],
|
||||
name: 'idx_hosted_runner_usage_unique',
|
||||
unique: true
|
||||
|
||||
add_check_constraint(
|
||||
:ci_gitlab_hosted_runner_monthly_usages,
|
||||
"(billing_month = date_trunc('month', billing_month::timestamp with time zone))",
|
||||
'ci_hosted_runner_monthly_usages_month_constraint'
|
||||
)
|
||||
# rubocop:enable Migration/EnsureFactoryForTable -- False Positive
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :ci_gitlab_hosted_runner_monthly_usages if table_exists? :ci_gitlab_hosted_runner_monthly_usages
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
23937513149f40d61d67db1e2735693dd667bf23197e967d067416135c29374a
|
||||
|
|
@ -0,0 +1 @@
|
|||
27ff90b2bc2682e6f5a9a012302e271626a68fa027d2dad4db6f98dcad81f052
|
||||
|
|
@ -9905,6 +9905,29 @@ CREATE SEQUENCE ci_freeze_periods_id_seq
|
|||
|
||||
ALTER SEQUENCE ci_freeze_periods_id_seq OWNED BY ci_freeze_periods.id;
|
||||
|
||||
CREATE TABLE ci_gitlab_hosted_runner_monthly_usages (
|
||||
id bigint NOT NULL,
|
||||
runner_id bigint NOT NULL,
|
||||
runner_duration_seconds bigint DEFAULT 0 NOT NULL,
|
||||
project_id bigint NOT NULL,
|
||||
root_namespace_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
billing_month date NOT NULL,
|
||||
notification_level integer DEFAULT 100 NOT NULL,
|
||||
compute_minutes_used numeric(18,4) DEFAULT 0.0 NOT NULL,
|
||||
CONSTRAINT ci_hosted_runner_monthly_usages_month_constraint CHECK ((billing_month = date_trunc('month'::text, (billing_month)::timestamp with time zone)))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ci_gitlab_hosted_runner_monthly_usages_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE ci_gitlab_hosted_runner_monthly_usages_id_seq OWNED BY ci_gitlab_hosted_runner_monthly_usages.id;
|
||||
|
||||
CREATE TABLE ci_group_variables (
|
||||
id bigint NOT NULL,
|
||||
key character varying NOT NULL,
|
||||
|
|
@ -9935,6 +9958,29 @@ CREATE SEQUENCE ci_group_variables_id_seq
|
|||
|
||||
ALTER SEQUENCE ci_group_variables_id_seq OWNED BY ci_group_variables.id;
|
||||
|
||||
CREATE TABLE ci_instance_runner_monthly_usages (
|
||||
id bigint NOT NULL,
|
||||
runner_id bigint,
|
||||
runner_duration_seconds bigint DEFAULT 0 NOT NULL,
|
||||
project_id bigint,
|
||||
root_namespace_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
billing_month date NOT NULL,
|
||||
notification_level integer DEFAULT 100 NOT NULL,
|
||||
compute_minutes_used numeric(18,4) DEFAULT 0.0 NOT NULL,
|
||||
CONSTRAINT ci_instance_runner_monthly_usages_year_month_constraint CHECK ((billing_month = date_trunc('month'::text, (billing_month)::timestamp with time zone)))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ci_instance_runner_monthly_usages_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE ci_instance_runner_monthly_usages_id_seq OWNED BY ci_instance_runner_monthly_usages.id;
|
||||
|
||||
CREATE TABLE ci_instance_variables (
|
||||
id bigint NOT NULL,
|
||||
variable_type smallint DEFAULT 1 NOT NULL,
|
||||
|
|
@ -24346,8 +24392,12 @@ ALTER TABLE ONLY ci_deleted_objects ALTER COLUMN id SET DEFAULT nextval('ci_dele
|
|||
|
||||
ALTER TABLE ONLY ci_freeze_periods ALTER COLUMN id SET DEFAULT nextval('ci_freeze_periods_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_gitlab_hosted_runner_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_gitlab_hosted_runner_monthly_usages_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_group_variables ALTER COLUMN id SET DEFAULT nextval('ci_group_variables_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_instance_runner_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_instance_runner_monthly_usages_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_instance_variables_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_job_token_authorizations ALTER COLUMN id SET DEFAULT nextval('ci_job_token_authorizations_id_seq'::regclass);
|
||||
|
|
@ -26434,9 +26484,15 @@ ALTER TABLE ONLY ci_deleted_objects
|
|||
ALTER TABLE ONLY ci_freeze_periods
|
||||
ADD CONSTRAINT ci_freeze_periods_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY ci_gitlab_hosted_runner_monthly_usages
|
||||
ADD CONSTRAINT ci_gitlab_hosted_runner_monthly_usages_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY ci_group_variables
|
||||
ADD CONSTRAINT ci_group_variables_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY ci_instance_runner_monthly_usages
|
||||
ADD CONSTRAINT ci_instance_runner_monthly_usages_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY ci_instance_variables
|
||||
ADD CONSTRAINT ci_instance_variables_pkey PRIMARY KEY (id);
|
||||
|
||||
|
|
@ -30033,6 +30089,12 @@ CREATE INDEX idx_group_audit_events_on_project_created_at_id ON ONLY group_audit
|
|||
|
||||
CREATE INDEX idx_headers_instance_external_audit_event_destination_id ON instance_audit_events_streaming_headers USING btree (instance_external_audit_event_destination_id);
|
||||
|
||||
CREATE INDEX idx_hosted_runner_usage_on_namespace_billing_month ON ci_gitlab_hosted_runner_monthly_usages USING btree (root_namespace_id, billing_month);
|
||||
|
||||
CREATE INDEX idx_hosted_runner_usage_on_project_billing_month ON ci_gitlab_hosted_runner_monthly_usages USING btree (project_id, billing_month);
|
||||
|
||||
CREATE UNIQUE INDEX idx_hosted_runner_usage_unique ON ci_gitlab_hosted_runner_monthly_usages USING btree (runner_id, billing_month, root_namespace_id, project_id);
|
||||
|
||||
CREATE UNIQUE INDEX idx_import_placeholder_memberships_on_source_user_group_id ON import_placeholder_memberships USING btree (source_user_id, group_id);
|
||||
|
||||
CREATE INDEX idx_import_placeholder_memberships_on_source_user_id_and_id ON import_placeholder_memberships USING btree (source_user_id, id);
|
||||
|
|
@ -30055,6 +30117,8 @@ CREATE INDEX idx_instance_audit_events_on_author_id_created_at_id ON ONLY instan
|
|||
|
||||
CREATE UNIQUE INDEX idx_instance_external_audit_event_destination_id_key_uniq ON instance_audit_events_streaming_headers USING btree (instance_external_audit_event_destination_id, key);
|
||||
|
||||
CREATE UNIQUE INDEX idx_instance_runner_usage_unique ON ci_instance_runner_monthly_usages USING btree (runner_id, billing_month, root_namespace_id, project_id);
|
||||
|
||||
CREATE INDEX idx_issues_on_health_status_not_null ON issues USING btree (health_status) WHERE (health_status IS NOT NULL);
|
||||
|
||||
CREATE INDEX idx_issues_on_project_id_and_created_at_and_id_and_state_id ON issues USING btree (project_id, created_at, id, state_id);
|
||||
|
|
@ -30961,6 +31025,10 @@ CREATE INDEX index_ci_freeze_periods_on_project_id ON ci_freeze_periods USING bt
|
|||
|
||||
CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key_and_environment ON ci_group_variables USING btree (group_id, key, environment_scope);
|
||||
|
||||
CREATE INDEX index_ci_instance_runner_monthly_usages_on_namespace_and_month ON ci_instance_runner_monthly_usages USING btree (root_namespace_id, billing_month);
|
||||
|
||||
CREATE INDEX index_ci_instance_runner_monthly_usages_on_project_and_month ON ci_instance_runner_monthly_usages USING btree (project_id, billing_month);
|
||||
|
||||
CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON ci_instance_variables USING btree (key);
|
||||
|
||||
CREATE INDEX index_ci_job_artifact_states_on_job_artifact_id_partition_id ON ci_job_artifact_states USING btree (job_artifact_id, partition_id);
|
||||
|
|
@ -39643,6 +39711,9 @@ ALTER TABLE ONLY issue_user_mentions
|
|||
ALTER TABLE ONLY namespace_settings
|
||||
ADD CONSTRAINT fk_rails_3896d4fae5 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY ci_instance_runner_monthly_usages
|
||||
ADD CONSTRAINT fk_rails_38b9dcccc9 FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY packages_cleanup_policies
|
||||
ADD CONSTRAINT fk_rails_393ba98591 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,11 +43,13 @@ that are coded across multiple repositories.
|
|||
|---|---|---|
|
||||
| [All feature flags in GitLab](../../../user/feature_flags.md) | [Generated during docs build](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/raketasks.md#generate-the-feature-flag-tables) | [Technical Writing](https://handbook.gitlab.com/handbook/product/ux/technical-writing/) |
|
||||
| [GitLab Runner feature flags](https://docs.gitlab.com/runner/configuration/feature-flags.html) | [Page source](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/ec6e1797d2173a95c8ac7f726bd62f6f110b7211/docs/configuration/feature-flags.md?plain=1#L39) | [Runner](https://handbook.gitlab.com/handbook/engineering/development/ops/verify/runner/) |
|
||||
| [GitLab Runner Kubernetes API settings](https://docs.gitlab.com/runner/executors/kubernetes/) | Generated with [mage](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/.gitlab/ci/qa.gitlab-ci.yml#L133) | [Runner](https://handbook.gitlab.com/handbook/engineering/development/ops/verify/runner/) |
|
||||
| [Deprecations and removals by version](../../../update/deprecations.md) | [Update the deprecations and removals documentation](../../deprecation_guidelines/index.md#update-the-deprecations-and-removals-documentation) | |
|
||||
| [Breaking change windows](../../../update/breaking_windows.md) | [Update the breaking change windows documentation](../../deprecation_guidelines/index.md#update-the-breaking-change-windows-documentation) | |
|
||||
| [GraphQL API resources](../../../api/graphql/reference/index.md) | [GraphQL API style guide](../../api_graphql_styleguide.md#documentation-and-schema) | [Import and Integrate](https://handbook.gitlab.com/handbook/engineering/development/dev/foundations/import-and-integrate/) |
|
||||
| [Audit event types](../../../user/compliance/audit_event_types.md) | [Audit event development guidelines](../../audit_event_guide/index.md) | [Compliance](https://handbook.gitlab.com/handbook/engineering/development/sec/govern/compliance/) |
|
||||
| [Available custom role permissions](../../../user/custom_roles/abilities.md) | [Generated by Rake task](https://gitlab.com/gitlab-org/gitlab/-/blob/master/tooling/custom_roles/docs/templates/custom_abilities.md.erb) | [Authorization](https://handbook.gitlab.com/handbook/product/categories/#authorization-group)|
|
||||
| [Application settings analysis](../../cells/application_settings_analysis.md) | [Generated by Ruby script](https://gitlab.com/gitlab-org/gitlab/-/blob/2bb2910c84fad965bde473aa2881d88358b6e96e/scripts/cells/application-settings-analysis.rb#L353) | |
|
||||
| DAST vulnerability check documentation ([Example](../../../user/application_security/dast/browser/checks/798.19.md)) | [How to generate the Markdown](https://gitlab.com/gitlab-org/security-products/dast-cwe-checks/-/blob/main/doc/how-to-generate-the-markdown-documentation.md) | [Dynamic Analysis](https://handbook.gitlab.com/handbook/product/categories/#dynamic-analysis-group) |
|
||||
| [The docs homepage](../../../index.md) | | [Technical Writing](https://handbook.gitlab.com/handbook/product/ux/technical-writing/) |
|
||||
|
||||
|
|
|
|||
|
|
@ -631,3 +631,15 @@ If you notice any inconsistencies in your merge request approval rules, you can
|
|||
These actions help ensure that your merge request approval policies are correctly applied and consistent across all merge requests.
|
||||
|
||||
If you continue to experience issues with merge request approval policies after taking these steps, contact GitLab support for assistance.
|
||||
|
||||
### Merge requests that fix a detected vulnerability require approval
|
||||
|
||||
If your policy configuration includes the `detected` state, merge requests that
|
||||
fix previously detected vulnerabilities still require approval. The merge request
|
||||
approval policy evaluates based on vulnerabilities that existed before the changes
|
||||
in the merge request, which adds an additional layer of review for any changes that affect
|
||||
known vulnerabilities.
|
||||
|
||||
If you want to allow merge requests that fix vulnerabilities to proceed without
|
||||
any additional approvals due to a detected vulnerability, consider removing the
|
||||
`detected` state from your policy configuration.
|
||||
|
|
|
|||
|
|
@ -238,6 +238,23 @@ To do this:
|
|||
- Job
|
||||
```
|
||||
|
||||
## Configure Trivy report artifact deletion
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/480845) in GitLab 17.9.
|
||||
|
||||
By default, the GitLab agent deletes the Trivy report artifact after a scan has completed.
|
||||
|
||||
You can configure the GitLab agent to preserve the report artifact, so you can view the report in its raw state.
|
||||
|
||||
To do this:
|
||||
|
||||
- Set `delete_report_artifact` to `false`:
|
||||
|
||||
```yaml
|
||||
container_scanning:
|
||||
delete_report_artifact: false
|
||||
```
|
||||
|
||||
## View cluster vulnerabilities
|
||||
|
||||
To view vulnerability information in GitLab:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ module QA
|
|||
Runtime::Feature.disable(:ci_release_cli_catalog_publish_option)
|
||||
|
||||
Flow::Login.sign_in
|
||||
|
||||
Flow::Project.enable_catalog_resource_feature(project)
|
||||
end
|
||||
|
||||
|
|
@ -34,41 +33,52 @@ module QA
|
|||
project.create_repository_tag('1.0.0')
|
||||
|
||||
project.visit!
|
||||
visit_job('create-release-with-existing-tag')
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
project.visit_job('create-release-with-existing-tag')
|
||||
|
||||
Page::Project::Job::Show.perform do |show|
|
||||
expect(show.output).to have_content('release created successfully!')
|
||||
expect(show.output).to have_content('Tag: 1.0.0')
|
||||
expect(show.output).to have_content('Name: 1.0.0')
|
||||
expect(show.output).to have_content('Description: A long description of the release')
|
||||
Support::Waiter.wait_until { show.has_passed? }
|
||||
|
||||
aggregate_failures 'Job has expected contents' do
|
||||
expect(show.output).to have_content('release created successfully!')
|
||||
expect(show.output).to have_content('Tag: 1.0.0')
|
||||
expect(show.output).to have_content('Name: 1.0.0')
|
||||
expect(show.output).to have_content('Description: A long description of the release')
|
||||
end
|
||||
end
|
||||
|
||||
visit_catalog_resource_show_page
|
||||
|
||||
Page::Explore::CiCdCatalog::Show.perform do |show|
|
||||
expect(show).to have_version_badge('1.0.0')
|
||||
expect(show).to have_component_name('new_component')
|
||||
expect(show).to have_input(
|
||||
name: 'scanner-output',
|
||||
required: 'false',
|
||||
type: 'string',
|
||||
description: '',
|
||||
default: 'json'
|
||||
)
|
||||
aggregate_failures 'Catalog component has expected contents' do
|
||||
expect(show).to have_version_badge('1.0.0')
|
||||
expect(show).to have_component_name('new_component')
|
||||
expect(show).to have_input(
|
||||
name: 'scanner-output',
|
||||
required: 'false',
|
||||
type: 'string',
|
||||
description: '',
|
||||
default: 'json'
|
||||
)
|
||||
end
|
||||
|
||||
show.click_latest_version_badge
|
||||
end
|
||||
|
||||
Page::Project::Tag::Show.perform do |show|
|
||||
expect(show).to have_tag_name('1.0.0')
|
||||
expect(show).to have_no_tag_message
|
||||
aggregate_failures 'Project tag has expected contents' do
|
||||
expect(show).to have_tag_name('1.0.0')
|
||||
expect(show).to have_no_tag_message
|
||||
end
|
||||
|
||||
show.click_release_link
|
||||
end
|
||||
|
||||
Page::Project::Release::Show.perform do |show|
|
||||
expect(show).to have_release_name('1.0.0')
|
||||
expect(show).to have_release_description('A long description of the release')
|
||||
aggregate_failures 'Project release has expected contents' do
|
||||
expect(show).to have_release_name('1.0.0')
|
||||
expect(show).to have_release_description('A long description of the release')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -78,49 +88,60 @@ module QA
|
|||
project.create_repository_tag('1.0.0')
|
||||
|
||||
project.visit!
|
||||
visit_job('create-release-with-new-tag-filled-with-information')
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
project.visit_job('create-release-with-new-tag-filled-with-information')
|
||||
|
||||
Page::Project::Job::Show.perform do |show|
|
||||
expect(show.output).to have_content('release created successfully!')
|
||||
expect(show.output).to have_content('Tag: v9.0.2')
|
||||
expect(show.output).to have_content('Name: new release v9.0.2')
|
||||
expect(show.output).to have_content('Description: A long description of the release')
|
||||
expect(show.output).to have_content('Released At: 2026-01-01 00:00:00 +0000 UTC')
|
||||
expect(show.output).to have_content('Asset::Link::Name: Download link')
|
||||
expect(show.output).to have_content('Asset::Link::URL: https://gitlab-runner-downloads.s3.amazonaws.com/v16.9.0-rc2/binaries/gitlab-runner-linux-amd64')
|
||||
expect(show.output).to have_content('Milestone: v1.0 -')
|
||||
expect(show.output).to have_content('Milestone: v2.0 -')
|
||||
Support::Waiter.wait_until { show.has_passed? }
|
||||
|
||||
aggregate_failures 'Job has expected contents' do
|
||||
expect(show.output).to have_content('release created successfully!')
|
||||
expect(show.output).to have_content('Tag: v9.0.2')
|
||||
expect(show.output).to have_content('Name: new release v9.0.2')
|
||||
expect(show.output).to have_content('Description: A long description of the release')
|
||||
expect(show.output).to have_content('Released At: 2026-01-01 00:00:00 +0000 UTC')
|
||||
expect(show.output).to have_content('Asset::Link::Name: Download link')
|
||||
expect(show.output).to have_content('Asset::Link::URL: https://gitlab-runner-downloads.s3.amazonaws.com/v16.9.0-rc2/binaries/gitlab-runner-linux-amd64')
|
||||
expect(show.output).to have_content('Milestone: v1.0 -')
|
||||
expect(show.output).to have_content('Milestone: v2.0 -')
|
||||
end
|
||||
end
|
||||
|
||||
visit_catalog_resource_show_page
|
||||
|
||||
Page::Explore::CiCdCatalog::Show.perform do |show|
|
||||
expect(show).to have_version_badge('9.0.2')
|
||||
expect(show).to have_component_name('new_component')
|
||||
expect(show).to have_input(
|
||||
name: 'scanner-output',
|
||||
required: 'false',
|
||||
type: 'string',
|
||||
description: '',
|
||||
default: 'json'
|
||||
)
|
||||
aggregate_failures 'Catalog component has expected contents' do
|
||||
expect(show).to have_version_badge('9.0.2')
|
||||
expect(show).to have_component_name('new_component')
|
||||
expect(show).to have_input(
|
||||
name: 'scanner-output',
|
||||
required: 'false',
|
||||
type: 'string',
|
||||
description: '',
|
||||
default: 'json'
|
||||
)
|
||||
end
|
||||
|
||||
show.click_latest_version_badge
|
||||
end
|
||||
|
||||
Page::Project::Tag::Show.perform do |show|
|
||||
expect(show).to have_tag_name('v9.0.2')
|
||||
expect(show).to have_tag_message('a new tag')
|
||||
aggregate_failures 'Project tag has expected contents' do
|
||||
expect(show).to have_tag_name('v9.0.2')
|
||||
expect(show).to have_tag_message('a new tag')
|
||||
end
|
||||
|
||||
show.click_release_link
|
||||
end
|
||||
|
||||
Page::Project::Release::Show.perform do |show|
|
||||
expect(show).to have_release_name('new release v9.0.2')
|
||||
expect(show).to have_release_description('A long description of the release')
|
||||
expect(show).to have_milestone_title('v1.0')
|
||||
expect(show).to have_milestone_title('v2.0')
|
||||
expect(show).to have_asset_link('Download link', '/binaries/gitlab-runner-linux-amd64')
|
||||
aggregate_failures 'Project release has expected contents' do
|
||||
expect(show).to have_release_name('new release v9.0.2')
|
||||
expect(show).to have_release_description('A long description of the release')
|
||||
expect(show).to have_milestone_title('v1.0')
|
||||
expect(show).to have_milestone_title('v2.0')
|
||||
expect(show).to have_asset_link('Download link', '/binaries/gitlab-runner-linux-amd64')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -198,17 +219,6 @@ module QA
|
|||
YAML
|
||||
end
|
||||
|
||||
def visit_job(job_name)
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
|
||||
Page::Project::Pipeline::Show.perform do |show|
|
||||
Support::Waiter.wait_until { show.has_passed? }
|
||||
|
||||
expect(show).to have_job(job_name)
|
||||
show.click_job(job_name)
|
||||
end
|
||||
end
|
||||
|
||||
def visit_catalog_resource_show_page
|
||||
Page::Main::Menu.perform do |main|
|
||||
main.go_to_explore
|
||||
|
|
|
|||
|
|
@ -29,17 +29,16 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
Flow::Login.sign_in
|
||||
|
||||
project.change_pipeline_variables_minimum_override_role('developer')
|
||||
|
||||
Flow::Login.sign_in
|
||||
project.visit!
|
||||
Page::Project::Menu.perform(&:go_to_pipelines)
|
||||
Page::Project::Pipeline::Index.perform(&:click_run_pipeline_button)
|
||||
end
|
||||
|
||||
after do
|
||||
runner&.remove_via_api!
|
||||
runner.remove_via_api!
|
||||
end
|
||||
|
||||
it 'manually creates a pipeline and uses the defined custom variable value',
|
||||
|
|
|
|||
|
|
@ -8,15 +8,11 @@ module QA
|
|||
before do
|
||||
Flow::Login.sign_in
|
||||
add_files_to_project
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
project.remove_via_api!
|
||||
end
|
||||
|
||||
it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348002' do
|
||||
it 'runs the pipeline with composed config',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348002' do
|
||||
Page::Project::Pipeline::Show.perform do |pipeline|
|
||||
aggregate_failures 'pipeline has all expected jobs' do
|
||||
expect(pipeline).to have_job('build')
|
||||
|
|
@ -32,6 +28,7 @@ module QA
|
|||
create(:commit, project: project, commit_message: 'Add CI and local files', actions: [
|
||||
build_config_file, test_config_file, non_detectable_file, main_ci_file
|
||||
])
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
end
|
||||
|
||||
def main_ci_file
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
add_included_files
|
||||
add_main_ci_file
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline(status: 'Passed')
|
||||
project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
@ -47,6 +46,8 @@ module QA
|
|||
|
||||
def add_main_ci_file
|
||||
create(:commit, project: project, commit_message: 'Add config file', actions: [main_ci_file])
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: project, status: 'success')
|
||||
end
|
||||
|
||||
def add_included_files
|
||||
|
|
|
|||
|
|
@ -15,10 +15,9 @@ module QA
|
|||
add_included_files_for(main_project)
|
||||
add_included_files_for(project1)
|
||||
add_included_files_for(project2)
|
||||
add_main_ci_file(main_project)
|
||||
add_ci_file_to_main_project
|
||||
|
||||
main_project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline(status: 'Passed')
|
||||
main_project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
@ -43,7 +42,11 @@ module QA
|
|||
private
|
||||
|
||||
def add_included_files_for(project)
|
||||
files = [
|
||||
create(:commit, project: project, commit_message: 'Add files', actions: included_files(project))
|
||||
end
|
||||
|
||||
def included_files(project)
|
||||
[
|
||||
{
|
||||
action: 'create',
|
||||
file_path: 'file1.yml',
|
||||
|
|
@ -63,12 +66,12 @@ module QA
|
|||
YAML
|
||||
}
|
||||
]
|
||||
|
||||
create(:commit, project: project, commit_message: 'Add files', actions: files)
|
||||
end
|
||||
|
||||
def add_main_ci_file(project)
|
||||
create(:commit, project: project, commit_message: 'Add config file', actions: [main_ci_file])
|
||||
def add_ci_file_to_main_project
|
||||
create(:commit, project: main_project, commit_message: 'Add config file', actions: [main_ci_file])
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: main_project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: main_project, status: 'success')
|
||||
end
|
||||
|
||||
def main_ci_file
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module QA
|
|||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358059'
|
||||
) do
|
||||
add_ci_files(success_child_ci_file)
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
project.visit_latest_pipeline
|
||||
|
||||
Page::Project::Pipeline::Show.perform do |parent_pipeline|
|
||||
expect(parent_pipeline).to have_child_pipeline
|
||||
|
|
@ -32,7 +32,7 @@ module QA
|
|||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358060'
|
||||
) do
|
||||
add_ci_files(fail_child_ci_file)
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
project.visit_latest_pipeline
|
||||
|
||||
Page::Project::Pipeline::Show.perform do |parent_pipeline|
|
||||
expect(parent_pipeline).to have_child_pipeline
|
||||
|
|
@ -97,7 +97,9 @@ module QA
|
|||
create(:commit,
|
||||
project: project,
|
||||
commit_message: 'Add parent and child pipelines CI files.',
|
||||
actions: [child_ci_file, parent_ci_file]).project.visit!
|
||||
actions: [child_ci_file, parent_ci_file]
|
||||
)
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,19 +11,21 @@ module QA
|
|||
let!(:runner) { create(:group_runner, group: group, name: executor, tags: [executor]) }
|
||||
|
||||
before do
|
||||
Flow::Login.sign_in
|
||||
upstream_project.change_pipeline_variables_minimum_override_role('developer')
|
||||
downstream_project.change_pipeline_variables_minimum_override_role('developer')
|
||||
|
||||
add_ci_file(downstream_project, downstream_ci_file)
|
||||
add_ci_file(upstream_project, upstream_ci_file)
|
||||
|
||||
upstream_project.change_pipeline_variables_minimum_override_role('developer')
|
||||
downstream_project.change_pipeline_variables_minimum_override_role('developer')
|
||||
upstream_project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline(status: 'Passed')
|
||||
Flow::Login.sign_in
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: upstream_project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: upstream_project, status: 'success')
|
||||
|
||||
upstream_project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
runner.remove_via_api!
|
||||
[upstream_project, downstream_project].each(&:remove_via_api!)
|
||||
end
|
||||
|
||||
it 'runs the pipeline with composed config',
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
Flow::Login.sign_in
|
||||
update_runner_policy(allowed_policies)
|
||||
add_ci_file
|
||||
Flow::Login.sign_in
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
|
||||
project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
@ -63,7 +63,7 @@ module QA
|
|||
|
||||
with_them do
|
||||
it 'applies pull policy in job correctly', testcase: params[:testcase] do
|
||||
visit_job
|
||||
project.visit_job(job_name)
|
||||
|
||||
if pull_image
|
||||
expect(job_log).to have_content(message),
|
||||
|
|
@ -93,7 +93,7 @@ module QA
|
|||
issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/462232"
|
||||
}
|
||||
) do
|
||||
visit_job
|
||||
project.visit_job(job_name)
|
||||
|
||||
expect(job_log).to include(text1, text2),
|
||||
"Expected to find contents #{text1} and #{text2} in #{job_log}, but didn't."
|
||||
|
|
@ -140,14 +140,9 @@ module QA
|
|||
YAML
|
||||
}
|
||||
])
|
||||
end
|
||||
|
||||
def visit_job
|
||||
Page::Project::Pipeline::Show.perform do |show|
|
||||
Support::Waiter.wait_until(max_duration: 90) { show.completed? }
|
||||
|
||||
show.click_job(job_name)
|
||||
end
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: project, status: 'success')
|
||||
end
|
||||
|
||||
def job_log
|
||||
|
|
|
|||
|
|
@ -57,15 +57,14 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
make_sure_to_have_a_skipped_pipeline
|
||||
|
||||
Flow::Login.sign_in
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline(status: 'Skipped')
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: project, status: 'skipped')
|
||||
project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
runner&.remove_via_api!
|
||||
runner.remove_via_api!
|
||||
end
|
||||
|
||||
it(
|
||||
|
|
@ -74,10 +73,7 @@ module QA
|
|||
) do
|
||||
Page::Project::Pipeline::Show.perform do |show|
|
||||
show.click_job_action('Prep') # Trigger pipeline manually
|
||||
|
||||
show.wait_until(max_duration: 300, sleep_interval: 2, reload: false) do
|
||||
project.latest_pipeline[:status] == 'success'
|
||||
end
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: project, status: 'success', wait: 300)
|
||||
|
||||
aggregate_failures do
|
||||
expect(show).to have_build('Test', status: :success)
|
||||
|
|
@ -91,45 +87,6 @@ module QA
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Wait for first pipeline to finish and have "skipped" status
|
||||
# If it takes too long, create new pipeline and retry (2 times)
|
||||
def make_sure_to_have_a_skipped_pipeline
|
||||
attempts ||= 1
|
||||
Runtime::Logger.info('Waiting for pipeline to have status "skipped"...')
|
||||
Support::Waiter.wait_until(max_duration: 120, sleep_interval: 3, retry_on_exception: true) do
|
||||
project.latest_pipeline[:status] == 'skipped'
|
||||
end
|
||||
rescue Support::Repeater::WaitExceededError
|
||||
raise 'Failed to create skipped pipeline after 3 attempts.' unless (attempts += 1) < 4
|
||||
|
||||
Runtime::Logger.debug(
|
||||
"Previous pipeline took too long to finish. Potential jobs with problems:\n#{problematic_jobs}"
|
||||
)
|
||||
Runtime::Logger.info("Triggering a new pipeline...")
|
||||
trigger_new_pipeline
|
||||
retry
|
||||
end
|
||||
|
||||
def trigger_new_pipeline
|
||||
original_count = project.pipelines.length
|
||||
create(:pipeline, project: project)
|
||||
|
||||
Support::Waiter.wait_until(sleep_interval: 1) { project.pipelines.length > original_count }
|
||||
end
|
||||
|
||||
# We know that all the jobs in pipeline are purposely skipped
|
||||
# The pipeline should have status "skipped" almost right away after being created
|
||||
# If pipeline is held up, likely because there are some jobs that
|
||||
# doesn't have either "skipped" or "manual" status
|
||||
def problematic_jobs
|
||||
pipeline = create(:pipeline, project: project, id: project.latest_pipeline[:id])
|
||||
|
||||
acceptable_statuses = %w[skipped manual]
|
||||
pipeline.jobs.select { |job| !(acceptable_statuses.include? job[:status]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ module QA
|
|||
before do
|
||||
Flow::Login.sign_in
|
||||
add_ci_files
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline(status: 'Passed')
|
||||
project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
@ -29,9 +28,9 @@ module QA
|
|||
expect(parent_pipeline).not_to have_child_pipeline
|
||||
|
||||
parent_pipeline.click_job_action('trigger')
|
||||
Support::Waiter.wait_until { parent_pipeline.has_child_pipeline? }
|
||||
parent_pipeline.expand_child_pipeline
|
||||
Support::Waiter.wait_until(max_duration: 240) { parent_pipeline.has_child_pipeline? }
|
||||
|
||||
parent_pipeline.expand_child_pipeline
|
||||
expect(parent_pipeline).to have_build('child_build', status: nil)
|
||||
end
|
||||
end
|
||||
|
|
@ -42,6 +41,8 @@ module QA
|
|||
create(:commit, project: project, commit_message: 'Add parent and child pipelines CI files.', actions: [
|
||||
child_ci_file, parent_ci_file
|
||||
])
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: project, status: 'success')
|
||||
end
|
||||
|
||||
def parent_ci_file
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ module QA
|
|||
before do
|
||||
Flow::Login.sign_in
|
||||
add_ci_files
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline(status: 'Passed')
|
||||
project.visit_latest_pipeline
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
@ -47,6 +46,8 @@ module QA
|
|||
|
||||
def add_ci_files
|
||||
create(:commit, project: project, commit_message: 'todo', actions: [child_ci_file, parent_ci_file])
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
Flow::Pipeline.wait_for_latest_pipeline_to_have_status(project: project, status: 'success')
|
||||
end
|
||||
|
||||
def parent_ci_file
|
||||
|
|
|
|||
|
|
@ -54,13 +54,8 @@ module QA
|
|||
push.commit_message = 'Commit .gitlab-ci.yml'
|
||||
end
|
||||
|
||||
# observe pipeline creation
|
||||
project.visit!
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
|
||||
Page::Project::Pipeline::Show.perform do |show|
|
||||
show.click_job('test')
|
||||
end
|
||||
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
|
||||
project.visit_job('test')
|
||||
|
||||
Page::Project::Job::Show.perform do |show|
|
||||
# user views job succeeding
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ RSpec.describe 'Database schema',
|
|||
ci_builds_runner_session: %w[project_id],
|
||||
ci_daily_build_group_report_results: %w[partition_id],
|
||||
ci_deleted_objects: %w[project_id],
|
||||
ci_gitlab_hosted_runner_monthly_usages: %w[root_namespace_id project_id runner_id],
|
||||
ci_job_artifacts: %w[partition_id project_id job_id],
|
||||
ci_namespace_monthly_usages: %w[namespace_id],
|
||||
ci_pipeline_artifacts: %w[partition_id],
|
||||
|
|
|
|||
|
|
@ -564,6 +564,8 @@ container_repositories:
|
|||
- project
|
||||
- name
|
||||
project:
|
||||
- instance_runner_monthly_usages
|
||||
- hosted_runner_monthly_usages
|
||||
- catalog_resource
|
||||
- catalog_resource_sync_events
|
||||
- catalog_resource_versions
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ RSpec.describe 'Puma' do
|
|||
WebMock.allow_net_connect!
|
||||
end
|
||||
|
||||
%w[SIGQUIT SIGTERM SIGKILL].each do |signal|
|
||||
%w[SIGTERM SIGKILL].each do |signal|
|
||||
it "has a worker that self-terminates on signal #{signal}" do
|
||||
response = Excon.get('unix://', socket: @socket_path)
|
||||
expect(response.status).to eq(200)
|
||||
|
|
|
|||
|
|
@ -24,40 +24,63 @@ RSpec.describe MergeRequests::Mergeability::CheckLfsFileLocksService, feature_ca
|
|||
|
||||
context 'when lfs is enabled' do
|
||||
let(:only_allow_merge_if_pipeline_succeeds) { true }
|
||||
let(:changed_path) { instance_double('Gitlab::Git::ChangedPath', path: 'README.md') }
|
||||
let(:changed_paths) do
|
||||
[
|
||||
instance_double('Gitlab::Git::ChangedPath', path: 'README.md'),
|
||||
instance_double('Gitlab::Git::ChangedPath', path: 'conflict.rb'),
|
||||
instance_double('Gitlab::Git::ChangedPath', path: 'README.md')
|
||||
]
|
||||
end
|
||||
|
||||
before do
|
||||
allow(merge_request).to receive(:changed_paths).and_return([changed_path])
|
||||
allow(merge_request).to receive(:changed_paths).and_return(changed_paths)
|
||||
allow(project.lfs_file_locks).to receive(:exists?).and_call_original
|
||||
allow(project.lfs_file_locks).to receive(:for_paths).and_call_original
|
||||
end
|
||||
|
||||
context 'when there are no lfs files locks for this project' do
|
||||
it 'returns a check result with status success' do
|
||||
expect(execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
|
||||
end
|
||||
|
||||
it 'returns early before querying for matching file locks' do
|
||||
execute
|
||||
expect(project.lfs_file_locks).to have_received(:exists?)
|
||||
expect(project.lfs_file_locks).not_to have_received(:for_paths)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are lfs files locked by the merge request author' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(merge_request).to receive(:author_id).and_return(user.id)
|
||||
create(:lfs_file_lock, project: project, path: changed_path.path, user: user)
|
||||
create(:lfs_file_lock, project: project, path: changed_paths.first.path, user: merge_request.author)
|
||||
end
|
||||
|
||||
it 'returns a check result with status success' do
|
||||
expect(execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
|
||||
end
|
||||
|
||||
it 'deduplicates the changed paths' do
|
||||
execute
|
||||
expect(project.lfs_file_locks).to have_received(:exists?)
|
||||
expect(project.lfs_file_locks).to have_received(:for_paths).with(changed_paths.map(&:path).uniq)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are lfs files locked by another user' do
|
||||
before do
|
||||
allow(merge_request).to receive(:author_id).and_return(0)
|
||||
create(:lfs_file_lock, project: project, path: changed_path.path)
|
||||
create(:lfs_file_lock, project: project, path: changed_paths.second.path)
|
||||
end
|
||||
|
||||
it 'returns a check result with status failure' do
|
||||
expect(execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
|
||||
end
|
||||
|
||||
it 'deduplicates the changed paths' do
|
||||
execute
|
||||
expect(project.lfs_file_locks).to have_received(:exists?)
|
||||
expect(project.lfs_file_locks).to have_received(:for_paths).with(changed_paths.map(&:path).uniq)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue