You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2320431
Browse filesBrowse the repository at this point in the historyBrowse files
feat(discovery)!: match exclude patterns with picomatch under an owned glob grammar
The exclude discovery filter compiled its own RegExp from each pattern, with "*" the only operator and every other character literal. Each pattern is now healed and compiled once at the input boundary with picomatch (the posix entry, nocase, dot, posix classes, noglobstar, no fast paths, debug), and the boundary owns the grammar: name characters, at most one "/", "*", "?", "[abc]", "[!abc]" or "[^abc]", and one leading "!". Malformed input with one unambiguous repair (a leading "./", a run of stars, and for library callers surrounding whitespace) is repaired and the run prints a notice naming the pattern as written and as matched. Anything else is refused when the inputs are parsed, naming the reason and the fix, because picomatch reads braces, parentheses, quotes, backslashes, and "***" as regex syntax through paths no option closes and would otherwise compile a wrong or never-matching filter silently.
DiscoveryFilters.exclude carries the compiled ExcludePattern (written, pattern, scope, regex) instead of strings, so a config built from argv still equals one built from the environment, and compileExcludePattern, ExcludePattern, and formatHealNotice join the library surface. The e2e oracle's independent matcher learns "?", a leading "!", and the heals, and two scenarios pin the new forms end to end. The upgrading guide gains section 61.
BREAKING CHANGE: In an exclude pattern, "?" now matches one character, "[abc]" and "[!abc]" are classes, and a leading "!" negates the pattern; each matched nothing before, so a pattern that relied on one of them matching literally is deleted and one that meant a glob is rewritten in that grammar. A leading "./" and a run of stars are healed and noticed in the run output, so "./tmp-**" runs as "tmp-*". A "." or ".." side, a second "/", a doubled "!", and any regex token ("(a)+", "\d", "{a..b}", quotes) fail the run naming the fix. Library callers supply exclude as ExcludePattern values from compileExcludePattern instead of strings.
Copy file name to clipboardExpand all lines: docs/operate/multi-repo.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,7 +57,11 @@ Discovery takes six filter inputs that apply only to `repos: "*"`; setting any o
57
57
- `archived` defaults to `skip`, because settings writes fail on archived repositories; `archived: only` is mostly useful with `mode: check`.
58
58
- `forks`includes, excludes, or keeps only forks.
59
59
- `topics`keeps repositories carrying at least one listed topic, so a single marker topic can opt repositories in. It is unrelated to the `topics` settings section.
60
-
- `exclude` takes wildcard patterns where `*` matches anything: a pattern containing `/` is matched against the full `owner/name`, any other against the name alone, case-insensitively.
60
+
- `exclude` takes glob patterns, matched case-insensitively: a pattern containing `/` against the full `owner/name`, any other against the name alone.
61
+
- `*`matches any run of characters, `?` one character, `[abc]` one of a set, `[!abc]` or `[^abc]` one outside it.
62
+
- One leading `!` negates the pattern, so `!svc-*` drops everything except the services.
63
+
- A leading `./` and a run of stars are repaired, not refused: `./tmp-**`runs as `tmp-*`, and a notice names the pattern as written and as matched.
64
+
- Beyond those operators a pattern holds only name characters (letters, digits, `.`, `-`, `_`), at most one `/` with a non-empty glob on each side, and no side that is just `.` or `..`. Anything else (a brace, a parenthesis, a backslash, a quote, a second `/`, a class holding `*`) fails the run before discovery starts, as does a class like `[z-a]`. The matcher is [picomatch](https://github.com/micromatch/picomatch), confined to that grammar.
61
65
- `affiliation` selects which relationships to the token's user qualify, passed to GitHub's `/user/repos` listing: `owner`(the default), `collaborator`, or `organization_member`. The list replaces the default, so widening discovery beyond owned repositories takes `owner,collaborator`.
62
66
63
67
## Fallback for repositories without a settings file
Copy file name to clipboardExpand all lines: docs/reference/inputs.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,7 +38,7 @@ A list input (`sections`, `required-sections`, `repos`, `exclude`, `topics`, `af
38
38
|`visibility`| <p>Keeps only repositories of this visibility in repos: "*" discovery: all (default), public, private, or internal.</p> |`false`|`""`|
39
39
|`archived`| <p>Archived-repository policy for repos: "*" discovery: skip (default), include, or only.</p> |`false`|`""`|
40
40
|`forks`| <p>Fork policy for repos: "*" discovery: include (default), exclude, or only.</p> |`false`|`""`|
41
-
|`exclude`| <p>Comma- or newline-separated wildcard patterns removing repositories from repos: "*" discovery.</p> |`false`|`""`|
41
+
|`exclude`| <p>Comma- or newline-separated glob patterns removing repositories from repos: "*" discovery, compared case-insensitively against owner/name when the pattern has a "/" and against the name alone otherwise. A star matches any run of characters, "?" one character, "[abc]" one of a set, "[!abc]" or "[^abc]" one outside it, and one leading "!" negates the pattern. A leading "./" and a run of stars are repaired and noted in the run output. Beyond those a pattern holds only letters, digits, ".", "-", and "_", with at most one "/", nothing empty around it, and no side that is just "." or ".."; anything else, a regex token such as "(a)+" included, fails the run naming the fix.</p> |`false`|`""`|
42
42
|`topics`| <p>Comma- or newline-separated topics, of which repos: "*" discovery keeps the repositories carrying at least one.</p> |`false`|`""`|
43
43
|`affiliation`| <p>Comma- or newline-separated affiliations for repos: "*" discovery: owner (default), collaborator, or organization_member.</p> |`false`|`""`|
|`discoverRepos`| function | The repositories a token can see, filtered |
245
245
|`DiscoveryFilters`| type | The filters: `visibility`, `archived`, `forks`, `affiliation`, `topics`, `exclude`|
246
246
|`DEFAULT_DISCOVERY_FILTERS`| const | The action's defaults |
247
+
|`compileExcludePattern`| function | One `exclude` glob healed and compiled once, or the problem naming why it is unusable |
248
+
|`ExcludePattern`| type | A compiled `exclude` entry: the pattern as written, as matched after the heals, the scope its slash chose, and the regex |
249
+
|`formatHealNotice`| function | The notice the action prints for a healed `exclude` entry, naming it as written and as matched, or null when nothing was healed |
247
250
|`parseReposInput`| function | The `repos` input form: slugs, or `"*"` for discovery |
248
251
|`resolveCentralTargets`| function | The `<owner>/<name>.yml` files of a repos-dir as targets, with warnings for the files it skipped |
249
252
|`dedupeTargets`| function | Merge the central and the remote targets, central first; a remote target whose slug a central one already names is dropped with a notice |
Copy file name to clipboardExpand all lines: docs/upgrading/v2-to-v3.md
+34Lines changed: 34 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1265,6 +1265,40 @@ v3 merge build(deps): bump yaml -> green -> no release-PR refresh
1265
1265
1266
1266
Fix: nothing for a consumer of `@next`. For a build of one exact commit, install the packaged commit (`github:Vivswan/github-settings-as-code#<packaged sha>`, from a `build/<position>.<sha7>` tag, the ten newest kept, or a release tag).
1267
1267
1268
+
## 61. Discovery: `exclude` patterns are globs under an owned grammar
1269
+
1270
+
For every `repos: "*"` workflow that sets `exclude`, and for `@vivswan/github-settings-as-code` consumers building `DiscoveryFilters`. In v2 an `exclude` pattern knew one operator, `*`, and matched every other character literally, so a `?`, a `[`, or a leading `!` could only ever match nothing. In v3 the pattern is a glob matched by picomatch inside a grammar the input boundary owns: `*` any run of characters, `?` one character, `[abc]` one of a set, `[!abc]` or `[^abc]` one outside it, one leading `!` negating the whole pattern, and beyond those only name characters (letters, digits, `.`, `-`, `_`) with at most one `/`. The scope rule is unchanged: a pattern with `/` matches `owner/name`, any other the name alone, case-insensitively.
1271
+
1272
+
Three kinds of pattern move:
1273
+
1274
+
- A pattern that gains glob meaning: `tmp-?`, `svc-[ab]`, `!svc-*`. Each matched nothing in v2; in v3 `!svc-*` excludes every repository that is not a service.
1275
+
- A pattern with one unambiguous repair is healed and the run says so in a notice: a leading `./` drops and a run of stars becomes one `*`. `./tmp-**` runs as `tmp-*`.
1276
+
- A pattern outside the grammar fails the run before discovery starts, naming the fix: a `.` or `..` side (`x/..`), a second `/`, a doubled `!!`, or a regex token (`(a)+`, `\d`, `{a..b}`, a quote).
1277
+
1278
+
```text
1279
+
v2 exclude: "!svc-*" -> matched nothing, every repository discovered
1280
+
v3 exclude: "!svc-*" -> excludes every repository whose name is not svc-*
notice: repos: "*" discovery healed the exclude pattern "./tmp-**" to "tmp-*"
1286
+
1287
+
v3 exclude: "svc-(a)+" -> error: the "exclude" input pattern "svc-(a)+" is not a usable glob: it holds "(", ...
1288
+
```
1289
+
1290
+
Fix: delete a pattern that relied on `?`, `[`, `]`, or `!` matching literally, since it never matched a repository; rewrite one that meant a glob in the grammar above, and check the notices of the first run for a heal you did not intend.
1291
+
1292
+
For library callers, `DiscoveryFilters.exclude` takes compiled `ExcludePattern` values instead of strings: run each pattern through `compileExcludePattern` at your input boundary, and read `formatHealNotice` for the repair line the action prints.
1. Rename any settings file whose path contains a comma, rename `undeclared` to `_undeclared` in every settings file, and move every other underscore key into a YAML comment; the v2 line accepts the old spellings only, so do all three together with the pin move.
0 commit comments