180 lines · 5.7 KB · TypeScript
RawDownload
import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Path from "effect/Path";import * as Sink from "effect/Sink";import * as Stream from "effect/Stream";import { ChildProcessSpawner } from "effect/unstable/process"; import { referenceRepos } from "./lib/reference-repos.ts";import {  planReferenceRepoSync,  resolveReferenceRepoRef,  syncReferenceRepos,} from "./sync-reference-repos.ts"; const encoder = new TextEncoder();const effectSmol = referenceRepos[0]!;const alchemyEffect = referenceRepos[1]!; function mockHandle() {  return ChildProcessSpawner.makeHandle({    pid: ChildProcessSpawner.ProcessId(1),    exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(0)),    isRunning: Effect.succeed(false),    kill: () => Effect.void,    unref: Effect.succeed(Effect.void),    stdin: Sink.drain,    stdout: Stream.make(encoder.encode("done\n")),    stderr: Stream.empty,    all: Stream.empty,    getInputFd: () => Sink.drain,    getOutputFd: () => Stream.empty,  });} function mockSpawnerLayer(  commands: Array<{ readonly command: string; readonly args: ReadonlyArray<string> }>,) {  return Layer.succeed(    ChildProcessSpawner.ChildProcessSpawner,    ChildProcessSpawner.make((command) => {      const childProcess = command as unknown as {        readonly command: string;        readonly args: ReadonlyArray<string>;      };      commands.push({        command: childProcess.command,        args: childProcess.args,      });      return Effect.succeed(mockHandle());    }),  );} it.layer(NodeServices.layer)("sync-reference-repos", (it) => {  it.effect("resolves the effect-smol tag from the root catalog", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const path = yield* Path.Path;      const rootDir = yield* fs.makeTempDirectoryScoped({        prefix: "sync-reference-repos-version-",      });      yield* fs.writeFileString(        path.join(rootDir, "pnpm-workspace.yaml"),        "catalog:\n  effect: 4.0.0-beta.73\n",      );       assert.equal(        yield* resolveReferenceRepoRef(effectSmol, rootDir, false),        "effect@4.0.0-beta.73",      );    }),  );   it.effect("uses the latest branch without reading package versions", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const rootDir = yield* fs.makeTempDirectoryScoped({        prefix: "sync-reference-repos-latest-",      });       assert.equal(yield* resolveReferenceRepoRef(effectSmol, rootDir, true), "main");    }),  );   it.effect("resolves the alchemy-effect tag from the relay package", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const path = yield* Path.Path;      const rootDir = yield* fs.makeTempDirectoryScoped({        prefix: "sync-reference-repos-alchemy-version-",      });      yield* fs.makeDirectory(path.join(rootDir, "infra", "relay"), { recursive: true });      yield* fs.writeFileString(        path.join(rootDir, "infra", "relay", "package.json"),        '{"dependencies":{"alchemy":"2.0.0-beta.49"}}',      );       assert.equal(yield* resolveReferenceRepoRef(alchemyEffect, rootDir, false), "v2.0.0-beta.49");    }),  );   it.effect("plans an add for a missing subtree and a pull for an existing subtree", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const path = yield* Path.Path;      const rootDir = yield* fs.makeTempDirectoryScoped({        prefix: "sync-reference-repos-plan-",      });      yield* fs.writeFileString(        path.join(rootDir, "pnpm-workspace.yaml"),        "catalog:\n  effect: 4.0.0-beta.73\n",      );       const addPlan = yield* planReferenceRepoSync(effectSmol, rootDir, false);      assert.equal(addPlan.action, "add");      assert.deepStrictEqual(addPlan.args, [        "subtree",        "add",        "--prefix=.repos/effect-smol",        "https://github.com/Effect-TS/effect-smol.git",        "effect@4.0.0-beta.73",        "--squash",      ]);       yield* fs.makeDirectory(path.join(rootDir, effectSmol.prefix), { recursive: true });      assert.equal((yield* planReferenceRepoSync(effectSmol, rootDir, false)).action, "pull");    }),  );   it.effect("runs the planned git subtree command through the process service", () => {    const commands: Array<{ readonly command: string; readonly args: ReadonlyArray<string> }> = [];     return Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const path = yield* Path.Path;      const rootDir = yield* fs.makeTempDirectoryScoped({        prefix: "sync-reference-repos-run-",      });      yield* fs.writeFileString(        path.join(rootDir, "pnpm-workspace.yaml"),        "catalog:\n  effect: 4.0.0-beta.73\n",      );       yield* syncReferenceRepos({ rootDir, repoId: "effect-smol" }).pipe(        Effect.provide(mockSpawnerLayer(commands)),      );       assert.deepStrictEqual(commands, [        {          command: "git",          args: [            "subtree",            "add",            "--prefix=.repos/effect-smol",            "https://github.com/Effect-TS/effect-smol.git",            "effect@4.0.0-beta.73",            "--squash",          ],        },      ]);    });  });   it.effect("rejects unknown repo selectors", () =>    Effect.gen(function* () {      const error = yield* syncReferenceRepos({        repoId: "missing",        dryRun: true,      }).pipe(Effect.flip);       assert.equal(        error.message,        "Unknown reference repo 'missing'. Expected one of: effect-smol, alchemy-effect.",      );    }),  );});