From 4fc6493d7a0be58af7410f75014e5edfde116748 Mon Sep 17 00:00:00 2001 From: Avocado Date: Tue, 11 Aug 2026 13:36:14 +0900 Subject: [PATCH] Comment Bluesky post links on merged PRs After process.js runs, resolve bsky.app URLs and have process.yml comment them on the PR with gh. Fixes #9 Signed-off-by: Avocado Co-authored-by: Cursor --- .github/workflows/process.yml | 23 +++++++++++++++++++++++ actions/process.js | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/.github/workflows/process.yml b/.github/workflows/process.yml index 48432c4..afd5854 100644 --- a/.github/workflows/process.yml +++ b/.github/workflows/process.yml @@ -8,6 +8,7 @@ on: permissions: contents: write + pull-requests: write concurrency: group: process-json-${{ github.ref }} @@ -54,12 +55,34 @@ jobs: env: BLUESKY_IDENTIFIER_NODEJS_ORG: nodejs.org BLUESKY_APP_PASSWORD_NODEJS_ORG: ${{ secrets.BLUESKY_APP_PASSWORD_NODEJS_ORG }} + POST_URLS_FILE: ${{ runner.temp }}/bluesky-post-urls.txt run: | + : > "$POST_URLS_FILE" for file in ${{ steps.find-json.outputs.NEW_JSON_FILES }}; do echo "Processing $file..." node actions/process.js "$file" done + # Comment browsable bsky.app links on the merged PR (nodejs/bluesky#9). + - name: Comment post links on the PR + if: steps.find-json.outputs.NEW_JSON_FILES + env: + GH_TOKEN: ${{ github.token }} + POST_URLS_FILE: ${{ runner.temp }}/bluesky-post-urls.txt + run: | + if [ ! -s "$POST_URLS_FILE" ]; then + echo "No post URLs to comment" + exit 0 + fi + { + echo "Posted to Bluesky:" + echo + while IFS= read -r url; do + [ -n "$url" ] && echo "- $url" + done < "$POST_URLS_FILE" + } > "${{ runner.temp }}/pr-comment.md" + gh pr comment "${{ github.event.pull_request.number }}" --body-file "${{ runner.temp }}/pr-comment.md" + - name: Commit and push changes if: steps.find-json.outputs.NEW_JSON_FILES run: | diff --git a/actions/process.js b/actions/process.js index cafef2c..2e0a321 100755 --- a/actions/process.js +++ b/actions/process.js @@ -4,7 +4,7 @@ import fs from 'node:fs'; import assert from 'node:assert'; import process from 'node:process'; import path from 'node:path'; -import { post, maybeUpdateReplyInThread } from './lib/posts.js'; +import { post, maybeUpdateReplyInThread, getPostURLFromURI } from './lib/posts.js'; // This script takes a path to a JSON with the pattern $base_path/new/$any_name.json, // where $any_name can be anything, and then performs the action specified in it. @@ -13,6 +13,34 @@ import { post, maybeUpdateReplyInThread } from './lib/posts.js'; // starting from 0 based on the number of existing JSONs processed on the same date // and already in the processed directory. +/** + * Resolve a browsable bsky.app URL for the performed action. + * Reposts create `app.bsky.feed.repost` records (not /post/ URLs), so link the + * original post instead. + * @param {import('@atproto/api').AtpAgent} agent + * @param {{ action: string, repostURL?: string }} request + * @param {{ uri: string }} result + */ +async function getPublicPostURL(agent, request, result) { + if (request.action === 'repost') { + return request.repostURL; + } + return getPostURLFromURI(agent, result.uri); +} + +/** + * When POST_URLS_FILE is set (GitHub Actions), append URLs so the workflow can + * comment them on the merged PR. + * @param {string} postURL + */ +function appendPostURLForPRComment(postURL) { + const urlsFile = process.env.POST_URLS_FILE; + if (!urlsFile) { + return; + } + fs.appendFileSync(urlsFile, `${postURL}\n`); +} + assert(process.argv[2], `Usage: node process.js $base_path/new/$any_name.json`); const { agent, requests, requestFilePath, richTextFile } = await import('./login-and-validate.js'); @@ -47,6 +75,10 @@ for (const request of requests) { assert.fail('Unknown action ' + request.action); } console.log('Result', result); + const postURL = await getPublicPostURL(agent, request, result); + console.log('Post URL', postURL); + result.postURL = postURL; + appendPostURLForPRComment(postURL); // Extend the result to be written to the processed JSON file. request.result = result; previousPostInfo = {