Compare commits

..

5 Commits

7 changed files with 88 additions and 14 deletions
+25
View File
@@ -158,5 +158,30 @@
"role": "Aria",
"location": "app/llm.js",
"suggestion": "此 action 為 CLI 工具,process.exit(1) 是設計意圖讓 CI/CD workflow 失敗。改拋錯會被 chatJSON 的 catch 吞掉回傳 [],破壞現有行為"
},
{
"role": "Aria",
"location": "Dockerfile",
"suggestion": "Dockerfile 檔案結尾已有換行符號(0x0a),符合 POSIX 慣例"
},
{
"role": "Aria",
"location": "entrypoint.sh",
"suggestion": "entrypoint.sh 檔案結尾已有換行符號(0x0a),符合 POSIX 慣例"
},
{
"role": "Maya",
"location": "app/main.js",
"suggestion": "main.js 整合測試需要真實 Gitea API、LLM API、git 操作,不適合單元測試。各模組已有獨立單元測試覆蓋"
},
{
"role": "Maya",
"location": "app/comments.js",
"suggestion": "comments.js 的 buildTable 為簡單字串拼接,postComment 已透過 gitea.js mock 間接測試,補測試效益低"
},
{
"role": "Maya",
"location": "app/roles.js",
"suggestion": "roles.js 依賴容器內固定路徑 /action/app/prompts/roles,單元測試環境無法存取,且邏輯為簡單 YAML 讀取與字串拼接"
}
]
+49 -7
View File
@@ -1,23 +1,65 @@
[
{
"level": "critical",
"role": "Leo",
"location": "app/gitea.js:10",
"suggestion": "在 `app/gitea.js` 中,`https.Agent` 設定了 `rejectUnauthorized: false`,這會禁用 SSL/TLS 憑證驗證。這是一個嚴重的安全漏洞,會使應用程式容易受到中間人攻擊,並嚴重影響系統的安全性與可維護性。強烈建議移除此設定,或在必要時配置正確的憑證信任鏈。",
"is_new": true
},
{
"level": "critical",
"role": "Aria",
"location": "app/llm.js:39",
"suggestion": "在 `chat` 函式中直接呼叫 `process.exit(1)` 會導致應用程式立即終止,降低了模組的重用性和測試彈性。建議改為拋出一個自訂錯誤(例如 `AllApiKeysFailedError`),讓呼叫端(例如應用程式的入口點)來決定如何處理此錯誤,例如在頂層捕獲後再呼叫 `process.exit(1)`。",
"location": "Dockerfile",
"suggestion": "檔案結尾缺少換行符號(newline character),這不符合 POSIX 慣例,建議在檔案末尾新增一個空行。",
"is_new": true
},
{
"level": "critical",
"role": "Aria",
"location": "entrypoint.sh",
"suggestion": "檔案結尾缺少換行符號(newline character),這不符合 POSIX 慣例,建議在檔案末尾新增一個空行。",
"is_new": true
},
{
"level": "warning",
"role": "Aria",
"location": "app/llm.js:26",
"suggestion": "變數 `lastError` 在迴圈結束後並未使用。請考慮移除此變數,或在所有 API Key 均失敗時,將其包含在拋出的錯誤訊息中,以提供更詳細的失敗原因。",
"role": "Leo",
"location": "Dockerfile:2",
"suggestion": "在 `Dockerfile` 中,基礎映像檔使用了 `FROM alpine` 而沒有指定具體的版本標籤(例如 `alpine:3.18`)。這可能導致未來 `alpine:latest` 更新時,建置環境發生非預期的變更,影響建置的可重現性和穩定性。為了長期維護性,建議明確指定基礎映像檔的版本。",
"is_new": true
},
{
"level": "warning",
"role": "Zara",
"location": "Dockerfile",
"suggestion": "建議調整 Dockerfile 的層次,將 `COPY app/package.json app/package-lock.json /action/app/` 放在 `npm install` 之前,然後再 `COPY app/ /action/app/`。這樣可以利用 Docker 的層次快取,當 `package.json` 或 `package-lock.json` 未變更時,`npm install` 步驟就不會重複執行,顯著加快 Docker 映像檔的建置速度。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "app/main.js",
"suggestion": "儘管各單元模組(`config`, `git`, `llm`)已有良好的單元測試,但 `app/main.js` 作為整個 Action 的協調者,其整合邏輯和端到端流程缺乏測試。特別是 `TODO.md` 中提到的「阻擋嚴重問題 PR(exit 1)」等關鍵行為,應透過整合測試或端到端測試來驗證,確保各模組協同運作正確,且整體流程符合預期。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "app/comments.js",
"suggestion": "`app/comments.js` 模組負責生成評論內容和儲存 findings 檔案。其中 `buildTable` 等函式負責 Markdown 表格的生成,以及 `postOldFindingsComment`, `postNewNonCriticalComment`, `postNewCriticalComments` 中的過濾邏輯,應補齊單元測試,以確保評論內容的格式正確性及問題分類的準確性。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "app/roles.js",
"suggestion": "`app/roles.js` 模組負責載入和處理角色定義。`loadRoles` 函式應增加單元測試,以驗證其能正確解析 YAML 檔案,並處理檔案不存在或格式錯誤等異常情況。`getRoleIntro` 函式也應測試其生成的 Markdown 介紹內容是否符合預期格式。",
"is_new": true
},
{
"level": "info",
"role": "Rex",
"role": "Maya",
"location": "app/package.json",
"suggestion": "此次變更包含 `axios` 和 `openai` 等重要函式庫的版本更新,特別是 `openai` 從 `4.28.0` 升級到 `4.104.0`。建議審查這些函式庫的發行說明(changelog),以了解是否有任何安全修補、已知漏洞或行為變更,確保更新不會引入新的安全風險或不預期的行為。",
"suggestion": "目前的 `test` 腳本 (`node --test git.test.js config.test.js llm.test.js`) 僅涵蓋了部分單元測試。建議更新此腳本,使其能自動發現並執行所有 `*.test.js` 檔案,以確保所有新增的測試都能被納入 CI 流程中執行。",
"is_new": true
}
]
+5 -4
View File
@@ -1,4 +1,4 @@
FROM alpine
FROM alpine:3.20
RUN apk add --no-cache bash nodejs npm git \
&& node --version \
@@ -7,10 +7,11 @@ RUN apk add --no-cache bash nodejs npm git \
WORKDIR /action
COPY app/package.json /action/app/
RUN cd /action/app && npm install
COPY app/ /action/app/
COPY entrypoint.sh /entrypoint.sh
RUN cd /action/app && npm install && \
chmod +x /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
+5
View File
@@ -12,6 +12,10 @@ inputs:
GITEA_REPOSITORY:
description: 'Gitea Repository (owner/repo)'
required: false
GITEA_SKIP_TLS_VERIFY:
description: '跳過 Gitea SSL/TLS 憑證驗證(自簽憑證時使用)'
required: false
default: 'false'
PR_NUMBER:
description: 'Pull Request Number'
required: false
@@ -80,6 +84,7 @@ runs:
GITEA_TOKEN: ${{ inputs.GITEA_TOKEN || secrets.GITEA_TOKEN }}
GITEA_SERVER_URL: ${{ inputs.GITEA_SERVER_URL || gitea.server_url }}
GITEA_REPOSITORY: ${{ inputs.GITEA_REPOSITORY || gitea.repository }}
GITEA_SKIP_TLS_VERIFY: ${{ inputs.GITEA_SKIP_TLS_VERIFY }}
PR_NUMBER: ${{ inputs.PR_NUMBER || gitea.event.pull_request.number }}
PR_HEAD_BRANCH: ${{ inputs.PR_HEAD_BRANCH || gitea.event.pull_request.head.ref }}
PR_BASE_BRANCH: ${{ inputs.PR_BASE_BRANCH || gitea.event.pull_request.base.ref }}
+1
View File
@@ -1,6 +1,7 @@
export const GITEA_TOKEN = process.env.GITEA_TOKEN || '';
export const GITEA_SERVER_URL = process.env.GITEA_SERVER_URL || 'https://gitea.com';
export const GITEA_REPOSITORY = process.env.GITEA_REPOSITORY || '';
export const GITEA_SKIP_TLS_VERIFY = process.env.GITEA_SKIP_TLS_VERIFY === 'true';
export const PR_NUMBER = process.env.PR_NUMBER || '';
export const PR_HEAD_BRANCH = process.env.PR_HEAD_BRANCH || '';
export const PR_BASE_BRANCH = process.env.PR_BASE_BRANCH || '';
+2 -2
View File
@@ -1,8 +1,8 @@
import axios from 'axios';
import https from 'https';
import { GITEA_TOKEN, GITEA_SERVER_URL, GITEA_REPOSITORY, PR_NUMBER } from './config.js';
import { GITEA_TOKEN, GITEA_SERVER_URL, GITEA_REPOSITORY, GITEA_SKIP_TLS_VERIFY, PR_NUMBER } from './config.js';
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
const httpsAgent = GITEA_SKIP_TLS_VERIFY ? new https.Agent({ rejectUnauthorized: false }) : undefined;
const headers = () => ({ Authorization: `token ${GITEA_TOKEN}`, 'Content-Type': 'application/json' });
const api = (path) => `${GITEA_SERVER_URL.replace(/\/$/, '')}/api/v1${path}`;
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"type": "module",
"scripts": {
"test": "node --test git.test.js config.test.js llm.test.js"
"test": "node --test *.test.js"
},
"dependencies": {
"axios": "^1.6.7",