Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-18 21:08:27 +00:00
parent 6c0a6dd200
commit 3b67d92c35
37 changed files with 347 additions and 207 deletions

View file

@ -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

View file

@ -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:

View file

@ -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'

View file

@ -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"
>

View file

@ -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>

View file

@ -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,

View file

@ -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) : '',

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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`. |

View file

@ -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,

View file

@ -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 |

View file

@ -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

View file

@ -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}"

View file

@ -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}"

View file

@ -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}"

View 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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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] } }

View file

@ -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

View file

@ -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
View 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

View file

@ -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" => '',

View file

@ -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

View 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

View file

@ -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

View file

@ -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