Skip to content

release: 0.25.5.0 (Tor onion-service support) #11

release: 0.25.5.0 (Tor onion-service support)

release: 0.25.5.0 (Tor onion-service support) #11

Workflow file for this run

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"