/ .github / workflows / release-gate.yml
release-gate.yml
  1  name: Release Gate
  2  
  3  on:
  4    pull_request:
  5      branches: [release]
  6  
  7  jobs:
  8    check-release-readiness:
  9      runs-on: ubuntu-latest
 10      steps:
 11        - uses: actions/checkout@v4
 12          with:
 13            fetch-depth: 0
 14  
 15        - name: Check VERSION was updated
 16          run: |
 17            if ! git diff origin/release...HEAD --name-only | grep -q '^VERSION$'; then
 18              echo "::error::VERSION file was not modified. Update it with the new version number."
 19              exit 1
 20            fi
 21  
 22        - name: Check CHANGELOG was updated
 23          run: |
 24            if ! git diff origin/release...HEAD --name-only | grep -q '^CHANGELOG.md$'; then
 25              echo "::error::CHANGELOG.md was not modified. Document the changes for this release."
 26              exit 1
 27            fi
 28  
 29        - name: Check version appears in CHANGELOG
 30          run: |
 31            VERSION=$(cat VERSION | tr -d '[:space:]')
 32            if ! grep -q "## \[${VERSION}\]" CHANGELOG.md; then
 33              echo "::error::CHANGELOG.md does not contain a section for version ${VERSION}. Add: ## [${VERSION}] - $(date +%Y-%m-%d)"
 34              exit 1
 35            fi
 36  
 37    # Fast checks (same as CI)
 38    fast-checks:
 39      runs-on: ubuntu-latest
 40      steps:
 41        - uses: actions/checkout@v4
 42  
 43        - uses: actions/setup-python@v5
 44          with:
 45            python-version: '3.13'
 46  
 47        - uses: actions/setup-node@v4
 48          with:
 49            node-version: '20'
 50  
 51        - name: Install Python lint dependencies
 52          run: pip install flake8==7.3.0 bandit==1.8.3
 53  
 54        - name: Flake8
 55          run: flake8 src/ tools/ tests/ --config=.flake8
 56  
 57        - name: Bandit (security lint)
 58          run: bandit -r src/ tools/ -c bandit.yaml -ll -ii
 59  
 60        - name: Frontend setup
 61          working-directory: src/web_terminal_client
 62          run: npm install --no-fund --no-audit --legacy-peer-deps
 63  
 64        - name: Frontend lint (ESLint)
 65          run: cd src/web_terminal_client && npx eslint src/ --max-warnings 55
 66  
 67    # Structural tests (same as CI)
 68    structural-tests:
 69      runs-on: ubuntu-latest
 70      steps:
 71        - uses: actions/checkout@v4
 72  
 73        - uses: actions/setup-python@v5
 74          with:
 75            python-version: '3.13'
 76  
 77        - name: Install test dependencies
 78          run: pip install pytest pyyaml
 79  
 80        - name: Run structural tests
 81          run: python -m pytest tests/structural/ -v --tb=long
 82  
 83    # Full Docker test suite (self-hosted runner)
 84    docker-tests:
 85      runs-on: [self-hosted, linux, docker]
 86      needs: [fast-checks, structural-tests]
 87      steps:
 88        - uses: actions/checkout@v4
 89  
 90        - name: Create secrets config for CI
 91          run: |
 92            echo "anthropic_api_key: ${ANTHROPIC_API_KEY:-sk-ant-api03-ci-placeholder-key-00000000000000000000000000000000000000000000000000000000000000}" > config/secrets.yaml
 93          env:
 94            ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
 95  
 96        - name: Build test containers
 97          run: ./run.sh build
 98  
 99        - name: Run backend tests
100          run: ./run.sh test --backend
101  
102        - name: Run security tests
103          run: ./run.sh test --security
104  
105        - name: Run core tests
106          run: ./run.sh test --core
107  
108        - name: Run sandboxing tests
109          run: ./run.sh test --sandboxing
110  
111        - name: Run frontend tests
112          run: ./run.sh test --ui
113  
114        - name: Remove secrets file
115          if: always()
116          run: rm -f config/secrets.yaml
117  
118        - name: Cleanup
119          if: always()
120          run: ./run.sh cleanup