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 5a79aa3
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/src/content/docs/reference/checkout.md
+18-7Lines changed: 18 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,11 +48,12 @@ checkout:
48
48
49
49
| Field | Type | Description |
50
50
|-------|------|-------------|
51
-
| `repository` | string | Explicit repository in `owner/repo` format, or a newline-separated list with `allowed-repos`. Expressions require `allowed-repos`. Does not support wildcards. Defaults to the current repository. |
51
+
| `repository` | string | Explicit repository in `owner/repo` format, or a newline-separated list with `multi: true`. Without `multi`, expressions must resolve to exactly one repository and need no allowlist. Does not support wildcards. Defaults to the current repository. |
52
52
| `repo` | string | Alias for `repository`; specify only one. Does not support wildcards. |
53
-
| `allowed-repos` | string \| string[] | Mandatory allowlist for runtime repository-list expansion. Accepts newline-separated patterns, an array, or an expression; supports scoped patterns such as `owner/*` and `*/repo`, but not unrestricted `"*"` or `"*/*"`. |
54
-
| `max-repos` | integer | Maximum unique repositories per runtime checkout entry. Requires `allowed-repos`; defaults to `10`. Must be a positive literal integer. |
55
-
| `allow-private-repos` | boolean | Allow private/internal targets in a runtime list hosted by a private/internal repository. Requires `allowed-repos`; defaults to `false` and must be a literal boolean. Public hosts always reject non-public targets, even when `true`. |
53
+
| `multi` | boolean | Explicitly enables runtime repository-list expansion and its restrictions. Defaults to `false`; must be a literal boolean. |
54
+
| `allowed-repos` | string \| string[] | Mandatory allowlist for `multi: true`; does not enable multi mode by itself. Accepts newline-separated patterns, an array, or an expression; supports scoped patterns such as `owner/*` and `*/repo`, but not unrestricted `"*"` or `"*/*"`. Ignored in single-repository mode. |
55
+
| `max-repos` | integer | Maximum unique repositories per `multi: true` checkout entry. Requires `allowed-repos` in multi mode; defaults to `10`. Must be a positive literal integer. Ignored in single-repository mode. |
56
+
| `allow-private-repos` | boolean | With `multi: true`, allow private/internal targets in a runtime list hosted by a private/internal repository. Requires `allowed-repos` in multi mode; defaults to `false` and must be a literal boolean. Public hosts always reject non-public multi targets, even when `true`. Ignored in single-repository mode. |
56
57
| `ref` | string | Branch, tag, or SHA to checkout. Defaults to the triggering ref. |
57
58
| `path` | string | Path within `GITHUB_WORKSPACE` to place the checkout. Defaults to workspace root. |
58
59
| `github-token` | string | Token for authentication. Use `${{ secrets.MY_TOKEN }}` syntax. |
@@ -68,7 +69,16 @@ checkout:
68
69
69
70
## Runtime Repository Lists
70
71
71
-
An entry with `allowed-repos` expands `repository` (or `repo`) at runtime into one checkout per newline-separated `owner/repo` slug. This allows scheduled workers to process a changing repository set supplied through variables, inputs, or earlier step outputs:
72
+
An entry with `multi: true` expands `repository` (or `repo`) at runtime into one checkout per newline-separated `owner/repo` slug. It requires `allowed-repos`. This allows scheduled workers to process a changing repository set supplied through variables, inputs, or earlier step outputs.
73
+
74
+
Without `multi: true` (including `multi: false`), the runtime requires exactly one `owner/repo` slug. Repository expressions do not require `allowed-repos` or a non-root path prefix. Normal single-checkout authentication, private-repository access, LFS, submodules, `current`, and `wiki` behavior applies; none of the multi-repo restrictions below apply. Merely specifying `allowed-repos` does not enable expansion or constrain a single checkout.
75
+
76
+
```yaml wrap
77
+
checkout:
78
+
repo: ${{ inputs.repo }}
79
+
path: target
80
+
current: true
81
+
```
72
82
73
83
`repository`and `repo` select explicit repository names, not wildcard patterns. Their expressions must resolve to concrete `owner/repo` slugs. Wildcards are supported only in `allowed-repos`, which filters the selected list and never discovers or selects repositories.
74
84
@@ -78,14 +88,15 @@ An entry with `allowed-repos` expands `repository` (or `repo`) at runtime into o
78
88
on:
79
89
schedule: daily
80
90
checkout:
81
-
- repository: ${{ vars.WORKER_REPOS }}
91
+
- multi: true
92
+
repository: ${{ vars.WORKER_REPOS }}
82
93
path: targets
83
94
allowed-repos: ${{ vars.ALLOWED_WORKER_REPOS }}
84
95
max-repos: 5
85
96
github-token: ${{ secrets.CROSS_REPO_PAT }}
86
97
```
87
98
88
-
For `WORKER_REPOS` containing `org/api` and `org/web` on separate lines, the checkouts are placed at `targets/org/api` and `targets/org/web`. `path` must be a literal, non-root prefix. The compiler requires `allowed-repos` for `repository` or `repo` expressions, even when they select a single repository, except for the standalone `${{ github.repository }}` expression. That expression selects the workflow repository using normal single-checkout behavior and needs neither an allowlist nor a path prefix. Expressions that combine it with other values still require `allowed-repos`. The allowlist may contain scoped wildcard patterns such as `org/*` or `*/api`. Unrestricted patterns such as `*` and `*/*` are rejected, including when an expression resolves to them at runtime. Matching and deduplication are case-insensitive; an empty selected list produces no additional checkouts, not all allowlisted repositories.
99
+
For `WORKER_REPOS` containing `org/api` and `org/web` on separate lines, the checkouts are placed at `targets/org/api` and `targets/org/web`. With `multi: true`, `path` must be a literal, non-root prefix and `allowed-repos` is mandatory, even if the selector is literal or resolves to just the workflow repository. The allowlist may contain scoped wildcard patterns such as `org/*` or `*/api`. Unrestricted patterns such as `*` and `*/*` are rejected, including when an expression resolves to them at runtime. Matching and deduplication are case-insensitive; an empty selected list produces no additional checkouts, not all allowlisted repositories.
89
100
90
101
Every selected repository must pass the allowlist and GitHub API metadata checks before the checkout action is generated. Redirected repository names are checked against the allowlist again. Runtime lists allow only public targets by default. Set `allow-private-repos: true` on an entry to also allow private/internal targets when the hosting repository is private/internal. **Public workflow repositories cannot check out private or internal repositories**, even when this flag is `true` and the supplied token can access them. The flag requires `allowed-repos` and a literal boolean; it does not change ordinary static checkouts. Both checkout jobs enforce the same policy, and merged entries permit non-public targets only if every entry explicitly opts in. Omission or `false` prevents an imported entry from broadening access. Failed or incomplete visibility checks stop the job.
Copy file name to clipboardExpand all lines: docs/src/content/docs/specs/checkout-behavior-specification.md
+27-10Lines changed: 27 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ sidebar:
7
7
8
8
# Checkout Behavior Specification
9
9
10
-
**Version**: 1.3.2<br>
10
+
**Version**: 1.3.3<br>
11
11
**Status**: Working Draft
12
12
**Publication Date**: 2026-10-14<br>
13
13
**Editor**: GitHub Agentic Workflows Team
@@ -82,7 +82,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
82
82
### 3.1 Checkout Entry Parsing
83
83
84
84
`checkout:` MUST accept either a single object or an array of objects.
85
-
Each entry MAY define: `repository` (or `repo`), `allowed-repos`, `max-repos`, `allow-private-repos`, `ref`, `path`, `github-token` (or legacy `token`), `github-app` (or deprecated alias `app`), `safe-outputs-github-app`, `fetch-depth`, `fetch`, `sparse-checkout`, `submodules`, `lfs`, `current`, `wiki`, and `force-clean-git-credentials`.
85
+
Each entry MAY define: `repository` (or `repo`), `multi`, `allowed-repos`, `max-repos`, `allow-private-repos`, `ref`, `path`, `github-token` (or legacy `token`), `github-app` (or deprecated alias `app`), `safe-outputs-github-app`, `fetch-depth`, `fetch`, `sparse-checkout`, `submodules`, `lfs`, `current`, `wiki`, and `force-clean-git-credentials`.
86
86
87
87
`github-token` and `github-app` MUST be mutually exclusive per entry.
88
88
@@ -91,17 +91,24 @@ Each entry MAY define: `repository` (or `repo`), `allowed-repos`, `max-repos`, `
91
91
#### Runtime Repository Lists
92
92
93
93
`repo` MUST be accepted as an alias for `repository`; specifying both MUST fail.
94
-
Any GitHub Actions expression in `repository` or `repo` MUST require
95
-
`allowed-repos` at compile time, even for a single selected repository, except
96
-
the standalone `${{ github.repository }}` expression. Without `allowed-repos`,
97
-
that expression MUST retain normal single-repository checkout behavior and MUST
98
-
NOT require a path prefix. Whitespace within the expression MAY vary; combining
99
-
it with other expressions or literal values MUST NOT qualify for the exception.
94
+
`multi` MUST be a literal boolean and MUST default to false. Only `multi: true`
95
+
MUST enable repository-list expansion and the multi-repo restrictions in this
96
+
subsection. Neither an expression selector nor `allowed-repos` alone MUST
97
+
implicitly enable multi mode. Without multi mode, an explicit `repository` or
98
+
`repo` MUST resolve to exactly one `owner/repo` slug; empty, malformed, wildcard,
99
+
and multiple resolved slugs (including duplicates) MUST fail before checkout.
100
+
Literal lists MUST fail compilation. Runtime expression values MUST be validated
101
+
as data before `actions/checkout` in both agent and safe-output jobs.
102
+
Single-repository expressions MUST NOT require an allowlist, a non-root path
103
+
prefix, visibility preflight, private-target opt-in, or explicit App scoping.
104
+
Normal single-checkout LFS, submodule, `current`, and `wiki` support MUST remain
105
+
available. Multi-only policy fields MUST NOT activate or constrain a single
106
+
checkout; their declared types still apply.
100
107
`repository` and `repo` MUST select explicit repository names, not wildcard
101
108
patterns. Literal repository wildcards MUST fail at compile time, and wildcard
102
109
values in expression-resolved lists MUST fail at runtime. Wildcards MUST only
103
110
be used in `allowed-repos`; the allowlist MUST NOT discover or select repositories.
104
-
An entry with `allowed-repos` MUST expand its repository value as newline-separated
111
+
An entry with `multi: true` MUST expand its repository value as newline-separated
105
112
`owner/repo` slugs at runtime. List expansion MUST require a non-empty allowlist
106
113
and a literal, non-root path prefix. Each repository MUST be checked out under
107
114
`<prefix>/<owner>/<repo>`. Matching and deduplication MUST be case-insensitive.
@@ -162,7 +169,9 @@ Safe-output jobs MUST retain their intended authenticated-write credentials.
162
169
163
170
### 3.2 Entry Merge Rules
164
171
165
-
Entries with the same `(repository, path, wiki)` key MUST merge with these rules:
172
+
Entries with the same `(repository, path, wiki, multi)` key MUST merge with these rules.
173
+
Single and multi entries MUST remain distinct; an imported multi entry MUST NOT
174
+
silently turn a single entry into a repository list:
166
175
167
176
-`fetch-depth`: deepest wins (`0` wins over all)
168
177
-`ref`: first non-empty wins
@@ -375,6 +384,7 @@ When `GH_AW_TARGET_REPO_SLUG` is set but equals `GITHUB_REPOSITORY`, the impleme
375
384
-**T-CHK-017**: Activation sparse checkout pins supported pull-request events to the base SHA, retains non-PR and `workflow_call` fallback refs, excludes `pull_request_target`, and preserves the same-repo guard for optional App token fallback
376
385
-**T-CHK-018**: Checkout-time and final cleanup fail closed on helper failure or residual credentials, including included config files; successful verified cleanup and the no-checkout case remain usable
377
386
-**T-CHK-019**: Runtime private/internal targets require literal per-entry opt-in and a non-public host; public hosts reject them even with opt-in, merged entries cannot broaden access, and denials reach agent failure issues
387
+
-**T-CHK-020**: Only literal `multi: true` enables lists; omitted/false mode accepts single-repository expressions without multi restrictions, rejects empty/multiple/wildcard resolved slugs before either job's checkout, and remains distinct when imports merge
378
388
379
389
### 7.2 Compliance Checklist
380
390
@@ -394,6 +404,7 @@ When `GH_AW_TARGET_REPO_SLUG` is set but equals `GITHUB_REPOSITORY`, the impleme
0 commit comments