testPruneLeavesWhatsLeased

tcmts.cli.web.testPruneLeavesWhatsLeased · #twgjkfur · term

import type { Codebase } from "#codebase/tcmts/cli/codebase";
import { leaseBuilds, pruneBuilds } from "#codebase/tcmts/cli/web";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";

export const testPruneLeavesWhatsLeased = () => {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), "tcm-prune-"));
  try {
    // (a codebase with none of these apps' names: no build of them is current)
    const cb = {
      lay: { tcmDir: dir },
      lookupOne: () => {
        throw new Error("no such name");
      },
    } as unknown as Codebase;
    const apps = path.join(dir, "apps");
    fs.mkdirSync(path.join(apps, "assets"), { recursive: true });
    const build = (hash: string, builtAt: string, assets: string[]) => {
      fs.mkdirSync(path.join(apps, hash));
      fs.writeFileSync(
        path.join(apps, hash, "tcm-app.json"),
        JSON.stringify({ app: "a", hash, endpoints: [], assets, builtAt }),
      );
      for (const f of assets) fs.writeFileSync(path.join(apps, "assets", f), f);
    };
    build("old", "2026-01-01", ["old.js", "both.js"]);
    build("served", "2026-01-02", ["served.js", "both.js"]);
    build("new", "2026-01-03", ["new.js"]);
    // being made: an asset of a build not yet in place
    fs.writeFileSync(path.join(apps, "assets", "making.js"), "");
    const lease = leaseBuilds(path.join(dir, "build"));
    lease.hold({ builds: ["served"], assets: ["making.js"] });
    const removed = pruneBuilds(cb, 0, true)
      .map((b) => b.hash)
      .sort();
    assert.deepEqual(removed, ["new", "old"]);
    assert.deepEqual(fs.readdirSync(apps).sort(), ["assets", "served"]);
    assert.deepEqual(fs.readdirSync(path.join(apps, "assets")).sort(), [
      "both.js",
      "making.js",
      "served.js",
    ]);
    assert.deepEqual(
      fs.readdirSync(path.join(dir, "build")).filter((e) => !e.startsWith("lease.")),
      [],
      "nothing set aside is left",
    );
    lease.release();
    assert.deepEqual(
      pruneBuilds(cb, 0, true).map((b) => b.hash),
      ["served"],
      "released, it goes",
    );
  } finally {
    fs.rmSync(dir, { recursive: true, force: true });
  }
}

uses