ci: bump actions/deploy-pages from 4 to 5 #68
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: AI PR Review | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize, reopened] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| review: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| # Checkout base repo (not PR head) for safe access to CLAUDE.md and proposals. | |
| # The diff is fetched via GitHub API, not from the PR code. | |
| ref: ${{ github.event.pull_request.base.sha }} | |
| fetch-depth: 1 | |
| - name: Get PR diff | |
| id: diff | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| gh pr diff ${{ github.event.pull_request.number }} > /tmp/pr-full.diff | |
| FULL_SIZE=$(wc -c < /tmp/pr-full.diff) | |
| echo "diff_size=$FULL_SIZE" >> "$GITHUB_OUTPUT" | |
| # Truncate to ~80k chars to stay within API limits | |
| if [ "$FULL_SIZE" -gt 80000 ]; then | |
| head -c 80000 /tmp/pr-full.diff > /tmp/pr.diff | |
| echo "truncated=true" >> "$GITHUB_OUTPUT" | |
| else | |
| cp /tmp/pr-full.diff /tmp/pr.diff | |
| echo "truncated=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Get PR info | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| gh pr view ${{ github.event.pull_request.number }} --json title,body > /tmp/pr-info.json | |
| - name: Gather project context | |
| run: | | |
| # Read full CLAUDE.md (contains architecture, review checklist, key concepts) | |
| if [ -f "CLAUDE.md" ]; then | |
| cat CLAUDE.md > /tmp/project-context.txt | |
| else | |
| echo "No CLAUDE.md found." > /tmp/project-context.txt | |
| fi | |
| # List proposals | |
| if [ -d "docs/03-development/proposals" ]; then | |
| ls docs/03-development/proposals/ 2>/dev/null | head -20 > /tmp/proposals.txt | |
| else | |
| echo "No proposals directory." > /tmp/proposals.txt | |
| fi | |
| # List existing doctype test files for overlap checking | |
| if [ -d "mdl-examples/doctype-tests" ]; then | |
| ls mdl-examples/doctype-tests/ 2>/dev/null | head -30 > /tmp/doctype-tests.txt | |
| else | |
| echo "No doctype-tests directory." > /tmp/doctype-tests.txt | |
| fi | |
| - name: Build API request | |
| env: | |
| TRUNCATED: ${{ steps.diff.outputs.truncated }} | |
| DIFF_SIZE: ${{ steps.diff.outputs.diff_size }} | |
| run: | | |
| TRUNCATION_NOTE="" | |
| if [ "$TRUNCATED" = "true" ]; then | |
| TRUNCATION_NOTE="NOTE: The diff was truncated to 80k characters. Total size: ${DIFF_SIZE} bytes. Focus on what is visible." | |
| fi | |
| # Write the user prompt to a file (avoids shell variable limits) | |
| cat > /tmp/user-prompt.txt <<PROMPT | |
| Review this pull request. | |
| PR Info: | |
| $(cat /tmp/pr-info.json) | |
| Project context (CLAUDE.md — contains architecture + review checklist): | |
| $(cat /tmp/project-context.txt) | |
| Proposals in repo: | |
| $(cat /tmp/proposals.txt) | |
| Existing doctype test files: | |
| $(cat /tmp/doctype-tests.txt) | |
| ${TRUNCATION_NOTE} | |
| Review against ALL of the following checklist items: | |
| ## Overlap & duplication | |
| - Check proposals list above for existing proposals covering the same functionality | |
| - Check if the diff introduces code that duplicates existing implementations (look for similar function names, command names, types) | |
| - Check doctype test files above for existing test coverage of the feature area | |
| - Flag if the PR re-documents already-shipped features as new | |
| ## MDL syntax design (for new or modified MDL syntax) | |
| If the diff adds or modifies MDL syntax (grammar rules, keywords, statement types), check: | |
| - Follows standard CREATE/ALTER/DROP/SHOW/DESCRIBE pattern — no custom verbs for CRUD operations | |
| - Uses Module.Element qualified names everywhere — no bare names, no implicit module context | |
| - Property lists use ( Key: value, ... ) format with colon separators, one per line | |
| - Colon for property definitions (Key: value), AS for name-to-name mappings ('oldName' AS 'newName') — do not flag AS in mapping/renaming contexts as wrong | |
| - Keywords are full English words — no abbreviations, no symbols for domain operations | |
| - Statement reads as English — a business analyst can understand the intent | |
| - No keyword overloading — each keyword has one consistent meaning | |
| - Diff-friendly — adding one property produces a one-line diff | |
| - Consistent with existing MDL patterns (check docs/01-project/MDL_QUICK_REFERENCE.md) | |
| ## Full-stack consistency (for MDL features) | |
| New MDL commands or language features must be wired through the full pipeline. If the diff adds any MDL feature, check: | |
| - Grammar rule added to MDLParser.g4 (and MDLLexer.g4 if new tokens) | |
| - AST node type added in mdl/ast/ | |
| - Visitor handler in mdl/visitor/ | |
| - Executor handler in mdl/executor/ | |
| - LSP wiring (cmd/mxcli/lsp.go) if the feature adds formatting, diagnostics, or navigation | |
| - DESCRIBE roundtrip — if the feature creates artifacts, DESCRIBE should output re-executable MDL | |
| - VS Code extension (vscode-mdl/package.json) updated if new LSP capabilities added | |
| ## Test coverage | |
| - New packages should have test files | |
| - New executor commands should have MDL examples in mdl-examples/doctype-tests/ | |
| - Integration paths should be tested, not just helpers | |
| - No time.Sleep for synchronization — use channels or polling with timeout | |
| ## Security & robustness | |
| - Command injection, XSS, SQL injection, temp file issues | |
| - Unix sockets should use restrictive permissions (0600) | |
| - File I/O should not be in hot paths (event loops, per-keystroke handlers) | |
| - No silent side effects on typos (e.g., auto-creating resources on misspelled names) | |
| - Correct method receivers (pointer vs value) for mutations | |
| ## Scope & atomicity | |
| - Each commit should do one thing — a feature, a bugfix, or a refactor, not a mix | |
| - PR should be scoped to a single feature or concern — flag if description needs "and" between unrelated items | |
| - Independent features should be in separate PRs | |
| - Refactors touching many files should be their own commit | |
| ## Code quality | |
| - Refactors should be applied consistently (look for old patterns still present) | |
| - Manually maintained lists (keyword lists, type mappings) should be flagged as maintenance risks | |
| - Design docs should match the actual implementation | |
| ## Bugs & correctness | |
| - Logic errors, race conditions, resource leaks | |
| - Error handling gaps | |
| Structure your review as: Critical Issues, Moderate Issues, Minor Issues, What Looks Good, Recommendation (approve/request changes). | |
| Only list sections that have findings — skip empty sections. | |
| Diff: | |
| $(cat /tmp/pr.diff) | |
| PROMPT | |
| # Build JSON payload using jq with file input (no shell variable limits) | |
| jq -n --rawfile prompt /tmp/user-prompt.txt '{ | |
| model: "nvidia/nemotron-3-super-120b-a12b:free", | |
| messages: [ | |
| { | |
| role: "system", | |
| content: "You are a code reviewer for a Go CLI project (mxcli) that reads/modifies Mendix application projects. Key patterns: ANTLR4 grammar → AST → visitor → executor → BSON writer. New MDL features MUST be wired through the full pipeline (grammar → AST → visitor → executor → LSP → DESCRIBE roundtrip). New MDL syntax must follow design guidelines: reads as English (target audience is citizen developers), uses standard CRUD verbs (CREATE/ALTER/DROP/SHOW/DESCRIBE), consistent property format (Key: value) for property definitions, AS for name-to-name mappings ('old' AS 'new'), qualified names (Module.Element), no keyword overloading, no symbolic syntax. IMPORTANT: colon is for property definitions (Key: value), AS is for name mappings/renaming — do not flag AS in mapping contexts as a syntax violation. Generated ANTLR parser files (mdl/grammar/parser/) are noise — note but skip. The project context includes the full CLAUDE.md with architecture details and the review checklist. Review against the checklist thoroughly but concisely." | |
| }, | |
| { | |
| role: "user", | |
| content: $prompt | |
| } | |
| ], | |
| max_tokens: 4000 | |
| }' > /tmp/request.json | |
| echo "Request payload size: $(wc -c < /tmp/request.json) bytes" | |
| - name: Call OpenRouter API | |
| env: | |
| OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} | |
| run: | | |
| if [ -z "$OPENROUTER_API_KEY" ]; then | |
| echo "::warning::OPENROUTER_API_KEY secret is not set" | |
| exit 0 | |
| fi | |
| HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/response.json -X POST \ | |
| -H "Authorization: Bearer $OPENROUTER_API_KEY" \ | |
| -H "Content-Type: application/json" \ | |
| -d @/tmp/request.json \ | |
| https://openrouter.ai/api/v1/chat/completions) | |
| echo "HTTP status: $HTTP_CODE" | |
| if [ "$HTTP_CODE" != "200" ]; then | |
| echo "::warning::OpenRouter API returned HTTP $HTTP_CODE" | |
| cat /tmp/response.json | head -c 1000 | |
| exit 0 | |
| fi | |
| REVIEW=$(jq -r '.choices[0].message.content // empty' /tmp/response.json) | |
| if [ -z "$REVIEW" ]; then | |
| echo "::warning::AI review returned empty content. Response:" | |
| cat /tmp/response.json | head -c 1000 | |
| exit 0 | |
| fi | |
| # Save review for next step | |
| echo "$REVIEW" > /tmp/review.txt | |
| echo "Review generated ($(wc -c < /tmp/review.txt) bytes)" | |
| - name: Post review comment | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| if [ ! -f /tmp/review.txt ]; then | |
| echo "No review to post." | |
| exit 0 | |
| fi | |
| # Build comment body | |
| { | |
| echo "## AI Code Review" | |
| echo "" | |
| cat /tmp/review.txt | |
| echo "" | |
| echo "---" | |
| echo "*Automated review via OpenRouter (Nemotron Super 120B) — [workflow source](${{ github.server_url }}/${{ github.repository }}/blob/main/.github/workflows/ai-review.yml)*" | |
| } > /tmp/comment.md | |
| gh pr comment ${{ github.event.pull_request.number }} --body-file /tmp/comment.md |