目日常巡檢:CI、依賴和 Issue 響應(yīng))
開源項(xiàng)目日常巡檢CI、依賴和 Issue 響應(yīng)開源項(xiàng)目的日常巡檢可以很樸素確認(rèn) CI 主分支、依賴告警和待回應(yīng) Issue。自動(dòng)化只負(fù)責(zé)找出變化是否升級(jí)依賴仍要看兼容范圍和維護(hù)資源。1. 開源項(xiàng)目自動(dòng)化巡檢的三大核心場(chǎng)景在開源社區(qū)協(xié)作中依靠自動(dòng)化腳本替代人工巡檢主要解決以下三個(gè)維度的質(zhì)量與效率痛點(diǎn)Issue 垃圾信息過(guò)濾與 Stale 自動(dòng)標(biāo)記缺少?gòu)?fù)現(xiàn) Demo 或長(zhǎng)時(shí)間無(wú)響應(yīng)的懸掛 Issue定時(shí)巡檢并標(biāo)記needs-info或stale超過(guò) 14 天自動(dòng) Close。依賴漏洞與 Security 巡檢定時(shí)掃描第三方 npm / Go module 依賴庫(kù)的安全漏洞自動(dòng)提交 Bump PR。PR 提交規(guī)范與 Lint 門禁對(duì) Commit Message 格式、DCODeveloper Certificate of Origin簽名以及測(cè)試覆蓋率進(jìn)行剛性校驗(yàn)。2. GitHub Actions 巡檢與 Bot 自動(dòng)化腳本實(shí)現(xiàn)為了讓開源項(xiàng)目維護(hù)實(shí)現(xiàn)“無(wú)人值守”在倉(cāng)庫(kù)中編寫了兩個(gè)自動(dòng)化腳本一個(gè)是基于 GitHub Actions Workflow 的日常巡檢 Pipeline另一個(gè)是用 Node.js 寫的輕量級(jí) Stale Issue 治理 Bot。以下代碼展示了如何使用 GitHub Script 自動(dòng)化管理 Issue 狀態(tài)// .github/scripts/stale-checker.js const { octokit } require(octokit/rest); /** * 開源項(xiàng)目日常 Stale Issue 自動(dòng)化巡檢腳本 */ async function runStaleInspection({ ghes, context, core }) { const token process.env.GITHUB_TOKEN; const octokit ghes ? new octokit({ auth: token, baseUrl: ghes }) : new octokit({ auth: token }); const { owner, repo } context.repo; const STALE_LABEL stale; const WAITING_LABEL needs-reproduce; console.log([${new Date().toISOString()}] 開始執(zhí)行倉(cāng)庫(kù) ${owner}/${repo} 的日常 Issue 巡檢...); // 1. 查詢所有帶有 needs-reproduce 標(biāo)簽且更新時(shí)間超過(guò) 14 天的 Issue const issues await octokit.issues.listForRepo({ owner, repo, state: open, labels: WAITING_LABEL, sort: updated, direction: asc, per_page: 50 }); const now new Date().getTime(); const fourteenDaysMs 14 * 24 * 60 * 60 * 1000; for (const issue of issues.data) { // 跳過(guò) PR只處理 Issue if (issue.pull_request) continue; const lastUpdated new Date(issue.updated_at).getTime(); if (now - lastUpdated fourteenDaysMs) { console.log( 標(biāo)記 Stale Issue: #${issue.number} - ${issue.title}); // 檢查是否已經(jīng)打上了 stale 標(biāo)簽 const hasStaleLabel issue.labels.some(l l.name STALE_LABEL); if (!hasStaleLabel) { // 第一次超時(shí)打上 stale 標(biāo)簽并留言 await octokit.issues.addLabels({ owner, repo, issue_number: issue.number, labels: [STALE_LABEL] }); await octokit.issues.createComment({ owner, repo, issue_number: issue.number, body: **[Automated Notice]** This issue has been automatically marked as \stale\ because it has not had recent activity after requesting a minimal reproduction repo. It will be closed in 7 days if no further activity occurs. Thank you for your contributions! }); } else { // 第二次超時(shí)自動(dòng) Close console.log( 自動(dòng)關(guān)閉未解決的 Stale Issue: #${issue.number}); await octokit.issues.createComment({ owner, repo, issue_number: issue.number, body: **[Automated Notice]** Closing this issue due to inactivity. If you still experience this problem, please create a new issue with a runnable minimal reproduction. }); await octokit.issues.update({ owner, repo, issue_number: issue.number, state: closed, state_reason: not_planned }); } } } } module.exports runStaleInspection;配套的 GitHub Actions 配置文件.github/workflows/daily-inspection.ymlname: Daily Project Inspection on: schedule: # 每天凌晨 2 點(diǎn)自動(dòng)運(yùn)行日常巡檢 - cron: 0 2 * * * workflow_dispatch: jobs: inspect-and-clean: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkoutv4 - name: Setup Node.js uses: actions/setup-nodev4 with: node-version: 20 - name: Install Octokit Dependencies run: npm install octokit/rest - name: Run Stale Issue Inspector uses: actions/github-scriptv7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: script: | const inspector require(./.github/scripts/stale-checker.js); await inspector({ ghes: null, context, core });3. 本地與 CI 端的診斷與驗(yàn)證對(duì)于依賴安全漏洞和代碼格式規(guī)范維護(hù)者還可以在本地使用命令行診斷腳本進(jìn)行巡檢# 1. 運(yùn)行 Go 語(yǔ)言社區(qū)標(biāo)準(zhǔn)漏洞掃描 govulncheck ./... # 2. 本地觸發(fā) GitHub Actions Workflow 調(diào)試 (需安裝 act 工具) act schedule -s GITHUB_TOKENyour_personal_token # 3. 檢查所有 Open Issue 的 Label 分布情況 gh issue list --limit 100 --json number,title,labels | jq .[] | {number, title, labels: [.labels[].name]}通過(guò)這套自動(dòng)控制機(jī)制倉(cāng)庫(kù)的開放 Issue 列表中消除了大量沒有說(shuō)明文稿的無(wú)效抱怨。維護(hù)指標(biāo)引入自動(dòng)化巡檢前引入自動(dòng)化巡檢后無(wú)效/懸掛 Issue 平均存留時(shí)間引入自動(dòng)化巡檢前的基線引入自動(dòng)化巡檢后的結(jié)果CVE 高危漏洞平均修復(fù)時(shí)長(zhǎng)引入自動(dòng)化巡檢前的基線引入自動(dòng)化巡檢后的結(jié)果PR 格式規(guī)范合規(guī)率引入自動(dòng)化巡檢前的基線引入自動(dòng)化巡檢后的結(jié)果維護(hù)者每周事務(wù)性工時(shí)引入自動(dòng)化巡檢前的基線引入自動(dòng)化巡檢后的結(jié)果4. 開源項(xiàng)目治理經(jīng)驗(yàn)總結(jié)開源的生命力在于可持續(xù)性而維護(hù)者的精力是項(xiàng)目最大的瓶頸。搭建社區(qū)日常巡檢機(jī)制時(shí)建議遵循這三條法則用 Bot 扮演壞人關(guān)閉無(wú)效 Issue 或拒不要合規(guī) PR 的話讓自動(dòng)化 Bot 去說(shuō)避免維護(hù)者個(gè)人與貢獻(xiàn)者產(chǎn)生不必要的情感摩擦。模板必須強(qiáng)制包含復(fù)現(xiàn)倉(cāng)庫(kù)字段在 Issue Template 中要求用戶提供 CodeSandbox 或 Minimal Repro Repo沒有提供復(fù)現(xiàn)鏈接的自動(dòng)打上needs-reproduce標(biāo)簽。巡檢流程代碼化Pipeline as Code把所有的日常巡檢規(guī)則寫成可執(zhí)行腳本保存在.github目錄下讓任何新加入的 Co-maintainer 都能一目了然。