Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6c0a6dd200
commit
3b67d92c35
37 changed files with 347 additions and 207 deletions
|
@ -1373,6 +1373,10 @@
|
|||
rules:
|
||||
- changes: *code-backstage-qa-patterns
|
||||
|
||||
.static-analysis:rules:ee-and-foss-qa:
|
||||
rules:
|
||||
- changes: *qa-patterns
|
||||
|
||||
.static-analysis:rules:ee:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
|
|
|
@ -114,10 +114,27 @@ rubocop:
|
|||
qa:testcases:
|
||||
extends:
|
||||
- .static-analysis-base
|
||||
- .rubocop-job-cache
|
||||
- .static-analysis:rules:ee-and-foss
|
||||
- .static-analysis:rules:ee-and-foss-qa
|
||||
before_script:
|
||||
- !reference [.default-before_script, before_script]
|
||||
- cd qa/
|
||||
- bundle_install_script
|
||||
script:
|
||||
- run_timed_command "bundle exec rubocop qa/qa/specs/features/**/* --only QA/DuplicateTestcaseLink"
|
||||
- run_timed_command "bundle exec bin/qa Test::Instance::All http://localhost:3000 --test-metadata-only"
|
||||
- cd ..
|
||||
- run_timed_command "./scripts/qa/testcases-check qa/tmp/test-metadata.json"
|
||||
variables:
|
||||
USE_BUNDLE_INSTALL: "false"
|
||||
SETUP_DB: "false"
|
||||
QA_EXPORT_TEST_METRICS: "false"
|
||||
# Disable warnings in browserslist which can break on backports
|
||||
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
|
||||
BROWSERSLIST_IGNORE_OLD_DATA: "true"
|
||||
artifacts:
|
||||
expire_in: 31d
|
||||
when: always
|
||||
paths:
|
||||
- qa/tmp/
|
||||
|
||||
feature-flags-usage:
|
||||
extends:
|
||||
|
|
|
@ -738,10 +738,6 @@ QA/SelectorUsage:
|
|||
Exclude:
|
||||
- 'spec/rubocop/**/*_spec.rb'
|
||||
|
||||
QA/DuplicateTestcaseLink:
|
||||
# this cop is executed in static-analysis.gitlab-ci.yml since it cannot be run in parallel
|
||||
Enabled: false
|
||||
|
||||
Performance/ActiveRecordSubtransactions:
|
||||
Exclude:
|
||||
- 'spec/**/*.rb'
|
||||
|
|
|
@ -55,7 +55,7 @@ export default {
|
|||
{{ s__('Metrics|View documentation') }}
|
||||
</gl-button>
|
||||
<gl-button
|
||||
variant="success"
|
||||
variant="confirm"
|
||||
data-testid="create-dashboard-modal-repo-button"
|
||||
:href="projectPath"
|
||||
>
|
||||
|
|
|
@ -28,7 +28,7 @@ export default {
|
|||
api.trackRedisHllUserEvent('i_code_review_widget_nothing_merge_click_new_file');
|
||||
},
|
||||
},
|
||||
ciHelpPage: helpPagePath('/ci/quick_start/index.html'),
|
||||
ciHelpPage: helpPagePath('ci/quick_start/index.html'),
|
||||
safeHtmlConfig: { ADD_TAGS: ['use'] },
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -6,8 +6,8 @@ module Ci
|
|||
{
|
||||
"endpoint" => project_job_path(@project, @build, format: :json),
|
||||
"project_path" => @project.full_path,
|
||||
"artifact_help_url" => help_page_path('user/gitlab_com/index.html', anchor: 'gitlab-cicd'),
|
||||
"deployment_help_url" => help_page_path('user/project/clusters/deploy_to_cluster.html', anchor: 'troubleshooting'),
|
||||
"artifact_help_url" => help_page_path('user/gitlab_com/index.md', anchor: 'gitlab-cicd'),
|
||||
"deployment_help_url" => help_page_path('user/project/clusters/deploy_to_cluster.md', anchor: 'troubleshooting'),
|
||||
"runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
|
||||
"page_path" => project_job_path(@project, @build),
|
||||
"build_status" => @build.status,
|
||||
|
|
|
@ -21,8 +21,8 @@ module Ci
|
|||
"default-branch" => project.default_branch_or_main,
|
||||
"empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'),
|
||||
"initial-branch-name" => initial_branch,
|
||||
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
|
||||
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available'),
|
||||
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
|
||||
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
|
||||
"needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
|
||||
"new-merge-request-path" => namespace_project_new_merge_request_path,
|
||||
"pipeline_etag" => latest_commit ? graphql_etag_pipeline_sha_path(commit_sha) : '',
|
||||
|
|
|
@ -169,6 +169,7 @@ options:
|
|||
- p_ci_templates_qualys_iac_security
|
||||
- p_ci_templates_liquibase
|
||||
- p_ci_templates_matlab
|
||||
- p_ci_templates_themekit
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_themekit_monthly
|
||||
description: ''
|
||||
product_section: ''
|
||||
product_stage: ''
|
||||
product_group: ''
|
||||
product_category: ''
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "14.10"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52279
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_themekit
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -169,6 +169,7 @@ options:
|
|||
- p_ci_templates_qualys_iac_security
|
||||
- p_ci_templates_liquibase
|
||||
- p_ci_templates_matlab
|
||||
- p_ci_templates_themekit
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_themekit_weekly
|
||||
description: ''
|
||||
product_section: ''
|
||||
product_stage: ''
|
||||
product_group: ''
|
||||
product_category: ''
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "14.10"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52279
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_themekit
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -1229,7 +1229,7 @@ POST /projects
|
|||
| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time, in seconds, that a job can run. |
|
||||
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
|
||||
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
|
||||
| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). Valid values for `cadence` are: `1d` (every day), `7d` (every week), `14d` (every two weeks), `1month` (every month), or `3month` (every quarter). |
|
||||
| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). See the [Container Registry](../user/packages/container_registry/reduce_container_registry_storage.md#use-the-cleanup-policy-api) documentation for more information on `cadence`, `keep_n` and `older_than` values. |
|
||||
| `container_registry_access_level` | string | **{dotted-circle}** No | Set visibility of container registry, for this project, to one of `disabled`, `private` or `enabled`. |
|
||||
| `container_registry_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable container registry for this project. Use `container_registry_access_level` instead. |
|
||||
| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. Requires `initialize_with_readme` to be `true`. |
|
||||
|
|
|
@ -238,7 +238,7 @@ by a [canonicalization](#canonicalization-of-html) process.
|
|||
|
||||
#### Canonicalization of HTML
|
||||
|
||||
Neither the backed (Ruby) nor the frontend (JavaScript) rendered can directly render canonical HTML.
|
||||
Neither the backend (Ruby) nor the frontend (JavaScript) rendered can directly render canonical HTML.
|
||||
Nor should they be able to, because:
|
||||
|
||||
- It's not a direct requirement to support any GitLab application feature.
|
||||
|
@ -282,7 +282,7 @@ specification and testing infrastructure:
|
|||
which is a [script used to run the Markdown conformance tests](https://github.github.com/gfm/#about-this-document)
|
||||
against all examples contained in a `spec.txt`.
|
||||
1. The GLFM parsers and HTML renderers for
|
||||
both the static backed (Ruby) and WYSIWYG frontend (JavaScript) implementations
|
||||
both the static backend (Ruby) and WYSIWYG frontend (JavaScript) implementations
|
||||
support _consistent_ rendering of all canonical Markdown + HTML examples in the
|
||||
GLFM `spec.txt` specification, as verified by `spec_tests.py`.
|
||||
|
||||
|
@ -292,7 +292,7 @@ specification and testing infrastructure:
|
|||
to the HTML they render, so therefore their rendered HTML is
|
||||
["canonicalized"](#canonicalization-of-html) to canonical HTML prior running
|
||||
the Markdown conformance tests.
|
||||
1. For _both_ the static backed (Ruby) and WYSIWYG frontend (JavaScript) implementations,
|
||||
1. For _both_ the static backend (Ruby) and WYSIWYG frontend (JavaScript) implementations,
|
||||
a set of example snapshots exists in the form of YAML files, which
|
||||
correspond to every Markdown example in the GLFM `spec.txt`. These example snapshots
|
||||
support the following usages for every GLFM Markdown example:
|
||||
|
@ -570,7 +570,7 @@ The `example_snapshots` directory contains files which are generated by the
|
|||
`glfm_specification/input` directory. They are used as fixtures to drive the
|
||||
various Markdown snapshot tests.
|
||||
|
||||
After the entire GLFM implementation is complete for both backed (Ruby) and
|
||||
After the entire GLFM implementation is complete for both backend (Ruby) and
|
||||
frontend (JavaScript), all of these YAML files can be automatically generated.
|
||||
However, while the implementations are still in progress, the `skip_update_example_snapshots`
|
||||
key in `glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml`
|
||||
|
@ -651,7 +651,7 @@ Three types of entries exist, with different HTML for each:
|
|||
- For GLFM examples, it is generated/updated from
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt`.
|
||||
- **Static**
|
||||
- This is the static (backed (Ruby)-generated) HTML for each entry in
|
||||
- This is the static (backend (Ruby)-generated) HTML for each entry in
|
||||
`spec/fixtures/glfm/example_snapshots/examples_index.yml`.
|
||||
- It is generated/updated from backend [Markdown API](../../../api/markdown.md)
|
||||
(or the underlying internal classes) via the `update-example-snapshots.rb` script,
|
||||
|
|
|
@ -81,6 +81,7 @@ You can also [view our language roadmap](https://about.gitlab.com/direction/secu
|
|||
| Go | [Semgrep](https://semgrep.dev) | 14.4 |
|
||||
| Groovy ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/), and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.3 (Gradle) & 11.9 (Ant, Maven, SBT) |
|
||||
| Helm Charts | [Kubesec](https://github.com/controlplaneio/kubesec) | 13.1 |
|
||||
| Java (any build system) | [Semgrep](https://semgrep.dev) | 14.10 |
|
||||
| Java ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/), and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 10.6 (Maven), 10.8 (Gradle) & 11.9 (Ant, SBT) |
|
||||
| Java (Android) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
|
||||
| JavaScript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.8 |
|
||||
|
|
|
@ -217,7 +217,23 @@ Valid values for `cadence` when using the API are:
|
|||
- `1month` (every month)
|
||||
- `3month` (every quarter)
|
||||
|
||||
See the API documentation for further details: [Edit project](../../../api/projects.md#edit-project).
|
||||
Valid values for `keep_n` (number of tags kept per image name) when using the API are:
|
||||
|
||||
- `1`
|
||||
- `5`
|
||||
- `10`
|
||||
- `25`
|
||||
- `50`
|
||||
- `100`
|
||||
|
||||
Valid values for `older_than` (days until tags are automatically removed) when using the API are:
|
||||
|
||||
- `7d`
|
||||
- `14d`
|
||||
- `30d`
|
||||
- `90d`
|
||||
|
||||
See the API documentation for further details: [Edit project API](../../../api/projects.md#edit-project).
|
||||
|
||||
### Use with external container registries
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.22.0'
|
||||
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.23.0'
|
||||
|
||||
.dast-auto-deploy:
|
||||
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.22.0'
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.23.0'
|
||||
|
||||
.auto-deploy:
|
||||
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.22.0'
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.23.0'
|
||||
|
||||
.auto-deploy:
|
||||
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
||||
|
|
27
lib/gitlab/ci/templates/ThemeKit.gitlab-ci.yml
Normal file
27
lib/gitlab/ci/templates/ThemeKit.gitlab-ci.yml
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Shopify Theme Kit is a CLI tool for Shopify Themes: https://shopify.github.io/themekit/
|
||||
# See the full usage of this template described in: https://medium.com/@gogl.alex/how-to-deploy-shopify-themes-automatically-1ac17ee1229c
|
||||
|
||||
image: python:2
|
||||
|
||||
stages:
|
||||
- deploy:staging
|
||||
- deploy:production
|
||||
|
||||
staging:
|
||||
image: python:2
|
||||
stage: deploy:staging
|
||||
script:
|
||||
- curl -s https://shopify.github.io/themekit/scripts/install.py | python
|
||||
- theme deploy --env=staging
|
||||
only:
|
||||
variables:
|
||||
- $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
|
||||
|
||||
production:
|
||||
image: python:2
|
||||
stage: deploy:production
|
||||
script:
|
||||
- curl -s https://shopify.github.io/themekit/scripts/install.py | python
|
||||
- theme deploy --env=production --allow-live
|
||||
only:
|
||||
- tags
|
|
@ -219,6 +219,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_themekit
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_terraform
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
|
@ -31,7 +31,7 @@ module QA
|
|||
end
|
||||
|
||||
next
|
||||
elsif opt.name == :count_examples_only
|
||||
elsif opt.name == :count_examples_only || opt.name == :test_metadata_only
|
||||
parser.on(opt.arg, opt.desc) do |value|
|
||||
QA::Runtime::Env.dry_run = true
|
||||
Runtime::Scenario.define(opt.name, value)
|
||||
|
|
|
@ -14,6 +14,7 @@ module QA
|
|||
attribute :parallel, '--parallel', 'Execute tests in parallel'
|
||||
attribute :loop, '--loop', 'Execute test repeatedly'
|
||||
attribute :count_examples_only, '--count-examples-only', 'Return the number of examples without running them'
|
||||
attribute :test_metadata_only, '--test-metadata-only', 'Return all e2e test metadata without running them'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -155,7 +155,7 @@ module QA
|
|||
end
|
||||
# rubocop:enable RSpec/InstanceVariable
|
||||
|
||||
it "migrates large gitlab group via api" do
|
||||
it "migrates large gitlab group via api", testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358842' do
|
||||
start = Time.now
|
||||
|
||||
# trigger import and log imported group path
|
||||
|
|
|
@ -10,7 +10,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it 'commits via the api' do
|
||||
it 'commits via the api', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/357234' do
|
||||
expect do
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
|
|
|
@ -16,7 +16,7 @@ module QA
|
|||
end
|
||||
|
||||
# Removing a runner via the UI is covered by `spec/features/runners_spec.rb``
|
||||
it 'removes the runner' do
|
||||
it 'removes the runner', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/354828' do
|
||||
runners = nil
|
||||
expect { (runners = runner.list_of_runners(tag_list: runner_tags)).size }
|
||||
.to eventually_eq(1).within(max_duration: 10, sleep_interval: 1)
|
||||
|
|
|
@ -19,7 +19,7 @@ module QA
|
|||
it(
|
||||
'is inheritable when forward:pipeline_variables is true',
|
||||
:aggregate_failures,
|
||||
test_case: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358197'
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358197'
|
||||
) do
|
||||
visit_job_page('child1', 'child1_job')
|
||||
verify_job_log_shows_variable_value
|
||||
|
|
|
@ -20,7 +20,7 @@ module QA
|
|||
it(
|
||||
'is not inheritable when forward:pipeline_variables is false',
|
||||
:aggregate_failures,
|
||||
test_case: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358199'
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358199'
|
||||
) do
|
||||
visit_job_page('child1', 'child1_job')
|
||||
verify_job_log_does_not_show_variable_value
|
||||
|
@ -34,7 +34,7 @@ module QA
|
|||
it(
|
||||
'is not inheritable by default',
|
||||
:aggregate_failures,
|
||||
test_case: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358200'
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358200'
|
||||
) do
|
||||
visit_job_page('child2', 'child2_job')
|
||||
verify_job_log_does_not_show_variable_value
|
||||
|
|
|
@ -52,6 +52,8 @@ module QA
|
|||
tags_for_rspec
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/CyclomaticComplexity
|
||||
def perform
|
||||
args = []
|
||||
args.push('--tty') if tty
|
||||
|
@ -89,12 +91,29 @@ module QA
|
|||
File.open(filename, 'w') { |f| f.write(total_examples) } if total_examples.to_i > 0
|
||||
|
||||
$stdout.puts "Total examples in #{Runtime::Scenario.klass}: #{total_examples}#{total_examples.to_i > 0 ? ". Saved to file: #{filename}" : ''}"
|
||||
elsif Runtime::Scenario.attributes[:test_metadata_only]
|
||||
args.unshift('--dry-run')
|
||||
|
||||
output_file = Pathname.new(File.join(Runtime::Path.qa_root, 'tmp', 'test-metadata.json'))
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.add_formatter(QA::Support::JsonFormatter, output_file)
|
||||
config.fail_if_no_examples = true
|
||||
end
|
||||
|
||||
RSpec::Core::Runner.run(args.flatten, $stderr, $stdout) do |status|
|
||||
abort if status.nonzero?
|
||||
end
|
||||
|
||||
$stdout.puts "Saved to file: #{output_file}"
|
||||
else
|
||||
RSpec::Core::Runner.run(args.flatten, *DEFAULT_STD_ARGS).tap do |status|
|
||||
abort if status.nonzero?
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/CyclomaticComplexity
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -86,6 +86,41 @@ RSpec.describe QA::Specs::Runner do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when test_metadata_only is set as an option' do
|
||||
let(:rspec_config) { instance_double('RSpec::Core::Configuration') }
|
||||
let(:output_file) { Pathname.new('/root/tmp/test-metadata.json') }
|
||||
|
||||
before do
|
||||
QA::Runtime::Scenario.define(:test_metadata_only, true)
|
||||
allow(RSpec).to receive(:configure).and_yield(rspec_config)
|
||||
allow(rspec_config).to receive(:add_formatter)
|
||||
allow(rspec_config).to receive(:fail_if_no_examples=)
|
||||
end
|
||||
|
||||
it 'sets the `--dry-run` flag' do
|
||||
expect_rspec_runner_arguments(['--dry-run', '--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS], [$stderr, anything])
|
||||
|
||||
subject.perform
|
||||
end
|
||||
|
||||
it 'configures json formatted output to file' do
|
||||
allow(QA::Runtime::Path).to receive(:qa_root).and_return('/root')
|
||||
|
||||
expect(rspec_config).to receive(:add_formatter)
|
||||
.with(QA::Support::JsonFormatter, output_file)
|
||||
expect(rspec_config).to receive(:fail_if_no_examples=)
|
||||
.with(true)
|
||||
|
||||
allow(RSpec::Core::Runner).to receive(:run).and_return(0)
|
||||
|
||||
subject.perform
|
||||
end
|
||||
|
||||
after do
|
||||
QA::Runtime::Scenario.attributes.delete(:test_metadata_only)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when tags are set' do
|
||||
subject { described_class.new.tap { |runner| runner.tags = %i[orchestrated github] } }
|
||||
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module QA
|
||||
# This cop checks for duplicate testcase links across e2e specs
|
||||
#
|
||||
# @example
|
||||
#
|
||||
# # bad
|
||||
# it 'some test', testcase: '(...)/quality/test_cases/1892'
|
||||
# it 'another test, testcase: '(...)/quality/test_cases/1892'
|
||||
#
|
||||
# # good
|
||||
# it 'some test', testcase: '(...)/quality/test_cases/1892'
|
||||
# it 'another test, testcase: '(...)/quality/test_cases/1894'
|
||||
class DuplicateTestcaseLink < RuboCop::Cop::Cop
|
||||
MESSAGE = "Don't reuse the same testcase link in different tests. Replace one of `%s`."
|
||||
|
||||
@testcase_set = Set.new
|
||||
|
||||
def_node_matcher :duplicate_testcase_link, <<~PATTERN
|
||||
(block
|
||||
(send nil? ...
|
||||
...
|
||||
(hash
|
||||
(pair
|
||||
(sym :testcase)
|
||||
(str $_))...)...)...)
|
||||
PATTERN
|
||||
|
||||
def on_block(node)
|
||||
duplicate_testcase_link(node) do |link|
|
||||
break unless self.class.duplicate?(link)
|
||||
|
||||
add_offense(node, message: MESSAGE % link)
|
||||
end
|
||||
end
|
||||
|
||||
def self.duplicate?(link)
|
||||
!@testcase_set.add?(link)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../qa_helpers'
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module QA
|
||||
# This cop checks for correct format of testcase links across e2e specs
|
||||
#
|
||||
# @example
|
||||
#
|
||||
# # bad
|
||||
# it 'some test', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/557'
|
||||
# it 'another test, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2455'
|
||||
#
|
||||
# # good
|
||||
# it 'some test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348312'
|
||||
# it 'another test, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348236'
|
||||
class TestcaseLinkFormat < RuboCop::Cop::Cop
|
||||
include QAHelpers
|
||||
|
||||
TESTCASE_FORMAT = %r{https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/\d+}.freeze
|
||||
MESSAGE = "Testcase link format incorrect. Please link a test case from the GitLab project. See: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html#link-a-test-to-its-test-case."
|
||||
|
||||
def_node_matcher :testcase_link_format, <<~PATTERN
|
||||
(block
|
||||
(send nil? ...
|
||||
...
|
||||
(hash
|
||||
(pair
|
||||
(sym :testcase)
|
||||
(str $_))...)...)...)
|
||||
PATTERN
|
||||
|
||||
def on_block(node)
|
||||
return unless in_qa_file?(node)
|
||||
|
||||
testcase_link_format(node) do |link|
|
||||
add_offense(node, message: MESSAGE % link) unless TESTCASE_FORMAT =~ link
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
79
scripts/qa/testcases-check
Executable file
79
scripts/qa/testcases-check
Executable file
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'json'
|
||||
|
||||
TESTCASE_FORMAT = %r{https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/\d+}.freeze
|
||||
|
||||
testcases = []
|
||||
missing_testcases = []
|
||||
formatted_duplicates = []
|
||||
testcase_format_errors = []
|
||||
missing_message = %"\n*** The following tests are missing testcase links:\n\n%s\n"
|
||||
duplicate_message = %"\n*** The following tests have duplicate testcase links:\n\n%s"
|
||||
format_message = %"\n*** The following testcase links are incorrectly formatted:\n\n%s\n"
|
||||
|
||||
test_metadata_file = ARGV.shift
|
||||
|
||||
unless test_metadata_file
|
||||
puts "usage: #{__FILE__} <test_metadata_file>"
|
||||
exit 1
|
||||
end
|
||||
|
||||
file = File.read(test_metadata_file)
|
||||
|
||||
unless file =~ %r{.*\"examples\":\[\{\"id\"\:.*}
|
||||
puts "\nRspec output did not match regex. Check test-metadata.json file.\n"
|
||||
exit 1
|
||||
end
|
||||
|
||||
puts "\nAnalyzing testcase data...\n"
|
||||
|
||||
data_hash = JSON.parse(file)
|
||||
tests = data_hash['examples']
|
||||
|
||||
tests.each do |test|
|
||||
next if test['id'] =~ %r{.\/qa\/specs\/features\/sanity\/*}
|
||||
|
||||
if test['testcase']
|
||||
testcases.push(["#{test['testcase']}", "#{test['id']} - #{test['full_description']}"])
|
||||
|
||||
unless TESTCASE_FORMAT =~ test['testcase']
|
||||
testcase_format_errors.push(
|
||||
<<~FORMAT_ERRORS
|
||||
==> #{test['testcase']} in file: #{test['id']} with title:
|
||||
#{test['full_description']}
|
||||
FORMAT_ERRORS
|
||||
)
|
||||
end
|
||||
else
|
||||
missing_testcases.push(" ==> #{test['id']} - #{test['full_description']}\n")
|
||||
end
|
||||
end
|
||||
|
||||
testcase_list = testcases.group_by {|testcase| testcase.shift}.transform_values(&:flatten)
|
||||
|
||||
duplicates = testcase_list.select {|k, v| v.count > 1}
|
||||
|
||||
unless duplicates.empty?
|
||||
duplicates.each do |duplicate|
|
||||
formatted_duplicates.append(
|
||||
<<~DUPLICATES
|
||||
Testcase link #{duplicate[0]} is used in too many tests:
|
||||
==> #{duplicate[1].join("\n ==> ")}\n
|
||||
DUPLICATES
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if formatted_duplicates.empty? && missing_testcases.empty? && testcase_format_errors.empty?
|
||||
puts "\nNo errors found."
|
||||
else
|
||||
puts "\n*** Testcase link violations detected! ***\n"
|
||||
puts duplicate_message % formatted_duplicates.join("\n") unless formatted_duplicates.empty?
|
||||
puts missing_message % missing_testcases.join("\n") unless missing_testcases.empty?
|
||||
puts format_message % testcase_format_errors.join("\n") unless testcase_format_errors.empty?
|
||||
puts "\n*** Please link a unique test case from the GitLab project for the errors listed above.\n"
|
||||
puts " See: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html#link-a-test-to-its-test-case."
|
||||
exit 1
|
||||
end
|
|
@ -45,8 +45,8 @@ RSpec.describe Ci::PipelineEditorHelper do
|
|||
"default-branch" => project.default_branch_or_main,
|
||||
"empty-state-illustration-path" => 'foo',
|
||||
"initial-branch-name" => nil,
|
||||
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
|
||||
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available'),
|
||||
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
|
||||
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
|
||||
"needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
|
||||
"new-merge-request-path" => '/mock/project/-/merge_requests/new',
|
||||
"pipeline_etag" => graphql_etag_pipeline_sha_path(project.commit.sha),
|
||||
|
@ -72,8 +72,8 @@ RSpec.describe Ci::PipelineEditorHelper do
|
|||
"default-branch" => project.default_branch_or_main,
|
||||
"empty-state-illustration-path" => 'foo',
|
||||
"initial-branch-name" => nil,
|
||||
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
|
||||
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available'),
|
||||
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
|
||||
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
|
||||
"needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
|
||||
"new-merge-request-path" => '/mock/project/-/merge_requests/new',
|
||||
"pipeline_etag" => '',
|
||||
|
|
|
@ -23,7 +23,8 @@ RSpec.describe 'CI YML Templates' do
|
|||
exceptions = [
|
||||
'Security/DAST.gitlab-ci.yml', # DAST stage is defined inside AutoDevops yml
|
||||
'Security/DAST-API.gitlab-ci.yml', # no auto-devops
|
||||
'Security/API-Fuzzing.gitlab-ci.yml' # no auto-devops
|
||||
'Security/API-Fuzzing.gitlab-ci.yml', # no auto-devops
|
||||
'ThemeKit.gitlab-ci.yml'
|
||||
]
|
||||
|
||||
context 'when including available templates in a CI YAML configuration' do
|
||||
|
|
60
spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
Normal file
60
spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'ThemeKit.gitlab-ci.yml' do
|
||||
before do
|
||||
allow(Gitlab::Template::GitlabCiYmlTemplate).to receive(:excluded_patterns).and_return([])
|
||||
end
|
||||
|
||||
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('ThemeKit') }
|
||||
|
||||
describe 'the created pipeline' do
|
||||
let(:pipeline_ref) { project.default_branch_or_main }
|
||||
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
|
||||
let(:user) { project.first_owner }
|
||||
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
|
||||
let(:pipeline) { service.execute!(:push).payload }
|
||||
let(:build_names) { pipeline.builds.pluck(:name) }
|
||||
|
||||
before do
|
||||
stub_ci_pipeline_yaml_file(template.content)
|
||||
end
|
||||
|
||||
context 'on the default branch' do
|
||||
it 'only creates staging deploy', :aggregate_failures do
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(build_names).to include('staging')
|
||||
expect(build_names).not_to include('production')
|
||||
end
|
||||
end
|
||||
|
||||
context 'on a tag' do
|
||||
let(:pipeline_ref) { '1.0' }
|
||||
|
||||
before do
|
||||
project.repository.add_tag(user, pipeline_ref, project.default_branch_or_main)
|
||||
end
|
||||
|
||||
it 'only creates a production deploy', :aggregate_failures do
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(build_names).to include('production')
|
||||
expect(build_names).not_to include('staging')
|
||||
end
|
||||
end
|
||||
|
||||
context 'outside of the default branch' do
|
||||
let(:pipeline_ref) { 'patch-1' }
|
||||
|
||||
before do
|
||||
project.repository.create_branch(pipeline_ref, project.default_branch_or_main)
|
||||
end
|
||||
|
||||
it 'has no jobs' do
|
||||
expect { pipeline }.to raise_error(
|
||||
Ci::CreatePipelineService::CreateError, 'No stages / jobs for this pipeline.'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,36 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
require_relative '../../../../rubocop/cop/qa/duplicate_testcase_link'
|
||||
|
||||
RSpec.describe RuboCop::Cop::QA::DuplicateTestcaseLink do
|
||||
let(:source_file) { 'qa/page.rb' }
|
||||
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context 'in a QA file' do
|
||||
before do
|
||||
allow(cop).to receive(:in_qa_file?).and_return(true)
|
||||
end
|
||||
|
||||
it "registers an offense for a duplicate testcase link" do
|
||||
expect_offense(<<-RUBY)
|
||||
it 'some test', testcase: '/quality/test_cases/1892' do
|
||||
end
|
||||
it 'another test', testcase: '/quality/test_cases/1892' do
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't reuse the same testcase link in different tests. Replace one of `/quality/test_cases/1892`.
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "doesnt offend if testcase link is unique" do
|
||||
expect_no_offenses(<<-RUBY)
|
||||
it 'some test', testcase: '/quality/test_cases/1893' do
|
||||
end
|
||||
it 'another test', testcase: '/quality/test_cases/1894' do
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
require_relative '../../../../rubocop/cop/qa/testcase_link_format'
|
||||
|
||||
RSpec.describe RuboCop::Cop::QA::TestcaseLinkFormat do
|
||||
let(:source_file) { 'qa/page.rb' }
|
||||
let(:msg) { 'Testcase link format incorrect. Please link a test case from the GitLab project. See: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html#link-a-test-to-its-test-case.' }
|
||||
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context 'in a QA file' do
|
||||
before do
|
||||
allow(cop).to receive(:in_qa_file?).and_return(true)
|
||||
end
|
||||
|
||||
it "registers an offense for a testcase link for an issue" do
|
||||
node = "it 'another test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/issues/557' do"
|
||||
|
||||
expect_offense(<<-RUBY, node: node, msg: msg)
|
||||
%{node}
|
||||
^{node} %{msg}
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "registers an offense for a testcase link for the wrong project" do
|
||||
node = "it 'another test', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2455' do"
|
||||
|
||||
expect_offense(<<-RUBY, node: node, msg: msg)
|
||||
%{node}
|
||||
^{node} %{msg}
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "doesnt offend if testcase link is correct" do
|
||||
expect_no_offenses(<<-RUBY)
|
||||
it 'some test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348312' do
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue