diff --git a/.github/workflows/similar-issues.yml b/.github/workflows/similar-issues.yml index c3f1da19f..ab96a6ca2 100644 --- a/.github/workflows/similar-issues.yml +++ b/.github/workflows/similar-issues.yml @@ -1,91 +1,73 @@ -name: Similar Issues via AI MCP +name: duplicate-issues on: - issues: - types: [opened] + issues: + types: [opened] + workflow_dispatch: + inputs: + issue_number: + description: Issue number to check manually + required: true + type: number jobs: - find-similar: - permissions: - contents: read - issues: write - models: read - runs-on: ubuntu-slim - steps: - - name: Check out repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + check-duplicates: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 - - name: Prepare prompt variables - id: prepare_input - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const issue = context.payload.issue || {}; - const title = issue.title || ''; - const body = issue.body || ''; - const indent = ' '; - // Indent subsequent lines so YAML block scalar indentation remains valid - const bodyIndented = body.replace(/\n/g, '\n' + indent); - core.setOutput('issue_title_json', JSON.stringify(title)); - core.setOutput('issue_body_indented_json', JSON.stringify(bodyIndented)); - core.setOutput('issue_number', issue.number); + - name: Set up Bun + uses: oven-sh/setup-bun@v2 - - name: Find similar issues with AI (MCP) - id: inference - uses: actions/ai-inference@a380166897b5408b8fb7dddd148142794cb5624a # v2.0.6 - with: - prompt-file: ./.github/prompts/similar_issues.prompt.yml - input: | - issue_title: ${{ steps.prepare_input.outputs.issue_title_json }} - issue_body: ${{ steps.prepare_input.outputs.issue_body_indented_json }} - issue_number: ${{ steps.prepare_input.outputs.issue_number }} - repository: ${{ github.repository }} - enable-github-mcp: true - # Inference token can use GITHUB_TOKEN. MCP specifically requires a PAT. - token: ${{ secrets.GITHUB_TOKEN }} - github-mcp-token: ${{ secrets.USER_PAT }} - max-tokens: 8000 + - name: Install opencode + run: curl -fsSL https://opencode.ai/install | bash - - name: Prepare comment body - id: prepare - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - AI_RESPONSE: ${{ steps.inference.outputs.response }} - with: - script: | - let data; - try { - data = JSON.parse(process.env.AI_RESPONSE || '{}'); - } catch (e) { - core.setOutput('has_matches', 'false'); - return; - } - const matches = Array.isArray(data.matches) ? data.matches.filter(m => m.number !== context.payload.issue.number) : []; - if (!matches.length) { - core.setOutput('has_matches', 'false'); - return; - } - const lines = []; - lines.push('I found similar issues that might help:'); - for (const m of matches.slice(0, 3)) { - const num = m.number != null ? `#${m.number}` : ''; - const title = m.title || 'Untitled'; - const url = m.url || ''; - const score = typeof m.similarity_score === 'number' ? ` (similarity: ${m.similarity_score.toFixed(2)})` : ''; - lines.push(`- ${url}${score}`.trim()); - } - core.setOutput('has_matches', 'true'); - core.setOutput('comment_body', lines.join('\n')); + - name: Check for duplicate issues + env: + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_NUMBER: ${{ github.event.issue.number || inputs.issue_number }} + OPENCODE_PERMISSION: | + { + "bash": { + "*": "deny", + "gh issue*": "allow" + }, + "webfetch": "deny" + } + run: | + if [ -z "$ISSUE_NUMBER" ]; then + echo "issue_number is required" + exit 1 + fi - - name: Comment similar issues - if: steps.prepare.outputs.has_matches == 'true' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const body = ${{ toJson(steps.prepare.outputs.comment_body) }}; - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.issue.number, - body - }); + opencode run -m ${{ vars.OPENCODE_MODEL }} "A new issue has been created:' + + Issue number: + $ISSUE_NUMBER + + Lookup this issue and search through existing issues (excluding #$ISSUE_NUMBER) in this repository to find any potential duplicates of this new issue. + Consider: + 1. Similar titles or descriptions + 2. Same error messages or symptoms + 3. Related functionality or components + 4. Similar feature requests + + If you find any potential duplicates, please comment on the new issue with: + - A brief explanation of why it might be a duplicate + - Links to the potentially duplicate issues + - A suggestion to check those issues first + + Use this format for the comment: + 'This issue might be a duplicate of existing issues. Please check: + - #[issue_number]: [brief description of similarity] + + Feel free to ignore if none of these address your specific case.' + + If no clear duplicates are found, do not comment."