name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag_name:
description: "Tag name to release (e.g. v0.2.0)"
required: false
type: string
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
ci:
name: CI Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Format check
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --workspace --lib --bins -- -D warnings
- name: Tests
run: cargo test --workspace --lib
publish-crate:
name: Publish to crates.io
needs: [ci]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }}
run: |
VERSION=$(cargo metadata --no-deps --format-version 1 | python3 -c 'import json,sys; print(json.load(sys.stdin)["packages"][0]["version"])')
if curl -fsSL "https://crates.io/api/v1/crates/a3s-acl/${VERSION}" >/dev/null 2>&1; then
echo "a3s-acl ${VERSION} already exists on crates.io, skipping publish."
exit 0
fi
set +e
OUTPUT=$(cargo publish --allow-dirty 2>&1)
STATUS=$?
set -e
echo "$OUTPUT"
if [ "$STATUS" -ne 0 ]; then
if echo "$OUTPUT" | grep -Eqi "already (uploaded|exists)"; then
echo "a3s-acl ${VERSION} was already published, treating as success."
exit 0
fi
exit "$STATUS"
fi
publish-node:
name: Publish Node SDK to npm
needs: [ci]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: https://registry.npmjs.org
- name: Install dependencies
working-directory: sdk/node
run: npm install
- name: TypeScript check
working-directory: sdk/node
run: npx tsc --noEmit
- name: Publish to npm
working-directory: sdk/node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
set -euo pipefail
NAME="$(node -p "require('./package.json').name")"
VERSION="$(node -p "require('./package.json').version")"
if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then
echo "${NAME}@${VERSION} already exists on npm, skipping."
exit 0
fi
set +e
OUTPUT="$(npm publish --access public 2>&1)"
STATUS=$?
set -e
echo "$OUTPUT"
if [ "$STATUS" -ne 0 ]; then
if echo "$OUTPUT" | grep -Eqi "previously published|cannot publish over|already exists"; then
echo "${NAME}@${VERSION} was already published, treating as success."
exit 0
fi
exit "$STATUS"
fi
github-release:
name: GitHub Release
needs: [publish-crate, publish-node]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate release notes
run: |
PREV_TAG=$(git tag --sort=-v:refname | grep '^v' | head -2 | tail -1)
if [ -z "$PREV_TAG" ]; then
echo "Initial release" > /tmp/release-notes.md
else
git log "${PREV_TAG}..HEAD" --oneline --no-merges --pretty=format:"- %s" | head -50 > /tmp/release-notes.md
fi
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.inputs.tag_name || github.ref_name }}
run: |
if gh release view "$RELEASE_TAG" &>/dev/null; then
gh release edit "$RELEASE_TAG" \
--title "$RELEASE_TAG" \
--notes-file /tmp/release-notes.md
else
gh release create "$RELEASE_TAG" \
--title "$RELEASE_TAG" \
--notes-file /tmp/release-notes.md
fi