Some checks failed
Secrets CLI - Build & Release / 版本 & Release (push) Successful in 1s
Secrets CLI - Build & Release / 通知 (push) Successful in 2s
Secrets CLI - Build & Release / 质量检查 (fmt / clippy / test) (push) Successful in 23s
Secrets CLI - Build & Release / Build (aarch64-apple-darwin) (push) Successful in 20s
Secrets CLI - Build & Release / Build (x86_64-unknown-linux-musl) (push) Successful in 28s
Secrets CLI - Build & Release / Build (x86_64-pc-windows-msvc) (push) Has been cancelled
Make notification fire independently of matrix builds so stalled runners do not block release publishing. Made-with: Cursor
277 lines
9.7 KiB
YAML
277 lines
9.7 KiB
YAML
name: Secrets CLI - Build & Release
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'src/**'
|
|
- 'Cargo.toml'
|
|
- 'Cargo.lock'
|
|
- '.gitea/workflows/secrets.yml'
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
env:
|
|
BINARY_NAME: secrets
|
|
CARGO_INCREMENTAL: 0
|
|
CARGO_NET_RETRY: 10
|
|
CARGO_TERM_COLOR: always
|
|
RUST_BACKTRACE: short
|
|
|
|
jobs:
|
|
# ========== 版本检查 + Release 预创建(单次运行,消除多 job 竞态)==========
|
|
version:
|
|
name: 版本 & Release
|
|
runs-on: debian
|
|
outputs:
|
|
version: ${{ steps.ver.outputs.version }}
|
|
tag: ${{ steps.ver.outputs.tag }}
|
|
tag_exists: ${{ steps.ver.outputs.tag_exists }}
|
|
release_id: ${{ steps.release.outputs.release_id }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: 解析版本
|
|
id: ver
|
|
run: |
|
|
version=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
|
|
tag="secrets-${version}"
|
|
echo "version=${version}" >> $GITHUB_OUTPUT
|
|
echo "tag=${tag}" >> $GITHUB_OUTPUT
|
|
|
|
if git rev-parse "refs/tags/${tag}" >/dev/null 2>&1; then
|
|
echo "tag_exists=true" >> $GITHUB_OUTPUT
|
|
echo "版本 ${tag} 已存在"
|
|
else
|
|
echo "tag_exists=false" >> $GITHUB_OUTPUT
|
|
echo "将创建新版本 ${tag}"
|
|
fi
|
|
|
|
- name: 创建 Tag
|
|
if: steps.ver.outputs.tag_exists == 'false'
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
git tag -a "${{ steps.ver.outputs.tag }}" -m "Release ${{ steps.ver.outputs.tag }}"
|
|
git push origin "${{ steps.ver.outputs.tag }}"
|
|
|
|
- name: 预创建 Release
|
|
id: release
|
|
if: steps.ver.outputs.tag_exists == 'false'
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
if [ -z "$RELEASE_TOKEN" ]; then
|
|
echo "release_id=" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
fi
|
|
|
|
command -v jq &>/dev/null || (sudo apt-get update -qq && sudo apt-get install -y -qq jq)
|
|
|
|
tag="${{ steps.ver.outputs.tag }}"
|
|
url="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases"
|
|
release_id=$(curl -sS -H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" -X POST "$url" \
|
|
-d "{\"tag_name\":\"${tag}\",\"name\":\"${tag}\",\"body\":\"Release ${tag}\"}" \
|
|
| jq -r '.id // empty')
|
|
|
|
echo "release_id=${release_id}" >> $GITHUB_OUTPUT
|
|
|
|
# ========== 代码质量检查(只在 Linux 跑一次)==========
|
|
check:
|
|
name: 质量检查 (fmt / clippy / test)
|
|
runs-on: debian
|
|
timeout-minutes: 1 # 超时1分钟
|
|
steps:
|
|
- name: 安装 Rust
|
|
run: |
|
|
if ! command -v cargo &>/dev/null; then
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
|
|
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
|
fi
|
|
source "$HOME/.cargo/env" 2>/dev/null || true
|
|
rustup component add rustfmt clippy
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 缓存 Cargo
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry/index
|
|
~/.cargo/registry/cache
|
|
~/.cargo/git/db
|
|
target
|
|
key: cargo-check-${{ hashFiles('Cargo.lock') }}
|
|
restore-keys: cargo-check-
|
|
|
|
- run: cargo fmt -- --check
|
|
- run: cargo clippy --locked -- -D warnings
|
|
- run: cargo test --locked
|
|
|
|
# ========== 多平台构建 ==========
|
|
build:
|
|
name: Build (${{ matrix.target }})
|
|
needs: [version, check]
|
|
continue-on-error: true
|
|
timeout-minutes: 10
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: debian
|
|
target: x86_64-unknown-linux-musl
|
|
archive_suffix: x86_64-linux-musl
|
|
os: linux
|
|
- runner: darwin-arm64
|
|
target: aarch64-apple-darwin
|
|
archive_suffix: aarch64-macos
|
|
os: macos
|
|
- runner: windows
|
|
target: x86_64-pc-windows-msvc
|
|
archive_suffix: x86_64-windows
|
|
os: windows
|
|
|
|
runs-on: ${{ matrix.runner }}
|
|
steps:
|
|
- name: 安装依赖 (Linux)
|
|
if: matrix.os == 'linux'
|
|
run: |
|
|
sudo apt-get update && sudo apt-get install -y pkg-config musl-tools binutils curl
|
|
if ! command -v cargo &>/dev/null; then
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
|
|
fi
|
|
source "$HOME/.cargo/env" 2>/dev/null || true
|
|
rustup target add ${{ matrix.target }}
|
|
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
|
|
|
- name: 安装依赖 (macOS)
|
|
if: matrix.os == 'macos'
|
|
run: |
|
|
if ! command -v cargo &>/dev/null; then
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
|
|
fi
|
|
source "$HOME/.cargo/env" 2>/dev/null || true
|
|
rustup target add ${{ matrix.target }}
|
|
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
|
|
|
- name: 安装依赖 (Windows)
|
|
if: matrix.os == 'windows'
|
|
shell: pwsh
|
|
run: |
|
|
if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) {
|
|
Invoke-WebRequest -Uri "https://win.rustup.rs/x86_64" -OutFile rustup-init.exe
|
|
.\rustup-init.exe -y --default-toolchain stable
|
|
Remove-Item rustup-init.exe
|
|
}
|
|
rustup target add ${{ matrix.target }}
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 缓存 Cargo
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry/index
|
|
~/.cargo/registry/cache
|
|
~/.cargo/git/db
|
|
target
|
|
key: cargo-${{ matrix.target }}-${{ hashFiles('Cargo.lock') }}
|
|
restore-keys: cargo-${{ matrix.target }}-
|
|
|
|
- name: 构建
|
|
if: matrix.os != 'windows'
|
|
run: cargo build --release --locked --target ${{ matrix.target }}
|
|
|
|
- name: 构建 (Windows)
|
|
if: matrix.os == 'windows'
|
|
shell: pwsh
|
|
run: cargo build --release --locked --target ${{ matrix.target }}
|
|
|
|
- name: Strip (Linux)
|
|
if: matrix.os == 'linux'
|
|
run: strip target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}
|
|
|
|
- name: Strip (macOS)
|
|
if: matrix.os == 'macos'
|
|
run: strip -x target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}
|
|
|
|
- name: 上传产物 (Linux/macOS)
|
|
if: needs.version.outputs.tag_exists == 'false' && needs.version.outputs.release_id && matrix.os != 'windows'
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
[ -z "$RELEASE_TOKEN" ] && exit 0
|
|
tag="${{ needs.version.outputs.tag }}"
|
|
bin="target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}"
|
|
archive="${{ env.BINARY_NAME }}-${tag}-${{ matrix.archive_suffix }}.tar.gz"
|
|
tar -czf "$archive" -C "$(dirname $bin)" "$(basename $bin)"
|
|
curl -sS -H "Authorization: token $RELEASE_TOKEN" \
|
|
-F "attachment=@${archive}" \
|
|
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/${{ needs.version.outputs.release_id }}/assets"
|
|
echo "已上传: ${archive}"
|
|
|
|
- name: 上传产物 (Windows)
|
|
if: needs.version.outputs.tag_exists == 'false' && needs.version.outputs.release_id && matrix.os == 'windows'
|
|
shell: pwsh
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
if (-not $env:RELEASE_TOKEN) { exit 0 }
|
|
$tag = "${{ needs.version.outputs.tag }}"
|
|
$bin = "target\${{ matrix.target }}\release\${{ env.BINARY_NAME }}.exe"
|
|
$archive = "${{ env.BINARY_NAME }}-${tag}-${{ matrix.archive_suffix }}.zip"
|
|
Compress-Archive -Path $bin -DestinationPath $archive
|
|
$url = "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/${{ needs.version.outputs.release_id }}/assets"
|
|
Invoke-RestMethod -Uri $url -Method Post `
|
|
-Headers @{ "Authorization" = "token $env:RELEASE_TOKEN" } `
|
|
-Form @{ attachment = Get-Item $archive }
|
|
Write-Host "已上传: ${archive}"
|
|
|
|
# ========== 通知 ==========
|
|
notify:
|
|
name: 通知
|
|
needs: [version]
|
|
if: always() && github.event_name == 'push'
|
|
runs-on: debian
|
|
timeout-minutes: 1
|
|
continue-on-error: true
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 发送飞书通知
|
|
env:
|
|
WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
|
|
run: |
|
|
[ -z "$WEBHOOK_URL" ] && exit 0
|
|
command -v jq &>/dev/null || (sudo apt-get update -qq && sudo apt-get install -y -qq jq)
|
|
|
|
tag="${{ needs.version.outputs.tag }}"
|
|
tag_exists="${{ needs.version.outputs.tag_exists }}"
|
|
commit=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "N/A")
|
|
url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
|
|
|
msg="${{ env.BINARY_NAME }} 通知"
|
|
if [ "$tag_exists" = "false" ]; then
|
|
msg="${msg}
|
|
🆕 已创建版本标签并开始构建发布"
|
|
else
|
|
msg="${msg}
|
|
🔄 检测到已有版本标签,已开始重复构建"
|
|
fi
|
|
msg="${msg}
|
|
提交:${commit}
|
|
版本:${tag}
|
|
作者:${{ github.actor }}
|
|
详情:${url}"
|
|
|
|
payload=$(jq -n --arg text "$msg" '{msg_type:"text",content:{text:$text}}')
|
|
curl -sS -H "Content-Type: application/json" -X POST -d "$payload" "$WEBHOOK_URL"
|