From acc55da874ea4374cceb995a619a5ef2157de084 Mon Sep 17 00:00:00 2001 From: rustmailer Date: Fri, 18 Jul 2025 11:21:11 +0800 Subject: [PATCH] chore(release): add complete GitHub Actions workflow for multi-platform release --- .github/workflows/release.yml | 107 ++++++++++++++++++++++++++++++++++ cliff.toml | 58 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 cliff.toml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..617b816 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,107 @@ +name: Release RustMailer + +on: + push: + tags: + - '[0-9]+.[0-9]+.[0-9]+' + +permissions: + contents: write + +jobs: + build: + name: Build ${{ matrix.target }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - target: x86_64-unknown-linux-gnu + os: ubuntu-latest + - target: x86_64-unknown-linux-musl + os: ubuntu-latest + - target: x86_64-apple-darwin + os: macos-latest + - target: x86_64-pc-windows-msvc + os: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: actions/setup-rust@v1 + with: + rust-version: stable + targets: ${{ matrix.target }} + + - name: Setup Node.js & pnpm + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "pnpm" + + - name: Install pnpm + run: npm install -g pnpm + + - name: Build frontend (web) + working-directory: ./web + run: | + pnpm install + pnpm run build + + - name: Add MUSL target (if needed) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: rustup target add x86_64-unknown-linux-musl + + - name: Build Rust backend + run: cargo build --release --target=${{ matrix.target }} + + - name: Prepare dist directory + run: mkdir -p dist + + - name: Copy binary to dist + run: | + BIN=rustmailer + EXT="" + if [[ "${{ matrix.target }}" == *windows* ]]; then EXT=".exe"; fi + cp target/${{ matrix.target }}/release/${BIN}${EXT} dist/ + + - name: Pack artifact + run: | + cd dist + tar -czvf rustmailer-${{ github.ref_name }}-${{ matrix.target }}.tar.gz rustmailer* + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }} + path: dist/rustmailer-${{ github.ref_name }}-${{ matrix.target }}.tar.gz + + release: + name: Create GitHub Release + needs: build + runs-on: ubuntu-latest + + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Generate changelog with git-cliff + id: changelog + uses: orhun/git-cliff-action@v2 + with: + args: --tag ${{ github.ref_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} + body: ${{ steps.changelog.outputs.content }} + draft: false + prerelease: false + files: ./artifacts/**/*.tar.gz diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..2974985 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,58 @@ +# configuration file for git-cliff (0.1.0) + +[changelog] +# changelog header +header = """ +# RustMailer Changelog\n +""" +# template for the changelog body +# https://tera.netlify.app/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# remove the leading and trailing whitespace from the template +trim = true +# changelog footer +footer = """ + +""" + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = false +# filter out the commits that are not conventional +filter_unconventional = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/rustmailer/rustmailer/issues/${2}))"}, +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat\\(frontend\\):", group = "Frontend Features" }, + { message = "^fix\\(backend\\):", group = "Backend Fixes" }, + { message = "^docs:", group = "Documentation" }, + { message = "^ci:", group = "CI/CD" }, + { message = ".*", group = "Others" }, +] +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "^[0-9]+(\\.[0-9]+){2}$" +# regex for skipping tags +#skip_tags = "v0.1.0-beta.1" +# regex for ignoring tags +ignore_tags = "" +# sort the tags chronologically +date_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" \ No newline at end of file