chore: import upstream snapshot with attribution
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
// Attach sandboxed-plugin tarballs to the GitHub releases that
|
||||
// `changesets/action` creates during a release run.
|
||||
//
|
||||
// The decentralized plugin registry (RFC 0001) stores only a *link* to the
|
||||
// plugin bytes, not the bytes themselves. By bundling each published
|
||||
// sandboxed plugin and uploading the tarball as a release asset, every
|
||||
// version automatically gets a stable public URL that an `emdash-plugin
|
||||
// publish --url ...` step (or a human) can point a registry record at.
|
||||
//
|
||||
// Input: the `publishedPackages` output from changesets/action, passed via
|
||||
// the PUBLISHED_PACKAGES env var as a JSON array of `{ name, version }`.
|
||||
// Only packages under `packages/plugins/*` that expose a `./sandbox` export
|
||||
// and are not private are processed; everything else (native plugins, test
|
||||
// fixtures) is skipped.
|
||||
//
|
||||
// Set DRY_RUN=1 to bundle and resolve tarballs without calling `gh`.
|
||||
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
const PLUGINS_DIR = "packages/plugins";
|
||||
const BUNDLER = "packages/plugin-cli/dist/index.mjs";
|
||||
|
||||
const SLASH_RE = /\//g;
|
||||
const LEADING_AT_RE = /^@/;
|
||||
|
||||
const repo = process.env.GITHUB_REPOSITORY;
|
||||
const dryRun = process.env.DRY_RUN === "1";
|
||||
|
||||
if (!dryRun && !repo) {
|
||||
console.error("GITHUB_REPOSITORY is not set; cannot target `gh release upload`.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// `?? "[]"` only catches undefined/null. An unset Actions output arrives as
|
||||
// an empty string, which would make JSON.parse throw, so coalesce that too.
|
||||
const raw = process.env.PUBLISHED_PACKAGES?.trim() || "[]";
|
||||
let published;
|
||||
try {
|
||||
published = JSON.parse(raw);
|
||||
} catch (error) {
|
||||
console.error(`Could not parse PUBLISHED_PACKAGES as JSON: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!Array.isArray(published) || published.length === 0) {
|
||||
console.log("No published packages to process.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// name -> version for the packages that were just published.
|
||||
const publishedVersions = new Map(published.map((p) => [p.name, p.version]));
|
||||
|
||||
/** Slugify a manifest id the same way the bundler names its tarball. */
|
||||
const slugify = (id) => id.replace(SLASH_RE, "-").replace(LEADING_AT_RE, "");
|
||||
|
||||
const failures = [];
|
||||
let attached = 0;
|
||||
|
||||
for (const entry of readdirSync(PLUGINS_DIR, { withFileTypes: true })) {
|
||||
if (!entry.isDirectory()) continue;
|
||||
|
||||
const dir = join(PLUGINS_DIR, entry.name);
|
||||
const pkgPath = join(dir, "package.json");
|
||||
if (!existsSync(pkgPath)) continue;
|
||||
|
||||
// We read every plugin dir, so a single malformed package.json must not
|
||||
// abort the whole step. Treat an unreadable manifest as a skip.
|
||||
let pkg;
|
||||
try {
|
||||
pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
||||
} catch {
|
||||
console.warn(`Skipping ${entry.name}: could not read/parse package.json`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only published, public, sandboxed plugins.
|
||||
if (!publishedVersions.has(pkg.name)) continue;
|
||||
if (pkg.private === true) continue;
|
||||
if (!pkg.exports?.["./sandbox"]) {
|
||||
console.log(`Skipping ${pkg.name}: no ./sandbox export (not a sandboxed plugin).`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const version = publishedVersions.get(pkg.name);
|
||||
const tag = `${pkg.name}@${version}`;
|
||||
console.log(`\n=== ${pkg.name}@${version} ===`);
|
||||
|
||||
try {
|
||||
// Bundle. This rebuilds from source and writes dist/<slug>-<version>.tar.gz
|
||||
// plus dist/manifest.json, so we can read the exact id/version back out
|
||||
// rather than guessing the filename (stale tarballs may linger in dist/).
|
||||
execFileSync("node", [BUNDLER, "bundle", "--dir", dir], { stdio: "inherit" });
|
||||
|
||||
const manifest = JSON.parse(readFileSync(join(dir, "dist", "manifest.json"), "utf-8"));
|
||||
const tarball = join(dir, "dist", `${slugify(manifest.id)}-${manifest.version}.tar.gz`);
|
||||
if (!existsSync(tarball)) {
|
||||
throw new Error(`Expected tarball not found: ${tarball}`);
|
||||
}
|
||||
|
||||
if (dryRun) {
|
||||
console.log(`[dry-run] would upload ${tarball} to release ${tag}`);
|
||||
} else {
|
||||
// --clobber so re-runs replace the asset instead of failing.
|
||||
execFileSync("gh", ["release", "upload", tag, tarball, "--clobber", "--repo", repo], {
|
||||
stdio: "inherit",
|
||||
});
|
||||
console.log(`Attached ${tarball} to ${tag}`);
|
||||
}
|
||||
attached++;
|
||||
} catch (error) {
|
||||
console.error(`Failed to attach tarball for ${pkg.name}: ${error.message}`);
|
||||
failures.push(pkg.name);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\nAttached ${attached} plugin tarball(s).`);
|
||||
if (failures.length > 0) {
|
||||
console.error(`Failed: ${failures.join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user