Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/bin/sh
# EasyBot pre-commit hook
# 安装: cargo-husky 在 cargo build 时自动配置
# 安装: bin/build.rs 在 cargo build/check/test 时自动配置 core.hooksPath
#
# 提交前自动检查 cargo fmt 和 cargo clippy,不通过则阻止提交。
# fmt 会尝试自动格式化后再阻止,clippy 直接阻止
# 提交前只运行快速检查,不通过则阻止提交。
# 更重的 clippy/test 放到 pre-push,完整验收请运行 make verify
#
# 跳过检查(不推荐): git commit --no-verify

Expand All @@ -15,7 +15,7 @@ if command -v cargo >/dev/null 2>&1; then
elif command -v wsl >/dev/null 2>&1; then
CARGO="wsl cargo"
else
echo ">>> 跳过 cargo fmt/clippy(cargo 不可用)"
echo ">>> 跳过 Rust 检查(cargo 不可用)"
exit 0
fi

Expand All @@ -33,13 +33,12 @@ if git diff --cached --name-only --diff-filter=ACMR | grep -q '\.rs$'; then
fi
echo ">>> cargo fmt 通过"

# ── cargo clippy ──
echo ">>> 检查 cargo clippy..."
if ! $CARGO clippy --all-targets -- -D warnings 2>/dev/null; then
# ── cargo check ──
echo ">>> 快速编译检查 cargo check..."
if ! $CARGO check --workspace --features "default,plugin-system"; then
echo ""
echo ">>> cargo clippy 未通过。请修复以上 warning/error 后重试。"
echo " 快速查看: cargo clippy --all-targets"
echo ">>> cargo check 未通过。请修复以上 error 后重试。"
exit 1
fi
echo ">>> cargo clippy 通过"
echo ">>> cargo check 通过"
fi
49 changes: 21 additions & 28 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#!/bin/sh
# EasyBot pre-push hook
# 安装: cargo-husky 在 cargo build 时自动配置
# 安装: bin/build.rs 在 cargo build/check/test 时自动配置 core.hooksPath
#
# push 前自动运行验收脚本,失败则阻止推送,避免 CI 不通过。
# 完整模式(默认):bash scripts/verify.sh
# 快速模式:设置 git config easybot.pre-push-fast true
# push 前自动运行中等强度门禁,失败则阻止推送,避免核心 CI 失败。
# 完整模式:设置 git config --bool easybot.pre-push-full true

set -e

Expand All @@ -13,34 +12,28 @@ if [ -z "$PROJECT_DIR" ]; then
echo ">>> 不在 git 仓库中,跳过验收"
exit 0
fi
SCRIPT="$PROJECT_DIR/scripts/verify.sh"

FULL=$(git config --bool easybot.pre-push-full 2>/dev/null || echo false)

if [ "$FULL" = true ]; then
SCRIPT="$PROJECT_DIR/scripts/verify.sh"
LABEL="完整验收"
else
SCRIPT="$PROJECT_DIR/scripts/verify-push.sh"
LABEL="push 门禁"
fi

if [ ! -f "$SCRIPT" ]; then
echo ">>> 找不到 $SCRIPT,跳过验收"
echo ">>> 找不到 $SCRIPT,跳过 $LABEL"
exit 0
fi

FAST=$(git config --bool easybot.pre-push-fast 2>/dev/null || echo false)

if [ "$FAST" = true ]; then
echo ">>> [快速模式] 运行验收 (check + matrix + build + test)..."
if bash "$SCRIPT" --fast; then
echo ">>> 验收通过,正在推送..."
exit 0
else
echo ""
echo "❌ 验收未通过,推送已阻止。修复后重试。"
exit 1
fi
echo ">>> 运行 $LABEL..."
if bash "$SCRIPT"; then
echo ">>> $LABEL 通过,正在推送..."
exit 0
else
echo ">>> [完整模式] 运行验收 (全部 8 步: fmt + clippy + check + matrix + build + test)..."
echo " (如嫌太慢可切换到快速模式: git config --bool easybot.pre-push-fast true)"
if bash "$SCRIPT"; then
echo ">>> 验收通过,正在推送..."
exit 0
else
echo ""
echo "❌ 验收未通过,推送已阻止。修复后重试。"
exit 1
fi
echo ""
echo "pre-push 未通过,推送已阻止。修复后重试。"
exit 1
fi
24 changes: 4 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,11 @@ jobs:
- name: Check (${{ matrix.features }})
run: cargo check --workspace ${{ matrix.features }} --locked

# ── Cross-platform check (Linux arm64, macOS arm64, Windows x64/arm64) ──
# ── Cross-platform check (Linux/macOS/Windows × x64/arm64) ──
cross-check:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-24.04-arm
- os: macos-latest
- os: windows-latest
- os: windows-11-arm
fail-fast: false
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
with:
install-protoc: auto
cache-shared-key: cross-check-${{ runner.os }}-${{ runner.arch }}
cache-save-if: ${{ github.ref == 'refs/heads/main' }}

- name: Check
run: cargo check --workspace --features "default,plugin-system" --locked
uses: ./.github/workflows/platform-matrix.yml
with:
operation: check

# ── Code coverage ───────────────────────────────────────────────────
coverage:
Expand Down
153 changes: 153 additions & 0 deletions .github/workflows/platform-matrix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: Platform Matrix

