diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json index 8e307bc1f19a4ce0c7a636628394595e16b76bee..3a1188d7aabc373c5e8186309f1c2c8fdae8cfc1 100644 --- a/app/assets/javascripts/editor/schema/ci.json +++ b/app/assets/javascripts/editor/schema/ci.json @@ -830,7 +830,8 @@ { "type": "string", "enum": [ - "never" + "never", + "always" ] }, { diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md index 5c818a81ff8a08d1dbedd22868acb2bdb70f58bd..69595b62de2107d1321084933e9725d21970a0a5 100644 --- a/doc/ci/yaml/includes.md +++ b/doc/ci/yaml/includes.md @@ -418,7 +418,7 @@ these keywords: ### `include` with `rules:if` -> Support for `when: never` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348146) in GitLab 16.1. +> Support for `when: never` and `when:always` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348146) in GitLab 16.1 [with a flag](../../administration/feature_flags.md) named `ci_support_include_rules_when_never`. Disabled by default. Use [`rules:if`](index.md#rulesif) to conditionally include other configuration files based on the status of CI/CD variables. For example: @@ -429,6 +429,10 @@ include: rules: - if: $DONT_INCLUDE_BUILDS == "true" when: never + - local: builds.yml + rules: + - if: $ALWAYS_INCLUDE_BUILDS == "true" + when: always - local: builds.yml rules: - if: $INCLUDE_BUILDS == "true" @@ -443,7 +447,7 @@ test: ### `include` with `rules:exists` -> Support for `when: never` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348146) in GitLab 16.1. +> Support for `when: never` and `when:always` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348146) in GitLab 16.1 [with a flag](../../administration/feature_flags.md) named `ci_support_include_rules_when_never`. Disabled by default. Use [`rules:exists`](index.md#rulesexists) to conditionally include other configuration files based on the existence of files. For example: @@ -455,6 +459,11 @@ include: - exists: - exception-file.md when: never + - local: builds.yml + rules: + - exists: + - important-file.md + when: always - local: builds.yml rules: - exists: diff --git a/lib/gitlab/ci/config/entry/include/rules/rule.rb b/lib/gitlab/ci/config/entry/include/rules/rule.rb index 60ce43a1546e1996ebfeb630f9d6d8c820fbccd9..9cdbd8cd037dcd31a429f83d64f915dc389a079f 100644 --- a/lib/gitlab/ci/config/entry/include/rules/rule.rb +++ b/lib/gitlab/ci/config/entry/include/rules/rule.rb @@ -10,7 +10,7 @@ class Rules::Rule < ::Gitlab::Config::Entry::Node include ::Gitlab::Config::Entry::Attributable ALLOWED_KEYS = %i[if exists when].freeze - ALLOWED_WHEN = %w[never].freeze + ALLOWED_WHEN = %w[never always].freeze attributes :if, :exists, :when diff --git a/lib/gitlab/ci/config/external/rules.rb b/lib/gitlab/ci/config/external/rules.rb index 8aaa14b3d7bd173de00f3cf83bf893e8c28631bf..134306332e6c9b8cceef2f0565a90156aefb4b41 100644 --- a/lib/gitlab/ci/config/external/rules.rb +++ b/lib/gitlab/ci/config/external/rules.rb @@ -19,7 +19,7 @@ def initialize(rule_hashes) def evaluate(context) if Feature.enabled?(:ci_support_include_rules_when_never, context.project) if @rule_list.nil? - Result.new(nil) + Result.new('always') elsif matched_rule = match_rule(context) Result.new(matched_rule.attributes[:when]) else diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml index fffdda8e6d6b31f0b5da4b93d2ed36fa22b5fa62..909911debf15a4103b9738af7f2a8641b01bbee1 100644 --- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml +++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml @@ -5,8 +5,34 @@ stages: include: - local: builds.yml rules: - - if: '$INCLUDE_BUILDS == "false"' + - if: $DONT_INCLUDE_BUILDS == "true" when: never + - local: builds.yml + rules: + - if: $INCLUDE_BUILDS == "true" + when: always + - local: deploys.yml + rules: + - if: $CI_COMMIT_BRANCH == "main" + - local: builds.yml + rules: + - exists: + - exception-file.md + when: never + - local: builds.yml + rules: + - exists: + - file.md + when: always + - local: builds.yml + rules: + - exists: + - file.md + when: null + - local: deploys.yml + rules: + - exists: + - file.md # valid trigger:include trigger:include accepts project and file properties: diff --git a/spec/lib/gitlab/ci/config/external/rules_spec.rb b/spec/lib/gitlab/ci/config/external/rules_spec.rb index 3cb9dedbefe6d37ac3f3a3c51cc1b8ef34367be2..1ba5caa1d4bcdc2610059b300fd8e36fd743e17d 100644 --- a/spec/lib/gitlab/ci/config/external/rules_spec.rb +++ b/spec/lib/gitlab/ci/config/external/rules_spec.rb @@ -80,6 +80,20 @@ end end + context 'with when: always' do + let(:rule_hashes) { [{ if: '$MY_VAR == "hello"', when: 'always' }] } + + it_behaves_like 'when there is a rule with if' + + context 'when FF `ci_support_include_rules_when_never` is disabled' do + before do + stub_feature_flags(ci_support_include_rules_when_never: false) + end + + it_behaves_like 'when there is a rule with if' + end + end + context 'with when: ' do let(:rule_hashes) { [{ if: '$MY_VAR == "hello"', when: 'on_success' }] } @@ -111,6 +125,20 @@ end end + context 'with when: always' do + let(:rule_hashes) { [{ exists: 'Dockerfile', when: 'always' }] } + + it_behaves_like 'when there is a rule with exists' + + context 'when FF `ci_support_include_rules_when_never` is disabled' do + before do + stub_feature_flags(ci_support_include_rules_when_never: false) + end + + it_behaves_like 'when there is a rule with exists' + end + end + context 'with when: ' do let(:rule_hashes) { [{ exists: 'Dockerfile', when: 'on_success' }] }