putitoutthere 0.2.7 → 0.2.9
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 +80 -0
- package/action.yml +15 -5
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +29 -4
- package/dist/action.js.map +1 -1
- package/dist/cli.d.ts +11 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +36 -7
- package/dist/cli.js.map +1 -1
- package/dist/write-version.d.ts +48 -0
- package/dist/write-version.d.ts.map +1 -0
- package/dist/write-version.js +134 -0
- package/dist/write-version.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,8 @@ are prefixed `**BREAKING**` and link to the matching section in
|
|
|
30
30
|
|
|
31
31
|
### Fixed
|
|
32
32
|
|
|
33
|
+
- **pypi/maturin wheels now ship at the planned version instead of the literal in `pyproject.toml`.** The reusable workflow's build matrix (`_matrix.yml`) now bumps `[project].version` in `pyproject.toml` (or `[package].version` in `Cargo.toml` when `pyproject.toml` declares `dynamic = ["version"]`) to `matrix.version` before each `PyO3/maturin-action@v1` invocation. Maturin reads its version source from disk at build time and honors no env override — `SETUPTOOLS_SCM_PRETEND_VERSION` is a setuptools-scm / hatch-vcs feature, not a maturin one. Without the bump, wheels left the build runner at whatever literal happened to be in the consumer's manifest — diverging from the planned version, tripping PyPI's "file already exists" rejection at upload, and turning otherwise-clean release runs red even when crates and npm shipped correctly. The bump is implemented as a new internal `putitoutthere write-version` CLI subcommand and exposed through the JS action's existing surface (new `version:` input on `action.yml`); the e2e fixture harness now verifies wheel `METADATA: Version:` matches `matrix.version` post-build. The CLI subcommand and action input are internal — consumers compose with the reusable workflow, not directly with the CLI. Hit in the wild on `dirsql`'s 0.2.8 release (issue #276). See [MIGRATIONS.md](./MIGRATIONS.md#pypi-maturin-version-bump-at-build).
|
|
34
|
+
|
|
33
35
|
- **npm publish no longer fails red when npm CLI retries a successful PUT.** When the registry acks a publish but the response comes back flaky to the client (timeout / 502 / connection reset), the npm CLI retries with the same payload. The retry lands on a registry that already has the new version and exits `E403 "cannot publish over the previously published versions: <ver>"`. Both the platform-package handler (`src/handlers/npm-platform.ts:npmPublish`) and the main publish path (`src/handlers/npm.ts:publishImpl`) now detect that exact stderr shape and treat it as success — the package is already on the registry at the requested version. Hit in the wild on PR #257's polyglot-everything multi-mode publish (10 platform packages × ~1 in 10 chance per request meant the race was nearly guaranteed).
|
|
34
36
|
|
|
35
37
|
- **Crates publish no longer refuses on workflow-managed install state in sibling packages.** Before, the engine's pre-publish dirty-workspace check (`scanDirtyOutsideManifest`) flagged anything dirty outside the package's `Cargo.toml`. For polyglot consumers (rust + js in one repo), the reusable workflow's `Build npm packages` step (#256) creates `node_modules/`, `package-lock.json`, and `dist/` inside each npm package's path before cargo publish runs — these are workflow scratch, not stray edits, and cargo can't pack them anyway (it only packs files inside the crate's own dir). The check now whitelists every other configured package's path, similar to how it already whitelists `artifacts/`. Stray edits elsewhere in the repo (a `README.md` change, etc.) still fail the check. Hit in the wild on the polyglot-everything e2e fixture; would also have hit any consumer with the same shape.
|
package/MIGRATIONS.md
CHANGED
|
@@ -21,6 +21,86 @@ Each section covers five things, in order:
|
|
|
21
21
|
|
|
22
22
|
## Unreleased
|
|
23
23
|
|
|
24
|
+
### pypi/maturin version bump at build
|
|
25
|
+
|
|
26
|
+
**Summary.** `pypi` packages built with `build = "maturin"` now ship
|
|
27
|
+
wheels at the planned version, not at whatever literal happened to be
|
|
28
|
+
in `pyproject.toml` on the build runner. The reusable workflow's
|
|
29
|
+
build matrix (`_matrix.yml`) bumps the version source on disk to
|
|
30
|
+
`matrix.version` immediately before each `PyO3/maturin-action@v1`
|
|
31
|
+
step. Two version-source shapes are supported:
|
|
32
|
+
|
|
33
|
+
- Static literal: `[project].version = "0.1.0"` in `pyproject.toml`
|
|
34
|
+
is rewritten in place. This is maturin's default project shape and
|
|
35
|
+
the case that was previously broken for every consumer.
|
|
36
|
+
- Dynamic: `pyproject.toml` declaring `[project].dynamic = ["version"]`
|
|
37
|
+
with the version sourced from a sibling `Cargo.toml`'s
|
|
38
|
+
`[package].version` — that's where the bump lands instead.
|
|
39
|
+
|
|
40
|
+
Why it matters: maturin reads its version source from disk at build
|
|
41
|
+
time and honors no env override. Other build paths bumped elsewhere
|
|
42
|
+
in the contract — crates and npm at publish (`writeVersion` rewrites
|
|
43
|
+
the manifest before `cargo publish` / `npm publish` reads it),
|
|
44
|
+
setuptools-scm / hatch-vcs through `SETUPTOOLS_SCM_PRETEND_VERSION`
|
|
45
|
+
in the build step. Maturin had no equivalent, so wheels left the
|
|
46
|
+
build runner pre-versioned at the consumer's stale literal. PyPI
|
|
47
|
+
rejected the upload with `400 File already exists` whenever that
|
|
48
|
+
literal had been previously registered, even when crates and npm
|
|
49
|
+
shipped correctly. Hit in the wild on `dirsql`'s 0.2.8 release;
|
|
50
|
+
issue #276.
|
|
51
|
+
|
|
52
|
+
**Required changes.** None. The bump is internal to the reusable
|
|
53
|
+
workflow. Consumers pinning `release.yml@v0` and `build.yml@v0`
|
|
54
|
+
inherit the fix on the next workflow run with no `release.yml` edits
|
|
55
|
+
and no `putitoutthere.toml` edits. The fix applies equally to the
|
|
56
|
+
static-literal and dynamic-version shapes; consumers don't need to
|
|
57
|
+
restructure their pyproject to opt in.
|
|
58
|
+
|
|
59
|
+
The CLI gains a new internal subcommand,
|
|
60
|
+
`putitoutthere write-version --path <pkg-dir> --version <v>`, that
|
|
61
|
+
implements the bump dispatch. `action.yml` gains a new optional
|
|
62
|
+
`version:` input that the reusable workflow forwards. Both surfaces
|
|
63
|
+
are internal seams powering `_matrix.yml`; consumers compose with
|
|
64
|
+
the reusable workflow, not directly with the CLI or the JS action
|
|
65
|
+
(see [`notes/design-commitments.md`](./notes/design-commitments.md)
|
|
66
|
+
non-goal #7 and #10).
|
|
67
|
+
|
|
68
|
+
**Deprecations removed.** None.
|
|
69
|
+
|
|
70
|
+
**Behavior changes without code changes.** A maturin build run
|
|
71
|
+
through the reusable workflow now mutates the build runner's
|
|
72
|
+
`pyproject.toml` (or `Cargo.toml` for dynamic-version projects) in
|
|
73
|
+
place, bumping the version literal to `matrix.version`. The mutation
|
|
74
|
+
lives only on the build runner — the consumer's source tree is
|
|
75
|
+
untouched. Anyone fingerprinting on the on-disk manifest version
|
|
76
|
+
during a build (e.g. a custom shell step running between
|
|
77
|
+
`uses: thekevinscott/putitoutthere/.github/workflows/release.yml@v0`
|
|
78
|
+
and a follow-up step that reads the manifest) will now see the
|
|
79
|
+
planned version where they previously saw the consumer's stale
|
|
80
|
+
literal. Custom build steps that grep on a specific literal version
|
|
81
|
+
need to grep on `matrix.version` instead.
|
|
82
|
+
|
|
83
|
+
`pyproject.toml` projects whose `[project]` table is malformed
|
|
84
|
+
(neither a static `version = "..."` line nor `dynamic = ["version"]`)
|
|
85
|
+
now fail the build matrix with a clear error. Previously the same
|
|
86
|
+
shape produced wheels at whatever fallback the build backend chose,
|
|
87
|
+
which silently disagreed with the plan.
|
|
88
|
+
|
|
89
|
+
**Verification.** Cut a release on a maturin package whose
|
|
90
|
+
`pyproject.toml` carries a stale literal (e.g. `version = "0.1.0"`
|
|
91
|
+
when the planned version is `0.2.8`). The reusable workflow's
|
|
92
|
+
build matrix logs a `write-version: ... → 0.2.8` line before each
|
|
93
|
+
maturin invocation, and the produced wheel's `METADATA: Version:`
|
|
94
|
+
matches the planned version:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
unzip -p dist/*.whl '*.dist-info/METADATA' | grep '^Version:'
|
|
98
|
+
# Version: 0.2.8
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
PyPI accepts the upload — assuming the planned version itself isn't
|
|
102
|
+
a duplicate of a previously-registered file.
|
|
103
|
+
|
|
24
104
|
### New `build.yml` reusable workflow for PR-time build verification
|
|
25
105
|
|
|
26
106
|
**Summary.** A second consumer-facing reusable workflow,
|
package/action.yml
CHANGED
|
@@ -4,15 +4,25 @@ author: 'Kevin Scott'
|
|
|
4
4
|
|
|
5
5
|
inputs:
|
|
6
6
|
command:
|
|
7
|
-
description: 'Which CLI subcommand to run. Canonical values are `plan` and `
|
|
7
|
+
description: 'Which CLI subcommand to run. Canonical values are `plan`, `publish`, and `write-version`.'
|
|
8
8
|
required: false
|
|
9
9
|
default: 'plan'
|
|
10
10
|
working_directory:
|
|
11
11
|
description: >-
|
|
12
|
-
Path the CLI runs against
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
Path the CLI runs against. For `plan` / `publish`, forwarded as
|
|
13
|
+
`--cwd`. For `write-version` (#276), forwarded as `--path` —
|
|
14
|
+
the package directory whose pyproject.toml / Cargo.toml gets
|
|
15
|
+
bumped. Defaults to the runner working directory. Internal use;
|
|
16
|
+
the reusable workflow supplies this when invoked against a
|
|
17
|
+
non-root tree (e.g. e2e fixtures materialized into a subdir,
|
|
18
|
+
or a per-package `matrix.path`).
|
|
19
|
+
required: false
|
|
20
|
+
default: ''
|
|
21
|
+
version:
|
|
22
|
+
description: >-
|
|
23
|
+
Planned version string. Required when `command: write-version`
|
|
24
|
+
(#276); ignored otherwise. The reusable workflow forwards the
|
|
25
|
+
build matrix's `version` row from the planner.
|
|
16
26
|
required: false
|
|
17
27
|
default: ''
|
|
18
28
|
fail_on_error:
|
package/dist/action.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAmC1C"}
|
package/dist/action.js
CHANGED
|
@@ -7,18 +7,33 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Issue #24. Plan: §5.2, §5.3.
|
|
9
9
|
*/
|
|
10
|
+
import { pathToFileURL } from 'node:url';
|
|
10
11
|
import { run } from './cli.js';
|
|
11
12
|
export async function main() {
|
|
12
13
|
const command = process.env.INPUT_COMMAND ?? '';
|
|
13
14
|
const workingDirectory = process.env.INPUT_WORKING_DIRECTORY ?? '';
|
|
15
|
+
const versionInput = process.env.INPUT_VERSION ?? '';
|
|
14
16
|
const failOnError = (process.env.INPUT_FAIL_ON_ERROR ?? 'true').toLowerCase() !== 'false';
|
|
15
17
|
if (!command) {
|
|
16
18
|
process.stderr.write('putitoutthere action: missing required input `command`\n');
|
|
17
19
|
process.exit(1);
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
// #276: write-version uses a different argv shape — `--path` (the
|
|
22
|
+
// package dir, sourced from `working_directory`) and `--version`.
|
|
23
|
+
// No `--json`: the subcommand emits a single human line; there's
|
|
24
|
+
// no structured output to consume.
|
|
25
|
+
const argv = ['node', 'putitoutthere', command];
|
|
26
|
+
if (command === 'write-version') {
|
|
27
|
+
if (workingDirectory)
|
|
28
|
+
argv.push('--path', workingDirectory);
|
|
29
|
+
if (versionInput)
|
|
30
|
+
argv.push('--version', versionInput);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
argv.push('--json');
|
|
34
|
+
if (workingDirectory)
|
|
35
|
+
argv.push('--cwd', workingDirectory);
|
|
36
|
+
}
|
|
22
37
|
const code = await run(argv);
|
|
23
38
|
if (code !== 0 && !failOnError) {
|
|
24
39
|
process.stderr.write(`putitoutthere action: ignoring non-zero exit (fail_on_error=false): ${code}\n`);
|
|
@@ -26,8 +41,18 @@ export async function main() {
|
|
|
26
41
|
}
|
|
27
42
|
process.exit(code);
|
|
28
43
|
}
|
|
44
|
+
// Entry-point guard. Compare via `pathToFileURL` so the guard fires on
|
|
45
|
+
// Windows too: `import.meta.url` is a `file://` URL with forward
|
|
46
|
+
// slashes (`file:///D:/.../index.js`), while `process.argv[1]` is the
|
|
47
|
+
// native path (`D:\...\index.js`). Concatenating `file://` to the
|
|
48
|
+
// native path produces a string that never equals the URL on Windows,
|
|
49
|
+
// so the previous guard silently no-op'd the entire action when ncc-
|
|
50
|
+
// bundled and invoked via `uses: ./` on a windows-latest runner —
|
|
51
|
+
// `main()` was never called, the action exited 0 immediately, and
|
|
52
|
+
// `_matrix.yml`'s pre-maturin write-version step bumped nothing
|
|
53
|
+
// (PR #277, e2e Windows maturin failures). Issue #276.
|
|
29
54
|
/* v8 ignore next 3 -- entry-point guard; only reachable when invoked as a binary */
|
|
30
|
-
if (import.meta.url ===
|
|
55
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
31
56
|
void main();
|
|
32
57
|
}
|
|
33
58
|
//# sourceMappingURL=action.js.map
|
package/dist/action.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IAChD,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC;IACnE,MAAM,WAAW,GACf,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC;IAExE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0DAA0D,CAC3D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IAChD,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC;IACnE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IACrD,MAAM,WAAW,GACf,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC;IAExE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0DAA0D,CAC3D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kEAAkE;IAClE,kEAAkE;IAClE,iEAAiE;IACjE,mCAAmC;IACnC,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;QAChC,IAAI,gBAAgB;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QAC5D,IAAI,YAAY;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpB,IAAI,gBAAgB;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uEAAuE,IAAI,IAAI,CAChF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,uEAAuE;AACvE,iEAAiE;AACjE,sEAAsE;AACtE,kEAAkE;AAClE,sEAAsE;AACtE,qEAAqE;AACrE,kEAAkE;AAClE,kEAAkE;AAClE,gEAAgE;AAChE,uDAAuD;AACvD,oFAAoF;AACpF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/E,KAAK,IAAI,EAAE,CAAC;AACd,CAAC"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -5,15 +5,21 @@
|
|
|
5
5
|
* not promised externally. See `notes/design-commitments.md`.
|
|
6
6
|
*
|
|
7
7
|
* Commands:
|
|
8
|
-
* plan
|
|
9
|
-
* publish
|
|
10
|
-
* version
|
|
8
|
+
* plan — compute and emit the release plan
|
|
9
|
+
* publish — execute the plan against the registries
|
|
10
|
+
* write-version — bump a package's manifest to a planned version
|
|
11
|
+
* (pre-build hook for maturin; #276)
|
|
12
|
+
* version — print CLI version
|
|
11
13
|
*
|
|
12
14
|
* Global flags:
|
|
13
15
|
* --cwd <path> working directory (default: process.cwd())
|
|
14
16
|
* --config <path> path to putitoutthere.toml
|
|
15
17
|
* --json machine-readable output
|
|
16
18
|
*
|
|
19
|
+
* `write-version` flags:
|
|
20
|
+
* --path <dir> package directory (where pyproject.toml lives)
|
|
21
|
+
* --version <v> planned version to write
|
|
22
|
+
*
|
|
17
23
|
* `--dry-run` was removed deliberately (#244). The library's job is
|
|
18
24
|
* publishing; a non-publishing mode of the publish command was a
|
|
19
25
|
* coverage hole pretending to be a feature. Passing `--dry-run` now
|
|
@@ -23,6 +29,8 @@ interface ParsedFlags {
|
|
|
23
29
|
cwd: string;
|
|
24
30
|
config?: string | undefined;
|
|
25
31
|
json: boolean;
|
|
32
|
+
path?: string | undefined;
|
|
33
|
+
version?: string | undefined;
|
|
26
34
|
}
|
|
27
35
|
export declare function parseFlags(argv: readonly string[]): ParsedFlags;
|
|
28
36
|
export declare function run(argv: readonly string[]): Promise<number>;
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAwCH,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;IAId,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CA8B/D;AAED,wBAAsB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6GlE"}
|
package/dist/cli.js
CHANGED
|
@@ -5,15 +5,21 @@
|
|
|
5
5
|
* not promised externally. See `notes/design-commitments.md`.
|
|
6
6
|
*
|
|
7
7
|
* Commands:
|
|
8
|
-
* plan
|
|
9
|
-
* publish
|
|
10
|
-
* version
|
|
8
|
+
* plan — compute and emit the release plan
|
|
9
|
+
* publish — execute the plan against the registries
|
|
10
|
+
* write-version — bump a package's manifest to a planned version
|
|
11
|
+
* (pre-build hook for maturin; #276)
|
|
12
|
+
* version — print CLI version
|
|
11
13
|
*
|
|
12
14
|
* Global flags:
|
|
13
15
|
* --cwd <path> working directory (default: process.cwd())
|
|
14
16
|
* --config <path> path to putitoutthere.toml
|
|
15
17
|
* --json machine-readable output
|
|
16
18
|
*
|
|
19
|
+
* `write-version` flags:
|
|
20
|
+
* --path <dir> package directory (where pyproject.toml lives)
|
|
21
|
+
* --version <v> planned version to write
|
|
22
|
+
*
|
|
17
23
|
* `--dry-run` was removed deliberately (#244). The library's job is
|
|
18
24
|
* publishing; a non-publishing mode of the publish command was a
|
|
19
25
|
* coverage hole pretending to be a feature. Passing `--dry-run` now
|
|
@@ -22,8 +28,9 @@
|
|
|
22
28
|
import { isAbsolute, resolve } from 'node:path';
|
|
23
29
|
import { plan } from './plan.js';
|
|
24
30
|
import { publish } from './publish.js';
|
|
31
|
+
import { writeVersionForBuild } from './write-version.js';
|
|
25
32
|
import { VERSION } from './version.js';
|
|
26
|
-
const COMMANDS = ['plan', 'publish', 'version'];
|
|
33
|
+
const COMMANDS = ['plan', 'publish', 'write-version', 'version'];
|
|
27
34
|
function isCommand(value) {
|
|
28
35
|
return COMMANDS.includes(value);
|
|
29
36
|
}
|
|
@@ -32,13 +39,16 @@ function printUsage() {
|
|
|
32
39
|
'Usage: putitoutthere <command> [options]',
|
|
33
40
|
'',
|
|
34
41
|
'Commands:',
|
|
35
|
-
' plan
|
|
36
|
-
' publish
|
|
37
|
-
' version
|
|
42
|
+
' plan Compute and emit the release plan',
|
|
43
|
+
' publish Execute the plan',
|
|
44
|
+
' write-version Bump a package manifest to the planned version (pre-build; #276)',
|
|
45
|
+
' version Print CLI version',
|
|
38
46
|
'',
|
|
39
47
|
'Options:',
|
|
40
48
|
' --cwd <path> working directory',
|
|
41
49
|
' --config <path> path to putitoutthere.toml',
|
|
50
|
+
' --path <dir> package directory (write-version)',
|
|
51
|
+
' --version <v> planned version (write-version)',
|
|
42
52
|
' --json emit machine-readable output',
|
|
43
53
|
'',
|
|
44
54
|
'See https://github.com/thekevinscott/putitoutthere for docs.',
|
|
@@ -59,6 +69,10 @@ export function parseFlags(argv) {
|
|
|
59
69
|
out.config = argv[++i];
|
|
60
70
|
else if (a === '--json')
|
|
61
71
|
out.json = true;
|
|
72
|
+
else if (a === '--path')
|
|
73
|
+
out.path = argv[++i];
|
|
74
|
+
else if (a === '--version')
|
|
75
|
+
out.version = argv[++i];
|
|
62
76
|
else if (a === '--dry-run') {
|
|
63
77
|
// Removed in #244. Publishing is the library's only job; a
|
|
64
78
|
// non-publishing flavor of `publish` is a coverage hole, not
|
|
@@ -130,6 +144,21 @@ export async function run(argv) {
|
|
|
130
144
|
}
|
|
131
145
|
return 0;
|
|
132
146
|
}
|
|
147
|
+
case 'write-version': {
|
|
148
|
+
// #276: pre-build hook used by `_matrix.yml`'s maturin steps.
|
|
149
|
+
// Maturin reads the version from disk at build time with no
|
|
150
|
+
// env override, so the manifest must match the planned
|
|
151
|
+
// version before maturin runs. crates / npm bump at publish;
|
|
152
|
+
// setuptools-scm / hatch-vcs use SETUPTOOLS_SCM_PRETEND_VERSION.
|
|
153
|
+
if (!flags.path)
|
|
154
|
+
throw new Error('write-version: --path <pkg-dir> is required');
|
|
155
|
+
if (!flags.version)
|
|
156
|
+
throw new Error('write-version: --version <v> is required');
|
|
157
|
+
const target = isAbsolute(flags.path) ? flags.path : resolve(flags.cwd, flags.path);
|
|
158
|
+
const written = writeVersionForBuild(target, flags.version);
|
|
159
|
+
process.stdout.write(`write-version: ${target} → ${flags.version}; wrote ${written.join(', ')}\n`);
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
133
162
|
case 'publish': {
|
|
134
163
|
const result = await publish({
|
|
135
164
|
cwd: flags.cwd,
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,CAAU,CAAC;AAG1E,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAQ,QAA8B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB;QACE,0CAA0C;QAC1C,EAAE;QACF,WAAW;QACX,oDAAoD;QACpD,mCAAmC;QACnC,mFAAmF;QACnF,oCAAoC;QACpC,EAAE;QACF,UAAU;QACV,uCAAuC;QACvC,gDAAgD;QAChD,uDAAuD;QACvD,qDAAqD;QACrD,kDAAkD;QAClD,EAAE;QACF,8DAA8D;QAC9D,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC;AAaD,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,MAAM,GAAG,GAAgB;QACvB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,IAAI,EAAE,KAAK;KACZ,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,sFAAsF;QACtF,IAAI,CAAC,KAAK,OAAO;YAAE,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC;aAC7C,IAAI,CAAC,KAAK,UAAU;YAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC7C,IAAI,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;aACpC,IAAI,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACzC,IAAI,CAAC,KAAK,WAAW;YAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC/C,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YAC3B,2DAA2D;YAC3D,6DAA6D;YAC7D,6DAA6D;YAC7D,MAAM,IAAI,KAAK,CACb,sHAAsH,CACvH,CAAC;QACJ,CAAC;IACH,CAAC;IACD,oEAAoE;IACpE,wEAAwE;IACxE,oEAAoE;IACpE,kEAAkE;IAClE,mEAAmE;IACnE,8CAA8C;IAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAuB;IAC/C,MAAM,CAAC,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,qEAAqE;IACrE,kEAAkE;IAClE,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,yEAAyE,CAC1E,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrC,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,OAAO,IAAI,CAAC,CAAC;QACnD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,GAAG,IAAI,CAAC,CAAC;QACjE,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;oBACxB,GAAG,EAAE,KAAK,CAAC,GAAG;oBACd,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpE,CAAC,CAAC;gBACH,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;oBACnD,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,mBAAmB,CAAC,CAAC;wBAC1D,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;4BACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,GAAG,CAAC,IAAI,aAAa,GAAG,CAAC,OAAO,YAAY,GAAG,CAAC,MAAM,cAAc,GAAG,CAAC,aAAa,IAAI,CAC/F,CAAC;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,gEAAgE;gBAChE,+DAA+D;gBAC/D,iEAAiE;gBACjE,kEAAkE;gBAClE,kEAAkE;gBAClE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;gBAC/C,IAAI,YAAY,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAClC,EAAE,CAAC,cAAc,CACf,YAAY,EACZ,UAAU,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EACpC,MAAM,CACP,CACF,CAAC;gBACJ,CAAC;gBACD,OAAO,CAAC,CAAC;YACX,CAAC;YACD,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,8DAA8D;gBAC9D,4DAA4D;gBAC5D,uDAAuD;gBACvD,6DAA6D;gBAC7D,iEAAiE;gBACjE,IAAI,CAAC,KAAK,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;gBAChF,IAAI,CAAC,KAAK,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;gBAChF,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACpF,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC5D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kBAAkB,MAAM,MAAM,KAAK,CAAC,OAAO,WAAW,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAC7E,CAAC;gBACF,OAAO,CAAC,CAAC;YACX,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;oBAC3B,GAAG,EAAE,KAAK,CAAC,GAAG;oBACd,2FAA2F;oBAC3F,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpE,CAAC,CAAC;gBACH,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;gBACtD,CAAC;qBAAM,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;oBAC/C,6FAA6F;gBAC/F,CAAC;qBAAM,CAAC;oBACN,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;wBACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,cAAc,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CACpE,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,oBAAoB;gBACpB,OAAO,CAAC,CAAC;YACX,CAAC;YACD,6DAA6D;YAC7D,KAAK,SAAS;gBACZ,OAAO,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CACvE,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,yBAAyB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-build version bump used by `_matrix.yml`'s maturin steps. #276.
|
|
3
|
+
*
|
|
4
|
+
* Maturin reads `[project].version` from `pyproject.toml` (or
|
|
5
|
+
* `[package].version` from a sibling `Cargo.toml` when pyproject
|
|
6
|
+
* declares `dynamic = ["version"]`) at build time. There is no env
|
|
7
|
+
* override the build job can inject — `SETUPTOOLS_SCM_PRETEND_VERSION`
|
|
8
|
+
* is honored by hatch-vcs / setuptools-scm but not by maturin. So
|
|
9
|
+
* the on-disk manifest has to be rewritten before `maturin build`
|
|
10
|
+
* runs. crates and npm bump at publish (cargo / npm read the
|
|
11
|
+
* manifest at upload time, not before); maturin is the one path
|
|
12
|
+
* where the artifact (the wheel) leaves the build runner already
|
|
13
|
+
* versioned.
|
|
14
|
+
*
|
|
15
|
+
* This module is the build-time complement to `pypi.writeVersion`.
|
|
16
|
+
* The publish-time handler logs guidance for dynamic-version
|
|
17
|
+
* projects rather than rewriting Cargo.toml; here we actually do
|
|
18
|
+
* the rewrite, because the build step has no fallback.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Rewrite the version source(s) for a maturin package and return the
|
|
22
|
+
* list of absolute paths that were modified.
|
|
23
|
+
*
|
|
24
|
+
* Dispatch:
|
|
25
|
+
* - `[project].version = "..."` is a static literal → rewrite
|
|
26
|
+
* pyproject.toml in place. If a sibling `Cargo.toml` with a
|
|
27
|
+
* `[package].version` line is present, rewrite it too. This is
|
|
28
|
+
* not redundant: a python-rust-maturin shape with both a static
|
|
29
|
+
* pyproject literal AND a Cargo `[package].version` literal will
|
|
30
|
+
* have the two manifests disagree post-bump if only pyproject is
|
|
31
|
+
* rewritten, and maturin's mismatch-resolution behavior varies
|
|
32
|
+
* by platform / version (PR #277 hit this on Windows: wheels
|
|
33
|
+
* shipped at the stale Cargo literal even though pyproject was
|
|
34
|
+
* bumped). Bumping both keeps the contract straightforward.
|
|
35
|
+
* - `[project].dynamic = ["version", ...]` → rewrite the sibling
|
|
36
|
+
* `Cargo.toml`'s `[package].version`. Errors if Cargo.toml is
|
|
37
|
+
* missing.
|
|
38
|
+
*
|
|
39
|
+
* Throws on missing pyproject.toml, malformed TOML, or a `[project]`
|
|
40
|
+
* table that declares neither a literal nor `dynamic = ["version"]`.
|
|
41
|
+
*
|
|
42
|
+
* I/O uses `readFileSync` with `try` / `catch (ENOENT)` instead of an
|
|
43
|
+
* `existsSync` precheck — the precheck is a TOCTOU race CodeQL flags
|
|
44
|
+
* (`pull/277` advisories #13, #14), and `pypi.writeVersion` already
|
|
45
|
+
* uses the same try/catch shape we mirror here.
|
|
46
|
+
*/
|
|
47
|
+
export declare function writeVersionForBuild(pkgDir: string, version: string): string[];
|
|
48
|
+
//# sourceMappingURL=write-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-version.d.ts","sourceRoot":"","sources":["../src/write-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA6E9E"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-build version bump used by `_matrix.yml`'s maturin steps. #276.
|
|
3
|
+
*
|
|
4
|
+
* Maturin reads `[project].version` from `pyproject.toml` (or
|
|
5
|
+
* `[package].version` from a sibling `Cargo.toml` when pyproject
|
|
6
|
+
* declares `dynamic = ["version"]`) at build time. There is no env
|
|
7
|
+
* override the build job can inject — `SETUPTOOLS_SCM_PRETEND_VERSION`
|
|
8
|
+
* is honored by hatch-vcs / setuptools-scm but not by maturin. So
|
|
9
|
+
* the on-disk manifest has to be rewritten before `maturin build`
|
|
10
|
+
* runs. crates and npm bump at publish (cargo / npm read the
|
|
11
|
+
* manifest at upload time, not before); maturin is the one path
|
|
12
|
+
* where the artifact (the wheel) leaves the build runner already
|
|
13
|
+
* versioned.
|
|
14
|
+
*
|
|
15
|
+
* This module is the build-time complement to `pypi.writeVersion`.
|
|
16
|
+
* The publish-time handler logs guidance for dynamic-version
|
|
17
|
+
* projects rather than rewriting Cargo.toml; here we actually do
|
|
18
|
+
* the rewrite, because the build step has no fallback.
|
|
19
|
+
*/
|
|
20
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { parse as parseToml } from 'smol-toml';
|
|
23
|
+
import { replaceCargoVersion } from './handlers/crates.js';
|
|
24
|
+
import { replacePyProjectVersion } from './handlers/pypi.js';
|
|
25
|
+
/**
|
|
26
|
+
* Rewrite the version source(s) for a maturin package and return the
|
|
27
|
+
* list of absolute paths that were modified.
|
|
28
|
+
*
|
|
29
|
+
* Dispatch:
|
|
30
|
+
* - `[project].version = "..."` is a static literal → rewrite
|
|
31
|
+
* pyproject.toml in place. If a sibling `Cargo.toml` with a
|
|
32
|
+
* `[package].version` line is present, rewrite it too. This is
|
|
33
|
+
* not redundant: a python-rust-maturin shape with both a static
|
|
34
|
+
* pyproject literal AND a Cargo `[package].version` literal will
|
|
35
|
+
* have the two manifests disagree post-bump if only pyproject is
|
|
36
|
+
* rewritten, and maturin's mismatch-resolution behavior varies
|
|
37
|
+
* by platform / version (PR #277 hit this on Windows: wheels
|
|
38
|
+
* shipped at the stale Cargo literal even though pyproject was
|
|
39
|
+
* bumped). Bumping both keeps the contract straightforward.
|
|
40
|
+
* - `[project].dynamic = ["version", ...]` → rewrite the sibling
|
|
41
|
+
* `Cargo.toml`'s `[package].version`. Errors if Cargo.toml is
|
|
42
|
+
* missing.
|
|
43
|
+
*
|
|
44
|
+
* Throws on missing pyproject.toml, malformed TOML, or a `[project]`
|
|
45
|
+
* table that declares neither a literal nor `dynamic = ["version"]`.
|
|
46
|
+
*
|
|
47
|
+
* I/O uses `readFileSync` with `try` / `catch (ENOENT)` instead of an
|
|
48
|
+
* `existsSync` precheck — the precheck is a TOCTOU race CodeQL flags
|
|
49
|
+
* (`pull/277` advisories #13, #14), and `pypi.writeVersion` already
|
|
50
|
+
* uses the same try/catch shape we mirror here.
|
|
51
|
+
*/
|
|
52
|
+
export function writeVersionForBuild(pkgDir, version) {
|
|
53
|
+
const pyProjectPath = join(pkgDir, 'pyproject.toml');
|
|
54
|
+
let pyOriginal;
|
|
55
|
+
try {
|
|
56
|
+
pyOriginal = readFileSync(pyProjectPath, 'utf8');
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err.code === 'ENOENT') {
|
|
60
|
+
throw new Error(`write-version: pyproject.toml not found at ${pyProjectPath}`, {
|
|
61
|
+
cause: err,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/* v8 ignore next -- non-ENOENT read errors surface as-is */
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = parseToml(pyOriginal);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
73
|
+
throw new Error(`write-version: failed to parse ${pyProjectPath}: ${msg}`, { cause: err });
|
|
74
|
+
}
|
|
75
|
+
const project = parsed?.project;
|
|
76
|
+
if (!project) {
|
|
77
|
+
throw new Error(`write-version: ${pyProjectPath} has no [project] table -- declare [project].version or [project].dynamic = ["version"]`);
|
|
78
|
+
}
|
|
79
|
+
const cargoPath = join(pkgDir, 'Cargo.toml');
|
|
80
|
+
if (isDynamicVersion(project)) {
|
|
81
|
+
let cargoOriginal;
|
|
82
|
+
try {
|
|
83
|
+
cargoOriginal = readFileSync(cargoPath, 'utf8');
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (err.code === 'ENOENT') {
|
|
87
|
+
throw new Error(`write-version: pyproject.toml declares dynamic = ["version"] but Cargo.toml is missing at ${cargoPath}. Maturin's dynamic-version mode reads [package].version from Cargo.toml; without it there's nothing to bump.`, { cause: err });
|
|
88
|
+
}
|
|
89
|
+
/* v8 ignore next -- non-ENOENT read errors surface as-is */
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
const cargoUpdated = replaceCargoVersion(cargoOriginal, version);
|
|
93
|
+
if (cargoUpdated !== cargoOriginal)
|
|
94
|
+
writeFileSync(cargoPath, cargoUpdated, 'utf8');
|
|
95
|
+
return [cargoPath];
|
|
96
|
+
}
|
|
97
|
+
const written = [];
|
|
98
|
+
const pyUpdated = replacePyProjectVersion(pyOriginal, version);
|
|
99
|
+
if (pyUpdated !== pyOriginal)
|
|
100
|
+
writeFileSync(pyProjectPath, pyUpdated, 'utf8');
|
|
101
|
+
written.push(pyProjectPath);
|
|
102
|
+
// Bump a sibling Cargo.toml's [package].version too, when present.
|
|
103
|
+
// Pure-python pyproject (no Rust crate) → no Cargo.toml → skip.
|
|
104
|
+
// Cargo.toml without [package].version (workspace root) → skip
|
|
105
|
+
// (replaceCargoVersion throws on missing field; catch and continue).
|
|
106
|
+
let cargoOriginal;
|
|
107
|
+
try {
|
|
108
|
+
cargoOriginal = readFileSync(cargoPath, 'utf8');
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (err.code === 'ENOENT')
|
|
112
|
+
return written;
|
|
113
|
+
/* v8 ignore next -- non-ENOENT read errors surface as-is */
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
let cargoUpdated;
|
|
117
|
+
try {
|
|
118
|
+
cargoUpdated = replaceCargoVersion(cargoOriginal, version);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// No [package].version in Cargo.toml — nothing to bump on the
|
|
122
|
+
// Cargo side. The pyproject bump above is the source of truth.
|
|
123
|
+
return written;
|
|
124
|
+
}
|
|
125
|
+
if (cargoUpdated !== cargoOriginal)
|
|
126
|
+
writeFileSync(cargoPath, cargoUpdated, 'utf8');
|
|
127
|
+
written.push(cargoPath);
|
|
128
|
+
return written;
|
|
129
|
+
}
|
|
130
|
+
function isDynamicVersion(project) {
|
|
131
|
+
const { dynamic } = project;
|
|
132
|
+
return Array.isArray(dynamic) && dynamic.includes('version');
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=write-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-version.js","sourceRoot":"","sources":["../src/write-version.ts"],"names":[],"mappings":"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"}
|