name: release on: push: tags: ['v*'] permissions: contents: read concurrency: group: release-${{ github.ref }} jobs: gate: runs-on: ubuntu-latest outputs: release: ${{ steps.check.outputs.release }} steps: # The tag filter accepts v1.2.3-rc1 too; only plain vX[.Y.Z] tags # are releases, everything else makes this job a no-op so the # publish job reports "skipped" instead of failing. - id: check run: | if [[ "$GITHUB_REF_NAME" =~ ^v[0-9]+(\.[0-9]+)*$ ]]; then echo "release=true" >> "$GITHUB_OUTPUT" else echo "release=false" >> "$GITHUB_OUTPUT" fi build-snap: needs: gate if: needs.gate.outputs.release == 'true' strategy: fail-fast: false matrix: include: - os: ubuntu-latest artifact: snap-amd64 # GitHub's free arm64 runners build the arm64 snap natively: # libkrun compiles there, and the libkrunfw part picks the # arm64 pool .deb through CRAFT_ARCH_BUILD_FOR. riscv64 is a # declared platform but has no hosted runner: build and # publish that snap by hand (snapcraft remote-build). - os: ubuntu-24.04-arm artifact: snap-arm64 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Stamp the tag version into the manifests run: | v="${GITHUB_REF_NAME#v}" sed -i "s/^version = \".*\"/version = \"$v\"/" Cargo.toml # The snap adopts this version from Cargo.toml at pull time. grep -H '^version' Cargo.toml - uses: snapcore/action-build@v1 id: build - uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} path: ${{ steps.build.outputs.snap }} # The macos distribution is a signed tarball, not a store release: # brew taps install from it, and the entitlement signature rides in # the artifact. build-macos: needs: gate if: needs.gate.outputs.release == 'true' runs-on: macos-26 timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Stamp the tag version into the manifests run: | v="${GITHUB_REF_NAME#v}" sed -i '' "s/^version = \".*\"/version = \"$v\"/" Cargo.toml grep -H '^version' Cargo.toml - name: Build the CLI run: cargo build --release -p ecrou-cli - name: Sign the binary with the hypervisor entitlement run: codesign --force --sign - --entitlements packaging/macos/ecrou.entitlements target/release/ecrou - name: Package run: | v="${GITHUB_REF_NAME#v}" tar -czf "ecrou-v$v-darwin-arm64.tar.gz" -C target/release ecrou shasum -a 256 "ecrou-v$v-darwin-arm64.tar.gz" > "ecrou-v$v-darwin-arm64.tar.gz.sha256" mkdir dist && mv ecrou-v$v-darwin-* dist/ - uses: actions/upload-artifact@v4 with: name: ecrou-darwin-arm64 path: dist/* # The tap repo (vhaudiquet/homebrew-ecrou) is a publish target, not # the source of truth: the formula is maintained in packaging/ and # this job rewrites its url/sha256 for the release tarball and pushes # it. Needs a PAT with push access to the tap repo as the # HOMEBREW_TAP_TOKEN secret; without it the job is a no-op so tags # still release. update-homebrew: needs: build-macos runs-on: ubuntu-latest timeout-minutes: 5 steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: name: ecrou-darwin-arm64 path: dist - name: Push the formula to the tap env: TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} run: | set -euo pipefail if [[ -z "$TAP_TOKEN" ]]; then echo "::notice::no HOMEBREW_TAP_TOKEN secret set; tap not updated" exit 0 fi v="${GITHUB_REF_NAME#v}" sha="$(cut -d' ' -f1 "dist/ecrou-v$v-darwin-arm64.tar.gz.sha256")" url="https://github.com/vhaudiquet/ecrou/archive/refs/tags/v$v.tar.gz" mkdir -p formula/Formula sed -e 's|^ # Pinned by tag until the first release exists; switch to the$| # Published by the ecrou release workflow; do not edit by hand.|' -e '/^ # release tarball + sha256 then\.$/d' -e "s|^ url \"https://github.com/vhaudiquet/ecrou.git\", tag: \"v0.1.0\"$| url \"$url\"\n sha256 \"$sha\"|" \ packaging/homebrew/Formula/ecrou.rb > formula/Formula/ecrou.rb grep -q "sha256 \"$sha\"" formula/Formula/ecrou.rb git clone -q "https://x-access-token:$TAP_TOKEN@github.com/vhaudiquet/homebrew-ecrou" tap cp formula/Formula/ecrou.rb tap/Formula/ecrou.rb cd tap git add Formula/ecrou.rb git -c user.name="ecrou-release" -c user.email="noreply@github.com" \ commit -m "ecrou $v" git push -q publish-snap: needs: build-snap runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 with: pattern: snap-* path: snaps - name: Resolve the snap paths id: paths run: | echo "amd64=$(ls snaps/snap-amd64/*.snap)" >> "$GITHUB_OUTPUT" echo "arm64=$(ls snaps/snap-arm64/*.snap)" >> "$GITHUB_OUTPUT" # Requires the SNAP_STORE_LOGIN secret: the output of # snapcraft export-login --snaps ecrou --channels stable - - uses: snapcore/action-publish@v1 env: SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} with: snap: ${{ steps.paths.outputs.amd64 }} release: stable - uses: snapcore/action-publish@v1 env: SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} with: snap: ${{ steps.paths.outputs.arm64 }} release: stable