@rigkit/engine 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,7 +28,7 @@ describe("DevMachineEngine workflow runtime", () => {
28
28
  });
29
29
 
30
30
  const base = app.sequence("base").task("first", async ({ step, test }) => {
31
- step.log("preparing base\\n", { label: "setup" });
31
+ console.log("preparing base");
32
32
  const vm = await test.createVm();
33
33
  await vm.exec("touch /tmp/first", { name: "touch first" });
34
34
  if (!(await vm.exists("/tmp/first"))) throw new Error("first was not created");
@@ -138,8 +138,7 @@ describe("DevMachineEngine workflow runtime", () => {
138
138
  type: "log.output",
139
139
  nodePath: "base.first",
140
140
  stream: "info",
141
- label: "setup",
142
- data: "preparing base\n",
141
+ data: "preparing base",
143
142
  });
144
143
  expect(provider.snapshots).toHaveLength(2);
145
144
  expect(engine.listNodeRuns()).toHaveLength(4);
@@ -502,6 +501,165 @@ describe("DevMachineEngine workflow runtime", () => {
502
501
  expect(second.listNodeRuns()).toHaveLength(2);
503
502
  });
504
503
 
504
+ test("stores globally scoped sequence runs in fragment state and busts downstream local cache", async () => {
505
+ const projectDir = mkdtempSync(join(tmpdir(), "rigkit-global-fragment-"));
506
+ const statePath = join(projectDir, ".rigkit", "state.sqlite");
507
+ const fragmentRoot = join(projectDir, "fragments");
508
+ mkdirSync(join(projectDir, ".rigkit"));
509
+
510
+ const writeConfig = (configPath: string, value: string) =>
511
+ writeFileSync(
512
+ configPath,
513
+ `
514
+ import { sequence } from "${import.meta.dir}/index.ts";
515
+
516
+ const deps = sequence("deps")
517
+ .configure({ value: "${value}" })
518
+ .task("prepare", async ({ config }) => ({ ctx: { value: String(config.value) } }))
519
+ .global();
520
+
521
+ export default sequence("site")
522
+ .add(deps)
523
+ .task("install", async ({ step }) => ({ ctx: { installed: step.ctx.value } }));
524
+ `,
525
+ );
526
+
527
+ const firstConfigPath = join(projectDir, "rig.one.config.ts");
528
+ const secondConfigPath = join(projectDir, "rig.two.config.ts");
529
+ writeConfig(firstConfigPath, "one");
530
+ writeConfig(secondConfigPath, "two");
531
+
532
+ const engineOptions = {
533
+ projectDir,
534
+ statePath,
535
+ globalFragmentStateLocator: (fragment: { hash: string }) => ({
536
+ statePath: join(fragmentRoot, fragment.hash, "state.sqlite"),
537
+ }),
538
+ };
539
+
540
+ const first = await createDevMachineEngine({ ...engineOptions, configPath: firstConfigPath });
541
+ await first.load();
542
+ await first.apply();
543
+ expect((await first.plan()).cachedNodeCount).toBe(2);
544
+ expect(first.listNodeRuns().map((run) => run.nodePath)).toEqual(["install"]);
545
+
546
+ const fragmentHashes = readdirSync(fragmentRoot);
547
+ expect(fragmentHashes).toHaveLength(1);
548
+ const fragmentDb = new Database(join(fragmentRoot, fragmentHashes[0]!, "state.sqlite"));
549
+ const fragmentRuns = fragmentDb
550
+ .query<{ node_path: string }, []>("select node_path from workflow_node_runs order by node_path")
551
+ .all();
552
+ fragmentDb.close();
553
+ expect(fragmentRuns.map((run) => run.node_path)).toEqual(["deps.prepare"]);
554
+
555
+ const cache = await first.listCache();
556
+ expect(cache.entries.map((entry) => entry.scope).sort()).toEqual(["global", "local"]);
557
+
558
+ const second = await createDevMachineEngine({ ...engineOptions, configPath: secondConfigPath });
559
+ await second.load();
560
+ const changed = await second.plan();
561
+ expect(changed.cachedNodeCount).toBe(0);
562
+
563
+ const reapplied = await second.apply();
564
+ expect(reapplied.context.installed).toBe("two");
565
+ expect(readdirSync(fragmentRoot)).toHaveLength(2);
566
+ });
567
+
568
+ test("allows a later local task to invalidate an earlier global fragment task", async () => {
569
+ const projectDir = mkdtempSync(join(tmpdir(), "rigkit-global-invalidates-"));
570
+ const statePath = join(projectDir, ".rigkit", "state.sqlite");
571
+ const fragmentRoot = join(projectDir, "fragments");
572
+ mkdirSync(join(projectDir, ".rigkit"));
573
+
574
+ const previous = {
575
+ installCount: process.env.RIGKIT_GLOBAL_INSTALL_COUNT,
576
+ authCount: process.env.RIGKIT_GLOBAL_AUTH_COUNT,
577
+ repoCount: process.env.RIGKIT_LOCAL_REPO_COUNT,
578
+ checkCount: process.env.RIGKIT_LOCAL_CHECK_COUNT,
579
+ forceReauth: process.env.RIGKIT_FORCE_GLOBAL_REAUTH,
580
+ };
581
+ process.env.RIGKIT_GLOBAL_INSTALL_COUNT = "0";
582
+ process.env.RIGKIT_GLOBAL_AUTH_COUNT = "0";
583
+ process.env.RIGKIT_LOCAL_REPO_COUNT = "0";
584
+ process.env.RIGKIT_LOCAL_CHECK_COUNT = "0";
585
+ process.env.RIGKIT_FORCE_GLOBAL_REAUTH = "0";
586
+
587
+ writeFileSync(
588
+ join(projectDir, "rig.config.ts"),
589
+ `
590
+ import { sequence } from "${import.meta.dir}/index.ts";
591
+
592
+ const base = sequence("base")
593
+ .task("install", async () => {
594
+ const count = Number(process.env.RIGKIT_GLOBAL_INSTALL_COUNT ?? "0") + 1;
595
+ process.env.RIGKIT_GLOBAL_INSTALL_COUNT = String(count);
596
+ return { ctx: { installed: "install-" + count } };
597
+ })
598
+ .task("auth", async ({ step }) => {
599
+ const count = Number(process.env.RIGKIT_GLOBAL_AUTH_COUNT ?? "0") + 1;
600
+ process.env.RIGKIT_GLOBAL_AUTH_COUNT = String(count);
601
+ return { ctx: { ...step.ctx, token: "token-" + count } };
602
+ })
603
+ .global();
604
+
605
+ const repo = sequence("repo")
606
+ .task("clone", async ({ step }) => {
607
+ const count = Number(process.env.RIGKIT_LOCAL_REPO_COUNT ?? "0") + 1;
608
+ process.env.RIGKIT_LOCAL_REPO_COUNT = String(count);
609
+ return { ctx: { ...step.ctx, repoToken: step.ctx.token, repoCount: count } };
610
+ });
611
+
612
+ export default sequence("root")
613
+ .add(base)
614
+ .add(repo)
615
+ .task("check-auth", { cacheTTL: 0 }, async ({ step }) => {
616
+ const count = Number(process.env.RIGKIT_LOCAL_CHECK_COUNT ?? "0") + 1;
617
+ process.env.RIGKIT_LOCAL_CHECK_COUNT = String(count);
618
+ if (process.env.RIGKIT_FORCE_GLOBAL_REAUTH === "1") {
619
+ process.env.RIGKIT_FORCE_GLOBAL_REAUTH = "0";
620
+ return step.invalidate("auth");
621
+ }
622
+ return { ctx: step.ctx };
623
+ });
624
+ `,
625
+ );
626
+
627
+ try {
628
+ const engine = await createDevMachineEngine({
629
+ projectDir,
630
+ statePath,
631
+ globalFragmentStateLocator: (fragment: { hash: string }) => ({
632
+ statePath: join(fragmentRoot, fragment.hash, "state.sqlite"),
633
+ }),
634
+ });
635
+ await engine.load();
636
+
637
+ const first = await engine.apply();
638
+ expect(first.context.token).toBe("token-1");
639
+ expect(first.context.repoToken).toBe("token-1");
640
+ expect(process.env.RIGKIT_GLOBAL_INSTALL_COUNT).toBe("1");
641
+ expect(process.env.RIGKIT_GLOBAL_AUTH_COUNT).toBe("1");
642
+ expect(process.env.RIGKIT_LOCAL_REPO_COUNT).toBe("1");
643
+ expect(process.env.RIGKIT_LOCAL_CHECK_COUNT).toBe("1");
644
+
645
+ process.env.RIGKIT_FORCE_GLOBAL_REAUTH = "1";
646
+ const second = await engine.apply();
647
+ expect(second.context.token).toBe("token-2");
648
+ expect(second.context.repoToken).toBe("token-2");
649
+ expect(process.env.RIGKIT_GLOBAL_INSTALL_COUNT).toBe("1");
650
+ expect(process.env.RIGKIT_GLOBAL_AUTH_COUNT).toBe("2");
651
+ expect(process.env.RIGKIT_LOCAL_REPO_COUNT).toBe("2");
652
+ expect(process.env.RIGKIT_LOCAL_CHECK_COUNT).toBe("3");
653
+ expect(readdirSync(fragmentRoot)).toHaveLength(1);
654
+ } finally {
655
+ restoreEnv("RIGKIT_GLOBAL_INSTALL_COUNT", previous.installCount);
656
+ restoreEnv("RIGKIT_GLOBAL_AUTH_COUNT", previous.authCount);
657
+ restoreEnv("RIGKIT_LOCAL_REPO_COUNT", previous.repoCount);
658
+ restoreEnv("RIGKIT_LOCAL_CHECK_COUNT", previous.checkCount);
659
+ restoreEnv("RIGKIT_FORCE_GLOBAL_REAUTH", previous.forceReauth);
660
+ }
661
+ });
662
+
505
663
  test("stores provider JSON state in Rigkit-owned provider storage", async () => {
506
664
  const projectDir = mkdtempSync(join(tmpdir(), "rigkit-"));
507
665
  const plugin: BaseProviderPlugin = {