diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 52ded37c2a7..8a0662db6fd 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -393,7 +393,8 @@ There are a few rules that apply to the usage of refs policy: * `only` and `except` are inclusive. If both `only` and `except` are defined in a job specification, the ref is filtered by `only` and `except`. * `only` and `except` allow the use of regular expressions. -* `only` and `except` allow the use of special keywords: `branches`, `tags`, `triggers` and `schedules`. +* `only` and `except` allow the use of special keywords: +`api`, `branches`, `external`, `tags`, `pushes`, `schedules`, `triggers`, and `web` * `only` and `except` allow to specify a repository path to filter jobs for forks. diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 98600a48d0f..0b362921b06 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -207,17 +207,15 @@ module Ci def matching?(patterns, ref, tag, source) patterns.any? do |pattern| - match_ref?(pattern, ref, tag, source) + match_ref?(pattern, ref, tag) || match_source?(pattern, source) end end - def match_ref?(pattern, ref, tag, source) + def match_ref?(pattern, ref, tag) pattern, path = pattern.split('@', 2) return false if path && path != self.path return true if tag && pattern == 'tags' return true if !tag && pattern == 'branches' - return true if source == 'trigger' && pattern == 'triggers' - return true if source == 'schedule' && pattern == 'schedules' if pattern.first == "/" && pattern.last == "/" Regexp.new(pattern[1...-1]) =~ ref @@ -225,5 +223,14 @@ module Ci pattern == ref end end + + def match_source?(pattern, source) + return source_to_pattern(source) == pattern + end + + def source_to_pattern(source) + return source if ['api', 'external', 'web'].include? source + return source.pluralize + end end end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index aa281301faf..79ed1366336 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -219,48 +219,44 @@ module Ci expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0) end - it "returns builds if only has a triggers keyword specified and a trigger is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, only: ["triggers"] } - }) + it "returns builds if only has special keywords specified and source matches" do + possibilities = [{keyword: 'pushes', source: 'push'}, + {keyword: 'web', source: 'web'}, + {keyword: 'triggers', source: 'trigger'}, + {keyword: 'schedules', source: 'schedule'}, + {keyword: 'api', source: 'api'}, + {keyword: 'external', source: 'external'}] - config_processor = GitlabCiYamlProcessor.new(config, path) + possibilities.each do |possibility| + config = YAML.dump({ + before_script: ["pwd"], + rspec: { script: "rspec", type: type, only: [possibility[:keyword]] } + }) - expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, 'trigger').size).to eq(1) + config_processor = GitlabCiYamlProcessor.new(config, path) + + expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, possibility[:source]).size).to eq(1) + end end - it "returns builds if only has a schedules keyword specified and a schedule is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, only: ["schedules"] } - }) + it "does not return builds if only has special keywords specified and source doesn't match" do + possibilities = [{keyword: 'pushes', source: 'web'}, + {keyword: 'web', source: 'push'}, + {keyword: 'triggers', source: 'schedule'}, + {keyword: 'schedules', source: 'external'}, + {keyword: 'api', source: 'trigger'}, + {keyword: 'external', source: 'api'}] - config_processor = GitlabCiYamlProcessor.new(config, path) + possibilities.each do |possibility| + config = YAML.dump({ + before_script: ["pwd"], + rspec: { script: "rspec", type: type, only: [possibility[:keyword]] } + }) - expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, 'schedule').size).to eq(1) - end + config_processor = GitlabCiYamlProcessor.new(config, path) - it "does not return builds if only has a triggers keyword specified and no trigger is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, only: ["triggers"] } - }) - - config_processor = GitlabCiYamlProcessor.new(config, path) - - expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0) - end - - it "does not return builds if only has a schedules keyword specified and no schedule is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, only: ["schedules"] } - }) - - config_processor = GitlabCiYamlProcessor.new(config, path) - - expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0) + expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, possibility[:source]).size).to eq(0) + end end it "returns builds if only has current repository path" do @@ -397,48 +393,44 @@ module Ci expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1) end - it "does not return builds if except has a triggers keyword specified and a trigger is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, except: ["triggers"] } - }) + it "does not return builds if except has special keywords specified and source matches" do + possibilities = [{keyword: 'pushes', source: 'push'}, + {keyword: 'web', source: 'web'}, + {keyword: 'triggers', source: 'trigger'}, + {keyword: 'schedules', source: 'schedule'}, + {keyword: 'api', source: 'api'}, + {keyword: 'external', source: 'external'}] - config_processor = GitlabCiYamlProcessor.new(config, path) + possibilities.each do |possibility| + config = YAML.dump({ + before_script: ["pwd"], + rspec: { script: "rspec", type: type, except: [possibility[:keyword]] } + }) - expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, 'trigger').size).to eq(0) + config_processor = GitlabCiYamlProcessor.new(config, path) + + expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, possibility[:source]).size).to eq(0) + end end - it "does not return builds if except has a schedules keyword specified and a schedule is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, except: ["schedules"] } - }) + it "returns builds if except has special keywords specified and source doesn't match" do + possibilities = [{keyword: 'pushes', source: 'web'}, + {keyword: 'web', source: 'push'}, + {keyword: 'triggers', source: 'schedule'}, + {keyword: 'schedules', source: 'external'}, + {keyword: 'api', source: 'trigger'}, + {keyword: 'external', source: 'api'}] - config_processor = GitlabCiYamlProcessor.new(config, path) + possibilities.each do |possibility| + config = YAML.dump({ + before_script: ["pwd"], + rspec: { script: "rspec", type: type, only: [possibility[:keyword]] } + }) - expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, 'schedule').size).to eq(0) - end + config_processor = GitlabCiYamlProcessor.new(config, path) - it "returns builds if except has a triggers keyword specified and no trigger is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, except: ["triggers"] } - }) - - config_processor = GitlabCiYamlProcessor.new(config, path) - - expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1) - end - - it "returns builds if except has a schedules keyword specified and no schedule is provided" do - config = YAML.dump({ - before_script: ["pwd"], - rspec: { script: "rspec", type: type, except: ["schedules"] } - }) - - config_processor = GitlabCiYamlProcessor.new(config, path) - - expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1) + expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, possibility[:source]).size).to eq(1) + end end it "does not return builds if except has current repository path" do