I poked around and I don't think this is possible. You can use contains() to do a full match of items in a json array, but I don't see any other way to iterate. What we'd really want is a "map" function, to do something like:
map { startsWith(github.ref_name, $1) } fromJSON(vars.CI_CONFIG.allow_prefix)But no such "map" exists (and I guess we'd need to collapse the result down to "is any item true", similar to perl's "grep" function).
Do you need multiple prefixes, or would one each of allow/reject be sufficient? I tried this and it works:
jobs:
ci-config:
name: config
if: |
(fromJSON(vars.CI_CONFIG).allow == '' ||
contains(fromJSON(vars.CI_CONFIG).allow, github.ref_name)) &&
(fromJSON(vars.CI_CONFIG).reject == '' ||
!contains(fromJSON(vars.CI_CONFIG).reject, github.ref_name)) &&
(fromJSON(vars.CI_CONFIG).allow-prefix == '' ||
startsWith(github.ref_name, fromJSON(vars.CI_CONFIG).allow-prefix)) &&
(fromJSON(vars.CI_CONFIG).reject-prefix == '' ||
!startsWith(github.ref_name, fromJSON(vars.CI_CONFIG).reject-prefix))And then various values of CI_CONFIG seem to work:
- allow explicit branch names ("one" and "two" are run, everything
else is skipped) { "allow": ["one", "two"] } - reject explicit names (everything except "three" is skipped)
{ "reject": ["three"] } - allow by prefix ("ok/* is run, everything else is skipped) { "allow-prefix": "ok/" } - reject by prefix (everything except "nope/*" is run)
{ "reject-prefix": "nope/" } - every key must approve to run, but missing keys default to running.
So a reject overrides allow ("ok/one" and "ok/two" run, but
"ok/three" does not) {
"allow-prefix": "ok/",
"reject", "ok/three"
}I suppose one hacky way to support multiple prefixes is to just unroll the loop ourselves (since missing keys are ignored). I didn't test it, but something like:
(fromJSON(vars.CI_CONFIG).allow-prefix[0] == '' ||
startsWith(github.ref_name, fromJSON(vars.CI_CONFIG).allow-prefix[0])) &&
(fromJSON(vars.CI_CONFIG).allow-prefix[1] == '' ||
startsWith(github.ref_name, fromJSON(vars.CI_CONFIG).allow-prefix[1])) &&
(fromJSON(vars.CI_CONFIG).allow-prefix[2] == '' ||
startsWith(github.ref_name, fromJSON(vars.CI_CONFIG).allow-prefix[2])) &&
...etc...Would allow:
{
"allow-prefix": [
"ok/",
"also-ok/"
]
}Looking at the ci-config branch of phillipwood/git.git, I see this in your allow-refs:
refs/heads/main|refs/heads/master|refs/heads/maint|refs/heads/next|refs/heads/seen|refs/tags/gitgui-*|refs/tags/pr-[0-9]*|refs/tags/v[1-9].*)
So you do use multiple prefixes, though all in refs/tags/. Do you actually push tags for which you do want to run CI, or would it be sufficient to just reject "refs/tags/" completely (though that implies using the fully qualified ref and not the short name; it would also be easy to add a boolean "allow tags" config option).
-Peff