Commit 86c0d8d2 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'only-syntax' into 'master'

Extend yml syntax for only and except to support specifying repository path

This allows to limit execution of jobs to specific repository.

For example:
```yaml
job:
  only:
    - branches@gitlab-org/gitlab-ce
  except:
    - master@gitlab-org/gitlab-ce
```

The above will run `job` for all branches on `gitlab-org/gitlab-ce`, except master.

@dzaporozhets @JobV @vsizov Please review.


See merge request !1720
parents 819cfcef fe34b745
...@@ -13,6 +13,7 @@ v 8.2.0 (unreleased) ...@@ -13,6 +13,7 @@ v 8.2.0 (unreleased)
- Fix: Inability to reply to code comments in the MR view, if the MR comes from a fork - Fix: Inability to reply to code comments in the MR view, if the MR comes from a fork
- Use git follow flag for commits page when retrieve history for file or directory - Use git follow flag for commits page when retrieve history for file or directory
- Show merge request CI status on merge requests index page - Show merge request CI status on merge requests index page
- Extend yml syntax for only and except to support specifying repository path
- Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu) - Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu)
- Remove deprecated CI events from project settings page - Remove deprecated CI events from project settings page
- Use issue editor as cross reference comment author when issue is edited with a new mention. - Use issue editor as cross reference comment author when issue is edited with a new mention.
......
...@@ -187,7 +187,7 @@ module Ci ...@@ -187,7 +187,7 @@ module Ci
end end
def config_processor def config_processor
@config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file) @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file, gl_project.path_with_namespace)
rescue Ci::GitlabCiYamlProcessor::ValidationError => e rescue Ci::GitlabCiYamlProcessor::ValidationError => e
save_yaml_error(e.message) save_yaml_error(e.message)
nil nil
......
...@@ -169,7 +169,7 @@ This are two parameters that allow for setting a refs policy to limit when jobs ...@@ -169,7 +169,7 @@ This are two parameters that allow for setting a refs policy to limit when jobs
There are a few rules that apply to usage of refs policy: There are a few rules that apply to usage of refs policy:
1. `only` and `except` are exclusive. If both `only` and `except` are defined in job specification only `only` is taken into account. 1. `only` and `except` are inclusive. If both `only` and `except` are defined in job specification the ref is filtered by `only` and `except`.
1. `only` and `except` allow for using the regexp expressions. 1. `only` and `except` allow for using the regexp expressions.
1. `only` and `except` allow for using special keywords: `branches` and `tags`. 1. `only` and `except` allow for using special keywords: `branches` and `tags`.
These names can be used for example to exclude all tags and all branches. These names can be used for example to exclude all tags and all branches.
...@@ -182,6 +182,18 @@ job: ...@@ -182,6 +182,18 @@ job:
- branches # use special keyword - branches # use special keyword
``` ```
1. `only` and `except` allow for specify repository path to filter jobs for forks.
The repository path can be used to have jobs executed only for parent repository.
```yaml
job:
only:
- branches@gitlab-org/gitlab-ce
except:
- master@gitlab-org/gitlab-ce
```
The above will run `job` for all branches on `gitlab-org/gitlab-ce`, except master .
### tags ### tags
`tags` is used to select specific runners from the list of all runners that are allowed to run this project. `tags` is used to select specific runners from the list of all runners that are allowed to run this project.
......
...@@ -7,10 +7,11 @@ module Ci ...@@ -7,10 +7,11 @@ module Ci
ALLOWED_YAML_KEYS = [:before_script, :image, :services, :types, :stages, :variables] ALLOWED_YAML_KEYS = [:before_script, :image, :services, :types, :stages, :variables]
ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services, :allow_failure, :type, :stage, :when] ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services, :allow_failure, :type, :stage, :when]
attr_reader :before_script, :image, :services, :variables attr_reader :before_script, :image, :services, :variables, :path
def initialize(config) def initialize(config, path = nil)
@config = YAML.load(config) @config = YAML.load(config)
@path = path
unless @config.is_a? Hash unless @config.is_a? Hash
raise ValidationError, "YAML should be a hash" raise ValidationError, "YAML should be a hash"
...@@ -63,26 +64,6 @@ module Ci ...@@ -63,26 +64,6 @@ module Ci
end end
end end
def process?(only_params, except_params, ref, tag)
return true if only_params.nil? && except_params.nil?
if only_params
return true if tag && only_params.include?("tags")
return true if !tag && only_params.include?("branches")
only_params.find do |pattern|
match_ref?(pattern, ref)
end
else
return false if tag && except_params.include?("tags")
return false if !tag && except_params.include?("branches")
except_params.each do |pattern|
return false if match_ref?(pattern, ref)
end
end
end
def build_job(name, job) def build_job(name, job)
{ {
stage_idx: stages.index(job[:stage]), stage_idx: stages.index(job[:stage]),
...@@ -101,14 +82,6 @@ module Ci ...@@ -101,14 +82,6 @@ module Ci
} }
end end
def match_ref?(pattern, ref)
if pattern.first == "/" && pattern.last == "/"
Regexp.new(pattern[1...-1]) =~ ref
else
pattern == ref
end
end
def normalize_script(script) def normalize_script(script)
if script.is_a? Array if script.is_a? Array
script.join("\n") script.join("\n")
...@@ -208,5 +181,36 @@ module Ci ...@@ -208,5 +181,36 @@ module Ci
def validate_string(value) def validate_string(value)
value.is_a?(String) || value.is_a?(Symbol) value.is_a?(String) || value.is_a?(Symbol)
end end
def process?(only_params, except_params, ref, tag)
if only_params.present?
return false unless matching?(only_params, ref, tag)
end
if except_params.present?
return false if matching?(except_params, ref, tag)
end
true
end
def matching?(patterns, ref, tag)
patterns.any? do |pattern|
match_ref?(pattern, ref, tag)
end
end
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'
if pattern.first == "/" && pattern.last == "/"
Regexp.new(pattern[1...-1]) =~ ref
else
pattern == ref
end
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment