feat(strip-prefix): single-segment wildcard prefix (/apps/*) #36
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 | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| permissions: | |
| contents: write | |
| jobs: | |
| # ─────────────────────────────────────────────── | |
| # Gate: CI checks must pass before any publishing | |
| # ─────────────────────────────────────────────── | |
| ci: | |
| name: CI Checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup workspace context | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: bash .github/setup-workspace.sh | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Format check | |
| run: cargo fmt -p a3s-gateway -- --check | |
| - name: Clippy | |
| run: cargo clippy -p a3s-gateway --all-features -- -D warnings | |
| - name: Tests | |
| run: cargo test -p a3s-gateway --lib | |
| # ─────────────────────────────────────────────── | |
| # Build cross-compiled binaries | |
| # ─────────────────────────────────────────────── | |
| build: | |
| name: Build / ${{ matrix.target }} | |
| needs: ci | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: aarch64-apple-darwin | |
| os: macos-latest | |
| - target: x86_64-apple-darwin | |
| os: macos-latest | |
| - target: x86_64-unknown-linux-gnu | |
| os: ubuntu-latest | |
| - target: aarch64-unknown-linux-gnu | |
| os: ubuntu-latest | |
| use_cross: true | |
| - target: x86_64-unknown-linux-musl | |
| os: ubuntu-latest | |
| use_zigbuild: true | |
| - target: aarch64-unknown-linux-musl | |
| os: ubuntu-latest | |
| use_zigbuild: true | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup workspace context | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: bash .github/setup-workspace.sh | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: ${{ matrix.target }} | |
| - name: Install cross | |
| if: matrix.use_cross == true | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cross | |
| - name: Install cargo-zigbuild | |
| if: matrix.use_zigbuild == true | |
| run: | | |
| pip3 install ziglang --quiet | |
| cargo install cargo-zigbuild --quiet | |
| - name: Build | |
| # Linux targets enable `kube` and `redis` features for K8s Ingress + distributed rate-limiting. | |
| # macOS keeps default features (no K8s deployment use case). | |
| run: | | |
| if [[ "${{ matrix.target }}" == *"linux"* ]]; then | |
| FEATURES="--features kube,redis" | |
| else | |
| FEATURES="" | |
| fi | |
| if [ "${{ matrix.use_cross }}" = "true" ]; then | |
| cross build -p a3s-gateway --release --target ${{ matrix.target }} $FEATURES | |
| elif [ "${{ matrix.use_zigbuild }}" = "true" ]; then | |
| cargo zigbuild -p a3s-gateway --release --target ${{ matrix.target }} $FEATURES | |
| else | |
| cargo build -p a3s-gateway --release --target ${{ matrix.target }} $FEATURES | |
| fi | |
| - name: Strip (Linux gnu) | |
| if: runner.os == 'Linux' && matrix.use_zigbuild != true | |
| run: | | |
| BIN="target/${{ matrix.target }}/release/a3s-gateway" | |
| if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then | |
| sudo apt-get install -y --no-install-recommends binutils-aarch64-linux-gnu | |
| aarch64-linux-gnu-strip "$BIN" | |
| else | |
| strip "$BIN" | |
| fi | |
| - name: Strip (Linux musl) | |
| if: matrix.use_zigbuild == true | |
| run: | | |
| sudo apt-get install -y --no-install-recommends llvm | |
| llvm-strip "target/${{ matrix.target }}/release/a3s-gateway" | |
| - name: Strip (macOS) | |
| if: runner.os == 'macOS' | |
| run: strip "target/${{ matrix.target }}/release/a3s-gateway" | |
| - name: Package | |
| id: pkg | |
| run: | | |
| BIN="target/${{ matrix.target }}/release/a3s-gateway" | |
| VER="${GITHUB_REF_NAME#v}" | |
| # Map Rust target triple to updater's os-arch format | |
| case "${{ matrix.target }}" in | |
| aarch64-apple-darwin) PLATFORM="darwin-arm64" ;; | |
| x86_64-apple-darwin) PLATFORM="darwin-x86_64" ;; | |
| x86_64-unknown-linux-gnu) PLATFORM="linux-x86_64" ;; | |
| aarch64-unknown-linux-gnu) PLATFORM="linux-arm64" ;; | |
| x86_64-unknown-linux-musl) PLATFORM="linux-x86_64-musl" ;; | |
| aarch64-unknown-linux-musl) PLATFORM="linux-arm64-musl" ;; | |
| *) PLATFORM="${{ matrix.target }}" ;; | |
| esac | |
| ARCHIVE="a3s-gateway-${VER}-${PLATFORM}.tar.gz" | |
| tar czf "$ARCHIVE" -C "$(dirname $BIN)" a3s-gateway | |
| sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256" | |
| echo "archive=$ARCHIVE" >> "$GITHUB_OUTPUT" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.target }} | |
| path: | | |
| ${{ steps.pkg.outputs.archive }} | |
| ${{ steps.pkg.outputs.archive }}.sha256 | |
| # ─────────────────────────────────────────────── | |
| # Create GitHub Release with binaries | |
| # ─────────────────────────────────────────────── | |
| github-release: | |
| name: GitHub Release | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Collect assets | |
| run: | | |
| mkdir release | |
| find artifacts -type f \( -name '*.tar.gz' -o -name '*.sha256' \) \ | |
| -exec cp {} release/ \; | |
| ls -lh release/ | |
| - name: Generate release notes | |
| run: | | |
| VER="${GITHUB_REF_NAME#v}" | |
| # Extract the section for this version from CHANGELOG.md | |
| if [ -f CHANGELOG.md ]; then | |
| awk "/^## \[${VER}\]/{found=1; next} /^## \[/{if(found) exit} found" CHANGELOG.md > /tmp/notes.md | |
| fi | |
| # Fallback to git log if CHANGELOG section is empty | |
| if [ ! -s /tmp/notes.md ]; then | |
| PREV_TAG=$(git tag --sort=-v:refname | grep '^v' | head -2 | tail -1) | |
| if [ -z "$PREV_TAG" ]; then | |
| echo "Initial release." > /tmp/notes.md | |
| else | |
| git log "${PREV_TAG}..HEAD" --oneline --no-merges \ | |
| --pretty=format:"- %s" | head -60 > /tmp/notes.md | |
| fi | |
| fi | |
| - name: Create or update release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if gh release view "$GITHUB_REF_NAME" &>/dev/null; then | |
| gh release upload "$GITHUB_REF_NAME" release/* --clobber | |
| else | |
| gh release create "$GITHUB_REF_NAME" release/* \ | |
| --title "$GITHUB_REF_NAME" \ | |
| --notes-file /tmp/notes.md | |
| fi | |
| # ─────────────────────────────────────────────── | |
| # Publish to crates.io | |
| # ─────────────────────────────────────────────── | |
| publish-crate: | |
| name: Publish to crates.io | |
| needs: ci | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup workspace context | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: bash .github/setup-workspace.sh | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Publish dry-run | |
| working-directory: crates/gateway | |
| run: cargo publish --dry-run --allow-dirty | |
| - name: Publish | |
| working-directory: crates/gateway | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }} | |
| run: cargo publish --allow-dirty | |
| # ─────────────────────────────────────────────── | |
| # Build and push multi-arch OCI images to GHCR | |
| # ─────────────────────────────────────────────── | |
| publish-oci: | |
| name: Publish OCI Images | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download musl binaries | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: bin | |
| - name: Extract binaries and prepare build contexts | |
| shell: bash | |
| run: | | |
| mkdir -p bin/linux-amd64 bin/linux-arm64 | |
| tar -xzf bin/x86_64-unknown-linux-musl/*.tar.gz -C bin/linux-amd64 | |
| mv bin/linux-amd64/a3s-gateway bin/linux-amd64/a3s-gateway-amd64 | |
| tar -xzf bin/aarch64-unknown-linux-musl/*.tar.gz -C bin/linux-arm64 | |
| mv bin/linux-arm64/a3s-gateway bin/linux-arm64/a3s-gateway-arm64 | |
| cp Dockerfile bin/linux-amd64/ | |
| cp Dockerfile bin/linux-arm64/ | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract version | |
| id: version | |
| run: | | |
| VER="${GITHUB_REF_NAME#v}" | |
| REGISTRY="ghcr.io/$(echo "$GITHUB_REPOSITORY_OWNER" | tr '[:upper:]' '[:lower:]')/gateway" | |
| echo "VER=$VER" >> "$GITHUB_OUTPUT" | |
| echo "REGISTRY=$REGISTRY" >> "$GITHUB_OUTPUT" | |
| - name: Build and push linux/amd64 | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: bin/linux-amd64 | |
| file: bin/linux-amd64/Dockerfile | |
| platforms: linux/amd64 | |
| build-args: BINARY_NAME=a3s-gateway-amd64 | |
| tags: ${{ steps.version.outputs.REGISTRY }}:${{ steps.version.outputs.VER }}-amd64 | |
| push: true | |
| provenance: false | |
| - name: Build and push linux/arm64 | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: bin/linux-arm64 | |
| file: bin/linux-arm64/Dockerfile | |
| platforms: linux/arm64 | |
| build-args: BINARY_NAME=a3s-gateway-arm64 | |
| tags: ${{ steps.version.outputs.REGISTRY }}:${{ steps.version.outputs.VER }}-arm64 | |
| push: true | |
| provenance: false | |
| - name: Create and push multi-arch manifest | |
| run: | | |
| REGISTRY="${{ steps.version.outputs.REGISTRY }}" | |
| VER="${{ steps.version.outputs.VER }}" | |
| # Create manifest for versioned tag | |
| docker buildx imagetools create -t "${REGISTRY}:${VER}" \ | |
| "${REGISTRY}:${VER}-amd64" \ | |
| "${REGISTRY}:${VER}-arm64" | |
| # Create manifest for latest tag | |
| docker buildx imagetools create -t "${REGISTRY}:latest" \ | |
| "${REGISTRY}:${VER}-amd64" \ | |
| "${REGISTRY}:${VER}-arm64" | |
| - name: Verify multi-arch manifest | |
| run: | | |
| REGISTRY="${{ steps.version.outputs.REGISTRY }}" | |
| VER="${{ steps.version.outputs.VER }}" | |
| echo "=== ${REGISTRY}:${VER} ===" | |
| docker buildx imagetools inspect "${REGISTRY}:${VER}" | |
| echo "" | |
| echo "=== ${REGISTRY}:latest ===" | |
| docker buildx imagetools inspect "${REGISTRY}:latest" | |
| # ─────────────────────────────────────────────── | |
| # Update Homebrew formula | |
| # ─────────────────────────────────────────────── | |
| update-homebrew: | |
| name: Update Homebrew | |
| needs: github-release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Compute sha256 | |
| id: sha | |
| run: | | |
| VER="${GITHUB_REF_NAME#v}" | |
| sha() { sha256sum "artifacts/$1/a3s-gateway-${GITHUB_REF_NAME}-$1.tar.gz" | awk '{print $1}'; } | |
| echo "ver=$VER" >> "$GITHUB_OUTPUT" | |
| echo "macos_arm64=$(sha aarch64-apple-darwin)" >> "$GITHUB_OUTPUT" | |
| echo "macos_x64=$(sha x86_64-apple-darwin)" >> "$GITHUB_OUTPUT" | |
| echo "linux_arm64=$(sha aarch64-unknown-linux-musl)" >> "$GITHUB_OUTPUT" | |
| echo "linux_x64=$(sha x86_64-unknown-linux-musl)" >> "$GITHUB_OUTPUT" | |
| - uses: actions/checkout@v4 | |
| with: | |
| repository: A3S-Lab/homebrew-tap | |
| token: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| path: homebrew-tap | |
| - name: Regenerate formula | |
| working-directory: homebrew-tap | |
| env: | |
| VER: ${{ steps.sha.outputs.ver }} | |
| SHA_MACOS_ARM64: ${{ steps.sha.outputs.macos_arm64 }} | |
| SHA_MACOS_X64: ${{ steps.sha.outputs.macos_x64 }} | |
| SHA_LINUX_ARM64: ${{ steps.sha.outputs.linux_arm64 }} | |
| SHA_LINUX_X64: ${{ steps.sha.outputs.linux_x64 }} | |
| run: python3 ../.github/update-homebrew-formula.py | |
| - name: Commit and push | |
| working-directory: homebrew-tap | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add Formula/a3s-gateway.rb | |
| git diff --cached --quiet && exit 0 | |
| git commit -m "chore: update a3s-gateway to v${{ steps.sha.outputs.ver }}" | |
| git push origin main |