mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-31 07:35:24 +00:00
fix: dev stages local plugin builds on paths with spaces and builds them with the local SDK
This commit is contained in:
1 parent
878f1ebaa3
commit
4511cc0a42
4 files changed
+76
-8
No files matched your search
@@ -8,11 +8,12 @@
|
|||||||
*
|
*
|
||||||
* For development, `--local <dir>` (or TERMIX_LOCAL_PLUGINS) points at a
|
* For development, `--local <dir>` (or TERMIX_LOCAL_PLUGINS) points at a
|
||||||
* folder of plugin repos like ../Termix-Plugins. A plugin there whose sources
|
* folder of plugin repos like ../Termix-Plugins. A plugin there whose sources
|
||||||
* changed since its last build is rebuilt first, then any built one (has
|
* changed since its last build is rebuilt first with this checkout's SDK, so
|
||||||
|
* SDK edits apply without publishing, then any built one (has
|
||||||
* dist/) is copied in place of its pin, or added when it has no pin.
|
* dist/) is copied in place of its pin, or added when it has no pin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { execSync } = require("node:child_process");
|
const { execFileSync } = require("node:child_process");
|
||||||
const fs = require("node:fs");
|
const fs = require("node:fs");
|
||||||
const path = require("node:path");
|
const path = require("node:path");
|
||||||
const {
|
const {
|
||||||
@@ -21,6 +22,7 @@ const {
|
|||||||
extractArtifact,
|
extractArtifact,
|
||||||
findLocalPluginBuilds,
|
findLocalPluginBuilds,
|
||||||
rebuildLocalPlugins,
|
rebuildLocalPlugins,
|
||||||
|
localSdkBuildCommand,
|
||||||
copyLocalBuild,
|
copyLocalBuild,
|
||||||
buildBundledIndex,
|
buildBundledIndex,
|
||||||
} = require("./lib/bundled-plugins.cjs");
|
} = require("./lib/bundled-plugins.cjs");
|
||||||
@@ -34,9 +36,10 @@ async function main() {
|
|||||||
const localArg =
|
const localArg =
|
||||||
flag !== -1 ? process.argv[flag + 1] : process.env.TERMIX_LOCAL_PLUGINS;
|
flag !== -1 ? process.argv[flag + 1] : process.env.TERMIX_LOCAL_PLUGINS;
|
||||||
const localDir = localArg ? path.resolve(root, localArg) : null;
|
const localDir = localArg ? path.resolve(root, localArg) : null;
|
||||||
|
const [node, buildArgs] = localSdkBuildCommand();
|
||||||
rebuildLocalPlugins(localDir, null, (repo, id) => {
|
rebuildLocalPlugins(localDir, null, (repo, id) => {
|
||||||
console.log(`building ${id}`);
|
console.log(`building ${id}`);
|
||||||
execSync("npm run build", { cwd: repo, stdio: "inherit" });
|
execFileSync(node, buildArgs, { cwd: repo, stdio: "inherit" });
|
||||||
});
|
});
|
||||||
const local = findLocalPluginBuilds(localDir);
|
const local = findLocalPluginBuilds(localDir);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
buildBundledIndex,
|
buildBundledIndex,
|
||||||
findLocalPluginBuilds,
|
findLocalPluginBuilds,
|
||||||
isLocalBuildStale,
|
isLocalBuildStale,
|
||||||
|
localSdkBuildCommand,
|
||||||
rebuildLocalPlugins,
|
rebuildLocalPlugins,
|
||||||
copyLocalBuild,
|
copyLocalBuild,
|
||||||
} from "./lib/bundled-plugins.cjs";
|
} from "./lib/bundled-plugins.cjs";
|
||||||
@@ -354,6 +355,40 @@ describe("rebuilding local plugins", () => {
|
|||||||
expect(isLocalBuildStale(root)).toBe(true);
|
expect(isLocalBuildStale(root)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("is stale when the SDK CLI changed after the build", () => {
|
||||||
|
const root = repo(tempDir(), "Plugin-A", "a");
|
||||||
|
const cli = path.join(tempDir(), "cli");
|
||||||
|
fs.mkdirSync(cli);
|
||||||
|
fs.writeFileSync(path.join(cli, "index.mjs"), "x");
|
||||||
|
fs.mkdirSync(path.join(root, "dist"));
|
||||||
|
fs.writeFileSync(path.join(root, "dist", "frontend.js"), "x");
|
||||||
|
touch(path.join(root, "manifest.json"), 60);
|
||||||
|
touch(path.join(root, "src", "index.ts"), 60);
|
||||||
|
touch(path.join(cli, "index.mjs"), 60);
|
||||||
|
expect(isLocalBuildStale(root, cli)).toBe(false);
|
||||||
|
|
||||||
|
touch(path.join(root, "dist", "frontend.js"), 30);
|
||||||
|
touch(path.join(cli, "index.mjs"), 0);
|
||||||
|
expect(isLocalBuildStale(root, cli)).toBe(true);
|
||||||
|
expect(isLocalBuildStale(root)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds with this checkout's SDK CLI, not the plugin's own", () => {
|
||||||
|
const [command, args] = localSdkBuildCommand();
|
||||||
|
expect(command).toBe(process.execPath);
|
||||||
|
expect(args).toEqual([
|
||||||
|
path.resolve(
|
||||||
|
__dirname,
|
||||||
|
"..",
|
||||||
|
"packages",
|
||||||
|
"plugin-sdk",
|
||||||
|
"cli",
|
||||||
|
"index.mjs",
|
||||||
|
),
|
||||||
|
"build",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("builds only stale repos for bundled ids that have node_modules", () => {
|
it("builds only stale repos for bundled ids that have node_modules", () => {
|
||||||
const dir = tempDir();
|
const dir = tempDir();
|
||||||
repo(dir, "Plugin-A", "a");
|
repo(dir, "Plugin-A", "a");
|
||||||
|
|||||||
+8
-3
@@ -45,7 +45,10 @@ import {
|
|||||||
} from "./lib/dev-docker.mjs";
|
} from "./lib/dev-docker.mjs";
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
const { copyLocalBuild } = require("./lib/bundled-plugins.cjs");
|
const {
|
||||||
|
copyLocalBuild,
|
||||||
|
localSdkBuildCommand,
|
||||||
|
} = require("./lib/bundled-plugins.cjs");
|
||||||
|
|
||||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const BACKEND_ENTRY = path.join(
|
const BACKEND_ENTRY = path.join(
|
||||||
@@ -83,7 +86,9 @@ function run(command, args, cwd = root) {
|
|||||||
const child = spawn(command, args, {
|
const child = spawn(command, args, {
|
||||||
cwd,
|
cwd,
|
||||||
stdio: ["ignore", "inherit", "inherit"],
|
stdio: ["ignore", "inherit", "inherit"],
|
||||||
shell: process.platform === "win32",
|
// npm is a .cmd on Windows and needs the shell, but the shell splits
|
||||||
|
// arguments on spaces, so a path like "Personal Projects" gets cut.
|
||||||
|
shell: process.platform === "win32" && !path.isAbsolute(command),
|
||||||
});
|
});
|
||||||
child.on("error", reject);
|
child.on("error", reject);
|
||||||
child.on("exit", (code) =>
|
child.on("exit", (code) =>
|
||||||
@@ -541,7 +546,7 @@ function watchCoreForDocker() {
|
|||||||
async function rebuildPlugin({ id, repo }) {
|
async function rebuildPlugin({ id, repo }) {
|
||||||
log(`building ${id}`);
|
log(`building ${id}`);
|
||||||
try {
|
try {
|
||||||
await run("npm", ["run", "build"], repo);
|
await run(...localSdkBuildCommand(), repo);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
warn(`${id} failed to build: ${error.message}`);
|
warn(`${id} failed to build: ${error.message}`);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -299,14 +299,37 @@ function newestMtime(target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** True when a plugin repo has never been built or its sources changed since. */
|
/** True when a plugin repo has never been built or its sources changed since. */
|
||||||
function isLocalBuildStale(repo) {
|
/** The SDK CLI in this checkout, which dev builds local plugins with. */
|
||||||
|
const LOCAL_SDK_CLI = path.join(
|
||||||
|
__dirname,
|
||||||
|
"..",
|
||||||
|
"..",
|
||||||
|
"packages",
|
||||||
|
"plugin-sdk",
|
||||||
|
"cli",
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when the build is missing, a source is newer than it, or the SDK CLI
|
||||||
|
* that builds it changed since (sdkCli, when given).
|
||||||
|
*/
|
||||||
|
function isLocalBuildStale(repo, sdkCli) {
|
||||||
const built = newestMtime(path.join(repo, "dist"));
|
const built = newestMtime(path.join(repo, "dist"));
|
||||||
if (!built) return true;
|
if (!built) return true;
|
||||||
|
if (sdkCli && newestMtime(sdkCli) > built) return true;
|
||||||
return BUILD_INPUTS.some(
|
return BUILD_INPUTS.some(
|
||||||
(entry) => newestMtime(path.join(repo, entry)) > built,
|
(entry) => newestMtime(path.join(repo, entry)) > built,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command that builds a plugin repo with this checkout's SDK instead of
|
||||||
|
* the published one in its node_modules, so SDK edits apply right away.
|
||||||
|
*/
|
||||||
|
function localSdkBuildCommand() {
|
||||||
|
return [process.execPath, [path.join(LOCAL_SDK_CLI, "index.mjs"), "build"]];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds each plugin repo whose build is missing or out of date. ids limits
|
* Builds each plugin repo whose build is missing or out of date. ids limits
|
||||||
* it to those plugins; null builds every one.
|
* it to those plugins; null builds every one.
|
||||||
@@ -325,7 +348,8 @@ function rebuildLocalPlugins(dir, ids, run) {
|
|||||||
} catch {
|
} catch {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((ids && !ids.has(id)) || !isLocalBuildStale(repo)) continue;
|
if ((ids && !ids.has(id)) || !isLocalBuildStale(repo, LOCAL_SDK_CLI))
|
||||||
|
continue;
|
||||||
run(repo, id);
|
run(repo, id);
|
||||||
rebuilt.push(id);
|
rebuilt.push(id);
|
||||||
}
|
}
|
||||||
@@ -346,6 +370,7 @@ function copyLocalBuild(repo, destination) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
findLocalPluginBuilds,
|
findLocalPluginBuilds,
|
||||||
isLocalBuildStale,
|
isLocalBuildStale,
|
||||||
|
localSdkBuildCommand,
|
||||||
rebuildLocalPlugins,
|
rebuildLocalPlugins,
|
||||||
copyLocalBuild,
|
copyLocalBuild,
|
||||||
parseBundledPlugins,
|
parseBundledPlugins,
|
||||||
|
|||||||
Reference in new issue
Block a user