From a0d181fdb80b6882895400c86a15479af53ed76e Mon Sep 17 00:00:00 2001 From: Santiago Date: Thu, 21 May 2026 08:40:38 -0300 Subject: [PATCH] ci: rework release workflow as tag-triggered pipeline Reworks release.yml to conform to the umbrella SDK release pipeline contract (u5c-factory reference/sdk-pipeline.md): a v* version tag triggers verify -> build -> test -> publish. The verify job checks the pushed tag against the utxorpc-client and utxorpc-server cabal versions and fails the release if they disagree. The shared protoc-install and Stack-cache steps are extracted into a setup-haskell composite action. Verification: workflow YAML syntactically validated only; not executed this session. Requires the HACKAGE_REGISTRY_TOKEN repository secret before the first release. --- .github/actions/setup-haskell/action.yml | 26 ++++++ .github/workflows/release.yml | 113 +++++++++++------------ 2 files changed, 80 insertions(+), 59 deletions(-) create mode 100644 .github/actions/setup-haskell/action.yml diff --git a/.github/actions/setup-haskell/action.yml b/.github/actions/setup-haskell/action.yml new file mode 100644 index 0000000..bcff0b1 --- /dev/null +++ b/.github/actions/setup-haskell/action.yml @@ -0,0 +1,26 @@ +name: 'Setup Haskell build environment' +description: 'Installs protoc and restores the Stack cache for utxorpc-client/server.' + +runs: + using: composite + steps: + - name: Install protoc + shell: bash + run: | + PROTOC_ZIP=protoc-3.14.0-linux-x86_64.zip + curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/$PROTOC_ZIP + unzip -o $PROTOC_ZIP -d . bin/protoc + unzip -o $PROTOC_ZIP -d . 'include/*' + rm -f $PROTOC_ZIP + echo "$(pwd)/bin" >> "$GITHUB_PATH" + + - name: Cache Stack + uses: actions/cache@v4 + with: + path: | + /home/runner/.stack + .stack-work + server/.stack-work + client/.stack-work + key: stack-${{ hashFiles('stack.yaml.lock') }} + restore-keys: stack- diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 97bbc05..b44008a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,84 +1,79 @@ -name: "Release" +name: Release +# Conforms to the umbrella SDK release pipeline contract: +# u5c-factory reference/sdk-pipeline.md +# +# Haskell carve-out: the haskell-sdk packages use independent `0.0.x` +# numbering; the `v*` tag must match the version the `.cabal` files declare. on: - workflow_dispatch: push: - tags: [v*] + tags: ['v*'] jobs: - publish: + verify: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install protoc + - uses: actions/checkout@v4 + - name: Verify tag matches cabal versions run: | - PROTOC_ZIP=protoc-3.14.0-linux-x86_64.zip - curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/$PROTOC_ZIP - unzip -o $PROTOC_ZIP -d . bin/protoc - unzip -o $PROTOC_ZIP -d . 'include/*' - rm -f $PROTOC_ZIP - echo "$(pwd)/bin" >> "$GITHUB_PATH" + TAG="${GITHUB_REF_NAME#v}" + for f in client/utxorpc-client.cabal server/utxorpc-server.cabal; do + MANIFEST=$(sed -nE 's/^version:[[:space:]]*(.+)/\1/p' "$f") + if [ "$TAG" != "$MANIFEST" ]; then + echo "::error::tag $GITHUB_REF_NAME does not match $f version $MANIFEST" + exit 1 + fi + done - - name: Restore Stack - id: restore-stack - uses: actions/cache/restore@v4 - with: - path: | - /home/runner/.stack - .stack-work - server/.stack-work - client/.stack-work - key: stack-${{ hashFiles('stack.yaml.lock') }} - restore-keys: stack- + build: + needs: verify + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-haskell + - run: stack build - - name: Dry run - id: dry-run - shell: bash - run: | - export HACKAGE_KEY=${{ secrets.HACKAGE_REGISTRY_TOKEN }} - stack test - stack haddock --haddock-for-hackage - stack upload --candidate --test-tarball client server - stack upload --candidate client server --documentation + test: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-haskell + - run: stack test - - name: Publish - if: startsWith(github.ref, 'refs/tags/v') - shell: bash + publish: + needs: test + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-haskell + + - name: Build Haddocks + run: stack haddock --haddock-for-hackage + + - name: Publish to Hackage + env: + HACKAGE_KEY: ${{ secrets.HACKAGE_REGISTRY_TOKEN }} run: | - export HACKAGE_KEY=${{ secrets.HACKAGE_REGISTRY_TOKEN }} stack upload client server stack upload client server --documentation - - name: Make artifacts + - name: Make sdist artifacts id: make-artifacts - if: startsWith(github.ref, 'refs/tags/v') - shell: bash run: | - # Make tarballs and output location SERVER_DIST=$(stack sdist server 2>&1 | sed -nE 's|^(.*utxorpc-server-.*\.tar\.gz).*$|\1|p') - echo "SERVER_DIST=$SERVER_DIST" >> "GITHUB_OUTPUT" + echo "SERVER_DIST=$SERVER_DIST" >> "$GITHUB_OUTPUT" CLIENT_DIST=$(stack sdist client 2>&1 | - sed -nE 's|^(.*utxorpc-client-.*tar\.gz).*$|\1|p') - echo "CLIENT_DIST=$CLIENT_DIST" >> "GITHUB_OUTPUT" + sed -nE 's|^(.*utxorpc-client-.*\.tar\.gz).*$|\1|p') + echo "CLIENT_DIST=$CLIENT_DIST" >> "$GITHUB_OUTPUT" - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/v') + - name: GitHub Release + uses: softprops/action-gh-release@v2 with: + generate_release_notes: true files: | ${{ steps.make-artifacts.outputs.SERVER_DIST }} ${{ steps.make-artifacts.outputs.CLIENT_DIST }} - - - name: Cache Stack - if: always() && steps.restore-stack.outputs.cache-hit != 'true' - uses: actions/cache/save@v4 - with: - path: | - /home/runner/.stack - .stack-work - server/.stack-work - client/.stack-work - key: stack-${{ hashFiles('stack.yaml.lock') }}