ci: 优化 workflow 并行度与产物传递
- check 与 build-linux 改为并行执行,节省约 10min - 新增 upload-artifact / download-artifact,deploy-mcp 直接复用二进制,免重复编译(节省约 15min) - check / build 缓存加入 target/ 目录,加速增量编译 - 提取 MUSL_TARGET 全局变量,消除 x86_64-unknown-linux-musl 硬编码 - publish-release 增加 check 结果检查,质量失败时不发布 Release - 移除 build-linux 冗余飞书通知,publish-release 汇总已覆盖 Made-with: Cursor
This commit is contained in:
@@ -7,7 +7,6 @@ on:
|
|||||||
- 'crates/**'
|
- 'crates/**'
|
||||||
- 'Cargo.toml'
|
- 'Cargo.toml'
|
||||||
- 'Cargo.lock'
|
- 'Cargo.lock'
|
||||||
# systemd / 部署模板变更也应跑构建(产物无变时可快速跳过 check)
|
|
||||||
- 'deploy/**'
|
- 'deploy/**'
|
||||||
- '.gitea/workflows/**'
|
- '.gitea/workflows/**'
|
||||||
|
|
||||||
@@ -25,6 +24,7 @@ env:
|
|||||||
CARGO_NET_RETRY: 10
|
CARGO_NET_RETRY: 10
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
RUST_BACKTRACE: short
|
RUST_BACKTRACE: short
|
||||||
|
MUSL_TARGET: x86_64-unknown-linux-musl
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
version:
|
version:
|
||||||
@@ -138,6 +138,7 @@ jobs:
|
|||||||
echo "release_id=" >> "$GITHUB_OUTPUT"
|
echo "release_id=" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# check 与 build-linux 并行执行,互不阻塞
|
||||||
check:
|
check:
|
||||||
name: 质量检查 (fmt / clippy / test)
|
name: 质量检查 (fmt / clippy / test)
|
||||||
needs: [version]
|
needs: [version]
|
||||||
@@ -165,6 +166,7 @@ jobs:
|
|||||||
~/.cargo/registry/index
|
~/.cargo/registry/index
|
||||||
~/.cargo/registry/cache
|
~/.cargo/registry/cache
|
||||||
~/.cargo/git/db
|
~/.cargo/git/db
|
||||||
|
target
|
||||||
key: cargo-check-${{ env.RUST_TOOLCHAIN }}-${{ hashFiles('Cargo.lock') }}
|
key: cargo-check-${{ env.RUST_TOOLCHAIN }}-${{ hashFiles('Cargo.lock') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
cargo-check-${{ env.RUST_TOOLCHAIN }}-
|
cargo-check-${{ env.RUST_TOOLCHAIN }}-
|
||||||
@@ -175,8 +177,8 @@ jobs:
|
|||||||
- run: cargo test --locked
|
- run: cargo test --locked
|
||||||
|
|
||||||
build-linux:
|
build-linux:
|
||||||
name: Build Linux (secrets-mcp, musl)
|
name: Build Linux (musl)
|
||||||
needs: [version, check]
|
needs: [version]
|
||||||
runs-on: debian
|
runs-on: debian
|
||||||
timeout-minutes: 25
|
timeout-minutes: 25
|
||||||
steps:
|
steps:
|
||||||
@@ -191,7 +193,7 @@ jobs:
|
|||||||
source "$HOME/.cargo/env" 2>/dev/null || true
|
source "$HOME/.cargo/env" 2>/dev/null || true
|
||||||
rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal
|
rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal
|
||||||
rustup default "${RUST_TOOLCHAIN}"
|
rustup default "${RUST_TOOLCHAIN}"
|
||||||
rustup target add x86_64-unknown-linux-musl --toolchain "${RUST_TOOLCHAIN}"
|
rustup target add ${{ env.MUSL_TARGET }} --toolchain "${RUST_TOOLCHAIN}"
|
||||||
rustc -V
|
rustc -V
|
||||||
cargo -V
|
cargo -V
|
||||||
|
|
||||||
@@ -204,15 +206,23 @@ jobs:
|
|||||||
~/.cargo/registry/index
|
~/.cargo/registry/index
|
||||||
~/.cargo/registry/cache
|
~/.cargo/registry/cache
|
||||||
~/.cargo/git/db
|
~/.cargo/git/db
|
||||||
key: cargo-x86_64-unknown-linux-musl-${{ env.RUST_TOOLCHAIN }}-${{ hashFiles('Cargo.lock') }}
|
target
|
||||||
|
key: cargo-${{ env.MUSL_TARGET }}-${{ env.RUST_TOOLCHAIN }}-${{ hashFiles('Cargo.lock') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
cargo-x86_64-unknown-linux-musl-${{ env.RUST_TOOLCHAIN }}-
|
cargo-${{ env.MUSL_TARGET }}-${{ env.RUST_TOOLCHAIN }}-
|
||||||
cargo-x86_64-unknown-linux-musl-
|
cargo-${{ env.MUSL_TARGET }}-
|
||||||
|
|
||||||
- name: 构建 secrets-mcp (musl)
|
- name: 构建 secrets-mcp (musl)
|
||||||
run: |
|
run: |
|
||||||
cargo build --release --locked --target x86_64-unknown-linux-musl -p secrets-mcp
|
cargo build --release --locked --target ${{ env.MUSL_TARGET }} -p secrets-mcp
|
||||||
strip target/x86_64-unknown-linux-musl/release/${{ env.MCP_BINARY }}
|
strip target/${{ env.MUSL_TARGET }}/release/${{ env.MCP_BINARY }}
|
||||||
|
|
||||||
|
- name: 上传构建产物
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ env.MCP_BINARY }}-linux-musl
|
||||||
|
path: target/${{ env.MUSL_TARGET }}/release/${{ env.MCP_BINARY }}
|
||||||
|
retention-days: 3
|
||||||
|
|
||||||
- name: 上传 Release 产物
|
- name: 上传 Release 产物
|
||||||
if: needs.version.outputs.release_id != ''
|
if: needs.version.outputs.release_id != ''
|
||||||
@@ -221,7 +231,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
[ -z "$RELEASE_TOKEN" ] && exit 0
|
[ -z "$RELEASE_TOKEN" ] && exit 0
|
||||||
tag="${{ needs.version.outputs.tag }}"
|
tag="${{ needs.version.outputs.tag }}"
|
||||||
bin="target/x86_64-unknown-linux-musl/release/${{ env.MCP_BINARY }}"
|
bin="target/${{ env.MUSL_TARGET }}/release/${{ env.MCP_BINARY }}"
|
||||||
archive="${{ env.MCP_BINARY }}-${tag}-x86_64-linux-musl.tar.gz"
|
archive="${{ env.MCP_BINARY }}-${tag}-x86_64-linux-musl.tar.gz"
|
||||||
tar -czf "$archive" -C "$(dirname "$bin")" "$(basename "$bin")"
|
tar -czf "$archive" -C "$(dirname "$bin")" "$(basename "$bin")"
|
||||||
sha256sum "$archive" > "${archive}.sha256"
|
sha256sum "$archive" > "${archive}.sha256"
|
||||||
@@ -231,70 +241,21 @@ jobs:
|
|||||||
curl -fsS -H "Authorization: token $RELEASE_TOKEN" \
|
curl -fsS -H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@${archive}.sha256" "$release_url"
|
-F "attachment=@${archive}.sha256" "$release_url"
|
||||||
|
|
||||||
- name: 飞书通知
|
|
||||||
if: always()
|
|
||||||
env:
|
|
||||||
WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
|
|
||||||
run: |
|
|
||||||
[ -z "$WEBHOOK_URL" ] && exit 0
|
|
||||||
command -v jq >/dev/null 2>&1 || (sudo apt-get update -qq && sudo apt-get install -y -qq jq)
|
|
||||||
tag="${{ needs.version.outputs.tag }}"
|
|
||||||
commit=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "N/A")
|
|
||||||
url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
|
||||||
result="${{ job.status }}"
|
|
||||||
if [ "$result" = "success" ]; then icon="✅"; else icon="❌"; fi
|
|
||||||
msg="secrets-mcp linux 构建${icon}
|
|
||||||
版本:${tag}
|
|
||||||
提交:${commit}
|
|
||||||
作者:${{ 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"
|
|
||||||
|
|
||||||
deploy-mcp:
|
deploy-mcp:
|
||||||
name: 部署 secrets-mcp
|
name: 部署 secrets-mcp
|
||||||
needs: [version, build-linux]
|
needs: [version, check, build-linux]
|
||||||
# 部署目标由仓库 Actions 配置:vars.DEPLOY_HOST / vars.DEPLOY_USER;私钥 secrets.DEPLOY_SSH_KEY(PEM 原文,勿 base64)
|
if: |
|
||||||
# (可用 scripts/setup-gitea-actions.sh 或 Gitea API 写入,勿写进本文件)
|
needs.check.result == 'success' &&
|
||||||
# Google OAuth / SERVER_MASTER_KEY / SECRETS_DATABASE_URL 等勿写入 CI,请在 ECS 上
|
needs.build-linux.result == 'success' &&
|
||||||
# /opt/secrets-mcp/.env 配置(见 deploy/.env.example)。
|
(github.ref == 'refs/heads/main' || github.ref == 'refs/heads/feat/mcp' || github.ref == 'refs/heads/mcp')
|
||||||
# 若仓库 main 仍为纯 CLI、仅 feat/mcp 含本 workflow,请去掉条件里的 main,避免误部署。
|
|
||||||
if: needs.build-linux.result == 'success' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/feat/mcp' || github.ref == 'refs/heads/mcp')
|
|
||||||
runs-on: debian
|
runs-on: debian
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: 下载构建产物
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
- name: 安装 Rust
|
|
||||||
run: |
|
|
||||||
if ! command -v rustup >/dev/null 2>&1; then
|
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain "${RUST_TOOLCHAIN}"
|
|
||||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
||||||
fi
|
|
||||||
source "$HOME/.cargo/env" 2>/dev/null || true
|
|
||||||
sudo apt-get update -qq && sudo apt-get install -y -qq pkg-config musl-tools
|
|
||||||
rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal
|
|
||||||
rustup default "${RUST_TOOLCHAIN}"
|
|
||||||
rustup target add x86_64-unknown-linux-musl --toolchain "${RUST_TOOLCHAIN}"
|
|
||||||
rustc -V
|
|
||||||
cargo -V
|
|
||||||
|
|
||||||
- name: 缓存 Cargo
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
with:
|
||||||
path: |
|
name: ${{ env.MCP_BINARY }}-linux-musl
|
||||||
~/.cargo/registry/index
|
path: /tmp/artifact
|
||||||
~/.cargo/registry/cache
|
|
||||||
~/.cargo/git/db
|
|
||||||
key: cargo-x86_64-unknown-linux-musl-${{ env.RUST_TOOLCHAIN }}-${{ hashFiles('Cargo.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
cargo-x86_64-unknown-linux-musl-${{ env.RUST_TOOLCHAIN }}-
|
|
||||||
cargo-x86_64-unknown-linux-musl-
|
|
||||||
|
|
||||||
- name: 构建 secrets-mcp
|
|
||||||
run: |
|
|
||||||
cargo build --release --locked --target x86_64-unknown-linux-musl -p secrets-mcp
|
|
||||||
strip target/x86_64-unknown-linux-musl/release/${{ env.MCP_BINARY }}
|
|
||||||
|
|
||||||
- name: 部署到阿里云 ECS
|
- name: 部署到阿里云 ECS
|
||||||
env:
|
env:
|
||||||
@@ -312,7 +273,7 @@ jobs:
|
|||||||
|
|
||||||
SCP="scp -i /tmp/deploy_key -o StrictHostKeyChecking=no"
|
SCP="scp -i /tmp/deploy_key -o StrictHostKeyChecking=no"
|
||||||
|
|
||||||
$SCP target/x86_64-unknown-linux-musl/release/${{ env.MCP_BINARY }} \
|
$SCP /tmp/artifact/${{ env.MCP_BINARY }} \
|
||||||
"${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/secrets-mcp.new"
|
"${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/secrets-mcp.new"
|
||||||
|
|
||||||
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no "${DEPLOY_USER}@${DEPLOY_HOST}" "
|
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no "${DEPLOY_USER}@${DEPLOY_HOST}" "
|
||||||
@@ -333,13 +294,11 @@ jobs:
|
|||||||
[ -z "$WEBHOOK_URL" ] && exit 0
|
[ -z "$WEBHOOK_URL" ] && exit 0
|
||||||
command -v jq >/dev/null 2>&1 || (sudo apt-get update -qq && sudo apt-get install -y -qq jq)
|
command -v jq >/dev/null 2>&1 || (sudo apt-get update -qq && sudo apt-get install -y -qq jq)
|
||||||
tag="${{ needs.version.outputs.tag }}"
|
tag="${{ needs.version.outputs.tag }}"
|
||||||
commit=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "N/A")
|
|
||||||
url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
||||||
result="${{ job.status }}"
|
result="${{ job.status }}"
|
||||||
if [ "$result" = "success" ]; then icon="✅"; else icon="❌"; fi
|
if [ "$result" = "success" ]; then icon="✅"; else icon="❌"; fi
|
||||||
msg="secrets-mcp 部署${icon}
|
msg="secrets-mcp 部署${icon}
|
||||||
版本:${tag}
|
版本:${tag}
|
||||||
提交:${commit}
|
|
||||||
作者:${{ github.actor }}
|
作者:${{ github.actor }}
|
||||||
详情:${url}"
|
详情:${url}"
|
||||||
payload=$(jq -n --arg text "$msg" '{msg_type: "text", content: {text: $text}}')
|
payload=$(jq -n --arg text "$msg" '{msg_type: "text", content: {text: $text}}')
|
||||||
@@ -347,22 +306,21 @@ jobs:
|
|||||||
|
|
||||||
publish-release:
|
publish-release:
|
||||||
name: 发布草稿 Release
|
name: 发布草稿 Release
|
||||||
needs: [version, build-linux]
|
needs: [version, check, build-linux]
|
||||||
if: always() && needs.version.outputs.release_id != ''
|
if: always() && needs.version.outputs.release_id != ''
|
||||||
runs-on: debian
|
runs-on: debian
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: 发布草稿
|
- name: 发布草稿
|
||||||
env:
|
env:
|
||||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
[ -z "$RELEASE_TOKEN" ] && exit 0
|
[ -z "$RELEASE_TOKEN" ] && exit 0
|
||||||
|
|
||||||
|
check_r="${{ needs.check.result }}"
|
||||||
linux_r="${{ needs.build-linux.result }}"
|
linux_r="${{ needs.build-linux.result }}"
|
||||||
if [ "$linux_r" != "success" ]; then
|
if [ "$check_r" != "success" ] || [ "$linux_r" != "success" ]; then
|
||||||
echo "linux 构建未成功,保留草稿 Release"
|
echo "质量检查或构建未成功(check=${check_r}, build=${linux_r}),保留草稿 Release"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -394,13 +352,16 @@ jobs:
|
|||||||
[ -z "$commit" ] && commit="${{ github.sha }}"
|
[ -z "$commit" ] && commit="${{ github.sha }}"
|
||||||
url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
||||||
|
|
||||||
|
check_r="${{ needs.check.result }}"
|
||||||
linux_r="${{ needs.build-linux.result }}"
|
linux_r="${{ needs.build-linux.result }}"
|
||||||
publish_r="${{ job.status }}"
|
publish_r="${{ job.status }}"
|
||||||
|
|
||||||
icon() { case "$1" in success) echo "✅";; skipped) echo "⏭";; *) echo "❌";; esac; }
|
icon() { case "$1" in success) echo "✅";; skipped) echo "⏭";; *) echo "❌";; esac; }
|
||||||
|
|
||||||
if [ "$linux_r" = "success" ] && [ "$publish_r" = "success" ]; then
|
if [ "$check_r" = "success" ] && [ "$linux_r" = "success" ] && [ "$publish_r" = "success" ]; then
|
||||||
status="发布成功 ✅"
|
status="发布成功 ✅"
|
||||||
|
elif [ "$check_r" != "success" ]; then
|
||||||
|
status="检查失败 ❌"
|
||||||
elif [ "$linux_r" != "success" ]; then
|
elif [ "$linux_r" != "success" ]; then
|
||||||
status="构建失败 ❌"
|
status="构建失败 ❌"
|
||||||
else
|
else
|
||||||
@@ -415,7 +376,7 @@ jobs:
|
|||||||
|
|
||||||
msg="secrets-mcp ${status}
|
msg="secrets-mcp ${status}
|
||||||
${version_line}
|
${version_line}
|
||||||
linux $(icon "$linux_r") | Release $(icon "$publish_r")
|
check $(icon "$check_r") | linux $(icon "$linux_r") | Release $(icon "$publish_r")
|
||||||
提交:${commit}
|
提交:${commit}
|
||||||
作者:${{ github.actor }}
|
作者:${{ github.actor }}
|
||||||
详情:${url}"
|
详情:${url}"
|
||||||
|
|||||||
Reference in New Issue
Block a user