[Snyk] Fix for 3 vulnerabilities #15
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
| # @ai-generated: true | |
| # @ai-tool: GitHub Copilot | |
| name: Copilot PR Review (on-demand) | |
| on: | |
| issue_comment: | |
| types: [created] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| copilot-review: | |
| name: Generate Copilot review | |
| # Run only on PRs and only when explicitly asked | |
| if: >- | |
| ${{ github.event.issue.pull_request && | |
| (startsWith(github.event.comment.body, '/gov copilot') || | |
| startsWith(github.event.comment.body, '/copilot review')) }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Build PR context for Copilot | |
| id: ctx | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = context.payload.issue.number; | |
| const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: issue_number }); | |
| const files = await github.paginate(github.rest.pulls.listFiles, { owner, repo, pull_number: issue_number, per_page: 100 }); | |
| const truncate = (s, n) => (s ? (s.length > n ? s.slice(0, n) + '…' : s) : ''); | |
| const safeLines = (s, maxLines = 200) => (s || '').split('\n').slice(0, maxLines).join('\n'); | |
| const fileSummaries = files.map(f => `- ${f.filename} (+${f.additions}/-${f.deletions}, ${f.status}${f.changes ? ", ~"+f.changes+" lines" : ''})`).join('\n'); | |
| const diffs = files.slice(0, 10).map(f => { | |
| const patch = safeLines(truncate(f.patch || '', 6000), 250); | |
| return `--- ${f.filename} (${f.status}, +${f.additions}/-${f.deletions})\n${patch}`; | |
| }).join('\n\n'); | |
| const prBody = truncate(pr.body || '', 3000); | |
| const prompt = | |
| 'You are GitHub Copilot. Review the following Pull Request and provide a concise, helpful code review.\\n\\n\n'+ | |
| `Please include:\n`+ | |
| `- A 2-5 sentence summary of the changes.\n`+ | |
| `- Potential bugs, security issues, or edge cases (with reasons).\n`+ | |
| `- Testing gaps or scenarios to add.\n`+ | |
| `- Style or clarity suggestions.\n`+ | |
| `- Any breaking changes or migration notes.\n\n`+ | |
| `Use short bullet points, reference files and line ranges when relevant, and be factual. If nothing notable, say "No significant issues found."\n\n`+ | |
| `PR Title: ${pr.title}\n`+ | |
| `Author: @${pr.user.login}\n`+ | |
| `Base: ${pr.base.ref} -> Head: ${pr.head.ref}\n`+ | |
| `PR Description (truncated):\n${prBody}\n\n`+ | |
| `Changed files (${files.length}):\n${fileSummaries}\n\n`+ | |
| `Sample diffs (first up to 10 files, truncated for length):\n\n${diffs}`; | |
| core.setOutput('prompt', prompt); | |
| // Also write prompt to a workspace file to avoid shell quoting issues | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const promptPath = path.join(process.cwd(), 'copilot_prompt.txt'); | |
| fs.writeFileSync(promptPath, prompt, { encoding: 'utf8' }); | |
| core.setOutput('prompt_path', promptPath); | |
| - name: Install gh Copilot extension | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh --version | |
| gh extension install github/gh-copilot || gh extension upgrade github/gh-copilot || true | |
| - name: Ask Copilot for review | |
| id: ask | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| REVIEW_FILE="review.md" | |
| FINAL_FILE="final.md" | |
| PROMPT_FILE="copilot_prompt.txt" | |
| # Ensure prompt file exists | |
| if [ ! -f "$PROMPT_FILE" ]; then | |
| echo "::error::Prompt file not found at $PROMPT_FILE"; exit 1; | |
| fi | |
| # Try Copilot; if unavailable, produce a friendly fallback | |
| if gh extension list | grep -q "github/gh-copilot"; then | |
| if gh copilot --help > /dev/null 2>&1; then | |
| if ! gh copilot --plain -p "$(cat "$PROMPT_FILE")" > "$REVIEW_FILE" 2>/tmp/copilot.err; then | |
| printf "%s\n" "GitHub Copilot couldn't generate a review (perhaps not enabled for this org/repo)." > "$REVIEW_FILE" | |
| printf "\n%s\n" "Tip: Ensure GitHub Copilot is enabled for Pull Requests in your organization or repository." >> "$REVIEW_FILE" | |
| fi | |
| else | |
| echo "GitHub Copilot CLI not available on runner." > "$REVIEW_FILE" | |
| fi | |
| else | |
| echo "GitHub Copilot extension not installed or unavailable." > "$REVIEW_FILE" | |
| fi | |
| { | |
| echo "### GitHub Copilot PR Review" | |
| echo | |
| cat "$REVIEW_FILE" | |
| echo | |
| echo "_Generated by GitHub Copilot. Please verify important suggestions before applying._" | |
| } > "$FINAL_FILE" | |
| echo "final_path=$FINAL_FILE" >> "$GITHUB_OUTPUT" | |
| - name: Post review as PR comment | |
| if: always() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.issue.number }} | |
| run: | | |
| FILE="${{ steps.ask.outputs.final_path }}" | |
| if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then FILE="final.md"; fi | |
| gh pr comment "$PR_NUMBER" -F "$FILE" |