on:
workflow_call:
inputs:
operation:
description: "Run target checks or build release artifacts"
required: true
type: string
version:
description: "Release version applied before artifact builds"
required: false
default: ""
type: string
secrets:
APPLE_DEVELOPER_ID_CERT_BASE64:
required: false
APPLE_DEVELOPER_ID_CERT_PASSWORD:
required: false
APPLE_NOTARY_API_KEY_BASE64:
required: false
APPLE_NOTARY_API_KEY_ID:
required: false
APPLE_NOTARY_API_ISSUER:
required: false

env:
CARGO_TERM_COLOR: always

jobs:
targets:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
suffix: ""
- os: ubuntu-latest
target: aarch64-unknown-linux-musl
suffix: ""
- os: macos-latest
target: x86_64-apple-darwin
suffix: ""
macos-deployment-target: "10.15"
- os: macos-latest
target: aarch64-apple-darwin
suffix: ""
macos-deployment-target: "11.0"
- os: windows-latest
target: x86_64-pc-windows-msvc
suffix: ".exe"
- os: windows-11-arm
target: aarch64-pc-windows-msvc
suffix: ".exe"
fail-fast: false

steps:
- uses: actions/checkout@v7

- uses: ./.github/actions/apply-version-bump
if: inputs.operation == 'build'
with:
version: ${{ inputs.version }}

- uses: ./.github/actions/setup-rust
with:
target: ${{ matrix.target }}
install-protoc: auto
install-zigbuild: ${{ inputs.operation == 'build' && contains(matrix.target, 'musl') }}
cache-shared-key: platform-${{ inputs.operation }}-${{ matrix.target }}
cache-save-if: ${{ github.ref == 'refs/heads/main' }}

- name: Check target
if: inputs.operation == 'check'
run: cargo check --workspace --features "default,plugin-system" --target ${{ matrix.target }} --locked

- name: Build release binary (musl)
if: inputs.operation == 'build' && contains(matrix.target, 'musl')
run: cargo zigbuild --bin easybot --release --features "default,plugin-system" --target ${{ matrix.target }} --locked

- name: Build release binary (native)
if: inputs.operation == 'build' && !contains(matrix.target, 'musl')
env:
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macos-deployment-target || '' }}
run: cargo build --release --features "default,plugin-system" --target ${{ matrix.target }} --locked

- name: Check macOS signing credentials
if: inputs.operation == 'build' && contains(matrix.target, 'apple-darwin')
id: check-macos-cert
env:
CERT: ${{ secrets.APPLE_DEVELOPER_ID_CERT_BASE64 }}
run: |
if [ -n "$CERT" ]; then
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "available=false" >> "$GITHUB_OUTPUT"
echo "No Apple signing certificate - macOS binary will be unsigned"
fi

- name: Sign and notarize macOS binary
if: steps.check-macos-cert.outputs.available == 'true'
env:
CERT_BASE64: ${{ secrets.APPLE_DEVELOPER_ID_CERT_BASE64 }}
CERT_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_CERT_PASSWORD }}
NOTARY_API_KEY: ${{ secrets.APPLE_NOTARY_API_KEY_BASE64 }}
NOTARY_API_KEY_ID: ${{ secrets.APPLE_NOTARY_API_KEY_ID }}
NOTARY_ISSUER: ${{ secrets.APPLE_NOTARY_API_ISSUER }}
run: |
BINARY="target/${{ matrix.target }}/release/easybot${{ matrix.suffix }}"

echo "$CERT_BASE64" | base64 --decode > certificate.p12
security create-keychain -p temp temp.keychain
security default-keychain -s temp.keychain
security unlock-keychain -p temp temp.keychain
security import certificate.p12 -k temp.keychain \
-P "$CERT_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list \
-S apple-tool:,apple: -s -k temp temp.keychain

DEVELOPER_ID=$(security find-identity -v -p basic |
grep "Developer ID Application" | head -1 | sed 's/.*"\(.*\)"/\1/')
codesign --force --sign "$DEVELOPER_ID" \
--timestamp --options runtime "$BINARY"

if [ -n "$NOTARY_API_KEY" ]; then
echo "$NOTARY_API_KEY" | base64 --decode > auth_key.p8
zip -r "$BINARY.zip" "$BINARY"
xcrun notarytool submit "$BINARY.zip" \
--key auth_key.p8 --key-id "$NOTARY_API_KEY_ID" \
--issuer "$NOTARY_ISSUER" --wait
xcrun stapler staple "$BINARY"
rm -f "$BINARY.zip" auth_key.p8
fi

rm -f certificate.p12
security delete-keychain temp.keychain

- name: Prepare artifact
if: inputs.operation == 'build'
shell: bash
run: |
BINARY="target/${{ matrix.target }}/release/easybot${{ matrix.suffix }}"
ARCHIVE="easybot-${{ matrix.target }}${{ matrix.suffix }}"
cp "$BINARY" "$ARCHIVE"

- name: Upload artifact
if: inputs.operation == 'build'
uses: actions/upload-artifact@v7
with:
name: easybot-${{ matrix.target }}
path: easybot-${{ matrix.target }}${{ matrix.suffix }}
if-no-files-found: error
Loading
Loading