[codex] Improve author-action issue labeling #12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Evaluate Submission | |
| on: | |
| issues: | |
| types: [edited, labeled] | |
| issue_comment: | |
| types: [created] | |
| jobs: | |
| evaluate: | |
| if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'suggestion' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: write | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - run: pip install pyyaml | |
| - name: Extract GitHub repo from issue body | |
| id: extract | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const body = context.payload.issue.body || ''; | |
| function normalizeGitHubRepo(value) { | |
| if (!value) return ''; | |
| const trimmed = value.trim(); | |
| const slugMatch = trimmed.match(/^(?:https?:\/\/github\.com\/)?([a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+?)(?:\.git|\/)?$/); | |
| return slugMatch ? slugMatch[1] : ''; | |
| } | |
| // Try the structured "github" field first (from issue template) | |
| const ghFieldMatch = body.match(/### GitHub Repository\s*\n\s*\n?\s*([\s\S]*?)(?=\n###|$)/); | |
| const ghRepo = normalizeGitHubRepo(ghFieldMatch ? ghFieldMatch[1] : ''); | |
| if (ghRepo) { | |
| core.setOutput('repo', ghRepo); | |
| return; | |
| } | |
| // Fallback: extract from any GitHub URL in the body | |
| const urlMatch = body.match(/github\.com\/([a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+)/); | |
| if (urlMatch) { | |
| core.setOutput('repo', urlMatch[1]); | |
| return; | |
| } | |
| core.setOutput('repo', ''); | |
| - name: Run evaluation | |
| if: steps.extract.outputs.repo != '' | |
| id: eval | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| REPORT=$(python3 scripts/evaluate_entry.py --data-dir data/ "${{ steps.extract.outputs.repo }}" 2>&1) || true | |
| echo "$REPORT" > /tmp/eval-report.md | |
| python3 scripts/evaluate_entry.py --data-dir data/ --json "${{ steps.extract.outputs.repo }}" 2>/dev/null > /tmp/eval-result.json || true | |
| REC=$(python3 -c "import sys,json; print(json.load(open('/tmp/eval-result.json')).get('recommendation','error'))" 2>/dev/null || echo "error") | |
| ARCHIVED=$(python3 -c "import sys,json; print(str(json.load(open('/tmp/eval-result.json')).get('archived',False)).lower())" 2>/dev/null || echo "false") | |
| echo "recommendation=$REC" >> "$GITHUB_OUTPUT" | |
| echo "archived=$ARCHIVED" >> "$GITHUB_OUTPUT" | |
| - name: Post evaluation comment | |
| if: steps.extract.outputs.repo != '' | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const report = fs.readFileSync('/tmp/eval-report.md', 'utf8'); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: report | |
| }); | |
| - name: Apply label and handle outcome | |
| if: steps.extract.outputs.repo != '' | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const rec = '${{ steps.eval.outputs.recommendation }}'; | |
| const archived = '${{ steps.eval.outputs.archived }}' === 'true'; | |
| const issue = context.issue.number; | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| // Archived rejects close immediately; 0-score rejects stay in incubator queue | |
| let label; | |
| if (rec === 'reject' && archived) { | |
| label = 'rejected'; | |
| } else { | |
| const labelMap = { | |
| 'accept': 'accepted', | |
| 'likely_accept': 'accepted', | |
| 'incubator': 'incubator', | |
| 'reject': 'incubator', | |
| 'duplicate': 'duplicate', | |
| 'error': 'needs-review', | |
| }; | |
| label = labelMap[rec] || 'needs-review'; | |
| } | |
| await github.rest.issues.addLabels({ owner, repo, issue_number: issue, labels: [label] }); | |
| if (label === 'accepted') { | |
| await github.rest.actions.createWorkflowDispatch({ | |
| owner, | |
| repo, | |
| workflow_id: 'add-accepted-entry.yml', | |
| ref: context.payload.repository.default_branch, | |
| inputs: { | |
| issue_number: String(issue), | |
| }, | |
| }); | |
| } | |
| // Auto-close duplicates and archived rejects | |
| if (rec === 'duplicate' || (rec === 'reject' && archived)) { | |
| await github.rest.issues.update({ | |
| owner, repo, issue_number: issue, | |
| state: 'closed', | |
| state_reason: 'not_planned', | |
| }); | |
| } | |
| - name: Post fallback comment (no repo found) | |
| if: steps.extract.outputs.repo == '' | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: [ | |
| '👋 Thanks for the suggestion!', | |
| '', | |
| 'I couldn\'t find a GitHub repository in this issue. Could you add the **GitHub Repository** field ', | |
| '(e.g., `owner/repo`) so I can run an automated evaluation?', | |
| '', | |
| 'If the project isn\'t on GitHub, please reply confirming that this should be reviewed as a non-GitHub resource and include any public repository or documentation link maintainers should use.', | |
| '', | |
| 'This issue is labeled `question` while waiting for author input. If there is no update for about two weeks, automation will mark it stale; after another two weeks without activity, it may close automatically.', | |
| ].join('\n') | |
| }); | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| labels: ['needs-review', 'question'] | |
| }); | |
| clear-author-question: | |
| if: | | |
| (github.event_name == 'issues' && github.event.action == 'edited') || | |
| (github.event_name == 'issue_comment' && !github.event.issue.pull_request) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| issues: write | |
| steps: | |
| - name: Clear author-action labels after author update | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const issue = context.payload.issue; | |
| const labels = (issue.labels || []).map(label => typeof label === 'string' ? label : label.name); | |
| if (!labels.includes('suggestion') || !labels.includes('question')) { | |
| return; | |
| } | |
| const author = issue.user.login; | |
| const sender = context.payload.sender.login; | |
| if (sender !== author) { | |
| return; | |
| } | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = issue.number; | |
| async function removeLabel(label) { | |
| try { | |
| await github.rest.issues.removeLabel({ owner, repo, issue_number, name: label }); | |
| } catch (error) { | |
| if (error.status !== 404) { | |
| throw error; | |
| } | |
| } | |
| } | |
| await removeLabel('question'); | |
| await removeLabel('stale'); |