From d7a78102a978fbd269074690ff7c53a7fd25801f Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 15 May 2026 04:05:45 +0800 Subject: [PATCH] ci(release): add tag-driven release workflow --- .github/workflows/release.yml | 148 ++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..cb28903 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,148 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + +permissions: + contents: read + +env: + CARGO_TERM_COLOR: always + RUST_PROFILE: minimal + RUST_TOOLCHAIN: stable + +jobs: + validate: + name: Validate release version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check tag matches Cargo.toml version + id: version + run: | + python3 <<'PY' + import os + import re + import sys + import tomllib + + tag = os.environ["GITHUB_REF_NAME"] + if not re.fullmatch(r"v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)", tag): + print(f"Tag {tag!r} must match vMAJOR.MINOR.PATCH.", file=sys.stderr) + sys.exit(1) + + with open("Cargo.toml", "rb") as cargo_toml: + cargo_version = tomllib.load(cargo_toml)["package"]["version"] + + tag_version = tag.removeprefix("v") + if cargo_version != tag_version: + print( + f"Cargo.toml version {cargo_version!r} does not match tag {tag!r}.", + file=sys.stderr, + ) + sys.exit(1) + + with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output: + print(f"version={cargo_version}", file=output) + PY + + build: + name: Build ${{ matrix.target }} + needs: validate + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + - os: macos-latest + target: x86_64-apple-darwin + - os: macos-latest + target: aarch64-apple-darwin + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache Rust toolchain + uses: actions/cache@v4 + with: + path: | + ~/.rustup/toolchains + ~/.rustup/update-hashes + key: rustup-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN }}-${{ env.RUST_PROFILE }}-${{ matrix.target }} + restore-keys: | + rustup-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN }}-${{ env.RUST_PROFILE }}- + rustup-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN }}- + + - name: Install Rust + run: | + rustup toolchain install "$RUST_TOOLCHAIN" --profile "$RUST_PROFILE" --no-self-update + rustup target add "${{ matrix.target }}" --toolchain "$RUST_TOOLCHAIN" + + - name: Cache Cargo dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/git/db + ~/.cargo/registry/cache + ~/.cargo/registry/index + target + key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN }}-${{ matrix.target }}-${{ hashFiles('Cargo.lock') }} + restore-keys: | + cargo-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN }}-${{ matrix.target }}- + cargo-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN }}- + cargo-${{ runner.os }}-${{ runner.arch }}- + + - name: Build release binary + run: cargo build --locked --release --target "${{ matrix.target }}" + + - name: Package binary + run: | + package="confluence-cli-${{ needs.validate.outputs.version }}-${{ matrix.target }}" + mkdir -p "$package" dist + cp "target/${{ matrix.target }}/release/confluence-cli" "$package/confluence-cli" + tar -czf "dist/$package.tar.gz" "$package" + + - name: Upload release artifact + uses: actions/upload-artifact@v4 + with: + name: confluence-cli-${{ matrix.target }} + path: dist/*.tar.gz + if-no-files-found: error + + release: + name: Create GitHub Release + needs: + - validate + - build + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download release artifacts + uses: actions/download-artifact@v4 + with: + pattern: confluence-cli-* + path: dist + merge-multiple: true + + - name: Create release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "${{ github.ref_name }}" dist/*.tar.gz \ + --title "${{ github.ref_name }}" \ + --generate-notes