putitoutthere 0.1.48 → 0.1.49
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/CHANGELOG.md +2 -0
- package/MIGRATIONS.md +102 -0
- package/README.md +68 -10
- package/dist/error-codes.d.ts +31 -0
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/error-codes.js +32 -0
- package/dist/error-codes.js.map +1 -0
- package/dist/handlers/pypi.d.ts +30 -11
- package/dist/handlers/pypi.d.ts.map +1 -1
- package/dist/handlers/pypi.js +44 -170
- package/dist/handlers/pypi.js.map +1 -1
- package/dist/publish.d.ts +1 -1
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +5 -0
- package/dist/publish.js.map +1 -1
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -1
- package/dist/verbose.d.ts.map +1 -1
- package/dist/verbose.js +40 -0
- package/dist/verbose.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -12,12 +12,14 @@ are prefixed `**BREAKING**` and link to the matching section in
|
|
|
12
12
|
|
|
13
13
|
### Added
|
|
14
14
|
|
|
15
|
+
- **`workflow_call` output `has_pypi`.** The reusable workflow now emits a string `'true'`/`'false'` indicating whether the planned matrix contains any `kind = "pypi"` rows. Consumers gate their caller-side `pypi-publish` job on this so non-PyPI repos paste the canonical template verbatim without paying any runtime cost. Computed in the `plan` job from the matrix output.
|
|
15
16
|
- **Reusable workflow `.github/workflows/release.yml` (`workflow_call`).** The single user-facing surface. Consumer integration is one `uses: thekevinscott/putitoutthere/.github/workflows/release.yml@v0` line in their own `release.yml`; pinned action versions, plan/build/publish orchestration, and GitHub Release creation all live inside. Three optional inputs: `environment` (default `release`), `node_version` (default `24`), `python_version` (default `3.12`). No `dry_run`, `working_directory`, or `config` inputs — the plan job is already side-effect-free, the config file is `putitoutthere.toml` at the repo root, period. The engine is invoked via `uses: thekevinscott/putitoutthere@v0` so the workflow file and the engine always agree on a single git ref.
|
|
16
17
|
|
|
17
18
|
- **`[package.bundle_cli]` recipe for maturin pypi packages** (#217). Opt-in declarative shape for libraries that ship a Rust CLI inside each wheel (the `ruff` / `uv` / `pydantic-core` pattern). Declare `bin`, `stage_to`, and optional `crate_path`; the reusable workflow cross-compiles the binary per target, stages it into the package source tree, and maturin picks it up via `[tool.maturin].include`. Requires `build = "maturin"` and non-empty `targets`. See [README → Recipes → Rust CLI inside a PyPI wheel](./README.md#rust-cli-inside-a-pypi-wheel). No behavior change for existing packages that don't declare the block.
|
|
18
19
|
|
|
19
20
|
### Changed
|
|
20
21
|
|
|
22
|
+
- **BREAKING: PyPI uploads moved to a caller-side `pypi-publish` job.** PyPI's Trusted Publisher matching filters candidates by `repository_owner` + `repository_name` *before* checking `job_workflow_ref` ([Warehouse implementation](https://github.com/pypi/warehouse/blob/main/warehouse/oidc/models/github.py)); since the OIDC `repository` claim always reflects the caller's repo even inside a reusable workflow, a TP registered against `thekevinscott/putitoutthere` is filtered out before the workflow_ref is ever checked. PyPI explicitly documents this as unsupported ([troubleshooting](https://docs.pypi.org/trusted-publishers/troubleshooting/)). Tracked at [pypi/warehouse#11096](https://github.com/pypi/warehouse/issues/11096), no timeline. The engine still does plan + build + version-rewrite + git tag for PyPI; the actual upload (`pypa/gh-action-pypi-publish`) now runs in the consumer's workflow file as a second job, gated on `needs.release.outputs.has_pypi`. The canonical template grew from ~12 → ~30 lines but remains a single copy-paste — the `if:` skips the job for non-PyPI repos. See [MIGRATIONS.md](./MIGRATIONS.md#pypi-uploads-moved-to-caller-side-job) and [`notes/audits/2026-04-28-pypi-tp-reusable-workflow-constraint.md`](./notes/audits/2026-04-28-pypi-tp-reusable-workflow-constraint.md).
|
|
21
23
|
- **Public consumer surface collapsed to the README + the reusable workflow.** The CLI, the JS action (`action.yml`), and the diagnostic subcommands (`doctor`, `preflight`) are internal seams the reusable workflow invokes; consumers do not call them. The entire `docs/` directory is removed — `README.md` is the single user-facing surface. See [MIGRATIONS.md](./MIGRATIONS.md#public-surface-collapsed-to-a-reusable-workflow) for the before/after.
|
|
22
24
|
- **Auth is OIDC trusted publishers only.** The reusable workflow does not pass long-lived registry tokens (`NPM_TOKEN`, `PYPI_API_TOKEN`, `CARGO_REGISTRY_TOKEN`) as secrets. The engine's env-var fallback code paths still exist (in `src/auth.ts`); they're just not reachable through the reusable workflow.
|
|
23
25
|
- **Repository renamed `put-it-out-there` → `putitoutthere`.** GitHub auto-redirects the old slug, but consumers with the old URL pinned in `package.json`, `Cargo.toml`, `pyproject.toml`, or workflow files should update them. See [MIGRATIONS.md](./MIGRATIONS.md#repository-renamed-put-it-out-there--putitoutthere).
|
package/MIGRATIONS.md
CHANGED
|
@@ -21,6 +21,108 @@ Each section covers five things, in order:
|
|
|
21
21
|
|
|
22
22
|
## Unreleased
|
|
23
23
|
|
|
24
|
+
### PyPI uploads moved to caller-side job
|
|
25
|
+
|
|
26
|
+
**Summary.** PyPI's Trusted Publisher matching filters candidates by
|
|
27
|
+
`repository_owner` + `repository_name` *before* checking
|
|
28
|
+
`job_workflow_ref`
|
|
29
|
+
([Warehouse implementation](https://github.com/pypi/warehouse/blob/main/warehouse/oidc/models/github.py)).
|
|
30
|
+
The OIDC `repository` claim always reflects the caller's repo —
|
|
31
|
+
including inside a reusable workflow — so a TP registered against
|
|
32
|
+
the reusable workflow's repo is filtered out before workflow_ref
|
|
33
|
+
is even checked. PyPI documents this as unsupported
|
|
34
|
+
([troubleshooting](https://docs.pypi.org/trusted-publishers/troubleshooting/)).
|
|
35
|
+
Tracked at [pypi/warehouse#11096](https://github.com/pypi/warehouse/issues/11096),
|
|
36
|
+
no timeline.
|
|
37
|
+
|
|
38
|
+
To preserve OIDC trusted publishing for PyPI without setting
|
|
39
|
+
`PYPI_API_TOKEN`, the upload step (`pypa/gh-action-pypi-publish`)
|
|
40
|
+
now runs in the consumer's own workflow file as a second job,
|
|
41
|
+
gated on the new `has_pypi` output. The engine still owns plan,
|
|
42
|
+
build, version-rewrite, and git-tag creation for PyPI rows; only
|
|
43
|
+
the actual upload moves. See
|
|
44
|
+
[`notes/audits/2026-04-28-pypi-tp-reusable-workflow-constraint.md`](./notes/audits/2026-04-28-pypi-tp-reusable-workflow-constraint.md)
|
|
45
|
+
for the full diagnosis.
|
|
46
|
+
|
|
47
|
+
**Required changes.** Update `.github/workflows/release.yml`:
|
|
48
|
+
|
|
49
|
+
Before (~12 lines):
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
name: Release
|
|
53
|
+
on:
|
|
54
|
+
push:
|
|
55
|
+
branches: [main]
|
|
56
|
+
jobs:
|
|
57
|
+
release:
|
|
58
|
+
uses: thekevinscott/putitoutthere/.github/workflows/release.yml@v0
|
|
59
|
+
permissions:
|
|
60
|
+
contents: write
|
|
61
|
+
id-token: write
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
After (~30 lines, single copy-paste from README → Quickstart):
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
name: Release
|
|
68
|
+
on:
|
|
69
|
+
push:
|
|
70
|
+
branches: [main]
|
|
71
|
+
jobs:
|
|
72
|
+
release:
|
|
73
|
+
uses: thekevinscott/putitoutthere/.github/workflows/release.yml@v0
|
|
74
|
+
permissions:
|
|
75
|
+
contents: write
|
|
76
|
+
id-token: write
|
|
77
|
+
|
|
78
|
+
pypi-publish:
|
|
79
|
+
needs: release
|
|
80
|
+
if: needs.release.outputs.has_pypi == 'true'
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
permissions:
|
|
83
|
+
id-token: write
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/download-artifact@v4
|
|
86
|
+
with:
|
|
87
|
+
pattern: '*-sdist'
|
|
88
|
+
path: dist/
|
|
89
|
+
merge-multiple: true
|
|
90
|
+
- uses: actions/download-artifact@v4
|
|
91
|
+
with:
|
|
92
|
+
pattern: '*-wheel-*'
|
|
93
|
+
path: dist/
|
|
94
|
+
merge-multiple: true
|
|
95
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The `pypi-publish` job's `if:` gate skips it for non-PyPI repos —
|
|
99
|
+
paste verbatim regardless of what you publish. Crates.io and npm
|
|
100
|
+
are unaffected; their TP claim semantics work fine inside the
|
|
101
|
+
reusable workflow.
|
|
102
|
+
|
|
103
|
+
**No PyPI TP re-registration required.** Your existing TP
|
|
104
|
+
registration (against your repo, your `release.yml`, optional
|
|
105
|
+
environment) was already correct for this pattern. If you'd
|
|
106
|
+
attempted to register a TP against `thekevinscott/putitoutthere`
|
|
107
|
+
to work around the prior failure, remove that entry — it would
|
|
108
|
+
have never matched anyway.
|
|
109
|
+
|
|
110
|
+
**Deprecations removed.** None.
|
|
111
|
+
|
|
112
|
+
**Behavior changes without code changes.** PyPI upload step now
|
|
113
|
+
runs in the consumer's workflow context. The reusable workflow's
|
|
114
|
+
publish job no longer installs `twine` or `setup-python`; engine
|
|
115
|
+
log lines for PyPI rows now read "delegated to caller-side upload
|
|
116
|
+
step" instead of "authenticating via OIDC".
|
|
117
|
+
|
|
118
|
+
**Verification.** Push a release. The reusable workflow's
|
|
119
|
+
`release` job creates and pushes the git tag for PyPI rows; the
|
|
120
|
+
caller's `pypi-publish` job runs `pypa/gh-action-pypi-publish`
|
|
121
|
+
and uploads to PyPI. Check `https://pypi.org/project/<name>/<version>/`
|
|
122
|
+
to confirm.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
24
126
|
### PyPI artifact discovery matches `{name}-sdist` and `{name}-wheel-` exactly
|
|
25
127
|
|
|
26
128
|
**Summary.** `src/handlers/pypi.ts:collectArtifacts` used a bare prefix
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A reusable GitHub Actions workflow that publishes packages to crates.io, PyPI,
|
|
4
4
|
and npm from one repo. OIDC-first, cascade-aware, polyglot. The consumer
|
|
5
|
-
surface is one config file plus
|
|
5
|
+
surface is one config file plus one canonical YAML calling
|
|
6
6
|
`uses: thekevinscott/putitoutthere/.github/workflows/release.yml@v0`.
|
|
7
7
|
|
|
8
8
|
## Quickstart
|
|
@@ -22,10 +22,41 @@ jobs:
|
|
|
22
22
|
permissions:
|
|
23
23
|
contents: write
|
|
24
24
|
id-token: write
|
|
25
|
+
|
|
26
|
+
# PyPI upload runs in the caller's workflow context. Required because
|
|
27
|
+
# PyPI Trusted Publishers can't validate OIDC tokens minted from a
|
|
28
|
+
# cross-repo reusable workflow (pypi/warehouse#11096). The `if:`
|
|
29
|
+
# gate skips this job for non-PyPI repos — paste verbatim regardless
|
|
30
|
+
# of what you publish.
|
|
31
|
+
pypi-publish:
|
|
32
|
+
needs: release
|
|
33
|
+
if: needs.release.outputs.has_pypi == 'true'
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/download-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
pattern: '*-sdist'
|
|
41
|
+
path: dist/
|
|
42
|
+
merge-multiple: true
|
|
43
|
+
- uses: actions/download-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
pattern: '*-wheel-*'
|
|
46
|
+
path: dist/
|
|
47
|
+
merge-multiple: true
|
|
48
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
25
49
|
```
|
|
26
50
|
|
|
27
51
|
Pinned action versions, `plan → build → publish` orchestration, and GitHub
|
|
28
|
-
Release creation all live inside the reusable workflow.
|
|
52
|
+
Release creation all live inside the reusable workflow. The `pypi-publish`
|
|
53
|
+
job is the one piece that has to live in your workflow file: PyPI's
|
|
54
|
+
Trusted Publisher feature filters OIDC tokens by `repository_owner` /
|
|
55
|
+
`repository_name` claims, which always reflect the caller's repo — so a
|
|
56
|
+
TP registered against `thekevinscott/putitoutthere` is filtered out
|
|
57
|
+
before `job_workflow_ref` is even checked. Running `pypa/gh-action-pypi-publish`
|
|
58
|
+
in your workflow context aligns the claims with your TP registration.
|
|
59
|
+
The job is skipped automatically for repos that don't publish to PyPI.
|
|
29
60
|
|
|
30
61
|
Optional inputs — `with:` block at the call site:
|
|
31
62
|
|
|
@@ -216,11 +247,14 @@ releases without fighting registry-immutable-publish semantics.
|
|
|
216
247
|
|
|
217
248
|
## Trusted publishers
|
|
218
249
|
|
|
219
|
-
OIDC trusted publishers — the only auth path supported
|
|
220
|
-
|
|
250
|
+
OIDC trusted publishers — the only auth path supported. Long-lived
|
|
251
|
+
registry tokens are not reachable through the workflow.
|
|
221
252
|
|
|
222
|
-
|
|
223
|
-
filename (`release.yml`), and optionally
|
|
253
|
+
For all three registries the fields are the same: **your** repository
|
|
254
|
+
owner/name, **your** workflow filename (`release.yml`), and optionally
|
|
255
|
+
a GitHub environment name. Note: you register against your *own*
|
|
256
|
+
repository, not against `thekevinscott/putitoutthere` — see "How
|
|
257
|
+
auth flows" below for the why.
|
|
224
258
|
|
|
225
259
|
### crates.io
|
|
226
260
|
|
|
@@ -228,15 +262,15 @@ filename (`release.yml`), and optionally a GitHub environment name.
|
|
|
228
262
|
exists. (Trusted publishing needs a crate owner record.)
|
|
229
263
|
2. Go to `https://crates.io/crates/<crate>/settings` → **Trusted Publishing**
|
|
230
264
|
→ **Add**.
|
|
231
|
-
3. Fill in:
|
|
265
|
+
3. Fill in: your repo owner, your repo name, workflow filename
|
|
232
266
|
(`release.yml`), environment (optional).
|
|
233
267
|
|
|
234
268
|
### PyPI
|
|
235
269
|
|
|
236
270
|
1. Go to `https://pypi.org/manage/project/<name>/settings/publishing/` (or
|
|
237
271
|
**Publishing** on the project page).
|
|
238
|
-
2. Add a **GitHub** trusted publisher: owner, repo
|
|
239
|
-
environment (optional).
|
|
272
|
+
2. Add a **GitHub** trusted publisher: your repo owner, your repo name,
|
|
273
|
+
workflow filename (`release.yml`), environment (optional).
|
|
240
274
|
3. Brand-new project? Use a [pending publisher](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/)
|
|
241
275
|
to skip the bootstrap token.
|
|
242
276
|
|
|
@@ -247,9 +281,33 @@ filename (`release.yml`), and optionally a GitHub environment name.
|
|
|
247
281
|
publisher requires an existing package.)
|
|
248
282
|
2. Go to `https://www.npmjs.com/package/<name>/access` → **Require trusted
|
|
249
283
|
publisher**.
|
|
250
|
-
3. Fill in: repository, workflow filename
|
|
284
|
+
3. Fill in: your repository, workflow filename (`release.yml`),
|
|
285
|
+
environment (optional).
|
|
251
286
|
4. Delete the bootstrap token.
|
|
252
287
|
|
|
288
|
+
### How auth flows
|
|
289
|
+
|
|
290
|
+
`crates.io` and `npm` validate OIDC tokens that are minted by the
|
|
291
|
+
reusable workflow's `publish` job. The reusable workflow already
|
|
292
|
+
sits in your release path, so the OIDC `repository` and
|
|
293
|
+
`job_workflow_ref` claims line up with your TP registration.
|
|
294
|
+
|
|
295
|
+
PyPI is different. Its TP matching filters candidates by
|
|
296
|
+
`repository_owner` + `repository_name` *before* checking
|
|
297
|
+
`job_workflow_ref` ([Warehouse implementation](https://github.com/pypi/warehouse/blob/main/warehouse/oidc/models/github.py)).
|
|
298
|
+
The `repository` claim always reflects the caller's repo — even
|
|
299
|
+
inside a reusable workflow — so a TP registered against the
|
|
300
|
+
reusable workflow's repo would be filtered out before
|
|
301
|
+
`job_workflow_ref` is even checked. PyPI documents this:
|
|
302
|
+
"[Reusable workflows cannot currently be used as the workflow in
|
|
303
|
+
a Trusted Publisher.](https://docs.pypi.org/trusted-publishers/troubleshooting/)"
|
|
304
|
+
Tracked at [pypi/warehouse#11096](https://github.com/pypi/warehouse/issues/11096).
|
|
305
|
+
|
|
306
|
+
That's why the canonical template puts the PyPI upload step
|
|
307
|
+
(`pypa/gh-action-pypi-publish`) directly in *your* workflow,
|
|
308
|
+
gated on `needs.release.outputs.has_pypi`. In your workflow context
|
|
309
|
+
both claims resolve to your repo, so your TP registration matches.
|
|
310
|
+
|
|
253
311
|
## Recipes
|
|
254
312
|
|
|
255
313
|
### Bundled-CLI npm family
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable error-code vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* User-facing errors and GitHub Actions `::error::` annotations carry
|
|
5
|
+
* one of these codes so external observers — humans grepping the run
|
|
6
|
+
* log, foreign LLM agents debugging a failed publish, the docs site
|
|
7
|
+
* deep-linking from a code to a recipe — can fingerprint the failure
|
|
8
|
+
* mode without parsing free-form prose.
|
|
9
|
+
*
|
|
10
|
+
* Codes are deliberately verbose. The string is the diagnostic; brevity
|
|
11
|
+
* here just creates ambiguity at a distance.
|
|
12
|
+
*
|
|
13
|
+
* Adding a new code: add it to BOTH `ErrorCodes` and `ALL_ERROR_CODES`;
|
|
14
|
+
* the test in `error-codes.test.ts` enforces parity. Once a code ships
|
|
15
|
+
* in a public-surfaced error message it becomes a stable identifier —
|
|
16
|
+
* rename only with a migration entry.
|
|
17
|
+
*/
|
|
18
|
+
export declare const ErrorCodes: {
|
|
19
|
+
/** Generic auth failure when no registry token resolved. Used by
|
|
20
|
+
* npm/crates handlers; PyPI no longer surfaces this code (the
|
|
21
|
+
* upload moved to a caller-side job per the reusable-workflow
|
|
22
|
+
* TP constraint — see notes/audits/). */
|
|
23
|
+
readonly AUTH_NO_TOKEN: "PIOT_AUTH_NO_TOKEN";
|
|
24
|
+
};
|
|
25
|
+
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
26
|
+
/**
|
|
27
|
+
* Iterable form of the codes. Walked by tests for uniqueness/format
|
|
28
|
+
* checks and by future tooling that renders a code reference table.
|
|
29
|
+
*/
|
|
30
|
+
export declare const ALL_ERROR_CODES: readonly ErrorCode[];
|
|
31
|
+
//# sourceMappingURL=error-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,UAAU;IACrB;;;8CAG0C;;CAElC,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,SAAS,EAE/C,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable error-code vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* User-facing errors and GitHub Actions `::error::` annotations carry
|
|
5
|
+
* one of these codes so external observers — humans grepping the run
|
|
6
|
+
* log, foreign LLM agents debugging a failed publish, the docs site
|
|
7
|
+
* deep-linking from a code to a recipe — can fingerprint the failure
|
|
8
|
+
* mode without parsing free-form prose.
|
|
9
|
+
*
|
|
10
|
+
* Codes are deliberately verbose. The string is the diagnostic; brevity
|
|
11
|
+
* here just creates ambiguity at a distance.
|
|
12
|
+
*
|
|
13
|
+
* Adding a new code: add it to BOTH `ErrorCodes` and `ALL_ERROR_CODES`;
|
|
14
|
+
* the test in `error-codes.test.ts` enforces parity. Once a code ships
|
|
15
|
+
* in a public-surfaced error message it becomes a stable identifier —
|
|
16
|
+
* rename only with a migration entry.
|
|
17
|
+
*/
|
|
18
|
+
export const ErrorCodes = {
|
|
19
|
+
/** Generic auth failure when no registry token resolved. Used by
|
|
20
|
+
* npm/crates handlers; PyPI no longer surfaces this code (the
|
|
21
|
+
* upload moved to a caller-side job per the reusable-workflow
|
|
22
|
+
* TP constraint — see notes/audits/). */
|
|
23
|
+
AUTH_NO_TOKEN: 'PIOT_AUTH_NO_TOKEN',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Iterable form of the codes. Walked by tests for uniqueness/format
|
|
27
|
+
* checks and by future tooling that renders a code reference table.
|
|
28
|
+
*/
|
|
29
|
+
export const ALL_ERROR_CODES = [
|
|
30
|
+
ErrorCodes.AUTH_NO_TOKEN,
|
|
31
|
+
];
|
|
32
|
+
//# sourceMappingURL=error-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.js","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB;;;8CAG0C;IAC1C,aAAa,EAAE,oBAAoB;CAC3B,CAAC;AAIX;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAyB;IACnD,UAAU,CAAC,aAAa;CACzB,CAAC"}
|
package/dist/handlers/pypi.d.ts
CHANGED
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PyPI handler.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* **Architectural note (2026-04-28).** PyPI's Trusted Publisher matching
|
|
5
|
+
* filters candidate publishers by `repository_owner` + `repository_name`
|
|
6
|
+
* before checking `job_workflow_ref`. When OIDC tokens are minted from
|
|
7
|
+
* inside a cross-repo reusable workflow, the `repository` claim is the
|
|
8
|
+
* *caller's* repo and `job_workflow_ref` is the reusable workflow's
|
|
9
|
+
* path — so a TP registered against the reusable workflow's repo is
|
|
10
|
+
* filtered out before workflow_ref is even checked. PyPI documents this
|
|
11
|
+
* as unsupported and tracks the fix at pypi/warehouse#11096 (no
|
|
12
|
+
* timeline). See `notes/audits/2026-04-28-pypi-tp-reusable-workflow-
|
|
13
|
+
* constraint.md`.
|
|
14
|
+
*
|
|
15
|
+
* Consequence for `putitoutthere`: the engine cannot upload to PyPI
|
|
16
|
+
* from inside the reusable workflow's publish job. The actual upload
|
|
17
|
+
* is delegated to a caller-side `pypi-publish` job that runs
|
|
18
|
+
* `pypa/gh-action-pypi-publish` from the consumer's own workflow
|
|
19
|
+
* context (where both `repository` and `job_workflow_ref` align with
|
|
20
|
+
* the consumer's repo + their TP registration). The reusable workflow
|
|
21
|
+
* still emits the matrix, builds artifacts, and creates+pushes git
|
|
22
|
+
* tags; only the upload step moves.
|
|
5
23
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
24
|
+
* The handler therefore:
|
|
25
|
+
* - `isPublished`: unchanged. Public PyPI HEAD; no auth needed.
|
|
26
|
+
* - `writeVersion`: unchanged. Rewrites `[project].version` in-place
|
|
27
|
+
* or logs a SETUPTOOLS_SCM hint for dynamic-version projects.
|
|
28
|
+
* - `publish`: NO upload. Returns `{ status: 'published' }` so
|
|
29
|
+
* `publish.ts` creates+pushes the git tag. The tag is the engine's
|
|
30
|
+
* record-of-intent; the caller's `pypi-publish` job performs the
|
|
31
|
+
* actual upload using `pypa/gh-action-pypi-publish` (which is
|
|
32
|
+
* idempotent, so a transient caller-side failure is recoverable
|
|
33
|
+
* by re-triggering).
|
|
11
34
|
*
|
|
12
|
-
*
|
|
13
|
-
* `{pkg.name}-*` (the artifact naming contract from §12.4). Uploads
|
|
14
|
-
* all `.whl` and `.tar.gz` files found under those directories. Fails
|
|
15
|
-
* loud if nothing's found -- the completeness check (#13) should have
|
|
16
|
-
* caught that earlier, but defense in depth.
|
|
35
|
+
* Issue #17. Plan: §6.4, §12.2, §12.3, §13.1, §14.5, §16.1.
|
|
17
36
|
*/
|
|
18
37
|
import type { Handler } from '../types.js';
|
|
19
38
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pypi.d.ts","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pypi.d.ts","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAOH,OAAO,KAAK,EAAO,OAAO,EAAiB,MAAM,aAAa,CAAC;AAkI/D;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAa/E;AAaD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,eAAO,MAAM,IAAI,EAAE,OAKlB,CAAC"}
|
package/dist/handlers/pypi.js
CHANGED
|
@@ -1,27 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PyPI handler.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* **Architectural note (2026-04-28).** PyPI's Trusted Publisher matching
|
|
5
|
+
* filters candidate publishers by `repository_owner` + `repository_name`
|
|
6
|
+
* before checking `job_workflow_ref`. When OIDC tokens are minted from
|
|
7
|
+
* inside a cross-repo reusable workflow, the `repository` claim is the
|
|
8
|
+
* *caller's* repo and `job_workflow_ref` is the reusable workflow's
|
|
9
|
+
* path — so a TP registered against the reusable workflow's repo is
|
|
10
|
+
* filtered out before workflow_ref is even checked. PyPI documents this
|
|
11
|
+
* as unsupported and tracks the fix at pypi/warehouse#11096 (no
|
|
12
|
+
* timeline). See `notes/audits/2026-04-28-pypi-tp-reusable-workflow-
|
|
13
|
+
* constraint.md`.
|
|
14
|
+
*
|
|
15
|
+
* Consequence for `putitoutthere`: the engine cannot upload to PyPI
|
|
16
|
+
* from inside the reusable workflow's publish job. The actual upload
|
|
17
|
+
* is delegated to a caller-side `pypi-publish` job that runs
|
|
18
|
+
* `pypa/gh-action-pypi-publish` from the consumer's own workflow
|
|
19
|
+
* context (where both `repository` and `job_workflow_ref` align with
|
|
20
|
+
* the consumer's repo + their TP registration). The reusable workflow
|
|
21
|
+
* still emits the matrix, builds artifacts, and creates+pushes git
|
|
22
|
+
* tags; only the upload step moves.
|
|
5
23
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
24
|
+
* The handler therefore:
|
|
25
|
+
* - `isPublished`: unchanged. Public PyPI HEAD; no auth needed.
|
|
26
|
+
* - `writeVersion`: unchanged. Rewrites `[project].version` in-place
|
|
27
|
+
* or logs a SETUPTOOLS_SCM hint for dynamic-version projects.
|
|
28
|
+
* - `publish`: NO upload. Returns `{ status: 'published' }` so
|
|
29
|
+
* `publish.ts` creates+pushes the git tag. The tag is the engine's
|
|
30
|
+
* record-of-intent; the caller's `pypi-publish` job performs the
|
|
31
|
+
* actual upload using `pypa/gh-action-pypi-publish` (which is
|
|
32
|
+
* idempotent, so a transient caller-side failure is recoverable
|
|
33
|
+
* by re-triggering).
|
|
11
34
|
*
|
|
12
|
-
*
|
|
13
|
-
* `{pkg.name}-*` (the artifact naming contract from §12.4). Uploads
|
|
14
|
-
* all `.whl` and `.tar.gz` files found under those directories. Fails
|
|
15
|
-
* loud if nothing's found -- the completeness check (#13) should have
|
|
16
|
-
* caught that earlier, but defense in depth.
|
|
35
|
+
* Issue #17. Plan: §6.4, §12.2, §12.3, §13.1, §14.5, §16.1.
|
|
17
36
|
*/
|
|
18
|
-
import {
|
|
19
|
-
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
|
|
37
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
20
38
|
import { join } from 'node:path';
|
|
21
39
|
import { parse as parseToml } from 'smol-toml';
|
|
22
|
-
import { sanitizeArtifactName } from '../config.js';
|
|
23
40
|
import { TransientError } from '../types.js';
|
|
24
|
-
import { buildSubprocessEnv, nonEmpty } from '../env.js';
|
|
25
41
|
import { USER_AGENT } from '../version.js';
|
|
26
42
|
const REGISTRY = 'https://pypi.org';
|
|
27
43
|
async function isPublishedImpl(pkg, version, _ctx) {
|
|
@@ -105,69 +121,19 @@ async function publishImpl(pkg, version, ctx) {
|
|
|
105
121
|
if (await isPublishedImpl(pkg, version, ctx)) {
|
|
106
122
|
return { status: 'already-published' };
|
|
107
123
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
throw new Error([
|
|
122
|
-
'pypi: no auth available. Either:',
|
|
123
|
-
' - set PYPI_API_TOKEN (classic API token), or',
|
|
124
|
-
' - enable trusted publishing: add `permissions.id-token: write` to the job and register a pending publisher on pypi.org.',
|
|
125
|
-
// Points consumers at the published auth guide, not internal plan
|
|
126
|
-
// docs (#149).
|
|
127
|
-
'See https://thekevinscott.github.io/putitoutthere/guide/auth for setup.',
|
|
128
|
-
].join('\n'));
|
|
129
|
-
}
|
|
130
|
-
ctx.log.info(oidcToken ? 'pypi: authenticating via OIDC trusted publishing' : 'pypi: authenticating via PYPI_API_TOKEN');
|
|
131
|
-
try {
|
|
132
|
-
execFileSync('twine', ['upload', '--non-interactive', '--disable-progress-bar', '--verbose', ...files], {
|
|
133
|
-
cwd: ctx.cwd,
|
|
134
|
-
// #138: minimal env. Don't forward the whole parent process.env
|
|
135
|
-
// to twine.
|
|
136
|
-
env: buildSubprocessEnv(ctx.env, {
|
|
137
|
-
TWINE_USERNAME: '__token__',
|
|
138
|
-
TWINE_PASSWORD: token,
|
|
139
|
-
}),
|
|
140
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
catch (err) {
|
|
144
|
-
// ENOENT = twine not on PATH. The scaffolded publish job is supposed
|
|
145
|
-
// to install it (setup-python + pip install twine), but an adopter
|
|
146
|
-
// running an older template or a hand-rolled workflow will hit this.
|
|
147
|
-
// Give them an actionable message instead of a cryptic ENOENT. #205.
|
|
148
|
-
if (err.code === 'ENOENT') {
|
|
149
|
-
throw new Error([
|
|
150
|
-
'pypi: twine not found on PATH (ENOENT).',
|
|
151
|
-
'The publish job must install it before invoking piot. Add:',
|
|
152
|
-
' - uses: actions/setup-python@v5',
|
|
153
|
-
" with: { python-version: '3.12' }",
|
|
154
|
-
' - run: pip install twine',
|
|
155
|
-
'See https://thekevinscott.github.io/putitoutthere/guide/runner-prerequisites',
|
|
156
|
-
].join('\n'), { cause: err });
|
|
157
|
-
}
|
|
158
|
-
const stderr = err.stderr?.toString('utf8').trim();
|
|
159
|
-
const stdout = err.stdout?.toString('utf8').trim();
|
|
160
|
-
const base = err instanceof Error ? err.message : String(err);
|
|
161
|
-
// Twine sometimes writes its actual failure (4xx/5xx body, render
|
|
162
|
-
// diagnostic, etc.) to stdout rather than stderr; surface both so
|
|
163
|
-
// adopters see the registry's response, not a bare "Command failed".
|
|
164
|
-
const parts = [`twine upload failed: ${base}`];
|
|
165
|
-
if (stderr)
|
|
166
|
-
parts.push(`--- stderr ---\n${stderr}`);
|
|
167
|
-
if (stdout)
|
|
168
|
-
parts.push(`--- stdout ---\n${stdout}`);
|
|
169
|
-
throw new Error(parts.join('\n'), { cause: err });
|
|
170
|
-
}
|
|
124
|
+
// No upload from here. The engine's role for PyPI is plan + build +
|
|
125
|
+
// version-rewrite + tag — the actual `pypa/gh-action-pypi-publish`
|
|
126
|
+
// call lives in the caller's `pypi-publish` job, where the OIDC
|
|
127
|
+
// claims align with their TP registration. Returning 'published'
|
|
128
|
+
// triggers `publish.ts` to create + push the git tag, which is the
|
|
129
|
+
// engine's record-of-intent and the signal the caller's job uses to
|
|
130
|
+
// know there's work to do.
|
|
131
|
+
ctx.log.info([
|
|
132
|
+
`pypi: ${pkg.name}@${version} delegated to caller-side upload step.`,
|
|
133
|
+
' The engine creates and pushes the git tag from this job; the actual',
|
|
134
|
+
' upload runs in your `pypi-publish` job via `pypa/gh-action-pypi-publish`.',
|
|
135
|
+
' See README → "Publishing to PyPI" for the recipe.',
|
|
136
|
+
].join('\n'));
|
|
171
137
|
return {
|
|
172
138
|
status: 'published',
|
|
173
139
|
url: `${REGISTRY}/project/${pypiNameFor(pkg)}/${version}/`,
|
|
@@ -177,45 +143,6 @@ async function publishImpl(pkg, version, ctx) {
|
|
|
177
143
|
function pypiNameFor(pkg) {
|
|
178
144
|
return pkg.pypi ?? pkg.name;
|
|
179
145
|
}
|
|
180
|
-
/**
|
|
181
|
-
* Trusted-publishing OIDC exchange. Returns a short-lived API token
|
|
182
|
-
* from PyPI when the workflow exposes ACTIONS_ID_TOKEN_REQUEST_*; null
|
|
183
|
-
* when the env isn't there or the exchange fails (caller decides
|
|
184
|
-
* whether to error).
|
|
185
|
-
*/
|
|
186
|
-
async function mintOidcToken(ctx) {
|
|
187
|
-
const reqUrl = nonEmpty(ctx.env.ACTIONS_ID_TOKEN_REQUEST_URL) ??
|
|
188
|
-
nonEmpty(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);
|
|
189
|
-
const reqToken = nonEmpty(ctx.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN) ??
|
|
190
|
-
nonEmpty(process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN);
|
|
191
|
-
if (!reqUrl || !reqToken)
|
|
192
|
-
return null;
|
|
193
|
-
const idTokenRes = await fetch(`${reqUrl}&audience=pypi`, {
|
|
194
|
-
headers: { authorization: `bearer ${reqToken}` },
|
|
195
|
-
});
|
|
196
|
-
if (!idTokenRes.ok) {
|
|
197
|
-
ctx.log.warn(`pypi: OIDC id-token request failed: ${idTokenRes.status}`);
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
const idTokenJson = (await idTokenRes.json());
|
|
201
|
-
const idToken = idTokenJson.value;
|
|
202
|
-
if (!idToken) {
|
|
203
|
-
ctx.log.warn('pypi: OIDC id-token response missing `value`');
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
const mintRes = await fetch(`${REGISTRY}/_/oidc/mint-token`, {
|
|
207
|
-
method: 'POST',
|
|
208
|
-
headers: { 'content-type': 'application/json' },
|
|
209
|
-
body: JSON.stringify({ token: idToken }),
|
|
210
|
-
});
|
|
211
|
-
if (!mintRes.ok) {
|
|
212
|
-
const body = await mintRes.text();
|
|
213
|
-
ctx.log.warn(`pypi: OIDC mint-token failed (${mintRes.status}): ${body.slice(0, 200)}`);
|
|
214
|
-
return null;
|
|
215
|
-
}
|
|
216
|
-
const mintJson = (await mintRes.json());
|
|
217
|
-
return mintJson.token ?? null;
|
|
218
|
-
}
|
|
219
146
|
/**
|
|
220
147
|
* Rewrites the first `version = "x.y.z"` inside the `[project]` table.
|
|
221
148
|
*
|
|
@@ -254,59 +181,6 @@ function projectDynamicIncludesVersion(project) {
|
|
|
254
181
|
export function scmEnvSuffix(pkgName) {
|
|
255
182
|
return pkgName.replace(/[-._]+/g, '_').toUpperCase();
|
|
256
183
|
}
|
|
257
|
-
/**
|
|
258
|
-
* Collects `.whl` and `.tar.gz` files across every artifact subdir whose
|
|
259
|
-
* name starts with the package's pilot name. Matches the artifact naming
|
|
260
|
-
* contract from §12.4: `{name}-wheel-{target}` and `{name}-sdist`.
|
|
261
|
-
*/
|
|
262
|
-
function collectArtifacts(pkgName, artifactsRoot) {
|
|
263
|
-
if (!artifactsRoot || !existsSync(artifactsRoot))
|
|
264
|
-
return [];
|
|
265
|
-
// #237: encode pkg.name so slash-containing names (e.g. `py/foo` →
|
|
266
|
-
// `py__foo`) line up with the on-disk directory the planner emitted.
|
|
267
|
-
// Match exactly the two artifact-name shapes the planner emits per
|
|
268
|
-
// §12.4: `{name}-sdist` (single dir) and `{name}-wheel-{target}` (one
|
|
269
|
-
// dir per wheel target). A bare prefix match would also pick up
|
|
270
|
-
// sibling packages whose names extend the same prefix
|
|
271
|
-
// (`foo-extras-sdist` matched as if it were `foo`'s sdist) — the
|
|
272
|
-
// tighter shape mirrors the documented contract.
|
|
273
|
-
const base = sanitizeArtifactName(pkgName);
|
|
274
|
-
const sdistDir = `${base}-sdist`;
|
|
275
|
-
const wheelPrefix = `${base}-wheel-`;
|
|
276
|
-
const out = [];
|
|
277
|
-
for (const entry of readdirSync(artifactsRoot)) {
|
|
278
|
-
if (entry !== sdistDir && !entry.startsWith(wheelPrefix))
|
|
279
|
-
continue;
|
|
280
|
-
const sub = join(artifactsRoot, entry);
|
|
281
|
-
/* v8 ignore next -- fs entries shouldn't vanish between readdir and stat */
|
|
282
|
-
if (!statSync(sub).isDirectory())
|
|
283
|
-
continue;
|
|
284
|
-
// #237: walk recursively so we tolerate any layout inside the
|
|
285
|
-
// artifact directory. upload-artifact's behavior differs per
|
|
286
|
-
// path-input shape (directory vs glob), so a flat `readdir` here
|
|
287
|
-
// would miss files that landed in a workspace-relative subdir.
|
|
288
|
-
for (const file of walkFiles(sub)) {
|
|
289
|
-
if (file.endsWith('.whl') || file.endsWith('.tar.gz')) {
|
|
290
|
-
out.push(file);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
return out;
|
|
295
|
-
}
|
|
296
|
-
function walkFiles(dir) {
|
|
297
|
-
const out = [];
|
|
298
|
-
for (const entry of readdirSync(dir)) {
|
|
299
|
-
const full = join(dir, entry);
|
|
300
|
-
const st = statSync(full);
|
|
301
|
-
if (st.isDirectory()) {
|
|
302
|
-
out.push(...walkFiles(full));
|
|
303
|
-
}
|
|
304
|
-
else if (st.isFile()) {
|
|
305
|
-
out.push(full);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return out;
|
|
309
|
-
}
|
|
310
184
|
export const pypi = {
|
|
311
185
|
kind: 'pypi',
|
|
312
186
|
isPublished: isPublishedImpl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pypi.js","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pypi.js","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,kBAAkB,CAAC;AAEpC,KAAK,UAAU,eAAe,CAC5B,GAAoC,EACpC,OAAe,EACf,IAAS;IAET,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,GAAG,QAAQ,SAAS,kBAAkB,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;IAC/F,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE;KACtC,CAAC,CAAC;IACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QACtB,MAAM,IAAI,cAAc,CAAC,gBAAgB,GAAG,aAAa,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,yFAAyF;IACzF,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,aAAa,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,gBAAgB,CACvB,GAAoC,EACpC,OAAe,EACf,GAAQ;IAER,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACvD,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,aAAa,EAAE,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,4DAA4D;QAC5D,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,6EAA6E;IAC7E,sEAAsE;IACtE,6EAA6E;IAC7E,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,aAAa,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,OAAO,GAAI,MAA8C,EAAE,OAAO,CAAC;IACzE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,uGAAuG,CACxG,CACF,CAAC;IACJ,CAAC;IACD,uEAAuE;IACvE,0EAA0E;IAC1E,wEAAwE;IACxE,qEAAqE;IACrE,uEAAuE;IACvE,uEAAuE;IACvE,+DAA+D;IAC/D,IAAI,6BAA6B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACpD,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CACV;YACE,GAAG,GAAG,8DAA8D;YACpE,sBAAsB,OAAO,4CAA4C;YACzE,4CAA4C,SAAS,IAAI,OAAO,gCAAgC;YAChG,+DAA+D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,2BAA2B;YACxI,0FAA0F;YAC1F,4EAA4E;SAC7E,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;QACF,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,uBAAuB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,GAAkD,EAClD,OAAe,EACf,GAAQ;IAER,IAAI,MAAM,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACzC,CAAC;IAED,oEAAoE;IACpE,mEAAmE;IACnE,gEAAgE;IAChE,iEAAiE;IACjE,mEAAmE;IACnE,oEAAoE;IACpE,2BAA2B;IAC3B,GAAG,CAAC,GAAG,CAAC,IAAI,CACV;QACE,SAAS,GAAG,CAAC,IAAI,IAAI,OAAO,wCAAwC;QACpE,uEAAuE;QACvE,6EAA6E;QAC7E,qDAAqD;KACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,WAAW;QACnB,GAAG,EAAE,GAAG,QAAQ,YAAY,WAAW,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG;KAC3D,CAAC;AACJ,CAAC;AAED,6EAA6E;AAE7E,SAAS,WAAW,CAAC,GAAoC;IACvD,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,OAAe;IACrE,MAAM,EAAE,GAAG,uDAAuD,CAAC;IACnE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CACb,sGAAsG,CACvG,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAwD,CAAC;IAC9F,IAAI,GAAG,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC;IACnC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC;IACnC,MAAM,GAAG,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAChF,CAAC;AAED;;;;;GAKG;AACH,SAAS,6BAA6B,CAAC,OAA8B;IACnE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAY;IAC3B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,eAAe;IAC5B,YAAY,EAAE,gBAAgB;IAC9B,OAAO,EAAE,WAAW;CACrB,CAAC"}
|
package/dist/publish.d.ts
CHANGED
package/dist/publish.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,OAAO,EAA6B,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAGzF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC;CACjD;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;CAC/E;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAmH1E"}
|
package/dist/publish.js
CHANGED
|
@@ -25,6 +25,7 @@ import { plan } from './plan.js';
|
|
|
25
25
|
import { formatTag } from './tag-template.js';
|
|
26
26
|
import { requireAuth } from './preflight.js';
|
|
27
27
|
import { withRetry } from './retry.js';
|
|
28
|
+
import { readHandlerMeta } from './types.js';
|
|
28
29
|
import { dumpFailure } from './verbose.js';
|
|
29
30
|
export async function publish(opts) {
|
|
30
31
|
const cwd = opts.cwd;
|
|
@@ -112,6 +113,9 @@ export async function publish(opts) {
|
|
|
112
113
|
}
|
|
113
114
|
catch (err) {
|
|
114
115
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
116
|
+
// Phase 2 / Idea 9: handler-attached metadata (tool versions, etc.)
|
|
117
|
+
// rides through to the failure renderer.
|
|
118
|
+
const meta = readHandlerMeta(error);
|
|
115
119
|
dumpFailure(error, {
|
|
116
120
|
package: name,
|
|
117
121
|
handler: pkg.kind,
|
|
@@ -119,6 +123,7 @@ export async function publish(opts) {
|
|
|
119
123
|
stdout: '',
|
|
120
124
|
stderr: error.message,
|
|
121
125
|
exitCode: -1,
|
|
126
|
+
...(meta?.toolVersions ? { toolVersions: meta.toolVersions } : {}),
|
|
122
127
|
},
|
|
123
128
|
// Thread ctx.env through so handler-injected credentials (OIDC-
|
|
124
129
|
// minted twine/npm/crates tokens that live only on ctx.env, not
|
package/dist/publish.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,IAAI,EAAkB,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -99,4 +99,26 @@ export declare class AuthError extends Error {
|
|
|
99
99
|
export declare class TransientError extends Error {
|
|
100
100
|
readonly name = "TransientError";
|
|
101
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Diagnostic metadata a handler can attach to a thrown error so the
|
|
104
|
+
* failure renderer (`verbose.ts:dumpFailure`) can surface tool versions
|
|
105
|
+
* and other context without requiring every handler to plumb its own
|
|
106
|
+
* dump call. Phase 2 / Idea 9.
|
|
107
|
+
*
|
|
108
|
+
* Attached via `attachHandlerMeta(err, ...)` and read at the publish
|
|
109
|
+
* boundary via `readHandlerMeta(err)`.
|
|
110
|
+
*/
|
|
111
|
+
export interface HandlerErrorMeta {
|
|
112
|
+
/** `{tool: "tool --version output"}`. Examples: `twine`, `python`,
|
|
113
|
+
* `npm`, `cargo`. Capture is best-effort — keys may be absent if
|
|
114
|
+
* the tool isn't on PATH or its version probe failed. */
|
|
115
|
+
toolVersions?: Record<string, string>;
|
|
116
|
+
}
|
|
117
|
+
/** Attach handler-failure metadata to an Error and return the same
|
|
118
|
+
* Error (so callers can `throw attachHandlerMeta(new Error(...), {...})`). */
|
|
119
|
+
export declare function attachHandlerMeta<E extends Error>(err: E, meta: HandlerErrorMeta): E;
|
|
120
|
+
/** Read handler-failure metadata from a possibly-Error value. Returns
|
|
121
|
+
* undefined for non-Error values, plain Errors, and Errors without
|
|
122
|
+
* attached meta. */
|
|
123
|
+
export declare function readHandlerMeta(value: unknown): HandlerErrorMeta | undefined;
|
|
102
124
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -27,4 +27,20 @@ export class AuthError extends Error {
|
|
|
27
27
|
export class TransientError extends Error {
|
|
28
28
|
name = 'TransientError';
|
|
29
29
|
}
|
|
30
|
+
const HANDLER_META_KEY = '__piotHandlerMeta';
|
|
31
|
+
/** Attach handler-failure metadata to an Error and return the same
|
|
32
|
+
* Error (so callers can `throw attachHandlerMeta(new Error(...), {...})`). */
|
|
33
|
+
export function attachHandlerMeta(err, meta) {
|
|
34
|
+
err[HANDLER_META_KEY] = meta;
|
|
35
|
+
return err;
|
|
36
|
+
}
|
|
37
|
+
/** Read handler-failure metadata from a possibly-Error value. Returns
|
|
38
|
+
* undefined for non-Error values, plain Errors, and Errors without
|
|
39
|
+
* attached meta. */
|
|
40
|
+
export function readHandlerMeta(value) {
|
|
41
|
+
if (!(value instanceof Error))
|
|
42
|
+
return undefined;
|
|
43
|
+
const carrier = value;
|
|
44
|
+
return carrier[HANDLER_META_KEY];
|
|
45
|
+
}
|
|
30
46
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACxD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS;QAC/B,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;QAChD,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAC/B,CAAC;AAuED,2CAA2C;AAC3C,MAAM,OAAO,SAAU,SAAQ,KAAK;IAChB,IAAI,GAAG,WAAW,CAAC;CACtC;AAED,4DAA4D;AAC5D,MAAM,OAAO,cAAe,SAAQ,KAAK;IACrB,IAAI,GAAG,gBAAgB,CAAC;CAC3C"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACxD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS;QAC/B,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;QAChD,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAC/B,CAAC;AAuED,2CAA2C;AAC3C,MAAM,OAAO,SAAU,SAAQ,KAAK;IAChB,IAAI,GAAG,WAAW,CAAC;CACtC;AAED,4DAA4D;AAC5D,MAAM,OAAO,cAAe,SAAQ,KAAK;IACrB,IAAI,GAAG,gBAAgB,CAAC;CAC3C;AAkBD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAE7C;+EAC+E;AAC/E,MAAM,UAAU,iBAAiB,CAAkB,GAAM,EAAE,IAAsB;IAC9E,GAAqD,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAChF,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;qBAEqB;AACrB,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,OAAO,GAAG,KAA0D,CAAC;IAC3E,OAAO,OAAO,CAAC,gBAAgB,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/verbose.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verbose.d.ts","sourceRoot":"","sources":["../src/verbose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACnC;AAKD,wBAAgB,WAAW,CACzB,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,WAAW,GAChB,IAAI,
|
|
1
|
+
{"version":3,"file":"verbose.d.ts","sourceRoot":"","sources":["../src/verbose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACnC;AAKD,wBAAgB,WAAW,CACzB,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,WAAW,GAChB,IAAI,CA6BN"}
|
package/dist/verbose.js
CHANGED
|
@@ -24,6 +24,13 @@ export function dumpFailure(err, ctx, opts) {
|
|
|
24
24
|
: undefined;
|
|
25
25
|
const md = redact(renderMarkdown(err, ctx), sources);
|
|
26
26
|
writeSummary(truncate(md));
|
|
27
|
+
// Phase 3 / Idea 6. The markdown summary above is auth-gated on
|
|
28
|
+
// private repos and not always reachable to a foreign agent helping
|
|
29
|
+
// debug from outside; a workflow-command annotation written to
|
|
30
|
+
// stdout renders on the public run-summary page where any observer
|
|
31
|
+
// (including WebFetch) can read it. Carry the same redaction the
|
|
32
|
+
// markdown gets.
|
|
33
|
+
emitGhaAnnotation(err, ctx, redact(err.message, sources));
|
|
27
34
|
// A single structured record pairs the summary so downstream log
|
|
28
35
|
// pipelines (JSON sinks, GHA log grep) can find the failure by
|
|
29
36
|
// package + handler + exitCode without parsing markdown.
|
|
@@ -34,6 +41,39 @@ export function dumpFailure(err, ctx, opts) {
|
|
|
34
41
|
command: ctx.command.join(' '),
|
|
35
42
|
});
|
|
36
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Emit a GitHub Actions `::error::` workflow command on stdout.
|
|
46
|
+
* Visible on the run-summary page's annotation strip — the only
|
|
47
|
+
* failure surface reachable without GitHub auth.
|
|
48
|
+
*
|
|
49
|
+
* No-op outside GHA (gated on `GITHUB_ACTIONS=true`, the canonical
|
|
50
|
+
* runner env var). Stays one line: GH annotations are line-oriented
|
|
51
|
+
* and a bare embedded newline truncates the body.
|
|
52
|
+
*/
|
|
53
|
+
const ANNOTATION_MAX_LEN = 500;
|
|
54
|
+
function emitGhaAnnotation(err, ctx, redactedMsg) {
|
|
55
|
+
if (process.env.GITHUB_ACTIONS !== 'true')
|
|
56
|
+
return;
|
|
57
|
+
void err; // arity preserved for future callers; redactedMsg drives output
|
|
58
|
+
const codeMatch = /\[(PIOT_[A-Z0-9_]+)\]/.exec(redactedMsg);
|
|
59
|
+
const codeTag = codeMatch ? ` [${codeMatch[1]}]` : '';
|
|
60
|
+
// First non-empty line. The full diagnostic lives in the markdown
|
|
61
|
+
// summary and the structured log record; the annotation is the
|
|
62
|
+
// public one-liner.
|
|
63
|
+
const firstLine = redactedMsg
|
|
64
|
+
.split('\n')
|
|
65
|
+
.map((s) => s.trim())
|
|
66
|
+
.find((s) => s.length > 0) ?? '';
|
|
67
|
+
const head = `${ctx.handler}/${ctx.package}${codeTag}: ${firstLine}`;
|
|
68
|
+
const trimmed = head.length > ANNOTATION_MAX_LEN
|
|
69
|
+
? head.slice(0, ANNOTATION_MAX_LEN - 1) + '…'
|
|
70
|
+
: head;
|
|
71
|
+
// Strip any embedded line breaks that survived (defensive — first-line
|
|
72
|
+
// selection should have prevented them) so the annotation stays a
|
|
73
|
+
// single workflow command.
|
|
74
|
+
const oneLine = trimmed.replace(/[\r\n]+/g, ' ');
|
|
75
|
+
process.stdout.write(`::error::${oneLine}\n`);
|
|
76
|
+
}
|
|
37
77
|
function renderMarkdown(err, ctx) {
|
|
38
78
|
const lines = [];
|
|
39
79
|
lines.push(`## ❌ ${ctx.handler}/${ctx.package} failed`);
|
package/dist/verbose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verbose.js","sourceRoot":"","sources":["../src/verbose.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"verbose.js","sourceRoot":"","sources":["../src/verbose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,MAAM,EAAkB,MAAM,UAAU,CAAC;AA+ClD,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,8GAA8G;AACnJ,MAAM,UAAU,GAAG,gEAAgE,CAAC;AAEpF,MAAM,UAAU,WAAW,CACzB,GAAU,EACV,GAAmB,EACnB,IAAiB;IAEjB,kEAAkE;IAClE,mEAAmE;IACnE,oEAAoE;IACpE,0BAA0B;IAC1B,MAAM,OAAO,GACX,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACzD,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;QACnC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACrD,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAE3B,gEAAgE;IAChE,oEAAoE;IACpE,+DAA+D;IAC/D,mEAAmE;IACnE,iEAAiE;IACjE,iBAAiB;IACjB,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAE1D,iEAAiE;IACjE,+DAA+D;IAC/D,yDAAyD;IACzD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,YAAY,GAAG,CAAC,OAAO,EAAE,EAAE;QACrE,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;KAC/B,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,SAAS,iBAAiB,CACxB,GAAU,EACV,GAAmB,EACnB,WAAmB;IAEnB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM;QAAE,OAAO;IAClD,KAAK,GAAG,CAAC,CAAC,gEAAgE;IAC1E,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,kEAAkE;IAClE,+DAA+D;IAC/D,oBAAoB;IACpB,MAAM,SAAS,GACb,WAAW;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,GAAG,OAAO,KAAK,SAAS,EAAE,CAAC;IACrE,MAAM,OAAO,GACX,IAAI,CAAC,MAAM,GAAG,kBAAkB;QAC9B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,GAAG,CAAC,CAAC,GAAG,GAAG;QAC7C,CAAC,CAAC,IAAI,CAAC;IACX,uEAAuE;IACvE,kEAAkE;IAClE,2BAA2B;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,cAAc,CAAC,GAAU,EAAE,GAAmB;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC;IACxD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAElB,IAAI,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IACpC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAElB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IACpC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAElB,IAAI,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,EAAU;IAC1B,IAAI,EAAE,CAAC,MAAM,IAAI,WAAW;QAAE,OAAO,EAAE,CAAC;IACxC,+DAA+D;IAC/D,6DAA6D;IAC7D,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC1D,OAAO,IAAI,GAAG,UAAU,CAAC;AAC3B,CAAC;AAED,SAAS,YAAY,CAAC,EAAU;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,+CAA+C;IAClE,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC"}
|