feat(FN-2944): merge fusion/fn-2944

- test(FN-2944): cover already checked out worktree conflict recovery
- fix(FN-2944): recognize git already checked out worktree conflict
- fix(engine): auto-recover from squash-merge orphan rebase failures

Fusion-Task-Id: FN-2944
This commit is contained in:
Fusion
2026-04-29 07:10:52 -07:00
committed by gsxdsm
parent a74b77cec5
commit ba3d868c2d
46 changed files with 454 additions and 163 deletions

View File

@@ -1,4 +1,5 @@
import type { ProjectSettings } from "@fusion/core";
import { basename } from "node:path";
import { ApiError, badRequest, notFound } from "../api-error.js";
import { getFusionAuthPath } from "../auth-paths.js";
import { fetchFromRemoteNode, readStoredAuthProvidersFromDisk } from "./register-settings-sync-helpers.js";
@@ -74,7 +75,7 @@ export const registerSettingsSyncRoutes: ApiRouteRegistrar = (ctx) => {
// Build sync payload
const payload = {
global: globalSettings,
projects: { [store.getRootDir().split("/").pop()!]: projectSettings.project },
projects: { [basename(store.getRootDir())]: projectSettings.project },
exportedAt: new Date().toISOString(),
version: 1 as const,
};

View File

@@ -1,39 +1,11 @@
import { existsSync, readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { resolveGlobalDir } from "@fusion/core";
import { clearUpdateCheckCache, performUpdateCheck } from "../update-check.js";
import { getCliPackageVersion } from "../cli-package-version.js";
import type { ApiRouteRegistrar } from "./types.js";
// Walk up from this module to find the @runfusion/fusion package.json. Works
// across layouts: monorepo source (packages/dashboard/src/...), installed
// dependency (node_modules/@runfusion/fusion/dist/...), and the bundled CLI
// binary where dashboard code is inlined into bin.js next to the cli's
// package.json. Falls back to "0.0.0" when nothing is found.
const CLI_PACKAGE_VERSION = (() => {
try {
let cur = dirname(fileURLToPath(import.meta.url));
for (let i = 0; i < 8; i++) {
const pkgPath = resolve(cur, "package.json");
if (existsSync(pkgPath)) {
const parsed = JSON.parse(readFileSync(pkgPath, "utf-8")) as { name?: string; version?: string };
if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string" && parsed.version.length > 0) {
return parsed.version;
}
}
const parent = resolve(cur, "..");
if (parent === cur) break;
cur = parent;
}
} catch {
// Fall through to env/default fallback.
}
return process.env.npm_package_version ?? "0.0.0";
})();
export const registerUpdateCheckRoutes: ApiRouteRegistrar = (ctx) => {
const { router, store, rethrowAsApiError } = ctx;
const cliPackageVersion = getCliPackageVersion(import.meta.url);
router.get("/update-check", async (_req, res) => {
try {
@@ -42,14 +14,14 @@ export const registerUpdateCheckRoutes: ApiRouteRegistrar = (ctx) => {
res.json({
updateAvailable: false,
disabled: true,
currentVersion: CLI_PACKAGE_VERSION,
currentVersion: cliPackageVersion,
latestVersion: null,
lastChecked: Date.now(),
});
return;
}
const result = await performUpdateCheck(resolveGlobalDir(), CLI_PACKAGE_VERSION, {
const result = await performUpdateCheck(resolveGlobalDir(), cliPackageVersion, {
frequency: globalSettings.updateCheckFrequency,
});
res.json(result);
@@ -64,7 +36,7 @@ export const registerUpdateCheckRoutes: ApiRouteRegistrar = (ctx) => {
await clearUpdateCheckCache(fusionDir);
// Explicit `force: true` so a "manual" frequency setting doesn't short
// out the network fetch on the user's deliberate "Check now" click.
const result = await performUpdateCheck(fusionDir, CLI_PACKAGE_VERSION, {
const result = await performUpdateCheck(fusionDir, cliPackageVersion, {
force: true,
});
res.json(result);