From 9cd951d4505d98f3ab4d5d39e920f41ae117eab5 Mon Sep 17 00:00:00 2001 From: spacebear Date: Thu, 22 Oct 2026 09:21:35 +0000 Subject: [PATCH] Stage core from the revision on pull requests The staged Dart package takes payjoin-ffi from the pinned revision but payjoin and payjoin-mailroom from crates.io. Staging only switched a crate to the revision when its required version was missing from crates.io. A pull request that changes core without a version bump, which is how core changes normally land, kept the crates.io core, so the reproducible-linux job compiled the pull request's payjoin-ffi against an older payjoin and failed. #1971 hits this with new Monitor receiver methods. Add a --core-from-revision option that always patches the sibling release crates to the pinned revision and writes the UNPUBLISHED_CORE marker publish.sh refuses, and pass it on pull request runs only. Release runs keep staging against crates.io, so an unpublished core still fails there before anything is published. This also drops the crates.io API probing. --- .github/workflows/dart.yml | 10 +++- payjoin-ffi/dart/CONTRIBUTING.md | 11 ++-- payjoin-ffi/dart/contrib/prepare-publish.sh | 60 +++++++++------------ 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index c7cbd3a65..12c7e3787 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -55,7 +55,15 @@ jobs: - name: Set up nix uses: $/.github/actions/setup-nix - name: Generate production bindings and dry-run publish - run: nix develop .#dart -c ./payjoin-ffi/dart/contrib/prepare-publish.sh "$RUNNER_TEMP/payjoin-pub" + run: | + # Pull requests may change payjoin or payjoin-mailroom without a + # version bump, so they stage those crates from the checkout. + # Releases stage against crates.io, as consumers build them. + flags=() + if [[ $GITHUB_EVENT_NAME == pull_request ]]; then + flags+=(--core-from-revision) + fi + nix develop .#dart -c ./payjoin-ffi/dart/contrib/prepare-publish.sh "${flags[@]}" "$RUNNER_TEMP/payjoin-pub" # The release workflow publishes this exact stage, so it is archived # rather than regenerated in the publish job. - name: Archive the staged package diff --git a/payjoin-ffi/dart/CONTRIBUTING.md b/payjoin-ffi/dart/CONTRIBUTING.md index 2c84f7811..455284441 100644 --- a/payjoin-ffi/dart/CONTRIBUTING.md +++ b/payjoin-ffi/dart/CONTRIBUTING.md @@ -82,11 +82,12 @@ validates the archive with a publish dry run is seeded from `Cargo-recent.lock` and resolved against that revision, so consumers build the versions CI tested. A dependency fix reaches Dart consumers through `Cargo-recent.lock` and a new release. Staging - fetches the pinned commit from GitHub, so it must be pushed. When a - `payjoin` or `payjoin-mailroom` version that `payjoin-ffi` or - `payjoin-test-utils` requires is not on crates.io yet, staging takes - it from the same revision and writes an `UNPUBLISHED_CORE` marker, - which `contrib/publish.sh` refuses. Both the publish dry run and + fetches the pinned commit from GitHub, so it must be pushed. The + `payjoin` and `payjoin-mailroom` crates come from crates.io, except + with `--core-from-revision`, which pull requests use since they may + change those crates without a version bump. That option takes them + from the same revision and writes an `UNPUBLISHED_CORE` marker, which + `contrib/publish.sh` refuses. Both the publish dry run and publication use the staged package. For local checks: ```shell diff --git a/payjoin-ffi/dart/contrib/prepare-publish.sh b/payjoin-ffi/dart/contrib/prepare-publish.sh index bdda75c38..a6511a411 100755 --- a/payjoin-ffi/dart/contrib/prepare-publish.sh +++ b/payjoin-ffi/dart/contrib/prepare-publish.sh @@ -1,7 +1,12 @@ #!/usr/bin/env bash set -euo pipefail +core_from_revision=false +if [[ ${1:-} == --core-from-revision ]]; then + core_from_revision=true + shift +fi [ "$#" -eq 1 ] || { - echo "usage: prepare-publish.sh " >&2 + echo "usage: prepare-publish.sh [--core-from-revision] " >&2 exit 1 } # Resolve before changing directories; the destination must not exist. @@ -39,48 +44,31 @@ grep -Fq "rev = \"$revision\"" "$stage/native/Cargo.toml" || { # payjoin-ffi and payjoin-test-utils come from the pinned revision, but the # release crates they require, payjoin and payjoin-mailroom, come from -# crates.io. Between a version bump of one of those and its crates.io -# release, the lock below could not resolve it. Take such a crate from the -# pinned revision instead so pull requests can still stage, and leave a +# crates.io. A pull request can change those crates without a version bump, +# so its payjoin-ffi may not build against what crates.io has. With +# --core-from-revision, take them from the pinned revision too, and leave a # marker that publish.sh refuses: a published package must build against # crates its consumers can get from crates.io. -source "$REPO_ROOT/contrib/release/crates.sh" -# crates.io answers 404 for a version it does not have. Any other failure, -# such as a rate limit or an outage, must stop here rather than read as -# unpublished, or a release run would stage a package publish.sh refuses. -crates_io_status() { - curl -sL --retry 3 -o /dev/null -w '%{http_code}' \ - -H "User-Agent: rust-payjoin release tooling" \ - "https://crates.io/api/v1/crates/$1/$2" || true -} -siblings="$(sibling_deps payjoin-ffi && sibling_deps payjoin-test-utils)" -[[ $siblings == *payjoin$'\t'* ]] || { - echo "Could not read the payjoin version payjoin-ffi requires" >&2 - exit 1 -} -while IFS=$'\t' read -r dep req; do - version="${req#^}" - version="${version#=}" - status="$(crates_io_status "$dep" "$version")" - case $status in - 200) continue ;; - 404) ;; - *) - echo "Could not check $dep $version on crates.io (HTTP $status)" >&2 - exit 1 - ;; - esac - echo "==> $dep $version is not on crates.io; staging it from $revision" - cat >>"$stage/native/Cargo.toml" <&2 + exit 1 + } + while IFS=$'\t' read -r dep _; do + echo "==> Staging $dep from $revision" + cat >>"$stage/native/Cargo.toml" <>"$stage/UNPUBLISHED_CORE" -done < <(sort -u <<<"$siblings") + printf '%s comes from %s, not crates.io\n' "$dep" "$revision" \ + >>"$stage/UNPUBLISHED_CORE" + done < <(sort -u <<<"$siblings") +fi # Ship the dependency graph this release was tested against; hook/build.dart # builds it with --locked. Seeding from the maintained lockfile keeps every