scan-plugins.yml 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. name: Scan Plugins
  2. # Claude policy scan of changed external marketplace entries.
  3. #
  4. # `scan` is a required status check on main. A path-filtered workflow never
  5. # reports a check run when its paths don't match, which would leave unrelated
  6. # PRs blocked forever — so this workflow runs on every PR and skips the heavy
  7. # scan setup at the step level when nothing scan-relevant changed. The check
  8. # always reports.
  9. on:
  10. pull_request:
  11. workflow_dispatch:
  12. inputs:
  13. scan_all:
  14. description: Scan every external entry (full re-review). Slow.
  15. type: boolean
  16. default: false
  17. permissions:
  18. contents: read
  19. jobs:
  20. scan:
  21. runs-on: ubuntu-latest
  22. timeout-minutes: 360
  23. steps:
  24. - uses: actions/checkout@v4
  25. with:
  26. fetch-depth: 0
  27. # Same paths the workflow-level filter used to gate on. workflow_dispatch
  28. # always runs the scan (no PR diff to inspect).
  29. - name: Check for scan-relevant changes
  30. id: changes
  31. env:
  32. EVENT_NAME: ${{ github.event_name }}
  33. BASE_SHA: ${{ github.event.pull_request.base.sha }}
  34. run: |
  35. if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
  36. echo "relevant=true" >> "$GITHUB_OUTPUT"
  37. exit 0
  38. fi
  39. if git diff --quiet "$BASE_SHA" HEAD -- .claude-plugin/marketplace.json .github/policy/; then
  40. echo "relevant=false" >> "$GITHUB_OUTPUT"
  41. echo "::notice::No changes to marketplace.json or policy/ — skipping policy scan."
  42. else
  43. echo "relevant=true" >> "$GITHUB_OUTPUT"
  44. fi
  45. # The shared action no-ops gracefully when ANTHROPIC_API_KEY is unset
  46. # (sensible default for community repos). Here `scan` is a required
  47. # check, so a silent no-op would make it a rubber stamp — fail closed.
  48. - name: Require ANTHROPIC_API_KEY when a scan is needed
  49. if: steps.changes.outputs.relevant == 'true'
  50. env:
  51. API_KEY_SET: ${{ secrets.ANTHROPIC_API_KEY != '' }}
  52. run: |
  53. if [[ "$API_KEY_SET" != "true" ]]; then
  54. echo "::error::ANTHROPIC_API_KEY is not configured; refusing to skip a required policy scan."
  55. exit 1
  56. fi
  57. # Blocking: policy failures fail the job. Loosen by removing
  58. # fail-on-findings if the false-positive rate is too high.
  59. - if: steps.changes.outputs.relevant == 'true'
  60. uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@b277757588871fe55b2620de8c6dfda470e2e9d8
  61. with:
  62. anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
  63. policy-prompt: .github/policy/prompt.md
  64. fail-on-findings: "true"
  65. scan-all-external: ${{ inputs.scan_all || 'false' }}
  66. claude-cli-version: latest