name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-apple-darwin
os: macos-15
- target: aarch64-apple-darwin
os: macos-15
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
- target: x86_64-pc-windows-msvc
os: windows-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.96.1
targets: ${{ matrix.target }}
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install cargo-nextest
if: matrix.target == 'x86_64-pc-windows-msvc'
uses: taiki-e/install-action@v2
with:
tool: nextest@0.9.114
- name: Run Windows tests
if: matrix.target == 'x86_64-pc-windows-msvc'
run: cargo nextest run --lib --bins
- name: Build
run: cargo build --release --target ${{ matrix.target }} --features vendored-openssl
- name: Package (Unix)
if: matrix.target != 'x86_64-pc-windows-msvc'
run: |
cd target/${{ matrix.target }}/release
tar czf ../../../stax-${{ matrix.target }}.tar.gz stax st
cd ../../..
- name: Package (Windows)
if: matrix.target == 'x86_64-pc-windows-msvc'
shell: pwsh
run: |
Compress-Archive -Path "target/${{ matrix.target }}/release/stax.exe","target/${{ matrix.target }}/release/st.exe" -DestinationPath "stax-${{ matrix.target }}.zip"
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: stax-${{ matrix.target }}
path: stax-${{ matrix.target }}.*
gui-build:
name: Build Stax.app ${{ matrix.target }}
runs-on: macos-15
strategy:
fail-fast: false
matrix:
include:
- target: aarch64-apple-darwin
- target: x86_64-apple-darwin
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.96.1
targets: ${{ matrix.target }}
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
key: gui-${{ matrix.target }}
- name: Resolve app version
shell: bash
run: |
set -euo pipefail
package_version="$(cargo pkgid -p stax-gui | sed 's/.*#//')"
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
release_version="${GITHUB_REF_NAME#v}"
if [ "$release_version" != "$package_version" ]; then
echo "Release tag $GITHUB_REF_NAME does not match stax-gui $package_version." >&2
exit 1
fi
else
release_version="$package_version"
fi
echo "STAX_GUI_VERSION=$release_version" >> "$GITHUB_ENV"
echo "STAX_GUI_BUILD_NUMBER=$GITHUB_RUN_NUMBER" >> "$GITHUB_ENV"
- name: Configure optional signing certificate
shell: bash
env:
CERTIFICATE_P12: ${{ secrets.MACOS_CERTIFICATE_P12 }}
CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
run: |
set -euo pipefail
configured=0
for value in "$CERTIFICATE_P12" "$CERTIFICATE_PASSWORD" "$SIGNING_IDENTITY"; do
if [ -n "$value" ]; then
configured=$((configured + 1))
fi
done
if [ "$configured" -eq 0 ]; then
echo "STAX_GUI_SIGNING_IDENTITY=" >> "$GITHUB_ENV"
exit 0
fi
if [ "$configured" -ne 3 ]; then
echo "MACOS_CERTIFICATE_P12, MACOS_CERTIFICATE_PASSWORD, and MACOS_SIGNING_IDENTITY must be configured together." >&2
exit 1
fi
certificate_path="$RUNNER_TEMP/stax-signing.p12"
keychain_path="$RUNNER_TEMP/stax-signing.keychain-db"
keychain_password="$(openssl rand -hex 24)"
printf '%s' "$CERTIFICATE_P12" | base64 -D > "$certificate_path"
security create-keychain -p "$keychain_password" "$keychain_path"
security set-keychain-settings -lut 21600 "$keychain_path"
security unlock-keychain -p "$keychain_password" "$keychain_path"
security import "$certificate_path" \
-k "$keychain_path" \
-P "$CERTIFICATE_PASSWORD" \
-A \
-t cert \
-f pkcs12
security set-key-partition-list \
-S apple-tool:,apple:,codesign: \
-s \
-k "$keychain_password" \
"$keychain_path"
security list-keychains -d user -s "$keychain_path"
rm -f "$certificate_path"
echo "STAX_GUI_SIGNING_IDENTITY=$SIGNING_IDENTITY" >> "$GITHUB_ENV"
echo "STAX_GUI_KEYCHAIN=$keychain_path" >> "$GITHUB_ENV"
- name: Package app release
shell: bash
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
scripts/package-gui-release.sh \
--target "${{ matrix.target }}" \
--version "$STAX_GUI_VERSION" \
--build-number "$STAX_GUI_BUILD_NUMBER" \
--output-dir "$GITHUB_WORKSPACE"
- name: Upload app artifact
uses: actions/upload-artifact@v7
with:
name: Stax-${{ matrix.target }}
path: Stax-${{ matrix.target }}.zip
- name: Remove temporary signing keychain
if: always()
shell: bash
run: |
if [ -n "${STAX_GUI_KEYCHAIN:-}" ]; then
security delete-keychain "$STAX_GUI_KEYCHAIN"
fi
release:
name: Release
needs: [build, gui-build]
if: needs.build.result == 'success' && needs.gui-build.result == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Generate release notes
id: git-cliff
uses: orhun/git-cliff-action@v4
with:
config: cliff.toml
args: --latest --strip header
- name: Download all artifacts
uses: actions/download-artifact@v8
with:
path: artifacts
merge-multiple: true
- name: List artifacts
run: ls -la artifacts/
- name: Verify release artifacts
run: |
set -euo pipefail
expected_artifacts=(
stax-x86_64-apple-darwin.tar.gz
stax-aarch64-apple-darwin.tar.gz
stax-x86_64-unknown-linux-gnu.tar.gz
stax-aarch64-unknown-linux-gnu.tar.gz
stax-x86_64-pc-windows-msvc.zip
Stax-aarch64-apple-darwin.zip
Stax-x86_64-apple-darwin.zip
)
for artifact in "${expected_artifacts[@]}"; do
test -f "artifacts/${artifact}" || {
echo "Missing release artifact: ${artifact}" >&2
exit 1
}
done
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
files: artifacts/*
body: ${{ steps.git-cliff.outputs.content }}
- name: Compute checksums
run: |
cd artifacts
echo "ARM_SHA=$(sha256sum stax-aarch64-apple-darwin.tar.gz | cut -d' ' -f1)" >> $GITHUB_ENV
echo "INTEL_SHA=$(sha256sum stax-x86_64-apple-darwin.tar.gz | cut -d' ' -f1)" >> $GITHUB_ENV
echo "LINUX_SHA=$(sha256sum stax-x86_64-unknown-linux-gnu.tar.gz | cut -d' ' -f1)" >> $GITHUB_ENV
echo "LINUX_ARM_SHA=$(sha256sum stax-aarch64-unknown-linux-gnu.tar.gz | cut -d' ' -f1)" >> $GITHUB_ENV
- name: Checkout Homebrew tap
uses: actions/checkout@v7
with:
repository: cesarferreira/homebrew-tap
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: tap
- name: Update formula
env:
VERSION: ${{ github.ref_name }}
run: |
CLEAN_VERSION=${VERSION#v}
FORMULA=tap/Formula/stax.rb
sed -i "s/version \".*\"/version \"$CLEAN_VERSION\"/" $FORMULA
sed -i "s|releases/download/v[^/]*/stax-|releases/download/$VERSION/stax-|g" $FORMULA
sed -i "s/sha256 \"[a-f0-9]\{64\}\"/sha256 \"PLACEHOLDER\"/g" $FORMULA
sed -i "0,/PLACEHOLDER/s/PLACEHOLDER/$ARM_SHA/" $FORMULA
sed -i "0,/PLACEHOLDER/s/PLACEHOLDER/$INTEL_SHA/" $FORMULA
sed -i "0,/PLACEHOLDER/s/PLACEHOLDER/$LINUX_ARM_SHA/" $FORMULA
sed -i "0,/PLACEHOLDER/s/PLACEHOLDER/$LINUX_SHA/" $FORMULA
- name: Commit and push tap
env:
VERSION: ${{ github.ref_name }}
run: |
cd tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/stax.rb
git commit -m "stax $VERSION"
git push