@vzn/vx-ci 0.0.630 → 0.0.632
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +2 -2
- package/src/cache-scope.ts +40 -8
package/README.md
CHANGED
|
@@ -56,7 +56,8 @@ On Actions (`GITHUB_ACTIONS=true`), when `vx.workspace.ts` sets no `cacheScope`,
|
|
|
56
56
|
`config` stage sets it from the ref (`GITHUB_REF`, `GITHUB_REF_NAME`, and
|
|
57
57
|
the default branch from the `GITHUB_EVENT_PATH` payload): a push to the default branch stays
|
|
58
58
|
trusted (reads and writes the task keys), a pull request becomes
|
|
59
|
-
`pr-<n>`
|
|
59
|
+
`pr-<n>` (so is a `pull_request_target`, `issue_comment` or `workflow_run`
|
|
60
|
+
run on a PR's behalf, by `GITHUB_EVENT_NAME`, though its ref is main's) and any other branch or tag `ref-<name>`, which read their
|
|
60
61
|
own keys, then the trusted ones, and write only their own. A PR never writes what main
|
|
61
62
|
reads. `VX_CACHE_SCOPE` or a `cacheScope` in `vx.workspace.ts` overrides it. This is a client-side convention: the real boundary is a cache
|
|
62
63
|
token the server limits, so give PR jobs one that cannot write the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx-ci",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.632",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "GitHub Actions integration for vx — a telemetry plugin that writes the run as a GitHub Actions job summary.",
|
|
6
6
|
"keywords": [
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@vzn/vx": "^0.0.
|
|
36
|
+
"@vzn/vx": "^0.0.632"
|
|
37
37
|
},
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
package/src/cache-scope.ts
CHANGED
|
@@ -6,6 +6,10 @@ import { readFile } from 'node:fs/promises'
|
|
|
6
6
|
* `undefined` (leave the workspace's default, trusted) on a push to the
|
|
7
7
|
* default branch, outside Actions, or when the ref is unknown; else
|
|
8
8
|
* `pr-<n>` for a pull request and `ref-<name>` for any other branch or tag.
|
|
9
|
+
* An event that runs in the default branch's context on a pull request's
|
|
10
|
+
* behalf (`pull_request_target`, `issue_comment` on a PR, a `workflow_run`
|
|
11
|
+
* a PR started) is the PR's, whatever `GITHUB_REF` says: a workflow that
|
|
12
|
+
* checks out the PR's head there would otherwise write the trusted keys.
|
|
9
13
|
*/
|
|
10
14
|
export async function githubCacheScope(
|
|
11
15
|
env: Readonly<Record<string, string | undefined>>,
|
|
@@ -14,22 +18,50 @@ export async function githubCacheScope(
|
|
|
14
18
|
const ref = env['GITHUB_REF'] ?? ''
|
|
15
19
|
const pr = /^refs\/pull\/(\d+)\//.exec(ref)
|
|
16
20
|
if (pr !== null) return `pr-${pr[1]}`
|
|
21
|
+
const event = await eventOf(env['GITHUB_EVENT_PATH'])
|
|
22
|
+
const onBehalf = prOf(env['GITHUB_EVENT_NAME'], event)
|
|
23
|
+
if (onBehalf !== undefined) return onBehalf
|
|
17
24
|
const name = env['GITHUB_REF_NAME']
|
|
18
25
|
if (ref === '' || name === undefined || name === '') return undefined
|
|
19
|
-
|
|
26
|
+
const branch = event?.repository?.default_branch
|
|
27
|
+
if (typeof branch === 'string' && branch !== '' && ref === `refs/heads/${branch}`)
|
|
28
|
+
return undefined
|
|
20
29
|
// `cacheScope` takes letters, digits and . _ - / @; a ref may hold more.
|
|
21
30
|
return `ref-${name.replace(/[^\w.@/-]/g, '_').slice(0, 124)}`
|
|
22
31
|
}
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
interface ActionsEvent {
|
|
34
|
+
repository?: { default_branch?: unknown }
|
|
35
|
+
pull_request?: { number?: unknown }
|
|
36
|
+
issue?: { number?: unknown; pull_request?: unknown }
|
|
37
|
+
workflow_run?: { event?: unknown; pull_requests?: { number?: unknown }[] }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The PR scope of an event that runs in the base branch's context for a PR; `pr-target` when its number is unknown. */
|
|
41
|
+
function prOf(name: string | undefined, event: ActionsEvent | undefined): string | undefined {
|
|
42
|
+
const scope = (n: unknown): string =>
|
|
43
|
+
typeof n === 'number' && Number.isInteger(n) && n > 0 ? `pr-${n}` : 'pr-target'
|
|
44
|
+
if (name === 'pull_request_target') return scope(event?.pull_request?.number)
|
|
45
|
+
if (name === 'issue_comment' && event?.issue?.pull_request != null) {
|
|
46
|
+
return scope(event.issue.number)
|
|
47
|
+
}
|
|
48
|
+
const run = event?.workflow_run
|
|
49
|
+
if (
|
|
50
|
+
name === 'workflow_run' &&
|
|
51
|
+
typeof run?.event === 'string' &&
|
|
52
|
+
run.event.startsWith('pull_request')
|
|
53
|
+
) {
|
|
54
|
+
return scope(run.pull_requests?.[0]?.number)
|
|
55
|
+
}
|
|
56
|
+
return undefined
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The event payload the runner writes; undefined when it cannot be read. */
|
|
60
|
+
async function eventOf(eventPath: string | undefined): Promise<ActionsEvent | undefined> {
|
|
26
61
|
if (eventPath === undefined || eventPath === '') return undefined
|
|
27
62
|
try {
|
|
28
|
-
const event = JSON.parse(await readFile(eventPath, 'utf8')) as
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
const branch = event.repository?.default_branch
|
|
32
|
-
return typeof branch === 'string' && branch !== '' ? branch : undefined
|
|
63
|
+
const event = JSON.parse(await readFile(eventPath, 'utf8')) as unknown
|
|
64
|
+
return typeof event === 'object' && event !== null ? (event as ActionsEvent) : undefined
|
|
33
65
|
} catch {
|
|
34
66
|
return undefined
|
|
35
67
|
}
|