validate-registry.yml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. name: Validate Registry on PR
  2. # This workflow validates the registry.json and prompt library structure on all PRs.
  3. #
  4. # For bot-created PRs (like automated version bumps), the workflow won't trigger automatically
  5. # due to GitHub's security restrictions. In those cases, you can manually trigger this workflow:
  6. #
  7. # 1. Go to Actions > Validate Registry on PR > Run workflow
  8. # 2. Enter the PR number (e.g., 57)
  9. # 3. Click "Run workflow"
  10. #
  11. # This will run the validation checks and report the status to the PR.
  12. on:
  13. pull_request:
  14. branches:
  15. - main
  16. - dev
  17. # Removed paths filter - this check is required by repository ruleset
  18. # so it must run on ALL PRs to prevent blocking merges
  19. workflow_dispatch:
  20. inputs:
  21. pr_number:
  22. description: 'PR number to validate (for manual runs on bot-created PRs)'
  23. required: false
  24. type: number
  25. skip_validation:
  26. description: 'Skip validation checks (maintainer override)'
  27. required: false
  28. type: boolean
  29. default: false
  30. permissions:
  31. contents: write
  32. pull-requests: write
  33. jobs:
  34. validate-and-update:
  35. runs-on: ubuntu-latest
  36. steps:
  37. - name: Get PR details (for manual runs)
  38. if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number != ''
  39. id: get_pr
  40. run: |
  41. PR_DATA=$(gh pr view ${{ github.event.inputs.pr_number }} --json headRefName,headRepository,headRepositoryOwner)
  42. echo "head_ref=$(echo $PR_DATA | jq -r '.headRefName')" >> $GITHUB_OUTPUT
  43. echo "head_repo=$(echo $PR_DATA | jq -r '.headRepositoryOwner.login + "/" + .headRepository.name')" >> $GITHUB_OUTPUT
  44. env:
  45. GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  46. - name: Checkout PR branch
  47. uses: actions/checkout@v4
  48. with:
  49. # For manual runs: use PR details from get_pr step
  50. # For PR events: use event data
  51. repository: ${{ github.event_name == 'workflow_dispatch' && steps.get_pr.outputs.head_repo || github.event.pull_request.head.repo.full_name }}
  52. ref: ${{ github.event_name == 'workflow_dispatch' && steps.get_pr.outputs.head_ref || github.event.pull_request.head.ref }}
  53. fetch-depth: 0
  54. token: ${{ secrets.GITHUB_TOKEN }}
  55. - name: Detect fork PR
  56. id: fork_check
  57. run: |
  58. # For manual runs, use the fetched PR data
  59. if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
  60. HEAD_REPO="${{ steps.get_pr.outputs.head_repo }}"
  61. else
  62. HEAD_REPO="${{ github.event.pull_request.head.repo.full_name }}"
  63. fi
  64. if [ "$HEAD_REPO" != "${{ github.repository }}" ]; then
  65. echo "is_fork=true" >> $GITHUB_OUTPUT
  66. echo "🔀 Fork PR detected from: $HEAD_REPO"
  67. else
  68. echo "is_fork=false" >> $GITHUB_OUTPUT
  69. echo "📝 Internal PR detected"
  70. fi
  71. - name: Install dependencies
  72. run: |
  73. sudo apt-get update
  74. sudo apt-get install -y jq
  75. - name: Make scripts executable
  76. run: |
  77. chmod +x scripts/registry/validate-registry.sh
  78. chmod +x scripts/registry/auto-detect-components.sh
  79. chmod +x scripts/registry/register-component.sh
  80. chmod +x scripts/prompts/validate-pr.sh
  81. - name: Auto-detect new components
  82. id: auto_detect
  83. run: |
  84. echo "## 🔍 Auto-Detection Results" >> $GITHUB_STEP_SUMMARY
  85. echo "" >> $GITHUB_STEP_SUMMARY
  86. # Run auto-detect in dry-run mode first to see what would be added
  87. if ./scripts/registry/auto-detect-components.sh --dry-run > /tmp/detect-output.txt 2>&1; then
  88. cat /tmp/detect-output.txt >> $GITHUB_STEP_SUMMARY
  89. # Check if new components were found
  90. if grep -q "Found.*new component" /tmp/detect-output.txt; then
  91. echo "new_components=true" >> $GITHUB_OUTPUT
  92. echo "" >> $GITHUB_STEP_SUMMARY
  93. echo "⚠️ New components detected - will auto-add to registry" >> $GITHUB_STEP_SUMMARY
  94. else
  95. echo "new_components=false" >> $GITHUB_OUTPUT
  96. echo "✅ No new components found" >> $GITHUB_STEP_SUMMARY
  97. fi
  98. else
  99. echo "new_components=false" >> $GITHUB_OUTPUT
  100. echo "❌ Auto-detection failed" >> $GITHUB_STEP_SUMMARY
  101. fi
  102. - name: Add new components to registry
  103. if: steps.auto_detect.outputs.new_components == 'true'
  104. run: |
  105. echo "## 📝 Adding New Components" >> $GITHUB_STEP_SUMMARY
  106. echo "" >> $GITHUB_STEP_SUMMARY
  107. ./scripts/registry/auto-detect-components.sh --auto-add | tee -a $GITHUB_STEP_SUMMARY
  108. - name: Validate prompt library structure
  109. id: validate_prompts
  110. run: |
  111. echo "## 🔍 Prompt Library Validation" >> $GITHUB_STEP_SUMMARY
  112. echo "" >> $GITHUB_STEP_SUMMARY
  113. if ./scripts/prompts/validate-pr.sh > /tmp/prompt-validation.txt 2>&1; then
  114. echo "prompt_validation=passed" >> $GITHUB_OUTPUT
  115. echo "✅ Prompt library structure is valid!" >> $GITHUB_STEP_SUMMARY
  116. echo "" >> $GITHUB_STEP_SUMMARY
  117. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  118. cat /tmp/prompt-validation.txt >> $GITHUB_STEP_SUMMARY
  119. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  120. else
  121. echo "prompt_validation=failed" >> $GITHUB_OUTPUT
  122. echo "❌ Prompt library validation failed!" >> $GITHUB_STEP_SUMMARY
  123. echo "" >> $GITHUB_STEP_SUMMARY
  124. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  125. cat /tmp/prompt-validation.txt >> $GITHUB_STEP_SUMMARY
  126. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  127. echo "" >> $GITHUB_STEP_SUMMARY
  128. echo "**Architecture:**" >> $GITHUB_STEP_SUMMARY
  129. echo "- Agent files (.opencode/agent/**/*.md) = Canonical defaults" >> $GITHUB_STEP_SUMMARY
  130. echo "- Prompt variants (.opencode/prompts/<agent>/<model>.md) = Model-specific" >> $GITHUB_STEP_SUMMARY
  131. echo "- default.md files should NOT exist" >> $GITHUB_STEP_SUMMARY
  132. echo "- Agents organized in category subdirectories (core/, development/, content/, etc.)" >> $GITHUB_STEP_SUMMARY
  133. echo "" >> $GITHUB_STEP_SUMMARY
  134. echo "See [CONTRIBUTING.md](docs/contributing/CONTRIBUTING.md) for details" >> $GITHUB_STEP_SUMMARY
  135. exit 1
  136. fi
  137. - name: Validate registry
  138. id: validate
  139. run: |
  140. echo "## ✅ Registry Validation" >> $GITHUB_STEP_SUMMARY
  141. echo "" >> $GITHUB_STEP_SUMMARY
  142. if ./scripts/registry/validate-registry.sh -v > /tmp/validation-output.txt 2>&1; then
  143. echo "validation=passed" >> $GITHUB_OUTPUT
  144. echo "✅ All registry paths are valid!" >> $GITHUB_STEP_SUMMARY
  145. echo "" >> $GITHUB_STEP_SUMMARY
  146. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  147. tail -20 /tmp/validation-output.txt >> $GITHUB_STEP_SUMMARY
  148. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  149. else
  150. echo "validation=failed" >> $GITHUB_OUTPUT
  151. echo "❌ Registry validation failed!" >> $GITHUB_STEP_SUMMARY
  152. echo "" >> $GITHUB_STEP_SUMMARY
  153. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  154. cat /tmp/validation-output.txt >> $GITHUB_STEP_SUMMARY
  155. echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
  156. exit 1
  157. fi
  158. - name: Commit registry updates (Internal PRs only)
  159. if: |
  160. steps.fork_check.outputs.is_fork == 'false' &&
  161. steps.auto_detect.outputs.new_components == 'true' &&
  162. steps.validate_prompts.outputs.prompt_validation == 'passed' &&
  163. steps.validate.outputs.validation == 'passed'
  164. run: |
  165. git config --local user.email "github-actions[bot]@users.noreply.github.com"
  166. git config --local user.name "github-actions[bot]"
  167. if ! git diff --quiet registry.json; then
  168. git add registry.json
  169. git commit -m "chore: auto-update registry with new components [skip ci]"
  170. # For manual runs, use the fetched branch name
  171. BRANCH_NAME="${{ github.event_name == 'workflow_dispatch' && steps.get_pr.outputs.head_ref || github.event.pull_request.head.ref }}"
  172. git push origin "$BRANCH_NAME"
  173. echo "## 🚀 Registry Updated" >> $GITHUB_STEP_SUMMARY
  174. echo "" >> $GITHUB_STEP_SUMMARY
  175. echo "Registry has been automatically updated with new components." >> $GITHUB_STEP_SUMMARY
  176. echo "Changes have been pushed to this PR branch." >> $GITHUB_STEP_SUMMARY
  177. else
  178. echo "## ℹ️ No Changes to Commit" >> $GITHUB_STEP_SUMMARY
  179. echo "" >> $GITHUB_STEP_SUMMARY
  180. echo "Registry is already up to date." >> $GITHUB_STEP_SUMMARY
  181. fi
  182. - name: Fork PR notice
  183. if: |
  184. steps.fork_check.outputs.is_fork == 'true' &&
  185. steps.auto_detect.outputs.new_components == 'true' &&
  186. steps.validate_prompts.outputs.prompt_validation == 'passed' &&
  187. steps.validate.outputs.validation == 'passed'
  188. uses: actions/github-script@v7
  189. with:
  190. script: |
  191. github.rest.issues.createComment({
  192. issue_number: context.issue.number,
  193. owner: context.repo.owner,
  194. repo: context.repo.repo,
  195. body: `## 📝 Registry Update Needed
  196. Hi @${{ github.event.pull_request.user.login }}! 👋
  197. New components were detected in your PR. Since this is a fork PR, I can't auto-commit the registry updates for security reasons.
  198. **Please run these commands locally:**
  199. \`\`\`bash
  200. ./scripts/registry/auto-detect-components.sh --auto-add
  201. git add registry.json
  202. git commit -m "chore: update registry"
  203. git push
  204. \`\`\`
  205. Once you push the updated registry, the checks will pass! ✅`
  206. });
  207. - name: Fork PR summary
  208. if: steps.fork_check.outputs.is_fork == 'true'
  209. run: |
  210. echo "## 🔀 Fork PR Detected" >> $GITHUB_STEP_SUMMARY
  211. echo "" >> $GITHUB_STEP_SUMMARY
  212. echo "This is an external contribution - thank you! 🎉" >> $GITHUB_STEP_SUMMARY
  213. echo "" >> $GITHUB_STEP_SUMMARY
  214. if [ "${{ steps.auto_detect.outputs.new_components }}" == "true" ]; then
  215. echo "⚠️ **Action Required:** New components detected" >> $GITHUB_STEP_SUMMARY
  216. echo "" >> $GITHUB_STEP_SUMMARY
  217. echo "A comment has been posted with instructions to update the registry." >> $GITHUB_STEP_SUMMARY
  218. else
  219. echo "✅ No registry updates needed" >> $GITHUB_STEP_SUMMARY
  220. fi
  221. - name: Post validation summary
  222. if: always()
  223. run: |
  224. echo "" >> $GITHUB_STEP_SUMMARY
  225. echo "---" >> $GITHUB_STEP_SUMMARY
  226. echo "" >> $GITHUB_STEP_SUMMARY
  227. PROMPT_VALID="${{ steps.validate_prompts.outputs.prompt_validation }}"
  228. REGISTRY_VALID="${{ steps.validate.outputs.validation }}"
  229. if [ "$PROMPT_VALID" = "passed" ] && [ "$REGISTRY_VALID" = "passed" ]; then
  230. echo "### ✅ All Validations Passed" >> $GITHUB_STEP_SUMMARY
  231. echo "" >> $GITHUB_STEP_SUMMARY
  232. echo "- ✅ Prompt library structure is valid" >> $GITHUB_STEP_SUMMARY
  233. echo "- ✅ Registry paths are valid" >> $GITHUB_STEP_SUMMARY
  234. echo "" >> $GITHUB_STEP_SUMMARY
  235. echo "This PR is ready for review!" >> $GITHUB_STEP_SUMMARY
  236. else
  237. echo "### ❌ Validation Failed" >> $GITHUB_STEP_SUMMARY
  238. echo "" >> $GITHUB_STEP_SUMMARY
  239. if [ "$PROMPT_VALID" != "passed" ]; then
  240. echo "- ❌ Prompt library validation failed" >> $GITHUB_STEP_SUMMARY
  241. else
  242. echo "- ✅ Prompt library validation passed" >> $GITHUB_STEP_SUMMARY
  243. fi
  244. if [ "$REGISTRY_VALID" != "passed" ]; then
  245. echo "- ❌ Registry validation failed" >> $GITHUB_STEP_SUMMARY
  246. else
  247. echo "- ✅ Registry validation passed" >> $GITHUB_STEP_SUMMARY
  248. fi
  249. echo "" >> $GITHUB_STEP_SUMMARY
  250. echo "Please fix the issues above before merging." >> $GITHUB_STEP_SUMMARY
  251. fi
  252. - name: Fail if validation failed
  253. if: |
  254. (steps.validate_prompts.outputs.prompt_validation == 'failed' || steps.validate.outputs.validation == 'failed') &&
  255. github.event.inputs.skip_validation != 'true'
  256. run: |
  257. echo "❌ Validation failed - blocking PR merge"
  258. echo "Maintainer can override by running workflow manually with 'skip_validation' enabled"
  259. exit 1