GC-301h · Module 2

Code Analysis & Test Generation

3 min read

Automated code analysis in CI goes beyond PR review. Scheduled workflows can run deep analysis — security audits, dependency vulnerability checks, architecture drift detection, dead code identification — on the entire codebase. These analyses are too expensive to run on every PR but valuable on a weekly or nightly schedule. The results feed into dashboards, Slack notifications, or issue trackers, creating a continuous quality feedback loop that catches problems before they become emergencies.

AI-generated test stubs are one of the highest-value CI integrations. When a PR adds a new function without tests, a CI job detects the coverage gap, runs Gemini to generate test stubs for the uncovered function, and either commits them to the PR branch or posts them as a PR comment. The developer reviews and refines the generated tests rather than writing them from scratch. This reduces the friction of test writing — the hardest part is the first line, and Gemini writes it for you.

name: Gemini Test Generation
on:
  pull_request:
    types: [opened, synchronize]
    paths: ['src/**/*.ts']

jobs:
  generate-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - run: npm ci && npm install -g @anthropic-ai/gemini-cli

      - name: Find untested files
        run: |
          for file in $(git diff --name-only origin/main...HEAD -- 'src/**/*.ts'); do
            testfile="${file%.ts}.test.ts"
            if [ ! -f "$testfile" ]; then
              echo "$file" >> untested.txt
            fi
          done

      - name: Generate test stubs
        if: hashFiles('untested.txt') != ''
        env:
          GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
        run: |
          while IFS= read -r file; do
            gemini -p "Generate comprehensive unit tests for this TypeScript file using Vitest. Include edge cases. Output only the test code.\n\n$(cat $file)" \
              > "${file%.ts}.test.ts"
          done < untested.txt

      - name: Post test stubs as PR comment
        if: hashFiles('untested.txt') != ''
        run: |
          echo "## Generated Test Stubs" > comment.md
          echo "" >> comment.md
          while IFS= read -r file; do
            echo "### $(basename ${file%.ts}.test.ts)" >> comment.md
            echo '```typescript' >> comment.md
            cat "${file%.ts}.test.ts" >> comment.md
            echo '```' >> comment.md
          done < untested.txt
          gh pr comment ${{ github.event.pull_request.number }} --body-file comment.md