Skip to content

Commit 0a23ea1

Browse files
committed
refactor(ci): 提取复用构建流程 + 修复多处回归
- 新增 _build.yml(复用工作流),package-check + release 共用 - 修复 zip 路径错配:../../→../(zip 写 root 但 upload glob 找 dist/) - 恢复构建前质量检查(pnpm check/check:py),防止 release 漏检 - package-check 用 head_sha 定位触发 commit,fallback github.sha - 恢复路径过滤(paths-filter job),非打包变更跳过构建 - 恢复 permissions/uv sync/timeout/AFA 验证等防护 - check.yml 拆 pnpm ci 为 3 个命名 step,提升 CI 可观测性 - package.json 加 check:py:fast(lint+typecheck 不含 test) - package 步骤消 shell 注入风险(env 传参),7z 前 rm -f 旧档
1 parent 36fd172 commit 0a23ea1

5 files changed

Lines changed: 134 additions & 172 deletions

File tree

.github/workflows/_build.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Build
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
artifact_name:
7+
required: true
8+
type: string
9+
archive_prefix:
10+
required: true
11+
type: string
12+
13+
jobs:
14+
build:
15+
permissions:
16+
contents: read
17+
runs-on: windows-latest
18+
timeout-minutes: 30
19+
steps:
20+
- uses: actions/checkout@v6
21+
with:
22+
submodules: true
23+
# NOTE: python/node/uv versions must stay in sync with check.yml
24+
- uses: actions/setup-python@v6
25+
with:
26+
python-version: '3.13'
27+
- uses: astral-sh/setup-uv@v8.1.0
28+
- uses: pnpm/action-setup@v6
29+
- uses: actions/setup-node@v6
30+
with:
31+
node-version: 24
32+
cache: pnpm
33+
- run: pnpm install --frozen-lockfile
34+
- run: uv sync
35+
- run: pnpm check && pnpm check:py
36+
- name: Disable Windows Defender realtime monitoring
37+
shell: powershell
38+
run: |
39+
Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue
40+
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE" -ErrorAction SilentlyContinue
41+
Write-Host "Defender realtime monitoring disabled for build"
42+
- name: Configure OCR model
43+
run: uv run python tools/configure.py
44+
- name: Convert logo.png to ico
45+
shell: bash
46+
run: uv run python -c "from PIL import Image; Image.open('logo.png').save('logo.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)])"
47+
- name: Build (PyInstaller)
48+
run: uv run pyinstaller aao.spec --noconfirm
49+
- name: Smoke test packaged exe
50+
shell: bash
51+
run: |
52+
export QT_QPA_PLATFORM=offscreen
53+
timeout 20 ./dist/aao.app/aao.app.exe --no-api > smoke.log 2>&1 || true
54+
if grep -q "Could not load PyInstaller" smoke.log; then
55+
echo "[ERR] packaged exe failed to load PKG archive"
56+
cat smoke.log
57+
exit 1
58+
fi
59+
echo "[OK] packaged exe loads PKG archive"
60+
head -5 smoke.log
61+
- name: Download AFA (ArknightsFrameAssistant)
62+
shell: bash
63+
run: |
64+
mkdir -p dist/aao.app/afa
65+
repo="CloudTracey/arknights-frame-assistant"
66+
tag="$(curl -fsSL "https://api.github.com/repos/$repo/releases/latest" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')"
67+
echo "AFA latest tag: $tag"
68+
curl -fsSL "https://github.com/$repo/releases/download/$tag/AFA.exe" -o dist/aao.app/afa/AFA.exe
69+
curl -fsSL "https://raw.githubusercontent.com/$repo/$tag/LICENSE" -o dist/aao.app/afa/LICENSE || echo "[WARN] AFA LICENSE 未取到"
70+
ls -la dist/aao.app/afa/
71+
- name: Sync game data
72+
run: uv run python -m aao.resources.syncer
73+
- name: Stage external resources
74+
shell: bash
75+
run: |
76+
cp -r resource data examples dist/aao.app/
77+
cp logo.png dist/aao.app/
78+
rm -rf dist/aao.app/config dist/aao.app/debug
79+
- name: Package
80+
shell: bash
81+
env:
82+
ARCHIVE_PREFIX: ${{ inputs.archive_prefix }}
83+
run: |
84+
archive="${ARCHIVE_PREFIX}.zip"
85+
rm -f "dist/${archive}"
86+
( cd dist/aao.app && 7z a "../${archive}" . )
87+
- uses: actions/upload-artifact@v7
88+
with:
89+
name: ${{ inputs.artifact_name }}
90+
path: |
91+
dist/*.zip
92+
dist/aao.app

.github/workflows/check.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
runs-on: windows-latest
1313
steps:
1414
- uses: actions/checkout@v6
15+
# NOTE: python/node/uv versions must stay in sync with _build.yml
1516
- uses: actions/setup-python@v6
1617
with:
1718
python-version: '3.13'
@@ -23,6 +24,9 @@ jobs:
2324
cache: pnpm
2425
- run: pnpm install --frozen-lockfile
2526
- run: uv sync
26-
- run: pnpm check
27-
- run: pnpm check:py
28-
- run: uv run pytest tests/ -q
27+
- name: Format & schema
28+
run: pnpm check
29+
- name: Lint & typecheck
30+
run: pnpm check:py:fast
31+
- name: Tests
32+
run: pnpm test:py
Lines changed: 25 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,42 @@
11
name: Package Check
22

3-
# 每次 commit(push 改动打包相关文件)模拟完整打包:构建 + 冒烟验 PKG + 上传 artifact。
4-
# 不发版、不打 tag。尽早发现打包问题(PKG 损坏、CI 环境差异)。
5-
# 代码 lint/format 检查见 check.yml(轻量),本 workflow 只管打包。
6-
73
on:
8-
push:
4+
workflow_run:
5+
workflows: [Check]
6+
types: [completed]
97
branches: [main, master]
10-
paths:
11-
- 'aao/**'
12-
- 'custom/**'
13-
- 'resource/**'
14-
- 'examples/**'
15-
- 'aao.spec'
16-
- 'pyproject.toml'
17-
- 'uv.lock'
18-
- 'package.json'
19-
- 'pnpm-lock.yaml'
20-
- 'logo.png'
21-
- '.github/workflows/package-check.yml'
228
workflow_dispatch:
239

2410
concurrency:
2511
group: package-check-${{ github.ref }}
2612
cancel-in-progress: true
2713

2814
jobs:
29-
package-check:
30-
runs-on: windows-latest
15+
paths-filter:
16+
runs-on: ubuntu-latest
17+
outputs:
18+
packaging: ${{ steps.filter.outputs.packaging }}
3119
steps:
3220
- uses: actions/checkout@v6
3321
with:
34-
submodules: true # 拉取 MaaCommonAssets(OCR 模型来源)
35-
- uses: actions/setup-python@v6
36-
with:
37-
python-version: '3.13'
38-
- uses: astral-sh/setup-uv@v8.1.0
39-
- uses: pnpm/action-setup@v6
40-
- uses: actions/setup-node@v6
41-
with:
42-
node-version: 24
43-
cache: pnpm
44-
- run: pnpm install --frozen-lockfile
45-
- run: uv sync
46-
- run: pnpm check
47-
- run: pnpm check:py
48-
- name: Disable Windows Defender realtime monitoring
49-
shell: powershell
50-
run: |
51-
Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue
52-
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE" -ErrorAction SilentlyContinue
53-
Write-Host "Defender realtime monitoring disabled for build"
54-
- name: Configure OCR model
55-
run: uv run python tools/configure.py
56-
- name: Convert logo.png to ico
57-
shell: bash
58-
run: uv run python -c "from PIL import Image; Image.open('logo.png').save('logo.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)])"
59-
- name: Build (PyInstaller)
60-
run: uv run pyinstaller aao.spec --noconfirm
61-
- name: Smoke test packaged exe
22+
fetch-depth: 2
23+
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
24+
- id: filter
6225
shell: bash
6326
run: |
64-
export QT_QPA_PLATFORM=offscreen
65-
timeout 20 ./dist/aao.app/aao.app.exe --no-api > smoke.log 2>&1 || true
66-
if grep -q "Could not load PyInstaller" smoke.log; then
67-
echo "[ERR] packaged exe failed to load PKG archive"
68-
cat smoke.log
69-
exit 1
27+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
28+
echo "packaging=true" >> "$GITHUB_OUTPUT"
29+
elif git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -qE '^(aao/|custom/|resource/|examples/|aao\.spec|pyproject\.toml|uv\.lock|package\.json|pnpm-lock\.yaml|logo\.png|\.github/workflows/(package-check|_build)\.yml)'; then
30+
echo "packaging=true" >> "$GITHUB_OUTPUT"
31+
else
32+
echo "packaging=false" >> "$GITHUB_OUTPUT"
33+
echo "No packaging files changed, skipping build"
7034
fi
71-
echo "[OK] packaged exe loads PKG archive"
72-
head -5 smoke.log
73-
- name: Download AFA (ArknightsFrameAssistant)
74-
shell: bash
75-
run: |
76-
mkdir -p dist/aao.app/afa
77-
repo="CloudTracey/arknights-frame-assistant"
78-
tag="$(curl -fsSL "https://api.github.com/repos/$repo/releases/latest" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')"
79-
echo "AFA latest tag: $tag"
80-
curl -fsSL "https://github.com/$repo/releases/download/$tag/AFA.exe" -o dist/aao.app/afa/AFA.exe
81-
curl -fsSL "https://raw.githubusercontent.com/$repo/$tag/LICENSE" -o dist/aao.app/afa/LICENSE || echo "[WARN] AFA LICENSE 未取到"
82-
- name: Sync game data
83-
run: uv run python -m aao.resources.syncer
84-
- name: Stage external resources
85-
shell: bash
86-
run: |
87-
cp -r resource data examples dist/aao.app/
88-
cp logo.png dist/aao.app/
89-
rm -rf dist/aao.app/config dist/aao.app/debug
90-
- name: Package
91-
shell: bash
92-
run: |
93-
archive="ArknightsAutoOperator-check-${GITHUB_SHA::7}.zip"
94-
( cd dist/aao.app && 7z a "../../$archive" . )
95-
- uses: actions/upload-artifact@v7
96-
with:
97-
name: check-build
98-
path: |
99-
*.zip
100-
dist/aao.app
35+
36+
build:
37+
needs: paths-filter
38+
if: ${{ needs.paths-filter.outputs.packaging == 'true' && (github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch') }}
39+
uses: ./.github/workflows/_build.yml
40+
with:
41+
artifact_name: check-build
42+
archive_prefix: ArknightsAutoOperator-check-${{ github.event.workflow_run.head_sha || github.sha }}

.github/workflows/release.yml

Lines changed: 6 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,90 +7,11 @@ on:
77
workflow_dispatch:
88

99
jobs:
10-
package:
11-
permissions:
12-
contents: read
13-
runs-on: windows-latest
14-
steps:
15-
- uses: actions/checkout@v6
16-
with:
17-
submodules: true # 拉取 MaaCommonAssets(OCR 模型来源)
18-
- uses: actions/setup-python@v6
19-
with:
20-
python-version: '3.13'
21-
- uses: astral-sh/setup-uv@v8.1.0
22-
- uses: pnpm/action-setup@v6
23-
- uses: actions/setup-node@v6
24-
with:
25-
node-version: 24
26-
cache: pnpm
27-
- run: pnpm install --frozen-lockfile
28-
- run: pnpm check
29-
- run: pnpm check:py
30-
- name: Disable Windows Defender realtime monitoring
31-
shell: powershell
32-
run: |
33-
# PyInstaller 写入 exe 时 Defender 实时扫描会改动 PKG archive,
34-
# 导致产出的 exe "Could not load embedded PKG archive"。打包前关掉。
35-
Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue
36-
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE" -ErrorAction SilentlyContinue
37-
Write-Host "Defender realtime monitoring disabled for build"
38-
- name: Configure OCR model
39-
run: uv run python tools/configure.py
40-
- name: Convert logo.png to ico
41-
shell: bash
42-
run: uv run python -c "from PIL import Image; Image.open('logo.png').save('logo.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)])"
43-
- name: Build (PyInstaller)
44-
run: uv run pyinstaller aao.spec --noconfirm
45-
- name: Smoke test packaged exe
46-
shell: bash
47-
run: |
48-
# 打包后立即 offscreen 跑,验证 PKG archive 能加载(CI 自检,避免产出损坏的 exe 还发版)
49-
export QT_QPA_PLATFORM=offscreen
50-
timeout 20 ./dist/aao.app/aao.app.exe --no-api > smoke.log 2>&1 || true
51-
if grep -q "Could not load PyInstaller" smoke.log; then
52-
echo "[ERR] packaged exe failed to load PKG archive"
53-
cat smoke.log
54-
exit 1
55-
fi
56-
echo "[OK] packaged exe loads PKG archive"
57-
head -5 smoke.log
58-
- name: Download AFA (ArknightsFrameAssistant)
59-
shell: bash
60-
run: |
61-
mkdir -p dist/aao.app/afa
62-
# AFA 是 GPL-3.0(CloudTracey/arknights-frame-assistant),凹图热键依赖。
63-
# 查最新 release tag,下对应 AFA.exe + LICENSE(满足 GPL 分发要求)。
64-
repo="CloudTracey/arknights-frame-assistant"
65-
tag="$(curl -fsSL "https://api.github.com/repos/$repo/releases/latest" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')"
66-
echo "AFA latest tag: $tag"
67-
curl -fsSL "https://github.com/$repo/releases/download/$tag/AFA.exe" -o dist/aao.app/afa/AFA.exe
68-
curl -fsSL "https://raw.githubusercontent.com/$repo/$tag/LICENSE" -o dist/aao.app/afa/LICENSE || echo "[WARN] AFA LICENSE 未取到"
69-
ls -la dist/aao.app/afa/
70-
- name: Sync game data
71-
run: uv run python -m aao.resources.syncer
72-
- name: Stage external resources
73-
shell: bash
74-
run: |
75-
cp -r resource data examples dist/aao.app/
76-
cp logo.png dist/aao.app/
77-
# 清理冒烟测试生成的运行时目录(不该进发版包)
78-
rm -rf dist/aao.app/config dist/aao.app/debug
79-
- name: Package
80-
shell: bash
81-
run: |
82-
mkdir -p dist
83-
archive="ArknightsAutoOperator-win-x64-${GITHUB_REF_NAME}.zip"
84-
( cd dist/aao.app && 7z a "../$archive" . )
85-
- uses: actions/upload-artifact@v7
86-
with:
87-
name: win-x64
88-
path: dist/*.zip
89-
- name: Upload raw dist (诊断 PKG 损坏用)
90-
uses: actions/upload-artifact@v7
91-
with:
92-
name: win-x64-raw
93-
path: dist/aao.app
10+
build:
11+
uses: ./.github/workflows/_build.yml
12+
with:
13+
artifact_name: win-x64
14+
archive_prefix: ArknightsAutoOperator-win-x64-${{ github.ref_name }}
9415

9516
git_cliff:
9617
name: Generate release notes
@@ -126,7 +47,7 @@ jobs:
12647

12748
release:
12849
if: startsWith(github.ref, 'refs/tags/')
129-
needs: [package, git_cliff]
50+
needs: [build, git_cliff]
13051
permissions:
13152
contents: write
13253
runs-on: ubuntu-latest

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
"check:schema": "node tools/validate-schema.mjs",
1414
"sync:schema": "node tools/sync-schema.mjs",
1515
"check": "pnpm format:check && pnpm check:schema",
16+
"ci": "pnpm check && pnpm check:py",
1617
"format:py": "uv run ruff format .",
1718
"lint:py": "uv run ruff check .",
1819
"typecheck:py": "uv run pyright",
19-
"check:py": "pnpm lint:py && pnpm typecheck:py"
20+
"test:py": "uv run pytest tests/ -q",
21+
"check:py:fast": "pnpm lint:py && pnpm typecheck:py",
22+
"check:py": "pnpm check:py:fast && pnpm test:py"
2023
},
2124
"devDependencies": {
2225
"@nekosu/prettier-plugin-maafw-sort": "1.0.5",

0 commit comments

Comments
 (0)