From dc016d2cc01a12aec0e0e30cb108fd9a41c47a49 Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 15:33:44 +0100 Subject: [PATCH 1/8] Test AI code review workflow --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index fbef6f9..9504b9f 100644 --- a/README.md +++ b/README.md @@ -507,3 +507,6 @@ This project is licensed under the MIT License - see the LICENSE file for detail - [Incoming Webhooks](https://developers.mattermost.com/integrate/webhooks/incoming/) - [Message Attachments](https://developers.mattermost.com/integrate/reference/message-attachments/) - [Message Priority](https://developers.mattermost.com/integrate/reference/message-priority/) + +# AI Code Review Test +This change tests the automated AI code review workflow. From c4f0e2ee1272a88b07b498bfd51dc7505584a820 Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 15:34:55 +0100 Subject: [PATCH 2/8] Add AI code review workflow with GLM 4.7 --- .github/workflows/ai-code-review.yml | 107 +++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 .github/workflows/ai-code-review.yml diff --git a/.github/workflows/ai-code-review.yml b/.github/workflows/ai-code-review.yml new file mode 100644 index 0000000..a3774c0 --- /dev/null +++ b/.github/workflows/ai-code-review.yml @@ -0,0 +1,107 @@ +name: AI Code Review (Z.ai) + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + pull-requests: write + contents: read + +jobs: + code-review: + runs-on: ubuntu-latest + steps: + - name: Checkout PR code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get PR diff + id: diff + run: | + git diff origin/${{ github.base_ref }}...HEAD > pr.diff + MAX_SIZE=50000 + if [ $(wc -c < pr.diff) -gt $MAX_SIZE ]; then + head -c $MAX_SIZE pr.diff > pr_truncated.diff + mv pr_truncated.diff pr.diff + echo "warning=Diff truncated to ${MAX_SIZE} bytes" >> $GITHUB_OUTPUT + fi + FILES_CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | wc -l) + echo "files_changed=$FILES_CHANGED" >> $GITHUB_OUTPUT + + - name: Review with ${{ secrets.ZAI_MODEL }} + id: review + run: | + DIFF=$(cat pr.diff | jq -Rs .) + + RESPONSE=$(curl -s https://api.z.ai/api/coding/paas/v4/chat/completions \ + -H "Authorization: Bearer ${{ secrets.ZAI_API_KEY }}" \ + -H "Content-Type: application/json" \ + -H "Accept-Language: en-US,en" \ + -d "{ + \"model\": \"${{ secrets.ZAI_MODEL }}\", + \"messages\": [ + { + \"role\": \"system\", + \"content\": \"You are an expert code reviewer. Analyze the PR diff and provide:\\n\\n1. **Summary**: Brief overview\\n2. **Issues**: Bugs or problems (if any)\\n3. **Security**: Security concerns (if any)\\n4. **Performance**: Performance considerations (if any)\\n5. **Best Practices**: Swift 6, concurrency, architecture (if any)\\n6. **Suggestions**: Optional improvements\\n\\nBe concise but thorough. Use markdown formatting.\" + }, + { + \"role\": \"user\", + \"content\": ${DIFF} + } + ], + \"temperature\": 0.3, + \"max_tokens\": 4096 + }") + + REVIEW=$(echo "$RESPONSE" | jq -r '.choices[0].message.content') + echo "$REVIEW" > review.md + + cat > review_with_header.md << EOF + ### 🤖 AI Code Review (${{ secrets.ZAI_MODEL }}) + + $REVIEW + + --- + Reviewed by [${{ secrets.ZAI_MODEL }}](https://docs.z.ai/guides/llm/glm-4.7) from Z.ai + EOF + + if [ -n "${{ steps.diff.outputs.warning }}" ]; then + echo "" >> review_with_header.md + echo "⚠️ **Note**: ${{ steps.diff.outputs.warning }}" >> review_with_header.md + fi + + - name: Post review as PR comment + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const review = fs.readFileSync('review_with_header.md', 'utf8'); + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const botComment = comments.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('AI Code Review') + ); + + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: review + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: review + }); + } From ad0bdaf8ef94c18f0f9e4cf0ebd01a08fca5111e Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 15:45:18 +0100 Subject: [PATCH 3/8] Add error handling and safeguards for AI code review workflow --- .github/workflows/ai-code-review.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ai-code-review.yml b/.github/workflows/ai-code-review.yml index a3774c0..0d226f6 100644 --- a/.github/workflows/ai-code-review.yml +++ b/.github/workflows/ai-code-review.yml @@ -1,4 +1,4 @@ -name: AI Code Review (Z.ai) +name: AI Code Review on: pull_request: @@ -30,12 +30,13 @@ jobs: FILES_CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | wc -l) echo "files_changed=$FILES_CHANGED" >> $GITHUB_OUTPUT - - name: Review with ${{ secrets.ZAI_MODEL }} + - name: Code Review id: review run: | + set +x # Disable verbose mode to prevent secret leakage in logs DIFF=$(cat pr.diff | jq -Rs .) - RESPONSE=$(curl -s https://api.z.ai/api/coding/paas/v4/chat/completions \ + HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" https://api.z.ai/api/coding/paas/v4/chat/completions \ -H "Authorization: Bearer ${{ secrets.ZAI_API_KEY }}" \ -H "Content-Type: application/json" \ -H "Accept-Language: en-US,en" \ @@ -55,16 +56,20 @@ jobs: \"max_tokens\": 4096 }") + if [ "$HTTP_CODE" -ne 200 ]; then + echo "Error: API returned $HTTP_CODE" + cat response.json + exit 1 + fi + + RESPONSE=$(cat response.json) REVIEW=$(echo "$RESPONSE" | jq -r '.choices[0].message.content') echo "$REVIEW" > review.md cat > review_with_header.md << EOF - ### 🤖 AI Code Review (${{ secrets.ZAI_MODEL }}) + ### 🧠 AI Code Review $REVIEW - - --- - Reviewed by [${{ secrets.ZAI_MODEL }}](https://docs.z.ai/guides/llm/glm-4.7) from Z.ai EOF if [ -n "${{ steps.diff.outputs.warning }}" ]; then From 5376f9ee2135966c9857adf34707bdcd9d3451bc Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 15:50:00 +0100 Subject: [PATCH 4/8] Remove test changes from README --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 9504b9f..fbef6f9 100644 --- a/README.md +++ b/README.md @@ -507,6 +507,3 @@ This project is licensed under the MIT License - see the LICENSE file for detail - [Incoming Webhooks](https://developers.mattermost.com/integrate/webhooks/incoming/) - [Message Attachments](https://developers.mattermost.com/integrate/reference/message-attachments/) - [Message Priority](https://developers.mattermost.com/integrate/reference/message-priority/) - -# AI Code Review Test -This change tests the automated AI code review workflow. From 45bddd07cd5379f950ba81b7e0c3b776ce438146 Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 15:52:52 +0100 Subject: [PATCH 5/8] Add workflow_dispatch trigger for manual testing --- .github/workflows/ai-code-review.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ai-code-review.yml b/.github/workflows/ai-code-review.yml index 0d226f6..7c43b4b 100644 --- a/.github/workflows/ai-code-review.yml +++ b/.github/workflows/ai-code-review.yml @@ -3,6 +3,7 @@ name: AI Code Review on: pull_request: types: [opened, synchronize, reopened] + workflow_dispatch: permissions: pull-requests: write From 54b0d86d9da0ace50ef826ebcbde9cbe1f5b44d8 Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 15:58:19 +0100 Subject: [PATCH 6/8] Add validation for API response content --- .github/workflows/ai-code-review.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ai-code-review.yml b/.github/workflows/ai-code-review.yml index 7c43b4b..e769b68 100644 --- a/.github/workflows/ai-code-review.yml +++ b/.github/workflows/ai-code-review.yml @@ -65,6 +65,14 @@ jobs: RESPONSE=$(cat response.json) REVIEW=$(echo "$RESPONSE" | jq -r '.choices[0].message.content') + + # Check if review was extracted successfully + if [ -z "$REVIEW" ] || [ "$REVIEW" == "null" ]; then + echo "Error: Failed to extract review content from API response" + echo "Response: $RESPONSE" + exit 1 + fi + echo "$REVIEW" > review.md cat > review_with_header.md << EOF From fa5ee26de3ac9962f096b00e7ec84e9fb8ea02cd Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 16:06:06 +0100 Subject: [PATCH 7/8] Add API endpoint secret and retry logic with exponential backoff --- .github/workflows/ai-code-review.yml | 58 ++++++++++++++++++---------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ai-code-review.yml b/.github/workflows/ai-code-review.yml index e769b68..44f476a 100644 --- a/.github/workflows/ai-code-review.yml +++ b/.github/workflows/ai-code-review.yml @@ -37,28 +37,46 @@ jobs: set +x # Disable verbose mode to prevent secret leakage in logs DIFF=$(cat pr.diff | jq -Rs .) - HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" https://api.z.ai/api/coding/paas/v4/chat/completions \ - -H "Authorization: Bearer ${{ secrets.ZAI_API_KEY }}" \ - -H "Content-Type: application/json" \ - -H "Accept-Language: en-US,en" \ - -d "{ - \"model\": \"${{ secrets.ZAI_MODEL }}\", - \"messages\": [ - { - \"role\": \"system\", - \"content\": \"You are an expert code reviewer. Analyze the PR diff and provide:\\n\\n1. **Summary**: Brief overview\\n2. **Issues**: Bugs or problems (if any)\\n3. **Security**: Security concerns (if any)\\n4. **Performance**: Performance considerations (if any)\\n5. **Best Practices**: Swift 6, concurrency, architecture (if any)\\n6. **Suggestions**: Optional improvements\\n\\nBe concise but thorough. Use markdown formatting.\" - }, - { - \"role\": \"user\", - \"content\": ${DIFF} - } - ], - \"temperature\": 0.3, - \"max_tokens\": 4096 - }") + # Retry logic with exponential backoff + MAX_RETRIES=3 + RETRY_COUNT=0 + HTTP_CODE=0 + + while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do + HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" ${{ secrets.ZAI_API_ENDPOINT }} \ + -H "Authorization: Bearer ${{ secrets.ZAI_API_KEY }}" \ + -H "Content-Type: application/json" \ + -H "Accept-Language: en-US,en" \ + -d "{ + \"model\": \"${{ secrets.ZAI_MODEL }}\", + \"messages\": [ + { + \"role\": \"system\", + \"content\": \"You are an expert code reviewer. Analyze the PR diff and provide:\\n\\n1. **Summary**: Brief overview\\n2. **Issues**: Bugs or problems (if any)\\n3. **Security**: Security concerns (if any)\\n4. **Performance**: Performance considerations (if any)\\n5. **Best Practices**: Swift 6, concurrency, architecture (if any)\\n6. **Suggestions**: Optional improvements\\n\\nBe concise but thorough. Use markdown formatting.\" + }, + { + \"role\": \"user\", + \"content\": ${DIFF} + } + ], + \"temperature\": 0.3, + \"max_tokens\": 4096 + }") + + if [ "$HTTP_CODE" -eq 200 ]; then + break + fi + + RETRY_COUNT=$((RETRY_COUNT + 1)) + if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then + WAIT_TIME=$((2 ** RETRY_COUNT)) + echo "API returned $HTTP_CODE. Retrying in ${WAIT_TIME}s... (Attempt $RETRY_COUNT/$MAX_RETRIES)" + sleep $WAIT_TIME + fi + done if [ "$HTTP_CODE" -ne 200 ]; then - echo "Error: API returned $HTTP_CODE" + echo "Error: API returned $HTTP_CODE after $MAX_RETRIES attempts" cat response.json exit 1 fi From 1ece93ea7b975a29812bef3a86b96a3e29537f38 Mon Sep 17 00:00:00 2001 From: Diego Trevisan Lara Date: Wed, 4 Feb 2026 16:18:25 +0100 Subject: [PATCH 8/8] Use env block for secure secret passing --- .github/workflows/ai-code-review.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ai-code-review.yml b/.github/workflows/ai-code-review.yml index 44f476a..f2154c2 100644 --- a/.github/workflows/ai-code-review.yml +++ b/.github/workflows/ai-code-review.yml @@ -33,6 +33,10 @@ jobs: - name: Code Review id: review + env: + API_KEY: ${{ secrets.AI_PROVIDER_API_KEY }} + API_ENDPOINT: ${{ secrets.AI_PROVIDER_API_ENDPOINT }} + MODEL: ${{ secrets.AI_PROVIDER_MODEL }} run: | set +x # Disable verbose mode to prevent secret leakage in logs DIFF=$(cat pr.diff | jq -Rs .) @@ -43,12 +47,12 @@ jobs: HTTP_CODE=0 while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" ${{ secrets.ZAI_API_ENDPOINT }} \ - -H "Authorization: Bearer ${{ secrets.ZAI_API_KEY }}" \ + HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" $API_ENDPOINT \ + -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "Accept-Language: en-US,en" \ -d "{ - \"model\": \"${{ secrets.ZAI_MODEL }}\", + \"model\": \"$MODEL\", \"messages\": [ { \"role\": \"system\",