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 179d0a4
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 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 "!". Anything outside it is refused when the inputs are parsed, naming the reason and the fix, because picomatch reads braces, parentheses, quotes, backslashes, a leading "./", 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 (pattern, scope, regex) instead of strings, so a config built from argv still equals one built from the environment, and compileExcludePattern with ExcludePattern join the library surface. The e2e oracle's independent matcher learns "?" and a leading "!", and two scenarios pin the new forms end to end.
BREAKING CHANGE: "?", "[", "]", and a leading "!" in an exclude pattern are glob operators now ("?" one character, "[abc]" a class, "!" negation), and every other non-name character ("{", "(", "|", "+", "\", quotes, spaces) is refused at parse time instead of being matched literally. A pattern that relied on one of those matching literally never matched a GitHub repository, so drop it. A pattern meant as a glob keeps working unchanged.
Copy file name to clipboardExpand all lines: docs/operate/multi-repo.md
+4-1Lines changed: 4 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,7 +57,10 @@ 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
+
- 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
64
- `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
65
63
66
## 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. Beyond those operators a pattern holds only letters, digits, ".", "-", and "_", with at most one "/", nothing empty around it, and no side that is just "." or "..".</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 |
243
243
|`DiscoveryFilters`| type | The filters: `visibility`, `archived`, `forks`, `affiliation`, `topics`, `exclude`|
244
244
|`DEFAULT_DISCOVERY_FILTERS`| const | The action's defaults |
245
+
|`compileExcludePattern`| function | One `exclude` glob compiled once, or the problem naming why it is unusable |
246
+
|`ExcludePattern`| type | A compiled `exclude` entry: the operator's text, the scope its slash chose, and the regex |
245
247
|`parseReposInput`| function | The `repos` input form: slugs, or `"*"` for discovery |
246
248
|`resolveCentralTargets`| function | The `<owner>/<name>.yml` files of a repos-dir as targets, with warnings for the files it skipped |
247
249
|`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 |
@@ -509,12 +513,16 @@ export function describeProblem(problem: Problem): string {
509
513
return'the "private-report" input delivers reports only for redacted targets, but "private-repos" is "show", so nothing is redacted and no report would ever be sent. Set private-repos: redact, or set private-report: none';
510
514
case"input-affiliation-unsupported":
511
515
return`the "affiliation" input entry "${problem.entry}" is not a supported affiliation, so discovery cannot build the /user/repos query. Use a comma-separated list of ${quoteList(problem.allowed)}`;
`the "exclude" input pattern "${problem.pattern}" can never match an owner/name repository: a `+
515
-
`pattern takes at most one "/", with a non-empty glob on each side of it. Use `+
516
-
`"<name-glob>" or "<owner-glob>/<name-glob>", where "*" matches any characters`
520
+
`the "exclude" input pattern "${shown}" is not a usable glob: ${problem.reason}. Write `+
521
+
`"<name-glob>" or "<owner-glob>/<name-glob>", where a glob is letters, digits, ".", "-", "_", "*", "?", `+
522
+
`and the classes "[abc]" or "[!abc]" over those characters, with one optional leading "!" negating `+
523
+
`the whole pattern`
517
524
);
525
+
}
518
526
case"input-repository-with-multi":
519
527
return'the "repository" input cannot be combined with "repos" or "repos-dir"; multi-repo targets come from those inputs. Remove "repository", or remove the multi-repo inputs to stay in single-repo mode';
0 commit comments