mirror of
https://github.com/Heretek-Games/drop-emulation.git
synced 2026-10-12 02:05:15 +00:00
chore: configurable SDK scope (@droposs cutover) and .dropplugin release workflow
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
name: Release Drop Plugin
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build, validate, and publish .dropplugin
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # actions/[email protected]
|
||||
|
||||
- name: Set up Node.js 22
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # actions/[email protected]
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Test
|
||||
run: npm test
|
||||
|
||||
- name: Validate manifest
|
||||
run: npx --no-install drop-plugin validate .
|
||||
|
||||
- name: Pack plugin archive
|
||||
run: npx --no-install drop-plugin pack . ./dist-package
|
||||
|
||||
- name: Generate checksums
|
||||
id: pkg
|
||||
run: |
|
||||
FILE=$(find dist-package -name "*.dropplugin" -print -quit)
|
||||
echo "path=$FILE" >> "$GITHUB_OUTPUT"
|
||||
echo "name=$(basename "$FILE")" >> "$GITHUB_OUTPUT"
|
||||
sha256sum "$FILE" > "$FILE.sha256"
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
${{ steps.pkg.outputs.path }}
|
||||
${{ steps.pkg.outputs.path }}.sha256
|
||||
name: ${{ steps.pkg.outputs.name }}
|
||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
||||
generate_release_notes: true
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"sdk": "@droposs",
|
||||
"sdkVersion": "^0.5.9",
|
||||
"cliVersion": "^0.5.9"
|
||||
}
|
||||
Generated
+9
-9
@@ -9,10 +9,10 @@
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@droposs/plugin-sdk": "^0.4.0"
|
||||
"@droposs/plugin-sdk": "^0.5.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@droposs/plugin-cli": "^0.4.0",
|
||||
"@droposs/plugin-cli": "^0.5.9",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/node": "^22.0.0",
|
||||
"eslint": "^10.9.1",
|
||||
@@ -45,13 +45,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@droposs/plugin-cli": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@droposs/plugin-cli/-/plugin-cli-0.4.0.tgz",
|
||||
"integrity": "sha512-3gF/Z3Klf3CLBCtLpPdrzX46G/R+tkMQ9EYtUODD8aRm99jh/dkfalIxVCPQXsTGOph/06UbmJQa2gw9mZ/lag==",
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@droposs/plugin-cli/-/plugin-cli-0.5.9.tgz",
|
||||
"integrity": "sha512-EMUaeAkJhw+8Qz5mpQx0jf3hBBtGOlqMPziCnTQm1ZyvgC7DYt1VpqgzHz8O/wCK8UHQHJAFi7kKv2Tk+CSCEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@droposs/plugin-sdk": "0.4.0",
|
||||
"@droposs/plugin-sdk": "0.5.9",
|
||||
"ajv": "^8.20.0",
|
||||
"esbuild": "^0.28.2"
|
||||
},
|
||||
@@ -60,9 +60,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@droposs/plugin-sdk": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@droposs/plugin-sdk/-/plugin-sdk-0.4.0.tgz",
|
||||
"integrity": "sha512-BN9qhONnZPURAzvK0qCnO++5Ie5VenIY6G0kJvP141WfJI/72+a/2ojuKQsGKchSIYo9qnVIHrdmkMB3+GnzhQ==",
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@droposs/plugin-sdk/-/plugin-sdk-0.5.9.tgz",
|
||||
"integrity": "sha512-HK3sF964yHtssE0B3vbV+9p4D0L8mg6BJ3cFO7uadYCKkpWw582DVTM0FAJ+CPPSn3xYwZVDxomXTjc/Zmuomg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@droposs/plugin-sdk": "file:../drop-plugin-sdk/packages/plugin-sdk"
|
||||
"@droposs/plugin-sdk": "^0.5.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@droposs/plugin-cli": "file:../drop-plugin-sdk/packages/plugin-cli",
|
||||
"@droposs/plugin-cli": "^0.5.9",
|
||||
"typescript": "^7.0.2",
|
||||
"@types/node": "^22.0.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { readdirSync, readFileSync, statSync, writeFileSync, existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { execSync } from "node:child_process";
|
||||
|
||||
const LEGACY_SCOPE = "@droposs";
|
||||
const NEW_SCOPE = "@drop-oss";
|
||||
const SKIP_DIRS = new Set(["node_modules", ".git", "dist-package", "dist-packages"]);
|
||||
const LOCKFILES = new Set(["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "deno.lock"]);
|
||||
const TEXT_EXT = new Set([".ts", ".tsx", ".js", ".mjs", ".cjs", ".json", ".md", ".yml", ".yaml"]);
|
||||
|
||||
const configPath = path.resolve(process.cwd(), ".sdk-scope.json");
|
||||
if (!existsSync(configPath)) {
|
||||
console.error("Missing .sdk-scope.json in repo root");
|
||||
process.exit(1);
|
||||
}
|
||||
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
||||
const scope = config.sdk;
|
||||
if (scope !== NEW_SCOPE && scope !== LEGACY_SCOPE) {
|
||||
console.error(`Unknown scope '${scope}'; .sdk-scope.json sdk must be '${NEW_SCOPE}' or '${LEGACY_SCOPE}'`);
|
||||
process.exit(1);
|
||||
}
|
||||
const sdkVersion = config["sdkVersion"];
|
||||
const cliVersion = config["cliVersion"];
|
||||
if (typeof sdkVersion !== "string" || typeof cliVersion !== "string") {
|
||||
console.error(".sdk-scope.json must define sdkVersion and cliVersion");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const OTHER_SCOPES = scope === NEW_SCOPE ? [LEGACY_SCOPE] : [NEW_SCOPE];
|
||||
|
||||
function walk(dir, files = []) {
|
||||
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (SKIP_DIRS.has(entry.name)) continue;
|
||||
if (statSync(full).isDirectory()) walk(full, files);
|
||||
else files.push(full);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function normalizeSpecifiers(text) {
|
||||
let out = text;
|
||||
for (const other of OTHER_SCOPES) {
|
||||
out = out
|
||||
.replaceAll(`${other}/plugin-sdk`, `${scope}/plugin-sdk`)
|
||||
.replaceAll(`${other}/plugin-cli`, `${scope}/plugin-cli`);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function rewritePackageJson(file, text) {
|
||||
const indent = detectIndent(text);
|
||||
let pkg;
|
||||
try {
|
||||
pkg = JSON.parse(text);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
for (const sectionName of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
||||
const section = pkg[sectionName];
|
||||
if (!section) continue;
|
||||
const rebuilt = {};
|
||||
for (const dep of Object.keys(section)) {
|
||||
const kind = parseSdkDep(dep);
|
||||
if (!kind) {
|
||||
rebuilt[dep] = section[dep];
|
||||
continue;
|
||||
}
|
||||
const target = `${scope}/${kind}`;
|
||||
if (section[dep].startsWith("file:") || section[dep].startsWith("workspace:") || section[dep].startsWith("npm:")) {
|
||||
rebuilt[target] = kind === "plugin-sdk" ? sdkVersion : cliVersion;
|
||||
} else {
|
||||
rebuilt[target] = section[dep];
|
||||
}
|
||||
}
|
||||
pkg[sectionName] = rebuilt;
|
||||
}
|
||||
return JSON.stringify(pkg, null, indent) + (text.endsWith("\n") ? "\n" : "");
|
||||
}
|
||||
|
||||
function parseSdkDep(dep) {
|
||||
for (const scopeName of [LEGACY_SCOPE, NEW_SCOPE, "@drop"]) {
|
||||
if (dep === `${scopeName}/plugin-sdk`) return "plugin-sdk";
|
||||
if (dep === `${scopeName}/plugin-cli`) return "plugin-cli";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function detectIndent(text) {
|
||||
const match = text.match(/\n([ \t]+)"/);
|
||||
return match ? match[1] : "\t";
|
||||
}
|
||||
|
||||
const edited = [];
|
||||
|
||||
const files = walk(process.cwd());
|
||||
for (const file of files) {
|
||||
if (LOCKFILES.has(path.basename(file))) continue;
|
||||
if (!TEXT_EXT.has(path.extname(file))) continue;
|
||||
const before = readFileSync(file, "utf-8");
|
||||
let after = normalizeSpecifiers(before);
|
||||
if (path.basename(file) === "package.json") {
|
||||
after = rewritePackageJson(file, after);
|
||||
}
|
||||
if (after !== before) {
|
||||
writeFileSync(file, after);
|
||||
edited.push(path.relative(process.cwd(), file));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Scope set to '${scope}' (sdk ${sdkVersion}, cli ${cliVersion})`);
|
||||
if (edited.length) {
|
||||
for (const f of edited) console.log(` rewrote ${f}`);
|
||||
} else {
|
||||
console.log(" no specifier changes needed");
|
||||
}
|
||||
|
||||
const installDir = process.cwd();
|
||||
|
||||
if (existsSync(path.join(installDir, "package-lock.json"))) {
|
||||
try {
|
||||
execSync("npm install --no-audit --no-fund", { cwd: installDir, stdio: "inherit" });
|
||||
} catch {
|
||||
execSync("npm install --no-audit --no-fund --legacy-peer-deps", { cwd: installDir, stdio: "inherit" });
|
||||
}
|
||||
} else if (existsSync(path.join(installDir, "pnpm-lock.yaml"))) {
|
||||
execSync("pnpm install", { cwd: installDir, stdio: "inherit" });
|
||||
} else {
|
||||
console.warn("no lockfile found; skipping dependency install");
|
||||
}
|
||||
Reference in New Issue
Block a user