Skip to content

Commit ad255be

Browse files
authored
fix ci (#49)
1 parent 7b0cddf commit ad255be

1 file changed

Lines changed: 231 additions & 56 deletions

File tree

.github/workflows/docker-build.yml

Lines changed: 231 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,48 @@
11
name: Docker Build and Push
22

3+
# 🔒 工作流级权限控制
4+
permissions:
5+
contents: read
6+
packages: write
7+
pull-requests: write
8+
39
on:
4-
# PR 提交或更新时触发
10+
# PR 提交或更新时触发(用于构建检查)
511
pull_request:
612
branches: [main, master, develop]
713
types: [opened, synchronize, reopened]
814

15+
# 专门用于 PR 评论的触发器(支持 fork 仓库)
16+
pull_request_target:
17+
types: [opened, synchronize, reopened]
18+
branches: [main, master, develop]
19+
920
# 合并到主分支时触发
1021
push:
1122
branches: [main, master]
12-
# 支持手动触发
23+
24+
# 支持手动触发
1325
workflow_dispatch:
1426

1527
env:
1628
# 使用 vars 而不是 secrets 来存储用户名(推荐做法)
1729
DOCKER_IMAGE: ${{ vars.DOCKERHUB_USERNAME && vars.DOCKERHUB_USERNAME != '' && vars.DOCKERHUB_USERNAME || 'defaultuser' }}/ruiqi-waf
1830

19-
# 精简权限
20-
permissions:
21-
contents: read
22-
packages: write
23-
pull-requests: write
24-
2531
jobs:
26-
docker:
32+
# 主要的构建检查 job(使用 pull_request,安全执行外部代码)
33+
docker-build:
34+
name: Docker Build Check
2735
runs-on: ubuntu-latest
36+
# 只在 pull_request 和 push 事件时运行,不在 pull_request_target 时运行
37+
if: github.event_name != 'pull_request_target'
38+
39+
outputs:
40+
build-status: ${{ steps.set-status.outputs.build_status }}
41+
build-result: ${{ steps.set-status.outputs.build_result }}
42+
image-tags: ${{ steps.meta.outputs.tags }}
43+
build-time: ${{ steps.set-status.outputs.build_time }}
44+
commit-sha: ${{ steps.set-status.outputs.commit_sha }}
45+
2846
steps:
2947
- name: Checkout
3048
uses: actions/checkout@v4
@@ -89,6 +107,7 @@ jobs:
89107
# PR阶段优化:禁用不必要的功能
90108
provenance: false
91109
sbom: false
110+
continue-on-error: true
92111

93112
# 推送阶段:完整多平台构建
94113
- name: Build and push (Multi-platform)
@@ -109,76 +128,230 @@ jobs:
109128
provenance: true
110129
sbom: true
111130

112-
# 优化的PR评论
113-
- name: Comment PR
114-
if: github.event_name == 'pull_request'
131+
# 📤 设置输出状态
132+
- name: Set job outputs
133+
id: set-status
134+
if: always()
135+
run: |
136+
if [ "${{ job.status }}" = "success" ]; then
137+
echo "build_status=success" >> $GITHUB_OUTPUT
138+
echo "build_result=passed" >> $GITHUB_OUTPUT
139+
else
140+
echo "build_status=failure" >> $GITHUB_OUTPUT
141+
echo "build_result=failed" >> $GITHUB_OUTPUT
142+
fi
143+
echo "build_time=$(date '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_OUTPUT
144+
echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT
145+
146+
# 生成详细构建报告
147+
- name: Generate Docker build summary
148+
if: always()
149+
run: |
150+
echo "## 🚀 Docker Build Report" >> $GITHUB_STEP_SUMMARY
151+
echo "" >> $GITHUB_STEP_SUMMARY
152+
153+
# 构建状态
154+
echo "### 📋 Build Status" >> $GITHUB_STEP_SUMMARY
155+
echo "| Item | Status | Details |" >> $GITHUB_STEP_SUMMARY
156+
echo "|------|--------|---------|" >> $GITHUB_STEP_SUMMARY
157+
158+
if [ "${{ job.status }}" = "success" ]; then
159+
if [ "${{ github.event_name }}" = "pull_request" ]; then
160+
echo "| Docker Build | ✅ Passed | AMD64 architecture verification successful |" >> $GITHUB_STEP_SUMMARY
161+
echo "| Platform | 📱 Single | linux/amd64 (PR optimization) |" >> $GITHUB_STEP_SUMMARY
162+
echo "| Cache | 🚀 Optimized | GitHub Actions cache enabled |" >> $GITHUB_STEP_SUMMARY
163+
else
164+
echo "| Docker Build | ✅ Passed | Multi-platform build successful |" >> $GITHUB_STEP_SUMMARY
165+
echo "| Platform | 🌐 Multi | linux/amd64, linux/arm64 |" >> $GITHUB_STEP_SUMMARY
166+
echo "| Registry Push | ✅ Completed | Docker Hub + GitHub Container Registry |" >> $GITHUB_STEP_SUMMARY
167+
fi
168+
else
169+
echo "| Docker Build | ❌ Failed | Please check build logs |" >> $GITHUB_STEP_SUMMARY
170+
fi
171+
172+
echo "" >> $GITHUB_STEP_SUMMARY
173+
echo "### 📊 Build Information" >> $GITHUB_STEP_SUMMARY
174+
echo "- **Event Type**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
175+
echo "- **Commit SHA**: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
176+
echo "- **Branch**: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
177+
echo "- **Triggered by**: @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
178+
echo "- **Build Time**: $(date '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
179+
180+
# 🔒 安全的 PR 评论 job(使用 pull_request_target,但不 checkout 外部代码)
181+
pr-comment:
182+
name: PR Comment Handler
183+
runs-on: ubuntu-latest
184+
# 只在 pull_request_target 事件时运行
185+
if: github.event_name == 'pull_request_target'
186+
187+
steps:
188+
# 🔒 重要:不 checkout 任何代码,特别是 PR 代码!
189+
# 🔒 只使用 GitHub API 获取工作流运行结果
190+
191+
- name: Wait for main build to complete
115192
uses: actions/github-script@v7
193+
id: wait-for-build
116194
with:
117195
script: |
118-
const success = '${{ job.status }}' === 'success';
119-
const emoji = success ? '✅' : '❌';
120-
const statusEn = success ? 'Success' : 'Failed';
121-
const statusCn = success ? '成功' : '失败';
122-
const buildTime = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
196+
const { owner, repo } = context.repo;
197+
const headSha = context.payload.pull_request.head.sha;
198+
199+
console.log(`等待 commit ${headSha} 的构建完成...`);
200+
201+
// 等待最多 15 分钟(Docker 构建可能较长)
202+
const maxWaitTime = 15 * 60 * 1000; // 15 minutes
203+
const startTime = Date.now();
204+
205+
while (Date.now() - startTime < maxWaitTime) {
206+
try {
207+
// 获取 commit 的所有 check runs
208+
const { data: checkRuns } = await github.rest.checks.listForRef({
209+
owner,
210+
repo,
211+
ref: headSha,
212+
});
213+
214+
// 查找我们的Docker构建工作流
215+
const dockerCheck = checkRuns.check_runs.find(run =>
216+
run.name === 'Docker Build Check'
217+
);
218+
219+
if (dockerCheck) {
220+
console.log(`发现构建: ${dockerCheck.name}, 状态: ${dockerCheck.status}`);
221+
222+
if (dockerCheck.status === 'completed') {
223+
console.log(`构建完成,结论: ${dockerCheck.conclusion}`);
224+
return {
225+
completed: true,
226+
conclusion: dockerCheck.conclusion,
227+
details_url: dockerCheck.details_url
228+
};
229+
}
230+
}
231+
232+
// 等待 30 秒后重试
233+
await new Promise(resolve => setTimeout(resolve, 30000));
234+
} catch (error) {
235+
console.log(`获取构建状态时出错: ${error.message}`);
236+
await new Promise(resolve => setTimeout(resolve, 30000));
237+
}
238+
}
123239
124-
// 构建中文报告
125-
let chineseReport = `### 中文报告
240+
// 超时情况
241+
console.log('等待超时,使用默认值');
242+
return {
243+
completed: false,
244+
conclusion: 'timed_out',
245+
details_url: null
246+
};
126247
127-
**🏗️ 构建详情:**
128-
- 验证平台: \`linux/amd64\`
129-
- 构建状态: ${statusCn}
130-
- 提交: \`${{ github.event.pull_request.head.sha }}\`
131-
- 构建时间: ${buildTime}
248+
- name: Comment on PR
249+
uses: actions/github-script@v7
250+
with:
251+
script: |
252+
const buildResult = ${{ steps.wait-for-build.outputs.result }};
253+
const prNumber = context.payload.pull_request.number;
254+
const buildTime = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
132255
133-
`;
256+
let emoji, statusEn, statusCn, conclusion;
134257
135-
if (success) {
136-
chineseReport += `**✅ 结果:** 基础架构验证通过,合并后将自动构建完整多平台镜像
258+
if (!buildResult.completed) {
259+
emoji = '⏰';
260+
statusEn = 'In Progress';
261+
statusCn = '进行中';
262+
conclusion = 'pending';
263+
} else {
264+
switch(buildResult.conclusion) {
265+
case 'success':
266+
emoji = '✅';
267+
statusEn = 'Success';
268+
statusCn = '成功';
269+
conclusion = 'success';
270+
break;
271+
case 'failure':
272+
emoji = '❌';
273+
statusEn = 'Failed';
274+
statusCn = '失败';
275+
conclusion = 'failure';
276+
break;
277+
default:
278+
emoji = '⚠️';
279+
statusEn = 'Unknown';
280+
statusCn = '未知';
281+
conclusion = 'neutral';
282+
}
283+
}
137284
138-
**💡 优化说明:** PR阶段仅构建AMD64以提高速度,完整的多平台构建将在合并后进行`;
285+
// 构建中文报告
286+
let chineseReport = `### 中文报告\n\n`;
287+
288+
if (!buildResult.completed) {
289+
chineseReport += `**⏰ 状态:** Docker 构建正在进行中,请稍候查看结果。`;
290+
} else if (buildResult.conclusion === 'success') {
291+
chineseReport += `**🎉 结果:** Docker 构建验证通过!镜像构建成功。\n\n`;
292+
chineseReport += `**🏗️ 构建详情:**\n`;
293+
chineseReport += `- ✅ 验证平台: \`linux/amd64\`\n`;
294+
chineseReport += `- ✅ 构建状态: ${statusCn}\n`;
295+
chineseReport += `- ✅ 缓存优化: GitHub Actions 缓存已启用\n`;
296+
chineseReport += `- ✅ 提交: \`${context.payload.pull_request.head.sha}\`\n`;
297+
chineseReport += `- ✅ 构建时间: ${buildTime}\n\n`;
298+
chineseReport += `**💡 优化说明:** PR 阶段仅构建 AMD64 以提高速度,完整的多平台构建将在合并后进行。`;
299+
} else if (buildResult.conclusion === 'failure') {
300+
chineseReport += `**⚠️ 需要关注:** Docker 构建失败,请查看详细日志。\n\n`;
301+
chineseReport += `**🔧 常见解决方案:**\n`;
302+
chineseReport += `- 检查 Dockerfile 语法\n`;
303+
chineseReport += `- 确认依赖包版本\n`;
304+
chineseReport += `- 验证构建上下文路径\n\n`;
305+
chineseReport += `点击下方链接查看详细构建日志。`;
139306
} else {
140-
chineseReport += `**❌ 需要关注:** 请检查构建日志并修复问题`;
307+
chineseReport += `**ℹ️ 状态:** 构建状态异常,请检查工作流配置。`;
141308
}
142309
143310
// 构建英文报告
144-
let englishReport = `### English Report
145-
146-
**🏗️ Build Details:**
147-
- Verification Platform: \`linux/amd64\`
148-
- Build Status: ${statusEn}
149-
- Commit: \`${{ github.event.pull_request.head.sha }}\`
150-
- Build Time: ${buildTime}
151-
152-
`;
153-
154-
if (success) {
155-
englishReport += `**✅ Result:** Architecture verification passed, full multi-platform build will be triggered after merge
156-
157-
**💡 Optimization Note:** PR stage only builds AMD64 to improve speed, complete multi-platform build will be performed after merge`;
311+
let englishReport = `### English Report\n\n`;
312+
313+
if (!buildResult.completed) {
314+
englishReport += `**⏰ Status:** Docker build is in progress, please wait for results.`;
315+
} else if (buildResult.conclusion === 'success') {
316+
englishReport += `**🎉 Result:** Docker build verification passed! Image build successful.\n\n`;
317+
englishReport += `**🏗️ Build Details:**\n`;
318+
englishReport += `- ✅ Verification Platform: \`linux/amd64\`\n`;
319+
englishReport += `- ✅ Build Status: ${statusEn}\n`;
320+
englishReport += `- ✅ Cache Optimization: GitHub Actions cache enabled\n`;
321+
englishReport += `- ✅ Commit: \`${context.payload.pull_request.head.sha}\`\n`;
322+
englishReport += `- ✅ Build Time: ${buildTime}\n\n`;
323+
englishReport += `**💡 Optimization Note:** PR stage only builds AMD64 to improve speed, complete multi-platform build will be performed after merge.`;
324+
} else if (buildResult.conclusion === 'failure') {
325+
englishReport += `**⚠️ Attention Required:** Docker build failed, please check detailed logs.\n\n`;
326+
englishReport += `**🔧 Common Solutions:**\n`;
327+
englishReport += `- Check Dockerfile syntax\n`;
328+
englishReport += `- Verify dependency versions\n`;
329+
englishReport += `- Validate build context path\n\n`;
330+
englishReport += `Click the link below to view detailed build logs.`;
158331
} else {
159-
englishReport += `**❌ Attention Required:** Please check build logs and fix issues`;
332+
englishReport += `**ℹ️ Status:** Build status is abnormal, please check workflow configuration.`;
160333
}
161334
162-
// 组合最终内容(中文在前,英文在后)
163-
const body = `## 🚀 Docker Quick Build ${statusEn} ${emoji}
164-
165-
**PR #${{ github.event.pull_request.number }}** AMD64 platform verification completed (optimized to build single platform only for faster verification)
166-
167-
${chineseReport}
335+
// 组合最终内容
336+
let body = `## 🚀 Docker Quick Build ${statusEn} ${emoji}\n\n`;
337+
body += `**PR #${prNumber}** AMD64 platform verification completed (optimized for faster verification)\n\n`;
338+
body += `${chineseReport}\n\n---\n\n${englishReport}`;
168339
169-
---
170-
171-
${englishReport}`;
340+
// 如果有详细链接,添加到报告中
341+
if (buildResult.details_url) {
342+
body += `\n\n**🔗 查看详细信息 / View Details:** [点击查看完整构建结果 / Click here to see full build results](${buildResult.details_url})`;
343+
}
172344
173345
// 查找并更新现有评论
174346
const { data: comments } = await github.rest.issues.listComments({
175347
owner: context.repo.owner,
176348
repo: context.repo.repo,
177-
issue_number: context.issue.number,
349+
issue_number: prNumber,
178350
});
179351
180352
const botComment = comments.find(comment =>
181-
comment.user.type === 'Bot' && comment.body.includes('Docker Quick Build')
353+
comment.user.type === 'Bot' &&
354+
comment.body.includes('🚀 Docker Quick Build')
182355
);
183356
184357
if (botComment) {
@@ -188,11 +361,13 @@ jobs:
188361
comment_id: botComment.id,
189362
body: body
190363
});
364+
console.log('已更新现有的 PR 评论');
191365
} else {
192366
await github.rest.issues.createComment({
193367
owner: context.repo.owner,
194368
repo: context.repo.repo,
195-
issue_number: context.issue.number,
369+
issue_number: prNumber,
196370
body: body
197371
});
372+
console.log('已创建新的 PR 评论');
198373
}

0 commit comments

Comments
 (0)