diff --git a/.github/scripts/create-labels.sh b/.github/scripts/create-labels.sh index 3e5368b1..3ee32274 100755 --- a/.github/scripts/create-labels.sh +++ b/.github/scripts/create-labels.sh @@ -66,7 +66,7 @@ echo "==> Creating workflow labels..." create "skip-regression-check" "9E9E9E" "Acknowledged: fix without regression test" create "staging-ci-review" "D93F0B" "Auto-created by staging CI Claude Code review" create "skip-claude-gate" "FBCA04" "Override: bypass Claude CRITICAL gate on staging CI" -create "low-confidence" "C5DEF5" "Claude review finding with <50 confidence" +create "low-confidence" "C5DEF5" "Claude review finding with <50 confidence" echo "==> Creating contributor labels..." create "contributor: new" "FFF9C4" "First-time contributor" diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index fb4c02e5..8433ecef 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -145,14 +145,23 @@ jobs: cat /tmp/staging-diff.patch } > /tmp/review-prompt.txt + - name: Load prompt into env + id: load-prompt + if: steps.diff.outputs.diff_available == 'true' + run: | + # Use GITHUB_ENV with delimiter to handle multiline content + DELIM=$(openssl rand -hex 16) + echo "REVIEW_PROMPT<<${DELIM}" >> "$GITHUB_ENV" + cat /tmp/review-prompt.txt >> "$GITHUB_ENV" + echo "${DELIM}" >> "$GITHUB_ENV" + - name: Run Claude Code review id: claude-review if: steps.diff.outputs.diff_available == 'true' uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - prompt: | - $(cat /tmp/review-prompt.txt) + prompt: ${{ env.REVIEW_PROMPT }} claude_args: "--max-turns 30" - name: Validate and process results diff --git a/.github/workflows/code_style.yml b/.github/workflows/code_style.yml index 529c93df..c3efe282 100644 --- a/.github/workflows/code_style.yml +++ b/.github/workflows/code_style.yml @@ -69,7 +69,7 @@ jobs: echo "One or more jobs failed" exit 1 fi - if [[ "${{ needs.version-check.result }}" == "failure" ]]; then - echo "Version bump check failed" + if [[ "${{ needs.version-check.result }}" != "success" ]]; then + echo "Version bump check did not succeed (status: ${{ needs.version-check.result }})" exit 1 fi diff --git a/.github/workflows/staging-ci.yml b/.github/workflows/staging-ci.yml index 5481eca5..9b97c9b8 100644 --- a/.github/workflows/staging-ci.yml +++ b/.github/workflows/staging-ci.yml @@ -52,31 +52,38 @@ jobs: fi echo "last_tested=${LAST_TESTED}" >> "$GITHUB_OUTPUT" + DIFF_RANGE="" if [ -n "$LAST_TESTED" ] && [ "$LAST_TESTED" = "$CURRENT_HEAD" ]; then echo "No new commits since last tested (${CURRENT_HEAD})" - echo "has_changes=false" >> "$GITHUB_OUTPUT" - echo "diff_range=" >> "$GITHUB_OUTPUT" + HAS_CHANGES=false else + HAS_CHANGES=true if [ -n "$LAST_TESTED" ]; then COMMIT_COUNT=$(git rev-list --count "${LAST_TESTED}..HEAD") echo "Found ${COMMIT_COUNT} new commit(s) since last tested" - echo "diff_range=${LAST_TESTED}..${CURRENT_HEAD}" >> "$GITHUB_OUTPUT" + DIFF_RANGE="${LAST_TESTED}..${CURRENT_HEAD}" else # First run: use merge-base with main to capture all staging changes git fetch origin main MERGE_BASE=$(git merge-base origin/main HEAD) echo "First run -- reviewing from merge-base ${MERGE_BASE}" - echo "diff_range=${MERGE_BASE}..${CURRENT_HEAD}" >> "$GITHUB_OUTPUT" + DIFF_RANGE="${MERGE_BASE}..${CURRENT_HEAD}" fi - echo "has_changes=true" >> "$GITHUB_OUTPUT" fi # Force override from workflow_dispatch if [ "${{ inputs.force }}" = "true" ]; then echo "Force run requested" - echo "has_changes=true" >> "$GITHUB_OUTPUT" + HAS_CHANGES=true + # Use a valid empty range if no new commits + if [ -z "$DIFF_RANGE" ]; then + DIFF_RANGE="${CURRENT_HEAD}..${CURRENT_HEAD}" + fi fi + echo "has_changes=${HAS_CHANGES}" >> "$GITHUB_OUTPUT" + echo "diff_range=${DIFF_RANGE}" >> "$GITHUB_OUTPUT" + # ── Run full test suite ────────────────────────────────────────── tests: name: Test Suite @@ -110,30 +117,22 @@ jobs: always() && needs.check-changes.outputs.has_changes == 'true' && needs.tests.result == 'success' && - needs.e2e.result == 'success' + needs.e2e.result == 'success' && + needs.claude-review.result == 'success' runs-on: ubuntu-latest outputs: gate_passed: ${{ steps.gate.outputs.passed }} steps: - - name: Check for skip-claude-gate label - id: label-check - env: - GH_TOKEN: ${{ github.token }} - run: | - SKIP=$(gh label list --json name -q '.[].name' | grep -c 'skip-claude-gate' || true) - echo "skip_label=${SKIP}" >> "$GITHUB_OUTPUT" - - name: Evaluate gate id: gate run: | HAS_BLOCKING="${{ needs.claude-review.outputs.has_blocking }}" - SKIP_LABEL="${{ steps.label-check.outputs.skip_label }}" SKIP_INPUT="${{ inputs.skip_claude_gate }}" if [ "$HAS_BLOCKING" = "true" ]; then echo "::warning::Claude review found blocking issues (CRITICAL ≥80 confidence)" - if [ "$SKIP_LABEL" -gt 0 ] || [ "$SKIP_INPUT" = "true" ]; then - echo "::warning::Gate overridden by skip-claude-gate label or input" + if [ "$SKIP_INPUT" = "true" ]; then + echo "::warning::Gate overridden by skip_claude_gate workflow input" echo "passed=true" >> "$GITHUB_OUTPUT" else echo "::error::Blocking promotion to main due to CRITICAL findings (≥80 confidence)"