sync-docs.yml 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. name: Sync Documentation
  2. on:
  3. push:
  4. branches:
  5. - main
  6. paths:
  7. - 'registry.json'
  8. - '.opencode/agent/**'
  9. - '.opencode/command/**'
  10. - '.opencode/context/**'
  11. workflow_dispatch:
  12. inputs:
  13. force_update:
  14. description: 'Force documentation update even if no changes detected'
  15. required: false
  16. type: boolean
  17. default: false
  18. permissions:
  19. contents: write
  20. pull-requests: write
  21. issues: write
  22. jobs:
  23. check-sync-needed:
  24. name: Check if Docs Need Sync
  25. runs-on: ubuntu-latest
  26. outputs:
  27. needs_sync: ${{ steps.check.outputs.needs_sync }}
  28. changes_detected: ${{ steps.check.outputs.changes_detected }}
  29. steps:
  30. - name: Checkout repository
  31. uses: actions/checkout@v4
  32. with:
  33. fetch-depth: 2
  34. - name: Install dependencies
  35. run: |
  36. sudo apt-get update
  37. sudo apt-get install -y jq
  38. - name: Check if sync needed
  39. id: check
  40. run: |
  41. # Skip if this is an automated commit to prevent loops
  42. COMMIT_MSG=$(git log -1 --pretty=%B)
  43. if echo "$COMMIT_MSG" | grep -qE "\[skip ci\]|\[skip-docs\]|auto-update registry|bump version|Sync documentation"; then
  44. echo "needs_sync=false" >> $GITHUB_OUTPUT
  45. echo "changes_detected=Automated commit - skipping to prevent loops" >> $GITHUB_OUTPUT
  46. exit 0
  47. fi
  48. # Force update if requested
  49. if [ "${{ github.event.inputs.force_update }}" = "true" ]; then
  50. echo "needs_sync=true" >> $GITHUB_OUTPUT
  51. echo "changes_detected=Force update requested" >> $GITHUB_OUTPUT
  52. exit 0
  53. fi
  54. # Check if registry.json changed
  55. if git diff HEAD^ HEAD --name-only | grep -q "registry.json"; then
  56. echo "needs_sync=true" >> $GITHUB_OUTPUT
  57. echo "changes_detected=Registry updated" >> $GITHUB_OUTPUT
  58. exit 0
  59. fi
  60. # Check if component files changed
  61. if git diff HEAD^ HEAD --name-only | grep -qE "^\.opencode/(agent|command|context)/"; then
  62. echo "needs_sync=true" >> $GITHUB_OUTPUT
  63. echo "changes_detected=Component files updated" >> $GITHUB_OUTPUT
  64. exit 0
  65. fi
  66. echo "needs_sync=false" >> $GITHUB_OUTPUT
  67. echo "changes_detected=No relevant changes" >> $GITHUB_OUTPUT
  68. sync-documentation:
  69. name: Sync Documentation with OpenCode
  70. runs-on: ubuntu-latest
  71. needs: check-sync-needed
  72. if: needs.check-sync-needed.outputs.needs_sync == 'true'
  73. outputs:
  74. branch_name: ${{ steps.create_branch.outputs.branch_name }}
  75. issue_number: ${{ steps.create_issue.outputs.result }}
  76. steps:
  77. - name: Checkout repository
  78. uses: actions/checkout@v4
  79. with:
  80. fetch-depth: 0
  81. - name: Create sync branch
  82. id: create_branch
  83. run: |
  84. BRANCH_NAME="docs/auto-sync-$(date +%Y%m%d-%H%M%S)"
  85. echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
  86. git config user.name "github-actions[bot]"
  87. git config user.email "github-actions[bot]@users.noreply.github.com"
  88. git checkout -b "$BRANCH_NAME"
  89. git push -u origin "$BRANCH_NAME"
  90. - name: Create sync issue for OpenCode
  91. id: create_issue
  92. uses: actions/github-script@v7
  93. with:
  94. script: |
  95. const issue = await github.rest.issues.create({
  96. owner: context.repo.owner,
  97. repo: context.repo.repo,
  98. title: '🤖 Auto-sync documentation with registry',
  99. body: `## Documentation Sync Request
  100. **Trigger:** ${{ needs.check-sync-needed.outputs.changes_detected }}
  101. **Branch:** \`${{ steps.create_branch.outputs.branch_name }}\`
  102. **Commit:** ${{ github.sha }}
  103. ### Task
  104. Please review the current \`registry.json\` and update the following documentation files to ensure they accurately reflect the current component counts and descriptions:
  105. 1. **README.md** - Update installation profile component counts:
  106. - Essential profile: Update component count
  107. - Developer profile: Update component count
  108. - Business profile: Update component count
  109. - Full profile: Update component count
  110. - Advanced profile: Update component count
  111. 2. **README.md** - Verify "What's Included" section lists match registry
  112. 3. **docs/README.md** - Ensure component references are accurate
  113. ### Instructions
  114. 1. Read \`registry.json\` to get current component counts
  115. 2. Extract profile component counts from \`.profiles.<profile>.components | length\`
  116. 3. Update README.md sections that reference component counts
  117. 4. Ensure consistency across all documentation
  118. 5. Commit changes with message: "docs: sync component counts with registry [skip-docs]"
  119. **IMPORTANT:** Include \`[skip-docs]\` in commit message to prevent workflow loops!
  120. ### Context Files to Load
  121. - \`registry.json\` - Source of truth for components
  122. - \`README.md\` - Main documentation file
  123. - \`docs/README.md\` - Documentation index
  124. ### Validation
  125. After updates, verify:
  126. - All component counts match registry
  127. - No broken links
  128. - Consistent formatting
  129. - No duplicate information
  130. /opencode
  131. ---
  132. **Note:** This is an automated documentation sync. Review changes carefully before merging.`,
  133. labels: ['documentation', 'automated']
  134. });
  135. return issue.data.number;
  136. - name: Wait for OpenCode to process
  137. run: |
  138. echo "OpenCode will process the issue and make changes to branch: ${{ steps.create_branch.outputs.branch_name }}"
  139. echo "Issue created: #${{ steps.create_issue.outputs.result }}"
  140. echo ""
  141. echo "The workflow will:"
  142. echo "1. OpenCode reads the issue"
  143. echo "2. Analyzes registry.json"
  144. echo "3. Updates documentation files"
  145. echo "4. Commits changes to the branch"
  146. echo "5. Another workflow will create a PR after OpenCode finishes"
  147. echo ""
  148. echo "Check the issue for progress: https://github.com/${{ github.repository }}/issues/${{ steps.create_issue.outputs.result }}"
  149. echo ""
  150. echo "⏳ Note: OpenCode may take several minutes to complete the task."
  151. echo "The PR will be created automatically once OpenCode commits changes."
  152. # This job is intentionally removed - PR creation should be manual or triggered by a separate event
  153. # after OpenCode completes its work, not on a timer
  154. cleanup-on-failure:
  155. name: Cleanup on Failure
  156. runs-on: ubuntu-latest
  157. needs: [check-sync-needed, sync-documentation]
  158. if: failure()
  159. steps:
  160. - name: Checkout repository
  161. uses: actions/checkout@v4
  162. - name: Delete branch if created
  163. run: |
  164. BRANCH_NAME="${{ needs.sync-documentation.outputs.branch_name }}"
  165. if [ -n "$BRANCH_NAME" ]; then
  166. git push origin --delete "$BRANCH_NAME" || true
  167. echo "Cleaned up branch: $BRANCH_NAME"
  168. fi
  169. - name: Comment on issue
  170. if: needs.sync-documentation.outputs.issue_number
  171. uses: actions/github-script@v7
  172. with:
  173. script: |
  174. await github.rest.issues.createComment({
  175. owner: context.repo.owner,
  176. repo: context.repo.repo,
  177. issue_number: ${{ needs.sync-documentation.outputs.issue_number }},
  178. body: '❌ Documentation sync workflow failed. Please check the workflow logs and sync manually if needed.'
  179. });
  180. await github.rest.issues.update({
  181. owner: context.repo.owner,
  182. repo: context.repo.repo,
  183. issue_number: ${{ needs.sync-documentation.outputs.issue_number }},
  184. state: 'closed',
  185. labels: ['documentation', 'automated', 'failed']
  186. });