diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9585645..681564b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: CI on: + workflow_call: push: branches: [main, "**"] pull_request: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..fd1b6cf --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,54 @@ +name: Publish to pub.dev + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-*' + +permissions: + contents: read + +concurrency: + group: pub-dev-${{ github.ref }} + cancel-in-progress: false + +jobs: + release-version: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Verify release tag matches package version + env: + RELEASE_TAG: ${{ github.ref_name }} + run: | + python3 - <<'PY' + import os + import pathlib + import re + + pubspec = pathlib.Path('pubspec.yaml').read_text() + match = re.search(r'^version:\s*(\S+)\s*$', pubspec, re.MULTILINE) + if match is None: + raise SystemExit('Could not read package version from pubspec.yaml') + expected = f'v{match.group(1)}' + actual = os.environ['RELEASE_TAG'] + if actual != expected: + raise SystemExit(f'Tag {actual} does not match package version {expected}') + print(f'Publishing candidate: {actual}') + PY + + validate: + needs: release-version + uses: ./.github/workflows/ci.yml + + publish: + needs: validate + permissions: + contents: read + id-token: write + uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1 + with: + environment: pub.dev diff --git a/PUBDEV_RELEASE_CHECKLIST.md b/PUBDEV_RELEASE_CHECKLIST.md index a3f4c1d..ffba41d 100644 --- a/PUBDEV_RELEASE_CHECKLIST.md +++ b/PUBDEV_RELEASE_CHECKLIST.md @@ -2,6 +2,26 @@ Use this checklist before publishing `bdk_dart` to pub.dev. +## Automated publishing setup (one time) + +- [ ] In the [package Admin tab](https://pub.dev/packages/bdk_dart/admin), enable publishing from GitHub Actions for `bitcoindevkit/bdk-dart` with tag pattern `v{{version}}`. +- [ ] In the same pub.dev settings, require the GitHub Actions environment `pub.dev`. +- [ ] In the GitHub repository settings, create the `pub.dev` environment and configure required reviewers. If the maintainer who pushes the tag will also approve publication, leave **Prevent self-review** disabled. +- [ ] Restrict the environment's deployment tags to the release tags and configure repository tag rules to limit who can create or change them. +- [ ] Merge `.github/workflows/publish.yml` and the reusable CI configuration before creating a release tag. + +The workflow handles stable tags and prerelease tags such as `v1.0.0-rc.4`. +It checks the tag against `pubspec.yaml`, runs the full CI workflow on the tagged +commit, and then waits for environment approval. The official Dart publishing +workflow performs a dry run and publishes using a short-lived OIDC token; no +stored pub.dev credentials are needed. + +Creating the environment alone does not enable approval: required reviewers must +be configured. Confirm that this protection is available and enabled for the +repository before relying on the approval step. + +See [Dart's automated publishing documentation](https://dart.dev/tools/pub/automated-publishing). + ## 1. Package metadata - [ ] `pubspec.yaml` includes a clear `description`. @@ -49,8 +69,18 @@ dart pub publish --dry-run ## 6. Publish and verify -- [ ] Publish to pub.dev from the release commit/tag. +- [ ] Create and push the release tag from the reviewed release commit on `main` (for example, `v1.0.0-rc.4` for package version `1.0.0-rc.4`). Pushing the tag starts publication; creating a GitHub release for an existing tag does not start a new tag-push run. +- [ ] Wait for the **Publish to pub.dev** workflow's version check and full CI validation to pass. +- [ ] Review the tagged commit and approve deployment to the `pub.dev` environment. +- [ ] Confirm the publishing job's dry run and upload succeed. If a run fails, inspect its logs and pub.dev before retrying; do not move an existing release tag or attempt to overwrite a published version. - [ ] Verify package page renders correctly on pub.dev. - [ ] Verify version and metadata fields are correct. - [ ] Perform a clean install test from pub.dev in a sample project. - [ ] Announce release with release notes. + +### Manual fallback + +If automated publishing is unavailable, an authorized uploader can check out the +clean release tag and run `dart pub publish --dry-run`, then `dart pub publish`. +First ensure no automated publishing job is running or awaiting approval for the +same version. Do not approve that job after publishing manually.