Skip to content

ci: enhance GitHub Actions workflows with security and performance improvements #5

ci: enhance GitHub Actions workflows with security and performance improvements

ci: enhance GitHub Actions workflows with security and performance improvements #5

Workflow file for this run

name: PR Auto-Review
# IMPORTANT: Uses pull_request_target to support fork PRs
# This allows posting comments on PRs from forks while maintaining security
# by only checking out code for diff analysis (not executing PR code)
on:
pull_request_target:
types: [opened, synchronize, ready_for_review]
permissions:
contents: read
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true # Re-review on each push, cancel old reviews
jobs:
auto-review:
runs-on: ubuntu-latest
timeout-minutes: 15
# Skip draft PRs and PRs with skip-review label
if: |
github.event.pull_request.draft == false &&
!contains(github.event.pull_request.labels.*.name, 'skip-review')
steps:
- uses: actions/checkout@v4
with:
# SECURITY: Check out base branch, not PR code
# We only analyze diffs via GitHub API, never execute PR code
ref: ${{ github.event.pull_request.base.sha }}
fetch-depth: 0
- name: Fetch PR branch for diff analysis
run: |
# Fetch PR branch without checking it out (security)
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-branch
- name: Get changed files
id: changed
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
CHANGED_FILES=$(gh pr view "$PR_NUMBER" --json files -q '.files[].path' | tr '\n' ' ')
echo "files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
- name: Security review
id: security
env:
CHANGED_FILES: ${{ steps.changed.outputs.files }}
run: |
set -euo pipefail
FINDINGS=""
# Check for hardcoded secrets patterns
# Use pr-branch ref instead of HEAD for security (never checkout PR code)
if SECRETS_FOUND=$(git diff origin/${{ github.event.pull_request.base.ref }}...pr-branch | grep -iE "(password|secret|api_key|token)\s*=\s*['\"][^'\"]+['\"]" || true) && [ -n "$SECRETS_FOUND" ]; then
FINDINGS="${FINDINGS}🔴 **CRITICAL**: Potential hardcoded secrets detected\n"
fi
# Check for .env file additions
if echo "$CHANGED_FILES" | grep -qE "\.env$" || false; then
FINDINGS="${FINDINGS}🔴 **CRITICAL**: .env file should not be committed\n"
fi
# Check for TODO/FIXME in security-sensitive areas
if TODO_FOUND=$(git diff origin/${{ github.event.pull_request.base.ref }}...pr-branch | grep -iE "(security|auth|password)" | grep -iE "(todo|fixme|hack)" || true) && [ -n "$TODO_FOUND" ]; then
FINDINGS="${FINDINGS}🟡 **WARNING**: TODO/FIXME in security-sensitive code\n"
fi
if [ -n "$FINDINGS" ]; then
echo "has_findings=true" >> "$GITHUB_OUTPUT"
echo -e "findings=$FINDINGS" >> "$GITHUB_OUTPUT"
else
echo "has_findings=false" >> "$GITHUB_OUTPUT"
fi
- name: Code quality review
id: quality
env:
CHANGED_FILES: ${{ steps.changed.outputs.files }}
run: |
set -euo pipefail
FINDINGS=""
# Check for large files
LARGE_FILES=$(git diff --stat origin/${{ github.event.pull_request.base.ref }}...pr-branch | grep -E "\+[0-9]{3,}" | head -5 || true)
if [ -n "$LARGE_FILES" ]; then
FINDINGS="${FINDINGS}🟡 **WARNING**: Large changes detected - consider breaking into smaller PRs\n"
fi
# Check for missing tests in code changes
CODE_CHANGED=$(echo "$CHANGED_FILES" | grep -E "\.(py|js|ts)$" | grep -v test || true)
TEST_CHANGED=$(echo "$CHANGED_FILES" | grep -E "test" || true)
if [ -n "$CODE_CHANGED" ] && [ -z "$TEST_CHANGED" ]; then
FINDINGS="${FINDINGS}🟡 **WARNING**: Code changes without corresponding tests\n"
fi
if [ -n "$FINDINGS" ]; then
echo "has_findings=true" >> "$GITHUB_OUTPUT"
echo -e "findings=$FINDINGS" >> "$GITHUB_OUTPUT"
else
echo "has_findings=false" >> "$GITHUB_OUTPUT"
fi
- name: Post review comment
if: steps.security.outputs.has_findings == 'true' || steps.quality.outputs.has_findings == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
SECURITY_FINDINGS: ${{ steps.security.outputs.findings }}
QUALITY_FINDINGS: ${{ steps.quality.outputs.findings }}
HAS_SECURITY: ${{ steps.security.outputs.has_findings }}
HAS_QUALITY: ${{ steps.quality.outputs.has_findings }}
run: |
set -euo pipefail
# Build comment body
COMMENT="## 🤖 Automated PR Review
"

Check failure on line 124 in .github/workflows/pr-review.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/pr-review.yml

Invalid workflow file

You have an error in your yaml syntax on line 124
if [ "$HAS_SECURITY" == "true" ]; then
COMMENT="${COMMENT}### Security Findings
${SECURITY_FINDINGS}
"
fi
if [ "$HAS_QUALITY" == "true" ]; then
COMMENT="${COMMENT}### Code Quality
${QUALITY_FINDINGS}
"
fi
COMMENT="${COMMENT}---
*This is an automated review. Please address any 🔴 CRITICAL issues before merging.*"
# Post comment with explicit repository
echo "$COMMENT" | gh pr comment "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--body-file -
- name: Post success comment
if: steps.security.outputs.has_findings == 'false' && steps.quality.outputs.has_findings == 'false'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
gh pr comment "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--body "## 🤖 Automated PR Review
✅ No security or code quality issues detected.
---
*This is an automated review.*"