Update good-first-issues list #707
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: Update good-first-issues list | |
| on: | |
| workflow_dispatch: | |
| # Re-build when labels or state change | |
| issues: | |
| types: [opened, reopened, edited, labeled, unlabeled, closed] | |
| # …and every day as a safety net | |
| schedule: | |
| - cron: '0 3 * * *' # 03:00 UTC daily | |
| jobs: | |
| refresh: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # ---------- Build the embed ---------- | |
| - name: Build embed JSON (top-20) | |
| id: build | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { owner, repo } = context.repo; | |
| // pull first 20 open issues with that label | |
| const { data: issues } = await github.rest.issues.listForRepo({ | |
| owner, repo, | |
| state: 'open', | |
| labels: 'good first issue', | |
| per_page: 20 | |
| }); | |
| // map to bullets: show other labels comma-separated after a hyphen | |
| const lines = issues.map(i => { | |
| const extras = i.labels | |
| .filter(l => l.name !== 'good first issue') | |
| .map(l => `\`${l.name}\``); | |
| const base = `• [#${i.number}](${i.html_url}) ${i.title}`; | |
| return extras.length | |
| ? `${base} - ${extras.join(', ')}` | |
| : base; | |
| }); | |
| const embed = { | |
| embeds: [{ | |
| title: '🆕 Good-first-issues', | |
| url: `https://github.com/${owner}/${repo}/issues?q=is%3Aissue+state%3Aopen+label%3A%22good+first+issue%22`, | |
| description: lines.join('\n'), | |
| color: 504575, | |
| timestamp: new Date().toISOString() | |
| }] | |
| }; | |
| // expose as a base-64 string | |
| core.setOutput( | |
| 'b64', | |
| Buffer.from(JSON.stringify(embed)).toString('base64') | |
| ); | |
| # ---------- Post via bot ---------- | |
| - name: Push embed (replace old message) | |
| env: | |
| BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }} | |
| BOT_ID: ${{ secrets.DISCORD_BOT_ID }} | |
| CHANNEL_ID: ${{ secrets.DISCORD_CHANNEL_ID_GOOD_FIRST_ISSUES }} | |
| PAYLOAD_B64: ${{ steps.build.outputs.b64 }} | |
| run: | | |
| set -euo pipefail | |
| payload=$(printf '%s' "$PAYLOAD_B64" | base64 --decode) | |
| AUTH="Authorization: Bot ${BOT_TOKEN}" | |
| # 1) delete last bot message (if any) | |
| last=$(curl -sf -H "$AUTH" \ | |
| "https://discord.com/api/channels/${CHANNEL_ID}/messages?limit=50" | | |
| jq -r --arg BID "$BOT_ID" ' | |
| map(select(.author.id==$BID))[0].id // empty') | |
| if [ -n "$last" ]; then | |
| curl -s -X DELETE -H "$AUTH" \ | |
| "https://discord.com/api/channels/${CHANNEL_ID}/messages/${last}" >/dev/null | |
| fi | |
| # 2) post fresh embed | |
| curl -s -H "$AUTH" -H "Content-Type: application/json" \ | |
| -d "$payload" \ | |
| "https://discord.com/api/channels/${CHANNEL_ID}/messages" >/dev/null | |