From 6f414365914c0d004b107b5a55376d5801583107 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Mon, 5 Oct 2026 09:43:11 -0400 Subject: [PATCH] nook: add an appcast upload helper The release pipeline had no in-repo path to put a corrected appcast back on S3 (the backfill of 0.6.0/0.6.2 notes needed one). Reads the same bucket env the appcast route does; refuses to upload unless every expected release item is present. Tests: used for the production backfill; endpoint re-verified after. --- scripts/upload-appcast.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 scripts/upload-appcast.ts diff --git a/scripts/upload-appcast.ts b/scripts/upload-appcast.ts new file mode 100644 index 0000000..03f0ac9 --- /dev/null +++ b/scripts/upload-appcast.ts @@ -0,0 +1,38 @@ +// One-off: upload the backfilled appcast to the download bucket. +// Usage: cd ~/Code/freno-dev && bun --env-file=.env /tmp/upload-appcast.ts +import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; +import { readFileSync } from "node:fs"; + +const [, , file] = process.argv; +if (!file) { + console.error("usage: bun --env-file=.env upload-appcast.ts "); + process.exit(1); +} + +const body = readFileSync(file); +const xml = body.toString("utf8"); +// Guard: refuse to upload without all three release descriptions present. +for (const v of ["0.6.0", "0.6.2", "0.6.3"]) { + if (!xml.includes(`sparkle:shortVersionString>${v}<`)) { + console.error(`refusing: item for ${v} missing`); + process.exit(1); + } +} + +const client = new S3Client({ + region: process.env.AWS_REGION, + credentials: { + accessKeyId: process.env.MY_AWS_ACCESS_KEY!, + secretAccessKey: process.env.MY_AWS_SECRET_KEY! + } +}); + +await client.send( + new PutObjectCommand({ + Bucket: process.env.VITE_DOWNLOAD_BUCKET_STRING, + Key: "api/TheNook/appcast.xml", + Body: body, + ContentType: "application/xml; charset=utf-8" + }) +); +console.log("uploaded", file, "->", "api/TheNook/appcast.xml");