Files
indiekit-server/scripts/patch-store-github-put-fallback.mjs
Sven 50002ffc72
Deploy Indiekit Server / deploy (push) Successful in 1m14s
fix: fall back to createFile when PUT returns Not Found in updateFile
When updateFile gets a SHA from the read step but the PUT fails with
404 (race condition, or file disappears between read and write), the
error previously surfaced as "Could not update file: Not Found" with
no recovery path.

New patch-store-github-put-fallback.mjs catches Not Found in the PUT
catch block and retries via createFile(), mirroring the existing
read-step fallback. Also renames the catch-block `const message` to
`const updateMsg` to avoid a TDZ conflict with the outer commit
message parameter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:35:59 +02:00

75 lines
2.5 KiB
JavaScript

/**
* Patch: fall back to createFile when the PUT (update) itself returns Not Found.
*
* Problem: patch-store-github-update-fallback catches "Not Found" in the READ
* step (sha = undefined → createFile). But if the file exists during the read
* (sha obtained) and then disappears before the PUT (race condition, or any
* other Gitea edge case), the PUT returns 404 and the outer catch block throws
* "Could not update file" with no recovery path.
*
* Fix: in the PUT catch block, if the error includes "Not Found", fall back to
* createFile() just as the read-step fallback does.
*
* Note: renames `const message` inside the catch to `const updateMsg` to avoid
* a TDZ conflict — the outer `message` (commit message from function params)
* needs to be accessible in the new if-branch.
*/
import { readFile, writeFile, access } from "node:fs/promises";
const TARGET = "node_modules/@indiekit/store-github/index.js";
const MARKER = "// [patch] store-github-put-fallback";
const OLD_CATCH = ` } catch (error) {
const message = crudErrorMessage({
error,
operation: "update",
filePath,
repo,
branch,
});
debug(message);
throw new Error(message);
}`;
const NEW_CATCH = ` } catch (error) {
if (error.message && error.message.includes("Not Found")) { ${MARKER}
// File disappeared between read and write — fall back to create
debug(\`File \${filePath} not found during PUT in repo \${repo} — falling back to createFile\`);
return this.createFile(filePath, content, { message });
}
const updateMsg = crudErrorMessage({ ${MARKER}
error,
operation: "update",
filePath,
repo,
branch,
});
debug(updateMsg);
throw new Error(updateMsg);
}`;
async function exists(p) {
try { await access(p); return true; } catch { return false; }
}
if (!(await exists(TARGET))) {
console.log(`[postinstall] store-github-put-fallback: target not found, skipping`);
process.exit(0);
}
const source = await readFile(TARGET, "utf8");
if (source.includes(MARKER)) {
console.log("[postinstall] store-github-put-fallback: already patched");
process.exit(0);
}
if (!source.includes(OLD_CATCH)) {
console.warn("[postinstall] store-github-put-fallback: PUT catch snippet not found — skipping");
process.exit(0);
}
await writeFile(TARGET, source.replace(OLD_CATCH, NEW_CATCH), "utf8");
console.log(`[postinstall] store-github-put-fallback: patched ${TARGET}`);