release: 0.25.5.0 (Tor onion-service support) #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Triggered when a version tag is pushed. The existing tag format on this | |
| # repo is MAJOR.MINOR.PATCH.BUILD (no `v` prefix), e.g. 0.25.3.0. | |
| # | |
| # Also exposed as `workflow_dispatch` so the maintainer can rebuild and | |
| # re-upload assets for an existing tag without re-tagging. | |
| on: | |
| push: | |
| tags: | |
| - '[0-9]+.[0-9]+.[0-9]+.[0-9]+' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Existing tag to build and upload assets for' | |
| required: true | |
| type: string | |
| jobs: | |
| static-linux: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # The amd64 leg is the "primary": it also extracts the CHANGELOG | |
| # section for the release body. No arm64 leg: the static | |
| # (musl) cross-GHC fails to build for aarch64-linux (rts | |
| # compile errors), so there is nothing to ship; the arm64 | |
| # docker image covers that platform with dynamic binaries. | |
| - arch: x86_64-linux | |
| arch_short: amd64 | |
| runner: ubuntu-latest | |
| primary: true | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: write # for creating/updating the release and uploading assets | |
| steps: | |
| - name: Resolve tag | |
| id: tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "name=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "name=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.tag.outputs.name }} | |
| - name: Install Nix | |
| uses: DeterminateSystems/nix-installer-action@main | |
| - name: Set up nix store cache (GitHub Actions cache) | |
| uses: DeterminateSystems/magic-nix-cache-action@main | |
| - name: Build .#packages.${{ matrix.arch }}.static | |
| run: | | |
| nix build .#packages.${{ matrix.arch }}.static --no-link --print-out-paths -L | |
| - name: Package binaries | |
| id: pkg | |
| run: | | |
| set -euo pipefail | |
| STATIC=$(nix eval --raw .#packages.${{ matrix.arch }}.static) | |
| TAG="${{ steps.tag.outputs.name }}" | |
| DIR="hbs2-${TAG}-${{ matrix.arch_short }}-linux-musl" | |
| mkdir -p "${DIR}/bin" | |
| # cp -L resolves the symlinkJoin's symlinks into actual files. | |
| cp -L "${STATIC}/bin"/* "${DIR}/bin/" | |
| chmod +w "${DIR}/bin"/* # strip read-only from nix store | |
| # Include a small README so the archive is self-explanatory. | |
| cat > "${DIR}/README.txt" <<EOF | |
| hbs2 ${TAG}, statically linked against musl libc. | |
| Built for ${{ matrix.arch }}. No runtime dependencies; copy the bin/ | |
| contents anywhere on PATH. | |
| Source: https://github.com/NCrashed/hbs2 | |
| EOF | |
| ARCHIVE="${DIR}.tar.gz" | |
| tar czf "${ARCHIVE}" "${DIR}" | |
| echo "archive=${ARCHIVE}" >> "$GITHUB_OUTPUT" | |
| ls -la "${ARCHIVE}" | |
| sha256sum "${ARCHIVE}" | tee "${ARCHIVE}.sha256" | |
| - name: Extract release notes from CHANGELOG | |
| if: matrix.primary | |
| run: | | |
| set -euo pipefail | |
| TAG="${{ steps.tag.outputs.name }}" | |
| # Pull the section starting at `# ${TAG}` up to the next | |
| # top-level version header. | |
| awk -v tag="${TAG}" ' | |
| /^# [0-9]/ { | |
| if (found) exit | |
| if ($2 == tag) { found = 1; next } | |
| } | |
| found { print } | |
| ' CHANGELOG.md > release-body.md | |
| if [ ! -s release-body.md ]; then | |
| echo "::warning::No CHANGELOG section found for ${TAG}; release body will be empty" | |
| echo "Release ${TAG}." > release-body.md | |
| fi | |
| echo "--- release-body.md ---" | |
| cat release-body.md | |
| echo "--- end ---" | |
| - name: Upload to GitHub Release (primary, with body) | |
| if: matrix.primary | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.name }} | |
| body_path: release-body.md | |
| files: | | |
| ${{ steps.pkg.outputs.archive }} | |
| ${{ steps.pkg.outputs.archive }}.sha256 | |
| fail_on_unmatched_files: true | |
| - name: Upload to GitHub Release (secondary, assets only) | |
| if: ${{ !matrix.primary }} | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.name }} | |
| files: | | |
| ${{ steps.pkg.outputs.archive }} | |
| ${{ steps.pkg.outputs.archive }}.sha256 | |
| fail_on_unmatched_files: true | |
| darwin-bundle: | |
| # macos-latest is an Apple Silicon (arm64) runner since macos-14, | |
| # which is exactly the only darwin target we ship (the formula in | |
| # NCrashed/homebrew-hbs2 is on_arm-only). | |
| runs-on: macos-latest | |
| permissions: | |
| contents: write # for uploading release assets | |
| steps: | |
| - name: Resolve tag | |
| id: tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "name=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "name=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.tag.outputs.name }} | |
| - name: Install Nix | |
| uses: DeterminateSystems/nix-installer-action@main | |
| - name: Set up nix store cache (GitHub Actions cache) | |
| uses: DeterminateSystems/magic-nix-cache-action@main | |
| - name: Overlay bundle script from workflow ref | |
| # The checkout above is at the release tag, but older tags predate | |
| # scripts/bundle-darwin.sh. Take the script from the commit this | |
| # workflow run was dispatched from (github.sha) so the script and | |
| # the workflow always evolve together; for tag pushes github.sha | |
| # is the tag commit and this is a no-op. | |
| run: | | |
| set -euo pipefail | |
| if [ ! -x scripts/bundle-darwin.sh ]; then | |
| git fetch --depth 1 origin "${{ github.sha }}" | |
| mkdir -p scripts | |
| git show "${{ github.sha }}:scripts/bundle-darwin.sh" > scripts/bundle-darwin.sh | |
| chmod +x scripts/bundle-darwin.sh | |
| fi | |
| - name: Build darwin bundle | |
| run: ./scripts/bundle-darwin.sh "${{ steps.tag.outputs.name }}" | |
| - name: Smoke test bundle | |
| run: | | |
| set -euo pipefail | |
| TAG="${{ steps.tag.outputs.name }}" | |
| BUNDLE="dist-darwin/hbs2-${TAG}-aarch64-apple-darwin" | |
| # No leftover /nix/store references may survive bundling. | |
| for f in "${BUNDLE}/bin"/* "${BUNDLE}/lib"/*; do | |
| [ -L "$f" ] && continue | |
| if otool -L "$f" | grep -q '/nix/store'; then | |
| echo "::error::${f} still references /nix/store" | |
| otool -L "$f" | |
| exit 1 | |
| fi | |
| done | |
| "${BUNDLE}/bin/hbs2-peer" version | |
| "${BUNDLE}/bin/hbs2-cli" --help >/dev/null | |
| "${BUNDLE}/bin/hbs2-sync" --help >/dev/null | |
| - name: Upload to GitHub Release (assets only) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.name }} | |
| files: | | |
| dist-darwin/hbs2-${{ steps.tag.outputs.name }}-aarch64-apple-darwin.tar.gz | |
| dist-darwin/hbs2-${{ steps.tag.outputs.name }}-aarch64-apple-darwin.tar.gz.sha256 | |
| fail_on_unmatched_files: true | |
| homebrew-tap: | |
| # Bumps version/url/sha256 in NCrashed/homebrew-hbs2 once the darwin | |
| # asset is uploaded. Pushing to another repo needs more than the | |
| # job-scoped GITHUB_TOKEN: a fine-grained PAT with contents:write on | |
| # homebrew-hbs2, stored as the HOMEBREW_TAP_TOKEN secret. If the | |
| # secret is absent the job warns and exits green so tap-less forks | |
| # do not break the release. | |
| needs: darwin-bundle | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Resolve tag | |
| id: tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "name=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "name=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Bump formula in homebrew-hbs2 | |
| env: | |
| TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| OWNER: ${{ github.repository_owner }} | |
| REPO: ${{ github.repository }} | |
| TAG: ${{ steps.tag.outputs.name }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${TAP_TOKEN}" ]; then | |
| echo "::warning::HOMEBREW_TAP_TOKEN secret not set; skipping formula bump" | |
| exit 0 | |
| fi | |
| ASSET="hbs2-${TAG}-aarch64-apple-darwin.tar.gz" | |
| SHA=$(curl -fsSL "https://github.com/${REPO}/releases/download/${TAG}/${ASSET}.sha256" | awk '{print $1}') | |
| echo "sha256: ${SHA}" | |
| git clone --depth 1 "https://x-access-token:${TAP_TOKEN}@github.com/${OWNER}/homebrew-hbs2.git" tap | |
| cd tap | |
| F=Formula/hbs2-peer.rb | |
| sed -i -E "s|^( version \").*(\")|\1${TAG}\2|" "$F" | |
| sed -i -E "s|releases/download/[^/]+/hbs2-[^/]+-aarch64-apple-darwin\.tar\.gz|releases/download/${TAG}/${ASSET}|" "$F" | |
| sed -i -E "s|^( sha256 \").*(\")|\1${SHA}\2|" "$F" | |
| git diff | |
| if git diff --quiet; then | |
| echo "Formula already up to date for ${TAG}" | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git commit -am "hbs2-peer ${TAG}" | |
| git push | |
| docker-linux: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: x86_64-linux | |
| arch_short: amd64 | |
| runner: ubuntu-latest | |
| - arch: aarch64-linux | |
| arch_short: arm64 | |
| runner: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| packages: write # for pushing to ghcr.io | |
| steps: | |
| - name: Resolve tag | |
| id: tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "name=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "name=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.tag.outputs.name }} | |
| - name: Install Nix | |
| uses: DeterminateSystems/nix-installer-action@main | |
| - name: Set up nix store cache (GitHub Actions cache) | |
| uses: DeterminateSystems/magic-nix-cache-action@main | |
| - name: Build .#packages.${{ matrix.arch }}.docker | |
| run: | | |
| nix build .#packages.${{ matrix.arch }}.docker --print-out-paths -L | |
| - name: Load and push per-arch image | |
| env: | |
| # GITHUB_TOKEN has packages:write on this job via the permissions | |
| # block above; ghcr.io accepts it for github.repository_owner. | |
| REGISTRY: ghcr.io | |
| # github.repository_owner preserves the original GitHub case | |
| # (e.g. NCrashed), but OCI image references must be all | |
| # lowercase. Normalise here. | |
| OWNER_RAW: ${{ github.repository_owner }} | |
| TAG: ${{ steps.tag.outputs.name }} | |
| ARCH_SHORT: ${{ matrix.arch_short }} | |
| run: | | |
| set -euo pipefail | |
| OWNER="${OWNER_RAW,,}" | |
| IMAGE="${REGISTRY}/${OWNER}/hbs2-peer" | |
| # `docker load` reads the gzipped OCI tarball produced by buildImage. | |
| IMAGE_LOCAL=$(docker load -i ./result | awk '/Loaded image:/ {print $NF}') | |
| echo "Loaded: ${IMAGE_LOCAL}" | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login "$REGISTRY" -u "${{ github.actor }}" --password-stdin | |
| # Per-arch tag only; the manifest list pinning :TAG / :latest is | |
| # done by the docker-manifest job once both arches are pushed. | |
| docker tag "${IMAGE_LOCAL}" "${IMAGE}:${TAG}-${ARCH_SHORT}" | |
| docker push "${IMAGE}:${TAG}-${ARCH_SHORT}" | |
| docker-manifest: | |
| needs: docker-linux | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Resolve tag | |
| id: tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "name=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "name=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Login to GHCR | |
| env: | |
| REGISTRY: ghcr.io | |
| run: | | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login "$REGISTRY" -u "${{ github.actor }}" --password-stdin | |
| - name: Create multi-arch manifest for :TAG and :latest | |
| env: | |
| REGISTRY: ghcr.io | |
| OWNER_RAW: ${{ github.repository_owner }} | |
| TAG: ${{ steps.tag.outputs.name }} | |
| run: | | |
| set -euo pipefail | |
| OWNER="${OWNER_RAW,,}" | |
| IMAGE="${REGISTRY}/${OWNER}/hbs2-peer" | |
| # docker buildx imagetools is preinstalled on ubuntu-latest. | |
| docker buildx imagetools create -t "${IMAGE}:${TAG}" \ | |
| "${IMAGE}:${TAG}-amd64" \ | |
| "${IMAGE}:${TAG}-arm64" | |
| docker buildx imagetools create -t "${IMAGE}:latest" \ | |
| "${IMAGE}:${TAG}-amd64" \ | |
| "${IMAGE}:${TAG}-arm64" |