Filter publish output by registry version (cargo info)#21
Merged
Conversation
… registry
Previously the `publish` output contained every crate with `publish != false`,
even when the local Cargo.toml version matched what was already on the
registry — so a `cargo publish -p ${{ matrix.package }}` step would fail with
"crate version already uploaded" until a human pruned the matrix.
`parseMetadata` now returns `publishCandidates: [{name, version, registry}]`
and a new async `filterPublishable` runs `cargo info <name>` (with
`--registry` when the candidate is registry-restricted) for each candidate,
keeping only those whose local version is strictly greater per a full
semver §11 compare. Crates absent from the registry are kept (first publish);
other `cargo info` failures log a warning and skip the candidate, so a
transient outage cannot republish a stale crate.
Tests: rewrote publish-related cases for the new shape and added unit tests
for `compareSemver` (prerelease precedence, numeric vs lexical, build
metadata) and `parseCargoInfoVersion`. All 28 tests pass; dist rebuilt.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
New `publish` output filter (only crates with a newer-than-registry version) is a user-visible feature addition; bump minor. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refines the action’s publish output to include only workspace crates whose local Cargo.toml version is strictly newer than the latest version on the target registry, reducing “version already uploaded” failures in publish matrices.
Changes:
parseMetadatanow emitspublishCandidateswith{name, version, registry}instead of a flatpublishlist.- Added semver-precedence comparison (
compareSemver) pluscargo infoparsing and a newfilterPublishablestep to compute the finalpublishlist. - Updated docs and tests, and rebuilt the bundled
dist/index.js.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
lib.js |
Adds semver comparison + cargo info-based filtering and updates outputs accordingly. |
tests/parse-metadata.test.js |
Updates metadata expectations and adds unit tests for semver compare and cargo info parsing. |
README.md |
Documents new publish semantics and filtering behavior. |
action.yml |
Updates publish output description to match the new behavior. |
dist/index.js |
Rebuilt bundle reflecting the lib.js changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ixture Two related Fixtures-CI bugs surfaced once the publish output started using cargo info: 1. `cargo info <name>` (no `--registry`) probes the workspace at `cwd` first and returns the *local* member's version when the name matches. That made `local == published` for every workspace candidate and silently emptied the publish output. Always pass `--registry` (default `crates-io`) so cargo skips the local lookup. 2. The workspace-mixed fixture's `app` package collided with the real `app` crate on crates.io (already at 0.6.5), so the fixture's 0.1.0 was correctly classified as stale and excluded — but the workflow asserted the opposite. Rename the fixture to `rma-fixture-app` (with a comment explaining why) so it's guaranteed to be a first-publish, and update the workspace-mixed assertions accordingly. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
Three issues called out by the PR-21 review: 1. Multi-registry candidates (`publish = ["a","b"]`) only had their first entry queried, so a crate stale on registry "b" but absent from "a" could still appear in the publish list. parseMetadata now emits the full `registries: string[]` (with `[null]` for unrestricted), and the new `getMaxPublishedVersion` queries every entry and compares against the highest version found. 2. `getPublishedVersion` resolved to `null` when `cargo info` exited 0 but the parser couldn't find a `version:` line — `filterPublishable` then treated that as "first publish" and included the crate, which would mass-republish on any future cargo output drift. Reject in that path instead, so the catch path warns and skips (safe default). 3. `Promise.all` over every candidate spawned one `cargo info` per crate concurrently. Replaced with a small `asyncPool` (limit 4) so resource use stays predictable on large workspaces and we don't trip registry rate limits. Tests: updated publish-candidate fixtures to assert `registries: [...]`, added a multi-registry test case, plus three asyncPool tests (order, concurrency cap, empty input). 32/32 pass; dist rebuilt. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
`asyncPool`'s JSDoc already documented the worker as `worker(item)`, but the call site was `worker(items[i], i)` — passing an index that no caller consumes. Flagged by github-code-quality[bot] on PR 21. Drop the second arg so code matches the documented signature; trivially re-addable if a future caller actually wants the index. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
publishpreviously listed every crate withpublish != false, so acargo publish -p ${{ matrix.package }}matrix step would hit "crate version already uploaded" until a human pruned it.parseMetadatanow returnspublishCandidates: [{name, version, registry}]and a new asyncfilterPublishablerunscargo info <name>(with--registrywhen scoped) for each candidate, keeping only those whose local version is strictly greater per a full semver §11 compare.cargo infofailures log acore.warningand skip the candidate, so a transient outage cannot republish a stale crate.Test plan
npm test— 28/28 pass, including newcompareSemverandparseCargoInfoVersioncases.npm run check— prettier clean.npm run build—dist/index.jsrebuilt and committed.publish.publish(first-publish path).