putitoutthere 0.2.14 → 0.2.15
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 +49 -0
- package/README.md +19 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -34,6 +34,8 @@ are prefixed `**BREAKING**` and link to the matching section in
|
|
|
34
34
|
|
|
35
35
|
- **Bundled-CLI / napi npm consumers' `npm run build` step now sees `TARGET` and `BUILD` env vars on every matrix row.** The reusable workflow's `_matrix.yml` and `release.yml` previously ran the npm build step with no env block, so consumers' build scripts that read `process.env.TARGET` to know which triple to cross-compile saw `undefined` and either crashed or silently no-oped. Every per-platform matrix row then uploaded an empty `build/<triple>/` directory and `actions/upload-artifact@v7` flagged `No files were found with the provided path: ...`. The internal `e2e-fixture-job.yml` already passed `TARGET` / `BUILD` correctly — meaning the fixture suite passed but a real consumer's first publish still failed; an integration-tier divergence rather than a behavior bug per se. Both the build matrix step and the publish-job rebuild step in `release.yml` now set the env block. `_matrix.yml` exposes `TARGET=${{ matrix.target }}` / `BUILD=${{ matrix.build }}` per row; `release.yml`'s rebuild loop sets `TARGET=main BUILD=` per iteration (the publish-time rebuild only fires for the main package's row, since per-platform sub-packages stage from `artifacts/` via the engine's npm-platform handler). The README's [Bundled-CLI npm family](./README.md#bundled-cli-npm-family) recipe gained the consumer-side build-script contract that was previously missing — TARGET/BUILD vocabulary and a minimal `scripts/build.cjs` covering the simple single-workspace case. Hit in the wild on `thekevinscott/darkfactory`'s first release; tracked at #287. See [MIGRATIONS.md](./MIGRATIONS.md#npm-build-step-target-build-env-vars).
|
|
36
36
|
|
|
37
|
+
- **First-publish bundled-cli / napi npm builds no longer fail on lockfile drift.** Consumers of the bundled-cli / napi shape declare `optionalDependencies` for `<name>-<triple>@<version>` platform packages that this pipeline publishes. On the very first publish those entries 404 on the registry; pnpm 10 silently drops 404'd optionals from the lockfile when it is regenerated locally; a subsequent CI run with `pnpm install --frozen-lockfile` (or `npm ci`) refuses because lockfile and `package.json` disagree. Both install steps in the reusable workflow — `_matrix.yml`'s build-matrix install and `release.yml`'s publish-job rebuild step (added in #256) — now self-heal: a failed strict install falls back to its non-strict form (`pnpm install --no-frozen-lockfile` / `npm install`) with a `::warning::` line in the run log naming the recovery. No consumer-side change required; lockfiles can stay committed and `optionalDependencies` can stay declared. Hit in the wild on `thekevinscott/darkfactory`'s first release (#integration-2026-05-bundled-cli). The README's [Bundled-CLI npm family](./README.md#bundled-cli-npm-family) recipe grew a `[!NOTE]` callout documenting the chicken-and-egg and the workflow's transparent recovery. See [MIGRATIONS.md](./MIGRATIONS.md#first-publish-bundled-cli-lockfile-self-heal).
|
|
38
|
+
|
|
37
39
|
- **pypi/maturin `[package.bundle_cli]` now actually ships the bundled binary inside published wheels.** The recipe was advertised as shipped in v0.2.0 (#217) — config parsing accepted `[package.bundle_cli]`, the planner attached it to per-target wheel rows, and `MIGRATIONS.md` named the two scaffolded build steps consumers should expect. None of those steps existed in `.github/workflows/_matrix.yml`. Consumers who declared the block (us, in `thekevinscott/dirsql`) shipped wheels missing the binary; `pip install <pkg> && <pkg> ...` failed at runtime with `FileNotFoundError`. The reusable workflow's build job now, for every per-target wheel row that carries `matrix.bundle_cli`: (1) `rustup target add ${{ matrix.target }}`, (2) `cargo build --release --target ${{ matrix.target }} --bin ${{ matrix.bundle_cli.bin }}` against `crate_path`, (3) copies the resulting binary into `${{ matrix.path }}/${{ matrix.bundle_cli.stage_to }}/` so maturin's `[tool.maturin].include` glob picks it up as wheel data, and (4) runs a permanent post-build wheel-content guard that opens the produced `.whl` and refuses to upload-artifact if `<stage_to>/<bin>` is missing. The guard is independent of staging — it catches any future regression where the cross-compile silently routes the binary to the wrong path. Consumers do not need to change their existing `[package.bundle_cli]` config or their `[tool.maturin].include` glob; the recipe just starts working. The cross-compile assumes the binary is buildable with a vanilla `cargo build --release --bin <bin>` (no `--features`, no env, no special flags); crates that gate the CLI behind a Cargo feature are not yet supported. The `.exe` suffix on Windows is handled. See [README → Recipes → Rust CLI inside a PyPI wheel](./README.md#rust-cli-inside-a-pypi-wheel) and [MIGRATIONS.md](./MIGRATIONS.md#bundle_cli-now-actually-stages-the-binary). #282.
|
|
38
40
|
|
|
39
41
|
- **`putitoutthere.toml` validation now names common typos in the failure message.** A consumer integration shipped a config with `version` at the file root, `[[packages]]` (plural), `registry =` instead of `kind =`, and `files =` instead of `globs =`. The raw zod errors (`Invalid input: expected object, received undefined; ...; Unrecognized keys: "version", "packages"`) were opaque enough that the engine source had to be re-read to recover. A pre-pass in `parseConfig` now detects each of those four mistakes by name and emits a hint that pairs the wrong shape with the right one, e.g. `top-level table is \`[[packages]]\` (plural) but should be \`[[package]]\` (singular)`. README's [Drop in `putitoutthere.toml`](./README.md#2-drop-in-putitoutthere-toml) section grew a four-row "wrong → right" table covering the same four traps so the docs and the engine name them the same way; a new `[!IMPORTANT]` callout in [Drop in `.github/workflows/release.yml`](./README.md#1-drop-in-githubworkflowsreleaseyml) warns consumers off `push: branches: [main]` triggers on lane CI workflows (which fire duplicate runs against the merge commit and contend for runners with `release.yml`); `1b.` was promoted from "Optional" to "Recommended" since `build.yml` is the cheapest place to catch a malformed config before merge. See [MIGRATIONS.md](./MIGRATIONS.md#friendly-config-error-hints).
|
package/MIGRATIONS.md
CHANGED
|
@@ -72,6 +72,55 @@ artifacts: each `<pkg>-npm-<triple>` upload contains
|
|
|
72
72
|
`build/<triple>/<bin-name>`. The release run's `Upload artifact`
|
|
73
73
|
step no longer logs `No files were found with the provided path`
|
|
74
74
|
for any npm row.
|
|
75
|
+
### First-publish bundled-cli lockfile self-heal
|
|
76
|
+
|
|
77
|
+
**Summary.** The reusable workflow's npm install steps —
|
|
78
|
+
`_matrix.yml`'s build-matrix install and `release.yml`'s
|
|
79
|
+
publish-job rebuild (#256) — both ran strict installs (`npm ci`
|
|
80
|
+
or `pnpm install --frozen-lockfile`) and refused on any drift
|
|
81
|
+
between the committed lockfile and `package.json`. For consumers
|
|
82
|
+
of the bundled-cli / napi shape, drift is the *expected* state on
|
|
83
|
+
the first publish: `package.json` declares
|
|
84
|
+
`optionalDependencies` for `<name>-<triple>@<version>` platform
|
|
85
|
+
packages that this pipeline produces, those packages don't exist
|
|
86
|
+
on the registry yet, pnpm 10 silently drops 404'd optionals from
|
|
87
|
+
the lockfile when it is regenerated locally, and the next CI run
|
|
88
|
+
sees lockfile and `package.json` disagree. Hit in the wild on
|
|
89
|
+
`thekevinscott/darkfactory`'s first release.
|
|
90
|
+
|
|
91
|
+
Both install steps now fall back from the strict form to its
|
|
92
|
+
non-strict counterpart on failure (`pnpm install --no-frozen-lockfile`
|
|
93
|
+
/ `npm install`) and emit a `::warning::` line in the run log
|
|
94
|
+
naming the recovery. The README's
|
|
95
|
+
[Bundled-CLI npm family](./README.md#bundled-cli-npm-family)
|
|
96
|
+
recipe grew a `[!NOTE]` callout documenting the chicken-and-egg
|
|
97
|
+
and the workflow's transparent recovery.
|
|
98
|
+
|
|
99
|
+
**Required changes.** None. Consumers who were working around
|
|
100
|
+
the failure by gitignoring the lockfile, by suppressing
|
|
101
|
+
`optionalDependencies` from `package.json`, or by pinning to
|
|
102
|
+
older lockfile-tolerant pnpm versions can revert those
|
|
103
|
+
workarounds; the workflow now handles the bootstrap state on
|
|
104
|
+
its own.
|
|
105
|
+
|
|
106
|
+
**Deprecations removed.** None.
|
|
107
|
+
|
|
108
|
+
**Behavior changes without code changes.** Strict installs that
|
|
109
|
+
previously failed red on lockfile drift now succeed via the
|
|
110
|
+
non-strict fallback path. The build artifact is unchanged
|
|
111
|
+
(installs the deps `package.json` declares); only the strictness
|
|
112
|
+
of *how* it gets there relaxes. Healthy lockfiles still take
|
|
113
|
+
the strict path with no observable difference. The new
|
|
114
|
+
`::warning::` lines are visible in the run log on the GitHub
|
|
115
|
+
Actions UI but do not fail the run.
|
|
116
|
+
|
|
117
|
+
**Verification.** A bundled-cli / napi consumer's first-publish
|
|
118
|
+
release run completes the build matrix without manual lockfile
|
|
119
|
+
fiddling. The run log contains a single
|
|
120
|
+
`::warning::pnpm-lock.yaml drift ...` line per affected install
|
|
121
|
+
step (one in the build matrix, one in the publish-job rebuild)
|
|
122
|
+
when the strict install fails; healthy installs see no
|
|
123
|
+
warning.
|
|
75
124
|
|
|
76
125
|
### `[package.bundle_cli]` now actually stages the binary
|
|
77
126
|
|
package/README.md
CHANGED
|
@@ -546,6 +546,25 @@ Each per-platform sub-package needs its own npm trusted-publisher
|
|
|
546
546
|
registration (a policy on `my-cli` does not cover
|
|
547
547
|
`my-cli-x86_64-unknown-linux-gnu`).
|
|
548
548
|
|
|
549
|
+
> [!NOTE]
|
|
550
|
+
> **First-publish lockfile chicken-and-egg.** Some scaffolding will
|
|
551
|
+
> populate `optionalDependencies` in your top-level `package.json`
|
|
552
|
+
> with entries for `my-cli-<triple>@<version>` ahead of the first
|
|
553
|
+
> publish. Those packages don't exist on the registry yet — the
|
|
554
|
+
> engine publishes them as part of *this* run — so a locally-generated
|
|
555
|
+
> `package-lock.json` / `pnpm-lock.yaml` either fails to install or
|
|
556
|
+
> silently drops the entries (pnpm 10 does the silent drop). On the
|
|
557
|
+
> next CI run, the strict installs (`npm ci`,
|
|
558
|
+
> `pnpm install --frozen-lockfile`) refuse because lockfile and
|
|
559
|
+
> `package.json` disagree.
|
|
560
|
+
>
|
|
561
|
+
> The reusable workflow handles this transparently: every strict
|
|
562
|
+
> install in the build matrix and the publish-job rebuild step
|
|
563
|
+
> falls back to its non-strict form on failure (with a
|
|
564
|
+
> `::warning::` line in the run log so the recovery is visible).
|
|
565
|
+
> No consumer-side change is required; you can keep the lockfile
|
|
566
|
+
> committed and the `optionalDependencies` declared.
|
|
567
|
+
|
|
549
568
|
### Multi-mode npm family
|
|
550
569
|
|
|
551
570
|
For a package that is both a napi-rs Node addon (a `.node` library) **and**
|