@lizard-build/cli 4.0.66 → 4.0.68

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.
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { parseType, relativeName } from "../../src/commands/domain-owned.js";
2
+ import { parseType, recordsToReplace, relativeName } from "../../src/commands/domain-owned.js";
3
3
 
4
4
  describe("lizard domain dns: names and types", () => {
5
5
  it("makes names relative to the domain", () => {
@@ -15,3 +15,20 @@ describe("lizard domain dns: names and types", () => {
15
15
  expect(() => parseType("SRV")).toThrow(/Unknown record type/);
16
16
  });
17
17
  });
18
+
19
+ describe("lizard domain <bought domain>: records it would replace", () => {
20
+ const rec = (name: string, type: string, value: string) => ({ name, type, value, ttl: 1800 }) as never;
21
+ it("lists pointing records on the names being connected, and nothing else", () => {
22
+ const records = [
23
+ rec("@", "A", "203.0.113.10"), rec("@", "MX", "mail.example.com"), rec("@", "TXT", "v=spf1"),
24
+ rec("api", "CNAME", "elsewhere.example.net"), rec("www", "CNAME", "other.example.net"),
25
+ ];
26
+ expect(recordsToReplace(records, ["@", "www"]).map((r: { name: string }) => r.name)).toEqual(["@", "www"]);
27
+ expect(recordsToReplace(records, ["api"])).toHaveLength(1);
28
+ expect(recordsToReplace(records, ["blog"])).toHaveLength(0);
29
+ });
30
+ it("does not count the parking page or an earlier Lizard target", () => {
31
+ const records = [rec("www", "CNAME", "parkingpage.namecheap.com."), rec("@", "ALIAS", "eu.onlizard.com")];
32
+ expect(recordsToReplace(records, ["@", "www"])).toHaveLength(0);
33
+ });
34
+ });
@@ -1,5 +1,9 @@
1
1
  import { describe, it, expect, afterEach, vi } from "vitest";
2
- import { repoFromRemote, qs, gitURL, helperCommand, resolveRepo, lg, segs } from "../../src/lib/lizard-git.js";
2
+ import { mkdtempSync, mkdirSync, writeFileSync, symlinkSync, unlinkSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { qs, gitURL, resolveRepo, lg, segs } from "../../src/lib/lizard-git.js";
6
+ import { changesOf, scanWorking, saveCheckout, findCheckout, sha256, unifiedDiff, type Checkout } from "../../src/lib/checkout.js";
3
7
 
4
8
  afterEach(() => {
5
9
  vi.unstubAllGlobals();
@@ -7,18 +11,6 @@ afterEach(() => {
7
11
  });
8
12
 
9
13
  describe("lizard git helpers", () => {
10
- it("reads owner/name from Lizard Git remotes only", () => {
11
- expect(repoFromRemote("https://lizard.build/git/alice/app.git")).toBe("alice/app");
12
- expect(repoFromRemote("https://lizard:liz_x@lizard.build/git/alice/app")).toBe("alice/app");
13
- expect(repoFromRemote("https://git.lizard.build/alice/app.git")).toBe("alice/app"); // older clones
14
- expect(repoFromRemote("https://lizard:liz_x@git.lizard.build/alice/app")).toBe("alice/app");
15
- expect(repoFromRemote("https://github.com/alice/app.git")).toBeNull();
16
- expect(repoFromRemote("git@github.com:alice/app.git")).toBeNull();
17
- expect(repoFromRemote("https://lizard.build/alice/app.git")).toBeNull();
18
- expect(repoFromRemote("https://lizard.build/gitx/alice/app.git")).toBeNull();
19
- expect(repoFromRemote("https://lizard.build/git/alice/app/extra.git")).toBeNull();
20
- });
21
-
22
14
  it("drops empty query values", () => {
23
15
  expect(qs("/x", { a: "1", b: undefined, c: "", d: false, e: 2 })).toBe("/x?a=1&e=2");
24
16
  });
@@ -26,12 +18,6 @@ describe("lizard git helpers", () => {
26
18
  it("honours LIZARD_GIT_URL", () => {
27
19
  vi.stubEnv("LIZARD_GIT_URL", "http://localhost:8080/");
28
20
  expect(gitURL()).toBe("http://localhost:8080");
29
- expect(repoFromRemote("http://localhost:8080/a/b.git")).toBe("a/b");
30
- expect(repoFromRemote("https://git.lizard.build/a/b.git")).toBeNull(); // another server: only it
31
- });
32
-
33
- it("runs itself as git's credential helper", () => {
34
- expect(helperCommand()).toMatch(/^!'.+' .*git credential$/);
35
21
  });
36
22
 
37
23
  it("takes owner/name or a bare name (yours) for --repo", async () => {
@@ -66,8 +52,63 @@ describe("lizard git safety", () => {
66
52
  await expect(resolveRepo("a/..")).rejects.toThrow();
67
53
  expect(() => segs("../../api/user/tokens")).toThrow(/bad path/);
68
54
  expect(segs("src/a b.js")).toBe("src/a%20b.js");
69
- expect(repoFromRemote("https://git.lizard.build/../x.git")).toBeNull();
70
- expect(repoFromRemote("https://lizard.build/git/../x.git")).toBeNull();
71
- expect(repoFromRemote("https://lizard.build/git/a/...git")).toBeNull();
55
+ });
56
+ });
57
+
58
+ describe("lizard git checkouts", () => {
59
+ const make = (files: Record<string, string>, state: Partial<Checkout> = {}) => {
60
+ const root = mkdtempSync(join(tmpdir(), "lzg-"));
61
+ const c: Checkout = { version: 1, url: "x", repo: "alice/app", branch: "main", base: "b".repeat(64), root: "r".repeat(64), sparse: null, files: {}, ...state };
62
+ for (const [p, body] of Object.entries(files)) {
63
+ mkdirSync(join(root, p, ".."), { recursive: true });
64
+ writeFileSync(join(root, p), body);
65
+ c.files[p] = { h: sha256(body), m: "100644" };
66
+ }
67
+ saveCheckout(root, c);
68
+ return { root, c };
69
+ };
70
+
71
+ it("finds its checkout from a subdirectory and the repository from it", async () => {
72
+ const { root } = make({ "src/a.ts": "a" });
73
+ expect(findCheckout(join(root, "src"))).toBe(root);
74
+ const cwd = process.cwd();
75
+ process.chdir(join(root, "src"));
76
+ try {
77
+ expect(await resolveRepo()).toBe("alice/app");
78
+ } finally {
79
+ process.chdir(cwd);
80
+ }
81
+ });
82
+
83
+ it("sees added, modified and deleted files, and nothing it shouldn't", () => {
84
+ const { root, c } = make({ "a.txt": "a", "src/b.txt": "b", "gone.txt": "g" });
85
+ writeFileSync(join(root, "a.txt"), "a2");
86
+ writeFileSync(join(root, "new.txt"), "n");
87
+ mkdirSync(join(root, ".lizard/workflows"), { recursive: true }); // a repository's CI: content like any other
88
+ writeFileSync(join(root, ".lizard/workflows/ci.yml"), "on: push\n");
89
+ writeFileSync(join(root, ".gitignore"), "*.log\nbuild/\n");
90
+ writeFileSync(join(root, "debug.log"), "x");
91
+ mkdirSync(join(root, "build"));
92
+ writeFileSync(join(root, "build/out.js"), "x");
93
+ mkdirSync(join(root, "node_modules/x"), { recursive: true });
94
+ writeFileSync(join(root, "node_modules/x/i.js"), "x");
95
+ symlinkSync("a.txt", join(root, "link"));
96
+ unlinkSync(join(root, "gone.txt"));
97
+ const ch = changesOf(c, scanWorking(root, c));
98
+ expect(ch).toEqual({ added: [".gitignore", ".lizard/workflows/ci.yml", "link", "new.txt"], modified: ["a.txt"], deleted: ["gone.txt"] });
99
+ });
100
+
101
+ it("a sparse checkout only looks inside its folders", () => {
102
+ const { root, c } = make({ "src/a.txt": "a" }, { sparse: ["src"] });
103
+ writeFileSync(join(root, "outside.txt"), "o");
104
+ writeFileSync(join(root, "src/b.txt"), "b");
105
+ expect(changesOf(c, scanWorking(root, c)).added).toEqual(["src/b.txt"]);
106
+ });
107
+
108
+ it("diffs lines", () => {
109
+ const d = unifiedDiff("a\nb\nc\n", "a\nB\nc\n", "f");
110
+ expect(d).toContain("@@ -1,4 +1,4 @@");
111
+ expect(d).toContain("-b");
112
+ expect(d).toContain("+B");
72
113
  });
73
114
  });