Files
secrets/.gitea/workflows/secrets.yml
voson 102e394914
Some checks failed
Secrets CLI - Build & Release / 检查版本 (push) Successful in 2s
Secrets CLI - Build & Release / Build (x86_64-unknown-linux-musl) (push) Failing after 41s
Secrets CLI - Build & Release / Build (aarch64-apple-darwin) (push) Failing after 55s
Secrets CLI - Build & Release / 发送通知 (push) Has been cancelled
Secrets CLI - Build & Release / Build (x86_64-pc-windows-msvc) (push) Has been cancelled
feat: secrets CLI MVP — add/search/delete with PostgreSQL JSONB
- Single `secrets` table with namespace/kind/name/tags/metadata/encrypted
- Auto-migrate on startup using uuidv7() primary keys and GIN indexes
- CLI commands: add (upsert, @file support), search (full-text + tags), delete
- Multi-platform Gitea Actions: debian (x86_64-musl), darwin-arm64, windows
  - continue-on-error + timeout-minutes=30 for offline runner tolerance
- VS Code tasks.json for local build/test/seed
- AGENTS.md for AI context

Made-with: Cursor
2026-03-18 14:10:45 +08:00

314 lines
12 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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:
# ========== 版本检查(只跑一次,供后续 job 共用)==========
version:
name: 检查版本
runs-on: debian
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
tag_exists: ${{ steps.version.outputs.tag_exists }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 检查版本
id: version
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.version.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.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}"
git push origin "${{ steps.version.outputs.tag }}"
# ========== 矩阵构建 ==========
build:
name: Build (${{ matrix.target }})
needs: version
continue-on-error: true # 某平台失败/超时不阻断其他平台和 notify
timeout-minutes: 30 # runner 不在线时 30 分钟后放弃
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 jq curl git pkg-config musl-tools binutils
if ! command -v cargo &>/dev/null; then
echo "安装 Rust 工具链..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
source "$HOME/.cargo/env"
rustup component add rustfmt clippy
fi
rustup target add ${{ matrix.target }}
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: 安装依赖 (macOS)
if: matrix.os == 'macos'
run: |
brew install jq
if ! command -v cargo &>/dev/null; then
echo "安装 Rust 工具链..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
source "$HOME/.cargo/env"
rustup component add rustfmt clippy
fi
rustup target add ${{ matrix.target }}
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: 安装依赖 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: |
# 检查 Rust 是否已安装
if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) {
Write-Host "安装 Rust 工具链..."
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 component add rustfmt clippy
rustup target add ${{ matrix.target }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
# ========== Cargo 缓存 ==========
- name: 缓存 Cargo 依赖
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: cargo-secrets-${{ matrix.target }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-secrets-${{ matrix.target }}-
- name: 检查代码格式
if: matrix.os != 'windows'
run: cargo fmt -- --check
- name: 检查代码格式 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: cargo fmt -- --check
- name: 运行 Clippy 检查
if: matrix.os != 'windows'
run: cargo clippy --release --target ${{ matrix.target }} -- -D warnings
- name: 运行 Clippy 检查 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: cargo clippy --release --target ${{ matrix.target }} -- -D warnings
- name: 构建
if: matrix.os != 'windows'
env:
GIT_TAG: ${{ needs.version.outputs.version }}
run: cargo build --release --target ${{ matrix.target }} --verbose
- name: 构建 (Windows)
if: matrix.os == 'windows'
shell: pwsh
env:
GIT_TAG: ${{ needs.version.outputs.version }}
run: cargo build --release --target ${{ matrix.target }} --verbose
- 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 }}
# ========== 上传 Release 产物 ==========
- name: 上传 Release 产物 (Linux/macOS)
if: needs.version.outputs.tag_exists == 'false' && matrix.os != 'windows'
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
[ -z "$RELEASE_TOKEN" ] && echo "跳过:未配置 RELEASE_TOKEN" && exit 0
tag="${{ needs.version.outputs.tag }}"
binary="target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}"
archive="${{ env.BINARY_NAME }}-${tag}-${{ matrix.archive_suffix }}.tar.gz"
tar -czf "$archive" -C "$(dirname $binary)" "$(basename $binary)"
# 查找已有 Release由首个完成的 job 创建,后续 job 直接上传)
release_url="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases"
release_id=$(curl -sS -H "Authorization: token $RELEASE_TOKEN" \
"${release_url}/tags/${tag}" | jq -r '.id // empty')
if [ -z "$release_id" ]; then
release_id=$(curl -sS -H "Authorization: token $RELEASE_TOKEN" \
-H "Content-Type: application/json" \
-X POST "$release_url" \
-d "{\"tag_name\": \"${tag}\", \"name\": \"${tag}\", \"body\": \"Release ${tag}\"}" \
| jq -r '.id')
fi
upload_url="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/${release_id}/assets"
curl -sS -H "Authorization: token $RELEASE_TOKEN" \
-F "attachment=@${archive}" \
"$upload_url"
echo "已上传: ${archive} → Release ${tag}"
- name: 上传 Release 产物 (Windows)
if: needs.version.outputs.tag_exists == 'false' && matrix.os == 'windows'
shell: pwsh
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
if (-not $env:RELEASE_TOKEN) { Write-Host "跳过:未配置 RELEASE_TOKEN"; exit 0 }
$tag = "${{ needs.version.outputs.tag }}"
$binary = "target\${{ matrix.target }}\release\${{ env.BINARY_NAME }}.exe"
$archive = "${{ env.BINARY_NAME }}-${tag}-${{ matrix.archive_suffix }}.zip"
Compress-Archive -Path $binary -DestinationPath $archive
$headers = @{ "Authorization" = "token $env:RELEASE_TOKEN"; "Content-Type" = "application/json" }
$release_url = "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases"
# 查找已有 Release
$existing = Invoke-RestMethod -Uri "${release_url}/tags/${tag}" -Headers $headers -ErrorAction SilentlyContinue
if ($existing.id) {
$release_id = $existing.id
} else {
$body = @{ tag_name = $tag; name = $tag; body = "Release ${tag}" } | ConvertTo-Json
$release_id = (Invoke-RestMethod -Uri $release_url -Method Post -Headers $headers -Body $body).id
}
$upload_url = "${release_url}/${release_id}/assets"
$upload_headers = @{ "Authorization" = "token $env:RELEASE_TOKEN" }
$form = @{ attachment = Get-Item $archive }
Invoke-RestMethod -Uri $upload_url -Method Post -Headers $upload_headers -Form $form
Write-Host "已上传: ${archive} → Release ${tag}"
# ========== 汇总通知 ==========
notify:
name: 发送通知
needs: [version, build]
if: always() && github.event_name == 'push'
runs-on: debian
steps:
- uses: actions/checkout@v4
- name: 发送通知
continue-on-error: true
env:
WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
run: |
[ -z "$WEBHOOK_URL" ] && exit 0
tag="${{ needs.version.outputs.tag }}"
tag_exists="${{ needs.version.outputs.tag_exists }}"
build_result="${{ needs.build.result }}"
if [ "$build_result" = "success" ]; then
status_text="构建成功 ✅"
else
status_text="构建失败 ❌"
fi
commit_title=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "N/A")
workflow_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
if [ "$build_result" != "success" ]; then
payload=$(jq -n \
--arg title "${{ env.BINARY_NAME }} ${status_text}" \
--arg commit "$commit_title" \
--arg version "$tag" \
--arg author "${{ github.actor }}" \
--arg url "$workflow_url" \
'{msg_type: "text", content: {text: "\($title)\n提交\($commit)\n版本\($version)\n作者\($author)\n详情\($url)"}}')
elif [ "$tag_exists" = "false" ]; then
payload=$(jq -n \
--arg title "${{ env.BINARY_NAME }} ${status_text}" \
--arg commit "$commit_title" \
--arg version "$tag" \
--arg author "${{ github.actor }}" \
--arg url "$workflow_url" \
'{msg_type: "text", content: {text: "\($title)\n🆕 新版本已发布 (linux / macOS / windows)\n提交\($commit)\n版本\($version)\n作者\($author)\n详情\($url)"}}')
else
payload=$(jq -n \
--arg title "${{ env.BINARY_NAME }} ${status_text}" \
--arg commit "$commit_title" \
--arg version "$tag" \
--arg author "${{ github.actor }}" \
--arg url "$workflow_url" \
'{msg_type: "text", content: {text: "\($title)\n🔄 重复构建\n提交\($commit)\n版本\($version)\n作者\($author)\n详情\($url)"}}')
fi
curl -sS -H "Content-Type: application/json" -X POST -d "$payload" "$WEBHOOK_URL"