duplicate-issues.yml 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. name: duplicate-issues
  2. on:
  3. issues:
  4. types: [opened, edited]
  5. jobs:
  6. check-duplicates:
  7. if: github.event.action == 'opened'
  8. runs-on: blacksmith-4vcpu-ubuntu-2404
  9. permissions:
  10. contents: read
  11. issues: write
  12. steps:
  13. - name: Checkout repository
  14. uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
  15. with:
  16. fetch-depth: 1
  17. - name: Check exempt issue author
  18. id: author
  19. run: |
  20. LOGIN="${{ github.event.issue.user.login }}"
  21. ASSOCIATION="${{ github.event.issue.author_association }}"
  22. if [ "$LOGIN" = "opencode-agent[bot]" ] ||
  23. [ "$ASSOCIATION" = "OWNER" ] ||
  24. [ "$ASSOCIATION" = "MEMBER" ] ||
  25. grep -qxiF "$LOGIN" .github/TEAM_MEMBERS; then
  26. echo "skip=true" >> "$GITHUB_OUTPUT"
  27. echo "Skipping issue automation for exempt author: $LOGIN ($ASSOCIATION)"
  28. else
  29. echo "skip=false" >> "$GITHUB_OUTPUT"
  30. fi
  31. - uses: ./.github/actions/setup-bun
  32. if: steps.author.outputs.skip != 'true'
  33. - name: Install opencode
  34. if: steps.author.outputs.skip != 'true'
  35. run: curl -fsSL https://opencode.ai/install | bash
  36. - name: Check duplicates and compliance
  37. if: steps.author.outputs.skip != 'true'
  38. env:
  39. OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
  40. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  41. OPENCODE_PERMISSION: |
  42. {
  43. "bash": {
  44. "*": "deny",
  45. "gh issue*": "allow"
  46. },
  47. "webfetch": "deny"
  48. }
  49. run: |
  50. opencode run -m opencode/claude-sonnet-4-6 "A new issue has been created:
  51. Issue number: ${{ github.event.issue.number }}
  52. Issue author association: ${{ github.event.issue.author_association }}
  53. Lookup this issue with gh issue view ${{ github.event.issue.number }}.
  54. You have TWO tasks. Perform both, then post a SINGLE comment (if needed).
  55. ---
  56. TASK 1: CONTRIBUTING GUIDELINES COMPLIANCE CHECK
  57. Check whether the issue follows our contributing guidelines and issue templates.
  58. If the issue author association is OWNER or MEMBER, skip this compliance check. Do not add the needs:compliance label for organization-owned issues.
  59. This project has three issue templates that every issue MUST use one of:
  60. 1. Bug Report - requires a Description field with real content
  61. 2. Feature Request - requires a verification checkbox and description, title should start with [FEATURE]:
  62. 3. Question - requires the Question field with real content
  63. Additionally check:
  64. - No AI-generated walls of text (long, AI-generated descriptions are not acceptable)
  65. - The issue has real content, not just template placeholder text left unchanged
  66. - Bug reports should include some context about how to reproduce
  67. - Feature requests should explain the problem or need
  68. - We want to push for having the user provide system description & information
  69. Do NOT be nitpicky about optional fields. Only flag real problems like: no template used, required fields empty or placeholder text only, obviously AI-generated walls of text, or completely empty/nonsensical content.
  70. ---
  71. TASK 2: DUPLICATE CHECK
  72. Search through existing issues (excluding #${{ github.event.issue.number }}) to find potential duplicates.
  73. Consider:
  74. 1. Similar titles or descriptions
  75. 2. Same error messages or symptoms
  76. 3. Related functionality or components
  77. 4. Similar feature requests
  78. Additionally, if the issue mentions keybinds, keyboard shortcuts, or key bindings, note the pinned keybinds issue #4997.
  79. ---
  80. POSTING YOUR COMMENT:
  81. Based on your findings, post a SINGLE comment on issue #${{ github.event.issue.number }}. Build the comment as follows:
  82. If the issue is NOT compliant and the author association is not OWNER or MEMBER, start the comment with:
  83. <!-- issue-compliance -->
  84. Then explain what needs to be fixed and that they have 2 hours to edit the issue before it is automatically closed. Also add the label needs:compliance to the issue using: gh issue edit ${{ github.event.issue.number }} --add-label needs:compliance
  85. If duplicates were found, include a section about potential duplicates with links.
  86. If the issue mentions keybinds/keyboard shortcuts, include a note about #4997.
  87. If the issue IS compliant AND no duplicates were found AND no keybind reference, do NOT comment at all.
  88. Use this format for the comment:
  89. [If not compliant:]
  90. <!-- issue-compliance -->
  91. This issue doesn't fully meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md).
  92. **What needs to be fixed:**
  93. - [specific reasons]
  94. Please edit this issue to address the above within **2 hours**, or it will be automatically closed.
  95. [If duplicates found, add:]
  96. ---
  97. This issue might be a duplicate of existing issues. Please check:
  98. - #[issue_number]: [brief description of similarity]
  99. [If keybind-related, add:]
  100. For keybind-related issues, please also check our pinned keybinds documentation: #4997
  101. [End with if not compliant:]
  102. If you believe this was flagged incorrectly, please let a maintainer know.
  103. Remember: post at most ONE comment combining all findings. If everything is fine, post nothing."
  104. recheck-compliance:
  105. if: github.event.action == 'edited' && contains(github.event.issue.labels.*.name, 'needs:compliance')
  106. runs-on: blacksmith-4vcpu-ubuntu-2404
  107. permissions:
  108. contents: read
  109. issues: write
  110. steps:
  111. - name: Checkout repository
  112. uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
  113. with:
  114. fetch-depth: 1
  115. - name: Check exempt issue author
  116. id: author
  117. run: |
  118. LOGIN="${{ github.event.issue.user.login }}"
  119. ASSOCIATION="${{ github.event.issue.author_association }}"
  120. if [ "$LOGIN" = "opencode-agent[bot]" ] ||
  121. [ "$ASSOCIATION" = "OWNER" ] ||
  122. [ "$ASSOCIATION" = "MEMBER" ] ||
  123. grep -qxiF "$LOGIN" .github/TEAM_MEMBERS; then
  124. echo "skip=true" >> "$GITHUB_OUTPUT"
  125. echo "Skipping issue automation for exempt author: $LOGIN ($ASSOCIATION)"
  126. else
  127. echo "skip=false" >> "$GITHUB_OUTPUT"
  128. fi
  129. - uses: ./.github/actions/setup-bun
  130. if: steps.author.outputs.skip != 'true'
  131. - name: Install opencode
  132. if: steps.author.outputs.skip != 'true'
  133. run: curl -fsSL https://opencode.ai/install | bash
  134. - name: Recheck compliance
  135. if: steps.author.outputs.skip != 'true'
  136. env:
  137. OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
  138. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  139. OPENCODE_PERMISSION: |
  140. {
  141. "bash": {
  142. "*": "deny",
  143. "gh issue*": "allow"
  144. },
  145. "webfetch": "deny"
  146. }
  147. run: |
  148. opencode run -m opencode/claude-sonnet-4-6 "Issue #${{ github.event.issue.number }} was previously flagged as non-compliant and has been edited.
  149. Issue author association: ${{ github.event.issue.author_association }}
  150. Lookup this issue with gh issue view ${{ github.event.issue.number }}.
  151. If the issue author association is OWNER or MEMBER, remove the needs:compliance label if present, delete the previous compliance comment if present, and do not post a new comment.
  152. Re-check whether the issue now follows our contributing guidelines and issue templates.
  153. This project has three issue templates that every issue MUST use one of:
  154. 1. Bug Report - requires a Description field with real content
  155. 2. Feature Request - requires a verification checkbox and description, title should start with [FEATURE]:
  156. 3. Question - requires the Question field with real content
  157. Additionally check:
  158. - No AI-generated walls of text (long, AI-generated descriptions are not acceptable)
  159. - The issue has real content, not just template placeholder text left unchanged
  160. - Bug reports should include some context about how to reproduce
  161. - Feature requests should explain the problem or need
  162. - We want to push for having the user provide system description & information
  163. Do NOT be nitpicky about optional fields. Only flag real problems like: no template used, required fields empty or placeholder text only, obviously AI-generated walls of text, or completely empty/nonsensical content.
  164. If the issue is NOW compliant:
  165. 1. Remove the needs:compliance label: gh issue edit ${{ github.event.issue.number }} --remove-label needs:compliance
  166. 2. Find and delete the previous compliance comment (the one containing <!-- issue-compliance -->) using: gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments --jq '.[] | select(.body | contains(\"<!-- issue-compliance -->\")) | .id' then delete it with: gh api -X DELETE repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments/{id}
  167. 3. Post a short comment thanking them for updating the issue.
  168. If the issue is STILL not compliant:
  169. Post a comment explaining what still needs to be fixed. Keep the needs:compliance label."