putitoutthere 0.2.28 → 0.2.30
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 +40 -0
- package/MIGRATIONS.md +1274 -0
- package/README.md +343 -41
- package/action.yml +9 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +28 -6
- package/dist/action.js.map +1 -1
- package/dist/cascade.js +14 -7
- package/dist/cascade.js.map +1 -1
- package/dist/check-crate-size.d.ts +26 -0
- package/dist/check-crate-size.d.ts.map +1 -0
- package/dist/check-crate-size.js +99 -0
- package/dist/check-crate-size.js.map +1 -0
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +116 -16
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +17 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +156 -19
- package/dist/cli.js.map +1 -1
- package/dist/completeness.js +6 -3
- package/dist/completeness.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +20 -5
- package/dist/config.js.map +1 -1
- package/dist/ensure-tag.d.ts +17 -0
- package/dist/ensure-tag.d.ts.map +1 -0
- package/dist/ensure-tag.js +28 -0
- package/dist/ensure-tag.js.map +1 -0
- package/dist/env.js +6 -3
- package/dist/env.js.map +1 -1
- package/dist/error-codes.d.ts +89 -0
- package/dist/error-codes.d.ts.map +1 -1
- package/dist/error-codes.js +102 -0
- package/dist/error-codes.js.map +1 -1
- package/dist/git.d.ts +5 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +19 -6
- package/dist/git.js.map +1 -1
- package/dist/glob.d.ts +9 -0
- package/dist/glob.d.ts.map +1 -1
- package/dist/glob.js +29 -1
- package/dist/glob.js.map +1 -1
- package/dist/handlers/crates.d.ts +15 -0
- package/dist/handlers/crates.d.ts.map +1 -1
- package/dist/handlers/crates.js +84 -9
- package/dist/handlers/crates.js.map +1 -1
- package/dist/handlers/npm-platform.d.ts +11 -0
- package/dist/handlers/npm-platform.d.ts.map +1 -1
- package/dist/handlers/npm-platform.js +91 -8
- package/dist/handlers/npm-platform.js.map +1 -1
- package/dist/handlers/npm.d.ts.map +1 -1
- package/dist/handlers/npm.js +59 -9
- package/dist/handlers/npm.js.map +1 -1
- package/dist/handlers/pypi.d.ts +0 -6
- package/dist/handlers/pypi.d.ts.map +1 -1
- package/dist/handlers/pypi.js +28 -10
- package/dist/handlers/pypi.js.map +1 -1
- package/dist/log.js +16 -8
- package/dist/log.js.map +1 -1
- package/dist/normalize-artifacts.js +8 -4
- package/dist/normalize-artifacts.js.map +1 -1
- package/dist/plan.d.ts +8 -0
- package/dist/plan.d.ts.map +1 -1
- package/dist/plan.js +125 -25
- package/dist/plan.js.map +1 -1
- package/dist/preflight.d.ts +79 -0
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +715 -33
- package/dist/preflight.js.map +1 -1
- package/dist/publish.d.ts +7 -0
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +49 -18
- package/dist/publish.js.map +1 -1
- package/dist/python-versions.d.ts +40 -0
- package/dist/python-versions.d.ts.map +1 -0
- package/dist/python-versions.js +142 -0
- package/dist/python-versions.js.map +1 -0
- package/dist/reconcile-types.d.ts +36 -0
- package/dist/reconcile-types.d.ts.map +1 -0
- package/dist/reconcile-types.js +9 -0
- package/dist/reconcile-types.js.map +1 -0
- package/dist/reconcile.d.ts +21 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +54 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/release-packages.d.ts +33 -0
- package/dist/release-packages.d.ts.map +1 -0
- package/dist/release-packages.js +74 -0
- package/dist/release-packages.js.map +1 -0
- package/dist/resolve-tag-commit.d.ts +22 -0
- package/dist/resolve-tag-commit.d.ts.map +1 -0
- package/dist/resolve-tag-commit.js +26 -0
- package/dist/resolve-tag-commit.js.map +1 -0
- package/dist/retry.js +14 -7
- package/dist/retry.js.map +1 -1
- package/dist/status-classify.d.ts +17 -0
- package/dist/status-classify.d.ts.map +1 -0
- package/dist/status-classify.js +37 -0
- package/dist/status-classify.js.map +1 -0
- package/dist/status-format.d.ts +9 -0
- package/dist/status-format.d.ts.map +1 -0
- package/dist/status-format.js +19 -0
- package/dist/status-format.js.map +1 -0
- package/dist/status-types.d.ts +31 -0
- package/dist/status-types.d.ts.map +1 -0
- package/dist/status-types.js +8 -0
- package/dist/status-types.js.map +1 -0
- package/dist/status.d.ts +28 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +72 -0
- package/dist/status.js.map +1 -0
- package/dist/tag-template.js +2 -1
- package/dist/tag-template.js.map +1 -1
- package/dist/trailer.js +16 -9
- package/dist/trailer.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -2
- package/dist/types.js.map +1 -1
- package/dist/verbose.js +7 -4
- package/dist/verbose.js.map +1 -1
- package/dist/wheel-abi.d.ts +37 -0
- package/dist/wheel-abi.d.ts.map +1 -0
- package/dist/wheel-abi.js +118 -0
- package/dist/wheel-abi.js.map +1 -0
- package/dist/write-crate-version.d.ts +32 -0
- package/dist/write-crate-version.d.ts.map +1 -0
- package/dist/write-crate-version.js +52 -0
- package/dist/write-crate-version.js.map +1 -0
- package/dist/write-launcher.d.ts +82 -0
- package/dist/write-launcher.d.ts.map +1 -0
- package/dist/write-launcher.js +236 -0
- package/dist/write-launcher.js.map +1 -0
- package/dist/write-version.js +2 -1
- package/dist/write-version.js.map +1 -1
- package/package.json +4 -2
package/dist/error-codes.d.ts
CHANGED
|
@@ -36,6 +36,15 @@ export declare const ErrorCodes: {
|
|
|
36
36
|
* declares. Failing at preflight prevents wasting a build run on
|
|
37
37
|
* a precondition checkable in milliseconds. #280. */
|
|
38
38
|
readonly NPM_MISSING_REPOSITORY: "PIOT_NPM_MISSING_REPOSITORY";
|
|
39
|
+
/** An npm package's `package.json` declares a `name` that differs from
|
|
40
|
+
* the `[[package]].name` configured in `putitoutthere.toml` (or the
|
|
41
|
+
* `npm` override when set). `npm publish` packs the manifest `name`,
|
|
42
|
+
* but the engine's idempotency probe (`npm view <name>`) and the
|
|
43
|
+
* tag/URL bookkeeping use the configured name — so a divergence
|
|
44
|
+
* silently breaks idempotency and can publish under an unexpected
|
|
45
|
+
* name. The npm analogue of PIOT_PYPI_NAME_MISMATCH /
|
|
46
|
+
* PIOT_CRATES_NAME_MISMATCH. #301. */
|
|
47
|
+
readonly NPM_NAME_MISMATCH: "PIOT_NPM_NAME_MISMATCH";
|
|
39
48
|
/** A crates package's `Cargo.toml` is missing one or more
|
|
40
49
|
* required `[package]` metadata fields (`description` and
|
|
41
50
|
* `license`/`license-file`). crates.io rejects the publish with
|
|
@@ -54,6 +63,86 @@ export declare const ErrorCodes: {
|
|
|
54
63
|
* (the recommended path; setuptools-scm and the maturin
|
|
55
64
|
* Cargo.toml-driven path are equally valid). */
|
|
56
65
|
readonly PYPI_STATIC_VERSION: "PIOT_PYPI_STATIC_VERSION";
|
|
66
|
+
/** A pypi package's `pyproject.toml` declares a `[project].name` that
|
|
67
|
+
* differs from the `[[package]].name` configured in
|
|
68
|
+
* `putitoutthere.toml` (or the `pypi` override when set). The build
|
|
69
|
+
* tool will pack the wrong name and the upload either lands on the
|
|
70
|
+
* wrong registered project or 403s with a confusing "no such project"
|
|
71
|
+
* message. #301. */
|
|
72
|
+
readonly PYPI_NAME_MISMATCH: "PIOT_PYPI_NAME_MISMATCH";
|
|
73
|
+
/** A pypi package's `[build-system].build-backend` is set but does
|
|
74
|
+
* not match the configured `build` mode (e.g. `build = "maturin"`
|
|
75
|
+
* but the pyproject declares `hatchling.build`). The build tool
|
|
76
|
+
* surfaces a confusing tail-end error long after maturin has run.
|
|
77
|
+
* #301. */
|
|
78
|
+
readonly PYPI_BUILD_BACKEND_MISMATCH: "PIOT_PYPI_BUILD_BACKEND_MISMATCH";
|
|
79
|
+
/** A pypi package declares `dynamic = ["version"]` but no
|
|
80
|
+
* version-source backend block (`[tool.hatch.version]` /
|
|
81
|
+
* `[tool.setuptools_scm]`) is present, so the build backend has no
|
|
82
|
+
* way to compute a version at pack time. #301. */
|
|
83
|
+
readonly PYPI_DYNAMIC_VERSION_NO_BACKEND: "PIOT_PYPI_DYNAMIC_VERSION_NO_BACKEND";
|
|
84
|
+
/** A maturin pypi package declares `[package.bundle_cli]` but
|
|
85
|
+
* `[tool.maturin].include` does not cover the configured
|
|
86
|
+
* `bundle_cli.stage_to` path, so the cross-compiled binary will
|
|
87
|
+
* never make it inside the wheel. The post-build wheel-content
|
|
88
|
+
* guard catches it, but only after maturin has run. #301. */
|
|
89
|
+
readonly PYPI_MATURIN_INCLUDE_MISSING: "PIOT_PYPI_MATURIN_INCLUDE_MISSING";
|
|
90
|
+
/** A crates package's `Cargo.toml` declares a `[package].name` that
|
|
91
|
+
* differs from the `[[package]].name` configured in
|
|
92
|
+
* `putitoutthere.toml` (or the `crate` override when set). cargo
|
|
93
|
+
* publish will pack the wrong crate, often 404'ing on the registry
|
|
94
|
+
* side after a verification build that took 10+ minutes. #301. */
|
|
95
|
+
readonly CRATES_NAME_MISMATCH: "PIOT_CRATES_NAME_MISMATCH";
|
|
96
|
+
/** A `bundle_cli.bin` is configured but the target `Cargo.toml` has
|
|
97
|
+
* no `[[bin]]` table with that name (and the implicit-bin name
|
|
98
|
+
* derived from `[package].name` does not match either). `cargo
|
|
99
|
+
* build --bin <bin>` fails with `no bin target named ...` mid-
|
|
100
|
+
* build. #301. */
|
|
101
|
+
readonly CRATES_MISSING_BIN: "PIOT_CRATES_MISSING_BIN";
|
|
102
|
+
/** A `features` list (either on a `kind = "crates"` package or on
|
|
103
|
+
* a `bundle_cli` block) references a feature that the target
|
|
104
|
+
* `Cargo.toml` does not declare in `[features]`. `cargo build
|
|
105
|
+
* --features <list>` fails with `Package ... does not have these
|
|
106
|
+
* features`. #301. */
|
|
107
|
+
readonly CRATES_FEATURE_NOT_DECLARED: "PIOT_CRATES_FEATURE_NOT_DECLARED";
|
|
108
|
+
/** A crates package's `Cargo.toml` declares `version.workspace =
|
|
109
|
+
* true`, but no ancestor `Cargo.toml` with a `[workspace]` table
|
|
110
|
+
* declares `[workspace.package].version`. cargo fails with
|
|
111
|
+
* `error: failed to inherit "version" from workspace`. #301. */
|
|
112
|
+
readonly CRATES_WORKSPACE_VERSION_MISMATCH: "PIOT_CRATES_WORKSPACE_VERSION_MISMATCH";
|
|
113
|
+
/** crates.io rejected `cargo publish` because the crate has never been
|
|
114
|
+
* published. Trusted Publishing on crates.io binds to an
|
|
115
|
+
* already-published crate — the OIDC mint succeeds, the exchanged
|
|
116
|
+
* token reaches cargo, but the registry returns 404 ("crate `<name>`
|
|
117
|
+
* does not exist or you do not have permission to publish to it").
|
|
118
|
+
* The fix is one bootstrap publish with a classic `CARGO_REGISTRY_TOKEN`;
|
|
119
|
+
* trusted publishing works for every release after. #284. */
|
|
120
|
+
readonly CRATES_FIRST_PUBLISH_TP_REJECTED: "PIOT_CRATES_FIRST_PUBLISH_TP_REJECTED";
|
|
121
|
+
/** A crates package's `.crate`, as produced by `cargo package`, is
|
|
122
|
+
* larger than crates.io's 10 MiB (`10485760`-byte) upload limit.
|
|
123
|
+
* `cargo publish` would fail with `413 Payload Too Large` only
|
|
124
|
+
* mid-release, after the verification build; `runChecks` reproduces
|
|
125
|
+
* the tarball at PR time so the regression is caught before merge.
|
|
126
|
+
* A tracked symlink pointing into a build directory, or a missing
|
|
127
|
+
* `[package].exclude`, is the usual cause of build output landing
|
|
128
|
+
* in the crate. #362. */
|
|
129
|
+
readonly CRATES_PACKAGE_TOO_LARGE: "PIOT_CRATES_PACKAGE_TOO_LARGE";
|
|
130
|
+
/** A manifest's declared repository URL resolves to a different
|
|
131
|
+
* `owner/repo` than the GitHub repository the workflow is running
|
|
132
|
+
* from (`GITHUB_REPOSITORY`). npm's provenance verification compares
|
|
133
|
+
* `package.json#repository.url` against the OIDC source claim and
|
|
134
|
+
* returns a 422 after artifact upload — Cargo.toml `[package].repository`
|
|
135
|
+
* and pyproject.toml `[project.urls]` carry the same risk on
|
|
136
|
+
* crates.io / PyPI trusted-publisher paths. Failing at preflight
|
|
137
|
+
* catches the mismatch in milliseconds. */
|
|
138
|
+
readonly REPO_URL_MISMATCH: "PIOT_REPO_URL_MISMATCH";
|
|
139
|
+
/** The GitHub repository the workflow is running from is private.
|
|
140
|
+
* putitoutthere refuses to publish from a private repository:
|
|
141
|
+
* npm provenance attestations embed a source-ref pointer that
|
|
142
|
+
* consumers cannot dereference when the repo is private, and the
|
|
143
|
+
* same source-visibility expectation underpins the trusted-publisher
|
|
144
|
+
* story on the other registries. */
|
|
145
|
+
readonly REPO_PRIVATE: "PIOT_REPO_PRIVATE";
|
|
57
146
|
};
|
|
58
147
|
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
59
148
|
/**
|
|
@@ -1 +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;;IAE1C;;;;;;kDAM8C;;IAE9C;;;;;0DAKsD;;IAEtD;;;;;;iCAM6B;;IAE7B;;;;;;;;qDAQiD;;
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,UAAU;IACrB;;;8CAG0C;;IAE1C;;;;;;kDAM8C;;IAE9C;;;;;0DAKsD;;IAEtD;;;;;;;2CAOuC;;IAEvC;;;;;;iCAM6B;;IAE7B;;;;;;;;qDAQiD;;IAEjD;;;;;yBAKqB;;IAErB;;;;gBAIY;;IAEZ;;;uDAGmD;;IAEnD;;;;kEAI8D;;IAE9D;;;;uEAImE;;IAEnE;;;;uBAImB;;IAEnB;;;;2BAIuB;;IAEvB;;;qEAGiE;;IAEjE;;;;;;kEAM8D;;IAE9D;;;;;;;8BAO0B;;IAE1B;;;;;;;gDAO4C;;IAE5C;;;;;yCAKqC;;CAE7B,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,EAmB/C,CAAC"}
|
package/dist/error-codes.js
CHANGED
|
@@ -36,6 +36,15 @@ export const ErrorCodes = {
|
|
|
36
36
|
* declares. Failing at preflight prevents wasting a build run on
|
|
37
37
|
* a precondition checkable in milliseconds. #280. */
|
|
38
38
|
NPM_MISSING_REPOSITORY: 'PIOT_NPM_MISSING_REPOSITORY',
|
|
39
|
+
/** An npm package's `package.json` declares a `name` that differs from
|
|
40
|
+
* the `[[package]].name` configured in `putitoutthere.toml` (or the
|
|
41
|
+
* `npm` override when set). `npm publish` packs the manifest `name`,
|
|
42
|
+
* but the engine's idempotency probe (`npm view <name>`) and the
|
|
43
|
+
* tag/URL bookkeeping use the configured name — so a divergence
|
|
44
|
+
* silently breaks idempotency and can publish under an unexpected
|
|
45
|
+
* name. The npm analogue of PIOT_PYPI_NAME_MISMATCH /
|
|
46
|
+
* PIOT_CRATES_NAME_MISMATCH. #301. */
|
|
47
|
+
NPM_NAME_MISMATCH: 'PIOT_NPM_NAME_MISMATCH',
|
|
39
48
|
/** A crates package's `Cargo.toml` is missing one or more
|
|
40
49
|
* required `[package]` metadata fields (`description` and
|
|
41
50
|
* `license`/`license-file`). crates.io rejects the publish with
|
|
@@ -54,6 +63,86 @@ export const ErrorCodes = {
|
|
|
54
63
|
* (the recommended path; setuptools-scm and the maturin
|
|
55
64
|
* Cargo.toml-driven path are equally valid). */
|
|
56
65
|
PYPI_STATIC_VERSION: 'PIOT_PYPI_STATIC_VERSION',
|
|
66
|
+
/** A pypi package's `pyproject.toml` declares a `[project].name` that
|
|
67
|
+
* differs from the `[[package]].name` configured in
|
|
68
|
+
* `putitoutthere.toml` (or the `pypi` override when set). The build
|
|
69
|
+
* tool will pack the wrong name and the upload either lands on the
|
|
70
|
+
* wrong registered project or 403s with a confusing "no such project"
|
|
71
|
+
* message. #301. */
|
|
72
|
+
PYPI_NAME_MISMATCH: 'PIOT_PYPI_NAME_MISMATCH',
|
|
73
|
+
/** A pypi package's `[build-system].build-backend` is set but does
|
|
74
|
+
* not match the configured `build` mode (e.g. `build = "maturin"`
|
|
75
|
+
* but the pyproject declares `hatchling.build`). The build tool
|
|
76
|
+
* surfaces a confusing tail-end error long after maturin has run.
|
|
77
|
+
* #301. */
|
|
78
|
+
PYPI_BUILD_BACKEND_MISMATCH: 'PIOT_PYPI_BUILD_BACKEND_MISMATCH',
|
|
79
|
+
/** A pypi package declares `dynamic = ["version"]` but no
|
|
80
|
+
* version-source backend block (`[tool.hatch.version]` /
|
|
81
|
+
* `[tool.setuptools_scm]`) is present, so the build backend has no
|
|
82
|
+
* way to compute a version at pack time. #301. */
|
|
83
|
+
PYPI_DYNAMIC_VERSION_NO_BACKEND: 'PIOT_PYPI_DYNAMIC_VERSION_NO_BACKEND',
|
|
84
|
+
/** A maturin pypi package declares `[package.bundle_cli]` but
|
|
85
|
+
* `[tool.maturin].include` does not cover the configured
|
|
86
|
+
* `bundle_cli.stage_to` path, so the cross-compiled binary will
|
|
87
|
+
* never make it inside the wheel. The post-build wheel-content
|
|
88
|
+
* guard catches it, but only after maturin has run. #301. */
|
|
89
|
+
PYPI_MATURIN_INCLUDE_MISSING: 'PIOT_PYPI_MATURIN_INCLUDE_MISSING',
|
|
90
|
+
/** A crates package's `Cargo.toml` declares a `[package].name` that
|
|
91
|
+
* differs from the `[[package]].name` configured in
|
|
92
|
+
* `putitoutthere.toml` (or the `crate` override when set). cargo
|
|
93
|
+
* publish will pack the wrong crate, often 404'ing on the registry
|
|
94
|
+
* side after a verification build that took 10+ minutes. #301. */
|
|
95
|
+
CRATES_NAME_MISMATCH: 'PIOT_CRATES_NAME_MISMATCH',
|
|
96
|
+
/** A `bundle_cli.bin` is configured but the target `Cargo.toml` has
|
|
97
|
+
* no `[[bin]]` table with that name (and the implicit-bin name
|
|
98
|
+
* derived from `[package].name` does not match either). `cargo
|
|
99
|
+
* build --bin <bin>` fails with `no bin target named ...` mid-
|
|
100
|
+
* build. #301. */
|
|
101
|
+
CRATES_MISSING_BIN: 'PIOT_CRATES_MISSING_BIN',
|
|
102
|
+
/** A `features` list (either on a `kind = "crates"` package or on
|
|
103
|
+
* a `bundle_cli` block) references a feature that the target
|
|
104
|
+
* `Cargo.toml` does not declare in `[features]`. `cargo build
|
|
105
|
+
* --features <list>` fails with `Package ... does not have these
|
|
106
|
+
* features`. #301. */
|
|
107
|
+
CRATES_FEATURE_NOT_DECLARED: 'PIOT_CRATES_FEATURE_NOT_DECLARED',
|
|
108
|
+
/** A crates package's `Cargo.toml` declares `version.workspace =
|
|
109
|
+
* true`, but no ancestor `Cargo.toml` with a `[workspace]` table
|
|
110
|
+
* declares `[workspace.package].version`. cargo fails with
|
|
111
|
+
* `error: failed to inherit "version" from workspace`. #301. */
|
|
112
|
+
CRATES_WORKSPACE_VERSION_MISMATCH: 'PIOT_CRATES_WORKSPACE_VERSION_MISMATCH',
|
|
113
|
+
/** crates.io rejected `cargo publish` because the crate has never been
|
|
114
|
+
* published. Trusted Publishing on crates.io binds to an
|
|
115
|
+
* already-published crate — the OIDC mint succeeds, the exchanged
|
|
116
|
+
* token reaches cargo, but the registry returns 404 ("crate `<name>`
|
|
117
|
+
* does not exist or you do not have permission to publish to it").
|
|
118
|
+
* The fix is one bootstrap publish with a classic `CARGO_REGISTRY_TOKEN`;
|
|
119
|
+
* trusted publishing works for every release after. #284. */
|
|
120
|
+
CRATES_FIRST_PUBLISH_TP_REJECTED: 'PIOT_CRATES_FIRST_PUBLISH_TP_REJECTED',
|
|
121
|
+
/** A crates package's `.crate`, as produced by `cargo package`, is
|
|
122
|
+
* larger than crates.io's 10 MiB (`10485760`-byte) upload limit.
|
|
123
|
+
* `cargo publish` would fail with `413 Payload Too Large` only
|
|
124
|
+
* mid-release, after the verification build; `runChecks` reproduces
|
|
125
|
+
* the tarball at PR time so the regression is caught before merge.
|
|
126
|
+
* A tracked symlink pointing into a build directory, or a missing
|
|
127
|
+
* `[package].exclude`, is the usual cause of build output landing
|
|
128
|
+
* in the crate. #362. */
|
|
129
|
+
CRATES_PACKAGE_TOO_LARGE: 'PIOT_CRATES_PACKAGE_TOO_LARGE',
|
|
130
|
+
/** A manifest's declared repository URL resolves to a different
|
|
131
|
+
* `owner/repo` than the GitHub repository the workflow is running
|
|
132
|
+
* from (`GITHUB_REPOSITORY`). npm's provenance verification compares
|
|
133
|
+
* `package.json#repository.url` against the OIDC source claim and
|
|
134
|
+
* returns a 422 after artifact upload — Cargo.toml `[package].repository`
|
|
135
|
+
* and pyproject.toml `[project.urls]` carry the same risk on
|
|
136
|
+
* crates.io / PyPI trusted-publisher paths. Failing at preflight
|
|
137
|
+
* catches the mismatch in milliseconds. */
|
|
138
|
+
REPO_URL_MISMATCH: 'PIOT_REPO_URL_MISMATCH',
|
|
139
|
+
/** The GitHub repository the workflow is running from is private.
|
|
140
|
+
* putitoutthere refuses to publish from a private repository:
|
|
141
|
+
* npm provenance attestations embed a source-ref pointer that
|
|
142
|
+
* consumers cannot dereference when the repo is private, and the
|
|
143
|
+
* same source-visibility expectation underpins the trusted-publisher
|
|
144
|
+
* story on the other registries. */
|
|
145
|
+
REPO_PRIVATE: 'PIOT_REPO_PRIVATE',
|
|
57
146
|
};
|
|
58
147
|
/**
|
|
59
148
|
* Iterable form of the codes. Walked by tests for uniqueness/format
|
|
@@ -63,7 +152,20 @@ export const ALL_ERROR_CODES = [
|
|
|
63
152
|
ErrorCodes.AUTH_NO_TOKEN,
|
|
64
153
|
ErrorCodes.PUBLISH_EMPTY_PLAN,
|
|
65
154
|
ErrorCodes.NPM_MISSING_REPOSITORY,
|
|
155
|
+
ErrorCodes.NPM_NAME_MISMATCH,
|
|
66
156
|
ErrorCodes.CRATES_MISSING_METADATA,
|
|
67
157
|
ErrorCodes.PYPI_STATIC_VERSION,
|
|
158
|
+
ErrorCodes.PYPI_NAME_MISMATCH,
|
|
159
|
+
ErrorCodes.PYPI_BUILD_BACKEND_MISMATCH,
|
|
160
|
+
ErrorCodes.PYPI_DYNAMIC_VERSION_NO_BACKEND,
|
|
161
|
+
ErrorCodes.PYPI_MATURIN_INCLUDE_MISSING,
|
|
162
|
+
ErrorCodes.CRATES_NAME_MISMATCH,
|
|
163
|
+
ErrorCodes.CRATES_MISSING_BIN,
|
|
164
|
+
ErrorCodes.CRATES_FEATURE_NOT_DECLARED,
|
|
165
|
+
ErrorCodes.CRATES_WORKSPACE_VERSION_MISMATCH,
|
|
166
|
+
ErrorCodes.CRATES_FIRST_PUBLISH_TP_REJECTED,
|
|
167
|
+
ErrorCodes.CRATES_PACKAGE_TOO_LARGE,
|
|
168
|
+
ErrorCodes.REPO_URL_MISMATCH,
|
|
169
|
+
ErrorCodes.REPO_PRIVATE,
|
|
68
170
|
];
|
|
69
171
|
//# sourceMappingURL=error-codes.js.map
|
package/dist/error-codes.js.map
CHANGED
|
@@ -1 +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;IACnC;;;;;;kDAM8C;IAC9C,kBAAkB,EAAE,yBAAyB;IAC7C;;;;;0DAKsD;IACtD,sBAAsB,EAAE,6BAA6B;IACrD;;;;;;iCAM6B;IAC7B,uBAAuB,EAAE,8BAA8B;IACvD;;;;;;;;qDAQiD;IACjD,mBAAmB,EAAE,0BAA0B;
|
|
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;IACnC;;;;;;kDAM8C;IAC9C,kBAAkB,EAAE,yBAAyB;IAC7C;;;;;0DAKsD;IACtD,sBAAsB,EAAE,6BAA6B;IACrD;;;;;;;2CAOuC;IACvC,iBAAiB,EAAE,wBAAwB;IAC3C;;;;;;iCAM6B;IAC7B,uBAAuB,EAAE,8BAA8B;IACvD;;;;;;;;qDAQiD;IACjD,mBAAmB,EAAE,0BAA0B;IAC/C;;;;;yBAKqB;IACrB,kBAAkB,EAAE,yBAAyB;IAC7C;;;;gBAIY;IACZ,2BAA2B,EAAE,kCAAkC;IAC/D;;;uDAGmD;IACnD,+BAA+B,EAAE,sCAAsC;IACvE;;;;kEAI8D;IAC9D,4BAA4B,EAAE,mCAAmC;IACjE;;;;uEAImE;IACnE,oBAAoB,EAAE,2BAA2B;IACjD;;;;uBAImB;IACnB,kBAAkB,EAAE,yBAAyB;IAC7C;;;;2BAIuB;IACvB,2BAA2B,EAAE,kCAAkC;IAC/D;;;qEAGiE;IACjE,iCAAiC,EAAE,wCAAwC;IAC3E;;;;;;kEAM8D;IAC9D,gCAAgC,EAAE,uCAAuC;IACzE;;;;;;;8BAO0B;IAC1B,wBAAwB,EAAE,+BAA+B;IACzD;;;;;;;gDAO4C;IAC5C,iBAAiB,EAAE,wBAAwB;IAC3C;;;;;yCAKqC;IACrC,YAAY,EAAE,mBAAmB;CACzB,CAAC;AAIX;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAyB;IACnD,UAAU,CAAC,aAAa;IACxB,UAAU,CAAC,kBAAkB;IAC7B,UAAU,CAAC,sBAAsB;IACjC,UAAU,CAAC,iBAAiB;IAC5B,UAAU,CAAC,uBAAuB;IAClC,UAAU,CAAC,mBAAmB;IAC9B,UAAU,CAAC,kBAAkB;IAC7B,UAAU,CAAC,2BAA2B;IACtC,UAAU,CAAC,+BAA+B;IAC1C,UAAU,CAAC,4BAA4B;IACvC,UAAU,CAAC,oBAAoB;IAC/B,UAAU,CAAC,kBAAkB;IAC7B,UAAU,CAAC,2BAA2B;IACtC,UAAU,CAAC,iCAAiC;IAC5C,UAAU,CAAC,gCAAgC;IAC3C,UAAU,CAAC,wBAAwB;IACnC,UAAU,CAAC,iBAAiB;IAC5B,UAAU,CAAC,YAAY;CACxB,CAAC"}
|
package/dist/git.d.ts
CHANGED
|
@@ -21,6 +21,11 @@ export declare function diffNames(from: string, to: string, opts?: GitOptions):
|
|
|
21
21
|
export declare function tagList(glob: string, opts?: GitOptions): string[];
|
|
22
22
|
export declare function createTag(name: string, sha: string, opts?: TagOptions): void;
|
|
23
23
|
export declare function pushTag(name: string, opts?: GitOptions): void;
|
|
24
|
+
/**
|
|
25
|
+
* The commit a tag points at. `rev-list -n 1` dereferences an annotated
|
|
26
|
+
* tag down to the commit it ultimately references.
|
|
27
|
+
*/
|
|
28
|
+
export declare function tagCommit(name: string, opts?: GitOptions): string;
|
|
24
29
|
/**
|
|
25
30
|
* Find the highest-semver tag for a given package.
|
|
26
31
|
*
|
package/dist/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,UAAW,SAAQ,UAAU;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgDD,wBAAgB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,MAAM,CAExD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CAGrE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAM1E;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,UAAe,GACpB,MAAM,EAAE,CAIV;AAID,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAIrE;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,UAAe,GACpB,IAAI,CAGN;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,IAAI,CAEjE;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CACrB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,UAAe,GACpB,MAAM,GAAG,IAAI,CAmBf"}
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,UAAW,SAAQ,UAAU;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgDD,wBAAgB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,MAAM,CAExD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CAGrE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAM1E;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,UAAe,GACpB,MAAM,EAAE,CAIV;AAID,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAIrE;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,UAAe,GACpB,IAAI,CAGN;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,IAAI,CAEjE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CAErE;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CACrB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,UAAe,GACpB,MAAM,GAAG,IAAI,CAmBf"}
|
package/dist/git.js
CHANGED
|
@@ -62,21 +62,24 @@ export function commitParents(sha, opts = {}) {
|
|
|
62
62
|
// %P = parent SHAs, space-separated. Merge commits have ≥2;
|
|
63
63
|
// plain commits have 1; root commits have 0.
|
|
64
64
|
const out = run(['log', '-1', '--format=%P', sha], opts);
|
|
65
|
-
if (out === '')
|
|
65
|
+
if (out === '') {
|
|
66
66
|
return [];
|
|
67
|
+
}
|
|
67
68
|
return out.split(' ').filter((s) => s.length > 0);
|
|
68
69
|
}
|
|
69
70
|
export function diffNames(from, to, opts = {}) {
|
|
70
71
|
const out = run(['diff', '--name-only', `${from}..${to}`], opts);
|
|
71
|
-
if (out === '')
|
|
72
|
+
if (out === '') {
|
|
72
73
|
return [];
|
|
74
|
+
}
|
|
73
75
|
return out.split('\n').filter((l) => l.length > 0);
|
|
74
76
|
}
|
|
75
77
|
/* ------------------------------ tags ------------------------------ */
|
|
76
78
|
export function tagList(glob, opts = {}) {
|
|
77
79
|
const out = run(['tag', '-l', glob], opts);
|
|
78
|
-
if (out === '')
|
|
80
|
+
if (out === '') {
|
|
79
81
|
return [];
|
|
82
|
+
}
|
|
80
83
|
return out.split('\n').filter((l) => l.length > 0);
|
|
81
84
|
}
|
|
82
85
|
export function createTag(name, sha, opts = {}) {
|
|
@@ -86,6 +89,13 @@ export function createTag(name, sha, opts = {}) {
|
|
|
86
89
|
export function pushTag(name, opts = {}) {
|
|
87
90
|
run(['push', 'origin', name], opts);
|
|
88
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* The commit a tag points at. `rev-list -n 1` dereferences an annotated
|
|
94
|
+
* tag down to the commit it ultimately references.
|
|
95
|
+
*/
|
|
96
|
+
export function tagCommit(name, opts = {}) {
|
|
97
|
+
return run(['rev-list', '-n', '1', name], opts);
|
|
98
|
+
}
|
|
89
99
|
/* -------------------------- last-tag resolver -------------------------- */
|
|
90
100
|
/**
|
|
91
101
|
* Find the highest-semver tag for a given package.
|
|
@@ -103,8 +113,9 @@ export function lastTag(packageName, tagFormat, opts = {}) {
|
|
|
103
113
|
let best = null;
|
|
104
114
|
for (const tag of candidates) {
|
|
105
115
|
const versionPart = parseTagVersion(tagFormat, packageName, tag);
|
|
106
|
-
if (versionPart === null)
|
|
116
|
+
if (versionPart === null) {
|
|
107
117
|
continue;
|
|
118
|
+
}
|
|
108
119
|
let parsed;
|
|
109
120
|
try {
|
|
110
121
|
parsed = parseSemver(versionPart);
|
|
@@ -121,10 +132,12 @@ export function lastTag(packageName, tagFormat, opts = {}) {
|
|
|
121
132
|
}
|
|
122
133
|
function greater(a, b) {
|
|
123
134
|
/* v8 ignore next 2 -- comparison branches not all reachable from current test data */
|
|
124
|
-
if (a.major !== b.major)
|
|
135
|
+
if (a.major !== b.major) {
|
|
125
136
|
return a.major > b.major;
|
|
126
|
-
|
|
137
|
+
}
|
|
138
|
+
if (a.minor !== b.minor) {
|
|
127
139
|
return a.minor > b.minor;
|
|
140
|
+
}
|
|
128
141
|
return a.patch > b.patch;
|
|
129
142
|
}
|
|
130
143
|
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC;AAUxD,wEAAwE;AAExE,SAAS,GAAG,CAAC,IAAc,EAAE,OAAmB,EAAE;IAChD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC,OAAO,EAAE,CAAC;IACf,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,kEAAkE;QAClE,gEAAgE;QAChE,gDAAgD;QAChD,iFAAiF;QACjF,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5E,MAAM,IAAI,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9D,+DAA+D;QAC/D,8DAA8D;QAC9D,+DAA+D;QAC/D,yBAAyB;QACzB,MAAM,aAAa,GACjB,MAAM,KAAK,SAAS;YACpB,gEAAgE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChF,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb;gBACE,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,qCAAqC;gBACzD,oEAAoE;gBACpE,yDAAyD;gBACzD,YAAY;gBACZ,2DAA2D;gBAC3D,8FAA8F;gBAC9F,8EAA8E;gBAC9E,EAAE;gBACF,2BAA2B,MAAM,EAAE;aACpC,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtE,oBAAoB;IACtB,CAAC;AACH,CAAC;AAED,yEAAyE;AAEzE,MAAM,UAAU,UAAU,CAAC,OAAmB,EAAE;IAC9C,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,OAAmB,EAAE;IAC3D,sDAAsD;IACtD,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAAmB,EAAE;IAC9D,4DAA4D;IAC5D,6CAA6C;IAC7C,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,GAAG,KAAK,EAAE;
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC;AAUxD,wEAAwE;AAExE,SAAS,GAAG,CAAC,IAAc,EAAE,OAAmB,EAAE;IAChD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC,OAAO,EAAE,CAAC;IACf,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,kEAAkE;QAClE,gEAAgE;QAChE,gDAAgD;QAChD,iFAAiF;QACjF,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5E,MAAM,IAAI,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9D,+DAA+D;QAC/D,8DAA8D;QAC9D,+DAA+D;QAC/D,yBAAyB;QACzB,MAAM,aAAa,GACjB,MAAM,KAAK,SAAS;YACpB,gEAAgE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChF,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb;gBACE,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,qCAAqC;gBACzD,oEAAoE;gBACpE,yDAAyD;gBACzD,YAAY;gBACZ,2DAA2D;gBAC3D,8FAA8F;gBAC9F,8EAA8E;gBAC9E,EAAE;gBACF,2BAA2B,MAAM,EAAE;aACpC,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtE,oBAAoB;IACtB,CAAC;AACH,CAAC;AAED,yEAAyE;AAEzE,MAAM,UAAU,UAAU,CAAC,OAAmB,EAAE;IAC9C,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,OAAmB,EAAE;IAC3D,sDAAsD;IACtD,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAAmB,EAAE;IAC9D,4DAA4D;IAC5D,6CAA6C;IAC7C,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QAAA,OAAO,EAAE,CAAC;IAAA,CAAC;IAC5B,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,EAAU,EACV,OAAmB,EAAE;IAErB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IACjE,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QAAA,OAAO,EAAE,CAAC;IAAA,CAAC;IAC5B,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,wEAAwE;AAExE,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,OAAmB,EAAE;IACzD,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3C,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QAAA,OAAO,EAAE,CAAC;IAAA,CAAC;IAC5B,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,GAAW,EACX,OAAmB,EAAE;IAErB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IACrC,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,OAAmB,EAAE;IACzD,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAmB,EAAE;IAC3D,OAAO,GAAG,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC;AAED,6EAA6E;AAE7E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,OAAO,CACrB,WAAmB,EACnB,SAAiB,EACjB,OAAmB,EAAE;IAErB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;IAElE,IAAI,IAAI,GAA4C,IAAI,CAAC;IACzD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QACjE,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YAAA,SAAS;QAAA,CAAC;QACrC,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;YAClC,6EAA6E;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,IAAI,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC;AAC3B,CAAC;AAED,SAAS,OAAO,CAAC,CAAS,EAAE,CAAS;IACnC,sFAAsF;IACtF,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;QAAA,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAAA,CAAC;IACpD,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;QAAA,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAAA,CAAC;IACpD,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;AAC3B,CAAC"}
|
package/dist/glob.d.ts
CHANGED
|
@@ -12,4 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export declare function matchesGlob(pattern: string, path: string): boolean;
|
|
14
14
|
export declare function matchesAny(patterns: readonly string[], path: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Expand a relative path glob against the filesystem, returning the
|
|
17
|
+
* directories it matches. Mirrors how cargo resolves `[workspace].members`
|
|
18
|
+
* entries: a literal entry (no glob metacharacter) resolves to a single
|
|
19
|
+
* path returned whether or not it exists — callers handle a missing
|
|
20
|
+
* directory — while a glob entry is matched one path segment at a time
|
|
21
|
+
* against the real directory tree, so only existing directories come back.
|
|
22
|
+
*/
|
|
23
|
+
export declare function expandDirGlob(baseDir: string, pattern: string): string[];
|
|
15
24
|
//# sourceMappingURL=glob.d.ts.map
|
package/dist/glob.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7E;AAID;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBxE"}
|
package/dist/glob.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Issue #10.
|
|
12
12
|
*/
|
|
13
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
14
|
+
import { join } from 'node:path';
|
|
13
15
|
import { minimatch } from 'minimatch';
|
|
14
16
|
const OPTS = {
|
|
15
17
|
dot: true,
|
|
@@ -21,9 +23,35 @@ export function matchesGlob(pattern, path) {
|
|
|
21
23
|
}
|
|
22
24
|
export function matchesAny(patterns, path) {
|
|
23
25
|
for (const p of patterns) {
|
|
24
|
-
if (matchesGlob(p, path))
|
|
26
|
+
if (matchesGlob(p, path)) {
|
|
25
27
|
return true;
|
|
28
|
+
}
|
|
26
29
|
}
|
|
27
30
|
return false;
|
|
28
31
|
}
|
|
32
|
+
const GLOB_META = /[*?[\]{}]/;
|
|
33
|
+
/**
|
|
34
|
+
* Expand a relative path glob against the filesystem, returning the
|
|
35
|
+
* directories it matches. Mirrors how cargo resolves `[workspace].members`
|
|
36
|
+
* entries: a literal entry (no glob metacharacter) resolves to a single
|
|
37
|
+
* path returned whether or not it exists — callers handle a missing
|
|
38
|
+
* directory — while a glob entry is matched one path segment at a time
|
|
39
|
+
* against the real directory tree, so only existing directories come back.
|
|
40
|
+
*/
|
|
41
|
+
export function expandDirGlob(baseDir, pattern) {
|
|
42
|
+
const segments = pattern.split('/').filter((s) => s.length > 0);
|
|
43
|
+
let dirs = [baseDir];
|
|
44
|
+
for (const segment of segments) {
|
|
45
|
+
if (!GLOB_META.test(segment)) {
|
|
46
|
+
dirs = dirs.map((d) => join(d, segment));
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
dirs = dirs
|
|
50
|
+
.filter((d) => existsSync(d))
|
|
51
|
+
.flatMap((d) => readdirSync(d, { withFileTypes: true })
|
|
52
|
+
.filter((e) => e.isDirectory() && matchesGlob(segment, e.name))
|
|
53
|
+
.map((e) => join(d, e.name)));
|
|
54
|
+
}
|
|
55
|
+
return dirs;
|
|
56
|
+
}
|
|
29
57
|
//# sourceMappingURL=glob.js.map
|
package/dist/glob.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,IAAI,GAAG;IACX,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,IAAI,EAAE,oDAAoD;CAC7D,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,OAAO,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAA2B,EAAE,IAAY;IAClE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,IAAI,GAAG;IACX,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,IAAI,EAAE,oDAAoD;CAC7D,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,OAAO,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAA2B,EAAE,IAAY;IAClE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;YAAA,OAAO,IAAI,CAAC;QAAA,CAAC;IAC1C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,SAAS,GAAG,WAAW,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,OAAe;IAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChE,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,IAAI,GAAG,IAAI;aACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;aAC5B,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACb,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;aACpC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;aAC9D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAC/B,CAAC;IACN,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -27,6 +27,21 @@
|
|
|
27
27
|
* up (same for classic token fallback).
|
|
28
28
|
*/
|
|
29
29
|
import type { Handler } from '../types.js';
|
|
30
|
+
/**
|
|
31
|
+
* Match cargo's stderr shape when crates.io rejects the TP exchange
|
|
32
|
+
* because the crate has never been published. The fixture at
|
|
33
|
+
* `test/integration/fixtures/registry-responses/crates-io/publish-first-publish-tp-rejected.txt`
|
|
34
|
+
* captures the canonical shape; the catalog at
|
|
35
|
+
* `notes/upstream-behaviors.md` is the source of truth for the contract.
|
|
36
|
+
*
|
|
37
|
+
* Two anchors keep false positives out: a 404-status line and either
|
|
38
|
+
* the registry's "crate `<name>` does not exist" prose or the
|
|
39
|
+
* "trusted publish" mention. An unrelated 404 in some other cargo
|
|
40
|
+
* subcommand (e.g. a missing index file) won't carry the prose; an
|
|
41
|
+
* unrelated `does not exist` (e.g. a missing dependency) won't carry
|
|
42
|
+
* the 404 status.
|
|
43
|
+
*/
|
|
44
|
+
export declare function looksLikeFirstPublishTpRejection(stderr: string | undefined): boolean;
|
|
30
45
|
/**
|
|
31
46
|
* Rewrites the first `version = "..."` assignment inside `[package]`.
|
|
32
47
|
* Preserves everything else in the file byte-for-byte. Throws if the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crates.d.ts","sourceRoot":"","sources":["../../src/handlers/crates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,OAAO,KAAK,EAAO,OAAO,EAAiB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"crates.d.ts","sourceRoot":"","sources":["../../src/handlers/crates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,OAAO,KAAK,EAAO,OAAO,EAAiB,MAAM,aAAa,CAAC;AAmO/D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAOpF;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAa3E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,EACtB,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,GACtC,MAAM,EAAE,GAAG,IAAI,CA6FjB;AA8BD,eAAO,MAAM,MAAM,EAAE,OAMpB,CAAC"}
|
package/dist/handlers/crates.js
CHANGED
|
@@ -30,6 +30,7 @@ import { execFileSync } from 'node:child_process';
|
|
|
30
30
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
31
31
|
import { join, relative } from 'node:path';
|
|
32
32
|
import { TransientError } from '../types.js';
|
|
33
|
+
import { ErrorCodes } from '../error-codes.js';
|
|
33
34
|
import { buildSubprocessEnv, nonEmpty } from '../env.js';
|
|
34
35
|
import { USER_AGENT } from '../version.js';
|
|
35
36
|
const REGISTRY = 'https://crates.io';
|
|
@@ -40,10 +41,12 @@ async function isPublishedImpl(pkg, version, _ctx) {
|
|
|
40
41
|
method: 'GET',
|
|
41
42
|
headers: { 'user-agent': USER_AGENT },
|
|
42
43
|
});
|
|
43
|
-
if (res.status === 200)
|
|
44
|
+
if (res.status === 200) {
|
|
44
45
|
return true;
|
|
45
|
-
|
|
46
|
+
}
|
|
47
|
+
if (res.status === 404) {
|
|
46
48
|
return false;
|
|
49
|
+
}
|
|
47
50
|
if (res.status >= 500) {
|
|
48
51
|
throw new TransientError(`crates.io GET ${url} returned ${res.status}`);
|
|
49
52
|
}
|
|
@@ -70,8 +73,9 @@ function writeVersionImpl(pkg, version, _ctx) {
|
|
|
70
73
|
catch (err) {
|
|
71
74
|
return Promise.reject(err instanceof Error ? err : new Error(String(err)));
|
|
72
75
|
}
|
|
73
|
-
if (updated === original)
|
|
76
|
+
if (updated === original) {
|
|
74
77
|
return Promise.resolve([]);
|
|
78
|
+
}
|
|
75
79
|
writeFileSync(cargoPath, updated, 'utf8');
|
|
76
80
|
return Promise.resolve([cargoPath]);
|
|
77
81
|
}
|
|
@@ -175,6 +179,26 @@ async function publishImpl(pkg, version, ctx) {
|
|
|
175
179
|
url: `${fallbackUrl.replace(/\/$/, '')}/api/v1/crates/${crateNameFor(pkg)}/${version}`,
|
|
176
180
|
};
|
|
177
181
|
}
|
|
182
|
+
// crates.io's Trusted Publishing binds to an already-published
|
|
183
|
+
// crate: the OIDC mint succeeds and the exchanged token reaches
|
|
184
|
+
// cargo, but the registry returns a 404 ("crate `<name>` does not
|
|
185
|
+
// exist or you do not have permission to publish to it") on the
|
|
186
|
+
// very first publish. The naive "auth failed?" interpretation
|
|
187
|
+
// sends consumers down a credentials rabbit-hole when the real
|
|
188
|
+
// fix is one bootstrap publish with a classic CARGO_REGISTRY_TOKEN.
|
|
189
|
+
// Detect this exact shape and surface the bootstrap hint inline.
|
|
190
|
+
// Suppressed under the e2e seam (primary override in effect) — the
|
|
191
|
+
// alt-registry is configured `--no-auth` and doesn't model TP, so
|
|
192
|
+
// a 404 there is a different bug. #284.
|
|
193
|
+
if (primaryOverride === undefined &&
|
|
194
|
+
looksLikeFirstPublishTpRejection(stderr)) {
|
|
195
|
+
throw new Error([
|
|
196
|
+
`[${ErrorCodes.CRATES_FIRST_PUBLISH_TP_REJECTED}] cargo publish: crates.io rejected publishing "${crateNameFor(pkg)}" because the crate has never been published.`,
|
|
197
|
+
'crates.io Trusted Publishing binds to an already-published crate, so the very first release of a new crate name cannot use the TP path.',
|
|
198
|
+
'Bootstrap by setting CARGO_REGISTRY_TOKEN (a classic crates.io API token) for the first publish; every release after that can use trusted publishing.',
|
|
199
|
+
stderr ? `\n--- cargo stderr ---\n${stderr}` : '',
|
|
200
|
+
].filter((s) => s.length > 0).join('\n'), { cause: err });
|
|
201
|
+
}
|
|
178
202
|
const base = err instanceof Error ? err.message : String(err);
|
|
179
203
|
throw new Error(`cargo publish failed${stderr ? `:\n${stderr}` : `: ${base}`}`, { cause: err });
|
|
180
204
|
}
|
|
@@ -195,10 +219,35 @@ async function publishImpl(pkg, version, ctx) {
|
|
|
195
219
|
* wouldn't trigger the fallback.
|
|
196
220
|
*/
|
|
197
221
|
function isRateLimited(stderr) {
|
|
198
|
-
if (!stderr)
|
|
222
|
+
if (!stderr) {
|
|
199
223
|
return false;
|
|
224
|
+
}
|
|
200
225
|
return /status\s+429\b/i.test(stderr) || /429\s+Too\s+Many\s+Requests/i.test(stderr);
|
|
201
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Match cargo's stderr shape when crates.io rejects the TP exchange
|
|
229
|
+
* because the crate has never been published. The fixture at
|
|
230
|
+
* `test/integration/fixtures/registry-responses/crates-io/publish-first-publish-tp-rejected.txt`
|
|
231
|
+
* captures the canonical shape; the catalog at
|
|
232
|
+
* `notes/upstream-behaviors.md` is the source of truth for the contract.
|
|
233
|
+
*
|
|
234
|
+
* Two anchors keep false positives out: a 404-status line and either
|
|
235
|
+
* the registry's "crate `<name>` does not exist" prose or the
|
|
236
|
+
* "trusted publish" mention. An unrelated 404 in some other cargo
|
|
237
|
+
* subcommand (e.g. a missing index file) won't carry the prose; an
|
|
238
|
+
* unrelated `does not exist` (e.g. a missing dependency) won't carry
|
|
239
|
+
* the 404 status.
|
|
240
|
+
*/
|
|
241
|
+
export function looksLikeFirstPublishTpRejection(stderr) {
|
|
242
|
+
if (!stderr) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
if (!/status\s+404\b/i.test(stderr)) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
return (/crate\s+`[^`]+`\s+does\s+not\s+exist/i.test(stderr) ||
|
|
249
|
+
/trusted\s+publish/i.test(stderr));
|
|
250
|
+
}
|
|
202
251
|
/* ------------------------------ internals ------------------------------ */
|
|
203
252
|
/** The published name. Falls back to the pilot package name if no
|
|
204
253
|
* explicit `crate` field is set. */
|
|
@@ -220,8 +269,9 @@ export function replaceCargoVersion(source, version) {
|
|
|
220
269
|
throw new Error('Cargo.toml: no [package].version field found');
|
|
221
270
|
}
|
|
222
271
|
const [, pre, prefix, old, suffix] = m;
|
|
223
|
-
if (old === version)
|
|
272
|
+
if (old === version) {
|
|
224
273
|
return source;
|
|
274
|
+
}
|
|
225
275
|
const start = m.index + pre.length;
|
|
226
276
|
const end = start + prefix.length + old.length + suffix.length;
|
|
227
277
|
return source.slice(0, start) + prefix + version + suffix + source.slice(end);
|
|
@@ -241,8 +291,9 @@ export function scanDirtyOutsideManifest(cwd, pkgPath, artifactsRoot, siblingPac
|
|
|
241
291
|
encoding: 'utf8',
|
|
242
292
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
243
293
|
});
|
|
244
|
-
if (!topOut.trim())
|
|
294
|
+
if (!topOut.trim()) {
|
|
245
295
|
return null;
|
|
296
|
+
}
|
|
246
297
|
}
|
|
247
298
|
catch {
|
|
248
299
|
return null;
|
|
@@ -294,14 +345,16 @@ export function scanDirtyOutsideManifest(cwd, pkgPath, artifactsRoot, siblingPac
|
|
|
294
345
|
const siblingRels = [];
|
|
295
346
|
for (const p of siblingPackagePaths ?? []) {
|
|
296
347
|
const r = relative(cwd, p);
|
|
297
|
-
if (r === '' || r.startsWith('..'))
|
|
348
|
+
if (r === '' || r.startsWith('..')) {
|
|
298
349
|
continue;
|
|
350
|
+
}
|
|
299
351
|
siblingRels.push(r.replace(/\\/g, '/'));
|
|
300
352
|
}
|
|
301
353
|
const unexpected = [];
|
|
302
354
|
for (const raw of porcelain.split('\n')) {
|
|
303
|
-
if (raw.length < 4)
|
|
355
|
+
if (raw.length < 4) {
|
|
304
356
|
continue;
|
|
357
|
+
}
|
|
305
358
|
// Porcelain v1: "XY path" or "XY old -> new" for renames. Index 3+
|
|
306
359
|
// is the path; strip quoting if git applied any.
|
|
307
360
|
const rest = raw.slice(3);
|
|
@@ -309,8 +362,9 @@ export function scanDirtyOutsideManifest(cwd, pkgPath, artifactsRoot, siblingPac
|
|
|
309
362
|
const path = rest.includes(' -> ') ? rest.split(' -> ').pop() : rest;
|
|
310
363
|
/* v8 ignore next -- quoted-path rendering not exercised by current tests */
|
|
311
364
|
const normalized = path.startsWith('"') && path.endsWith('"') ? path.slice(1, -1) : path;
|
|
312
|
-
if (normalized === managedRel)
|
|
365
|
+
if (normalized === managedRel) {
|
|
313
366
|
continue;
|
|
367
|
+
}
|
|
314
368
|
if (artifactsRel !== '' &&
|
|
315
369
|
(normalized === artifactsRel ||
|
|
316
370
|
normalized === `${artifactsRel}/` ||
|
|
@@ -331,9 +385,30 @@ function relativeOrSelf(base, target) {
|
|
|
331
385
|
/* v8 ignore next -- relative() only returns '' when base === target */
|
|
332
386
|
return r === '' ? target : r;
|
|
333
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Latest published version of the crate, or null when it has never been
|
|
390
|
+
* published (404). GET /api/v1/crates/{name} → `crate.newest_version`.
|
|
391
|
+
* Reuses `crateNameFor` so this read resolves the crates.io name exactly
|
|
392
|
+
* as `isPublished` / `publish` do. Any non-200/404 is surfaced as a
|
|
393
|
+
* TransientError; the read-only caller renders that as "unreachable".
|
|
394
|
+
*/
|
|
395
|
+
async function latestVersionImpl(pkg, _ctx) {
|
|
396
|
+
const crateName = crateNameFor(pkg);
|
|
397
|
+
const url = `${REGISTRY}/api/v1/crates/${encodeURIComponent(crateName)}`;
|
|
398
|
+
const res = await fetch(url, { method: 'GET', headers: { 'user-agent': USER_AGENT } });
|
|
399
|
+
if (res.status === 200) {
|
|
400
|
+
const body = (await res.json());
|
|
401
|
+
return body.crate?.newest_version ?? null;
|
|
402
|
+
}
|
|
403
|
+
if (res.status === 404) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
throw new TransientError(`crates.io GET ${url} returned ${res.status}`);
|
|
407
|
+
}
|
|
334
408
|
export const crates = {
|
|
335
409
|
kind: 'crates',
|
|
336
410
|
isPublished: isPublishedImpl,
|
|
411
|
+
latestVersion: latestVersionImpl,
|
|
337
412
|
writeVersion: writeVersionImpl,
|
|
338
413
|
publish: publishImpl,
|
|
339
414
|
};
|