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