lula2 0.0.1 → 0.0.2

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.
package/README.md CHANGED
@@ -9,19 +9,4 @@
9
9
  > OWNER=defenseunicorns REPO=on-demand-compliance PULL_NUMBER=24 GITHUB_TOKEN=asdf npx tsx src/index.ts crawl
10
10
  Commenting on file1.ts: **Compliance Alert**: `file1.ts` changed between lines 9–16.
11
11
  UUID `123e4567-e89b-12d3-a456-426614174001` may be out of compliance. Please review.
12
- POST /repos/defenseunicorns/on-demand-compliance/pulls/24/reviews - 422 with id D2F8:C840C:48C6221:933C86B:6890F9BC in 452ms
13
- Error processing file1.ts: HttpError: Unprocessable Entity: "Can not request changes on your own pull request" - https://docs.github.com/rest/pulls/reviews#create-a-review-for-a-pull-request
14
- Commenting on file1.yaml: **Compliance Alert**: `file1.yaml` changed between lines 16–18.
15
- UUID `123e4567-e89b-12d3-a456-426614174000` may be out of compliance. Please review.
16
- POST /repos/defenseunicorns/on-demand-compliance/pulls/24/reviews - 422 with id D2F8:C840C:48C656D:933CF0C:6890F9BC in 405ms
17
- Error processing file1.yaml: HttpError: Unprocessable Entity: "Can not request changes on your own pull request" - https://docs.github.com/rest/pulls/reviews#create-a-review-for-a-pull-request
18
-
19
-
20
-
21
- ┌─[cmwylie19@C2WY6FCQVX] - [~/compliance-cli] - [2025-08-04 02:19:41]
22
- └─[0] <git:(2 23e3aad) > OWNER=defenseunicorns REPO=on-demand-compliance PULL_NUMBER=24 GITHUB_TOKEN=asdf npx tsx src/index.ts crawl
23
- Commenting on file1.ts: **Compliance Alert**: `file1.ts` changed between lines 9–16.
24
- UUID `123e4567-e89b-12d3-a456-426614174001` may be out of compliance. Please review.
25
- Commenting on file1.yaml: **Compliance Alert**: `file1.yaml` changed between lines 16–18.
26
- UUID `123e4567-e89b-12d3-a456-426614174000` may be out of compliance. Please review.
27
12
  ```
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controls/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;CAmBnB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controls/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;CAgBnB,CAAC"}
package/dist/crawl.d.ts CHANGED
@@ -1,3 +1,62 @@
1
+ import { Octokit } from "@octokit/rest";
1
2
  import { Command } from "commander";
3
+ /**
4
+ * Get the pull request context from the environment or GitHub event payload.
5
+ *
6
+ * @returns The pull request context containing the owner, repo, and pull number.
7
+ */
8
+ export declare function getPRContext(): {
9
+ owner: string;
10
+ repo: string;
11
+ pull_number: number;
12
+ };
13
+ /**
14
+ * Fetch a raw file from a GitHub repository via the GitHub API.
15
+ *
16
+ * @param params - The parameters.
17
+ * @param params.octokit - An authenticated Octokit instance.
18
+ * @param params.owner - The owner of the repository.
19
+ * @param params.repo - The name of the repository.
20
+ * @param params.path - The path to the file in the repository.
21
+ * @param params.ref - The git reference (branch, tag, or commit SHA).
22
+ * @returns The content of the file as a string.
23
+ */
24
+ export declare function fetchRawFileViaAPI({ octokit, owner, repo, path, ref, }: {
25
+ octokit: Octokit;
26
+ owner: string;
27
+ repo: string;
28
+ path: string;
29
+ ref: string;
30
+ }): Promise<string>;
31
+ /**
32
+ * Extracts all @mapStart and @mapEnd blocks from the given content.
33
+ *
34
+ * @param content - The content to extract blocks from.
35
+ *
36
+ * @returns An array of objects containing the UUID, start line, and end line of each block.
37
+ */
38
+ export declare function extractMapBlocks(content: string): {
39
+ uuid: string;
40
+ startLine: number;
41
+ endLine: number;
42
+ }[];
43
+ /**
44
+ * Get the changed blocks between two versions of text.
45
+ *
46
+ * @param oldText The original text.
47
+ * @param newText The modified text.
48
+ *
49
+ * @returns An array of objects representing the changed blocks.
50
+ */
51
+ export declare function getChangedBlocks(oldText: string, newText: string): {
52
+ uuid: string;
53
+ startLine: number;
54
+ endLine: number;
55
+ }[];
56
+ /**
57
+ * Defines the "crawl" command for the CLI.
58
+ *
59
+ * @returns The configured Command instance.
60
+ */
2
61
  export default function (): Command;
3
62
  //# sourceMappingURL=crawl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAwGnC,MAAM,CAAC,OAAO,cAAc,OAAO,CA6ClC"}
1
+ {"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC;;;;GAIG;AACH,wBAAgB,YAAY,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAsBnF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,OAAO,EACP,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BlB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,EAAE,CA0BF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd;IACD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,EAAE,CAkBF;AACD;;;;GAIG;AACH,MAAM,CAAC,OAAO,cAAc,OAAO,CA6ClC"}
package/dist/crawl.js CHANGED
@@ -1,7 +1,14 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2025-Present The Lula2 Authors
1
3
  import fs from "fs";
2
4
  import { Octokit } from "@octokit/rest";
3
5
  import { Command } from "commander";
4
- function getPRContext() {
6
+ /**
7
+ * Get the pull request context from the environment or GitHub event payload.
8
+ *
9
+ * @returns The pull request context containing the owner, repo, and pull number.
10
+ */
11
+ export function getPRContext() {
5
12
  const fallbackOwner = process.env.OWNER;
6
13
  const fallbackRepo = process.env.REPO;
7
14
  const fallbackNumber = process.env.PULL_NUMBER;
@@ -22,7 +29,18 @@ function getPRContext() {
22
29
  pull_number: parseInt(fallbackNumber, 10),
23
30
  };
24
31
  }
25
- async function fetchRawFileViaAPI(octokit, owner, repo, path, ref) {
32
+ /**
33
+ * Fetch a raw file from a GitHub repository via the GitHub API.
34
+ *
35
+ * @param params - The parameters.
36
+ * @param params.octokit - An authenticated Octokit instance.
37
+ * @param params.owner - The owner of the repository.
38
+ * @param params.repo - The name of the repository.
39
+ * @param params.path - The path to the file in the repository.
40
+ * @param params.ref - The git reference (branch, tag, or commit SHA).
41
+ * @returns The content of the file as a string.
42
+ */
43
+ export async function fetchRawFileViaAPI({ octokit, owner, repo, path, ref, }) {
26
44
  const res = await octokit.repos.getContent({
27
45
  owner,
28
46
  repo,
@@ -32,11 +50,26 @@ async function fetchRawFileViaAPI(octokit, owner, repo, path, ref) {
32
50
  accept: "application/vnd.github.v3.raw",
33
51
  },
34
52
  });
35
- return typeof res.data === "string"
36
- ? res.data
37
- : Buffer.from(res.data.content, "base64").toString("utf-8");
53
+ if (typeof res.data === "string") {
54
+ return res.data;
55
+ }
56
+ if (typeof res.data === "object" &&
57
+ res.data !== null &&
58
+ "content" in res.data &&
59
+ typeof res.data.content === "string") {
60
+ const { content } = res.data;
61
+ return Buffer.from(content, "base64").toString("utf-8");
62
+ }
63
+ throw new Error("Unexpected GitHub API response shape");
38
64
  }
39
- function extractMapBlocks(content) {
65
+ /**
66
+ * Extracts all @mapStart and @mapEnd blocks from the given content.
67
+ *
68
+ * @param content - The content to extract blocks from.
69
+ *
70
+ * @returns An array of objects containing the UUID, start line, and end line of each block.
71
+ */
72
+ export function extractMapBlocks(content) {
40
73
  const lines = content.split("\n");
41
74
  const blocks = [];
42
75
  const stack = [];
@@ -56,7 +89,15 @@ function extractMapBlocks(content) {
56
89
  });
57
90
  return blocks;
58
91
  }
59
- function getChangedBlocks(oldText, newText) {
92
+ /**
93
+ * Get the changed blocks between two versions of text.
94
+ *
95
+ * @param oldText The original text.
96
+ * @param newText The modified text.
97
+ *
98
+ * @returns An array of objects representing the changed blocks.
99
+ */
100
+ export function getChangedBlocks(oldText, newText) {
60
101
  const oldBlocks = extractMapBlocks(oldText);
61
102
  const newBlocks = extractMapBlocks(newText);
62
103
  const changed = [];
@@ -72,6 +113,11 @@ function getChangedBlocks(oldText, newText) {
72
113
  }
73
114
  return changed;
74
115
  }
116
+ /**
117
+ * Defines the "crawl" command for the CLI.
118
+ *
119
+ * @returns The configured Command instance.
120
+ */
75
121
  export default function () {
76
122
  return new Command()
77
123
  .command("crawl")
@@ -87,8 +133,8 @@ export default function () {
87
133
  continue;
88
134
  try {
89
135
  const [oldText, newText] = await Promise.all([
90
- fetchRawFileViaAPI(octokit, owner, repo, file.filename, "main"),
91
- fetchRawFileViaAPI(octokit, owner, repo, file.filename, prBranch),
136
+ fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: "main" }),
137
+ fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: prBranch }),
92
138
  ]);
93
139
  const changedBlocks = getChangedBlocks(oldText, newText);
94
140
  for (const block of changedBlocks) {
@@ -105,7 +151,7 @@ export default function () {
105
151
  // repo,
106
152
  // pull_number,
107
153
  // body: commentBody,
108
- // event: "REQUEST_CHANGES",
154
+ // event: "REQUEST_CHANGES",
109
155
  // })
110
156
  }
111
157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lula2",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Reports Reports and exports compliance status for defined controls.",
5
5
  "bin": "./dist/index.js",
6
6
  "main": "dist/index.js",
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "git+https://github.com/defenseunicorns/lula2.git"
14
+ "url": "git+https://github.com/defenseunicorns/lula-next.git"
15
15
  },
16
16
  "keywords": [
17
17
  "compliance",
@@ -21,9 +21,9 @@
21
21
  "author": "Defense Unicorns",
22
22
  "license": "Apache-2.0",
23
23
  "bugs": {
24
- "url": "https://github.com/defenseunicorns/lula2/issues"
24
+ "url": "https://github.com/defenseunicorns/lula-next/issues"
25
25
  },
26
- "homepage": "https://github.com/defenseunicorns/lula2#readme",
26
+ "homepage": "https://github.com/defenseunicorns/lula-next#readme",
27
27
  "files": [
28
28
  "/src",
29
29
  "/dist",
@@ -35,9 +35,10 @@
35
35
  "prebuild": "rm -rf dist",
36
36
  "build": "tsc",
37
37
  "semantic-release": "semantic-release",
38
- "format:check": "eslint src e2e && prettier . --check",
39
- "format:fix": "eslint --fix src e2e && prettier . --write",
40
- "prepare": "if [ \"$NODE_ENV\" != 'production' ]; then husky; fi"
38
+ "format:check": "eslint src && prettier . --check",
39
+ "format:fix": "eslint --fix src && prettier . --write",
40
+ "prepare": "if [ \"$NODE_ENV\" != 'production' ]; then husky; fi",
41
+ "test": "vitest run --coverage"
41
42
  },
42
43
  "dependencies": {
43
44
  "@octokit/rest": "^22.0.0",
@@ -55,6 +56,7 @@
55
56
  "esbuild": "^0.25.1",
56
57
  "eslint": "^9.26.0",
57
58
  "eslint-config-prettier": "^10.0.2",
59
+ "eslint-plugin-jsdoc": "^54.1.1",
58
60
  "globals": "^16.0.0",
59
61
  "husky": "^9.1.7",
60
62
  "prettier": "3.5.3",
@@ -1,22 +1,19 @@
1
- import { registerControls } from "compliance-reporter"
1
+ import { registerControls } from "compliance-reporter";
2
2
 
3
3
  export const controls = registerControls({
4
4
  "123e4567-e89b-12d3-a456-426614174001": {
5
5
  id: "AC-1",
6
6
  description: "Restrict Pods running as root",
7
- remarks:
8
- "This control ensures that no Pods are allowed to run as the root user.",
7
+ remarks: "This control ensures that no Pods are allowed to run as the root user.",
9
8
  },
10
9
  "123e4567-e89b-12d3-a456-426614174002": {
11
10
  id: "AC-2",
12
11
  description: "Restrict Pods running privileged containers",
13
- remarks:
14
- "This control ensures that no Pods are allowed to run as privileged containers.",
12
+ remarks: "This control ensures that no Pods are allowed to run as privileged containers.",
15
13
  },
16
14
  "123e4567-e89b-12d3-a456-426614174003": {
17
15
  id: "AC-3",
18
16
  description: "Restrict Pods running as root",
19
- remarks:
20
- "This control ensures that no Pods are allowed to run as the root user.",
17
+ remarks: "This control ensures that no Pods are allowed to run as the root user.",
21
18
  },
22
- })
19
+ });
package/src/crawl.ts CHANGED
@@ -1,38 +1,68 @@
1
- import fs from "fs"
2
- import { Octokit } from "@octokit/rest"
3
- import { Command } from "commander"
4
-
5
- function getPRContext(): { owner: string; repo: string; pull_number: number } {
6
- const fallbackOwner = process.env.OWNER
7
- const fallbackRepo = process.env.REPO
8
- const fallbackNumber = process.env.PULL_NUMBER
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2025-Present The Lula2 Authors
3
+
4
+ import fs from "fs";
5
+ import { Octokit } from "@octokit/rest";
6
+ import { Command } from "commander";
7
+
8
+ type FileContentResponse = {
9
+ content: string;
10
+ encoding: "base64" | string;
11
+ };
12
+
13
+ /**
14
+ * Get the pull request context from the environment or GitHub event payload.
15
+ *
16
+ * @returns The pull request context containing the owner, repo, and pull number.
17
+ */
18
+ export function getPRContext(): { owner: string; repo: string; pull_number: number } {
19
+ const fallbackOwner = process.env.OWNER;
20
+ const fallbackRepo = process.env.REPO;
21
+ const fallbackNumber = process.env.PULL_NUMBER;
9
22
 
10
23
  if (process.env.GITHUB_EVENT_PATH && process.env.GITHUB_REPOSITORY) {
11
- const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"))
12
- const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/")
13
- const pull_number = event.pull_request?.number
14
- if (!pull_number) throw new Error("PR number not found in GitHub event payload.")
15
- return { owner, repo, pull_number }
24
+ const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"));
25
+ const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
26
+ const pull_number = event.pull_request?.number;
27
+ if (!pull_number) throw new Error("PR number not found in GitHub event payload.");
28
+ return { owner, repo, pull_number };
16
29
  }
17
30
 
18
31
  if (!fallbackOwner || !fallbackRepo || !fallbackNumber) {
19
- throw new Error("Set OWNER, REPO, and PULL_NUMBER in the environment for local use.")
32
+ throw new Error("Set OWNER, REPO, and PULL_NUMBER in the environment for local use.");
20
33
  }
21
34
 
22
35
  return {
23
36
  owner: fallbackOwner,
24
37
  repo: fallbackRepo,
25
38
  pull_number: parseInt(fallbackNumber, 10),
26
- }
39
+ };
27
40
  }
28
41
 
29
- async function fetchRawFileViaAPI(
30
- octokit: Octokit,
31
- owner: string,
32
- repo: string,
33
- path: string,
34
- ref: string
35
- ): Promise<string> {
42
+ /**
43
+ * Fetch a raw file from a GitHub repository via the GitHub API.
44
+ *
45
+ * @param params - The parameters.
46
+ * @param params.octokit - An authenticated Octokit instance.
47
+ * @param params.owner - The owner of the repository.
48
+ * @param params.repo - The name of the repository.
49
+ * @param params.path - The path to the file in the repository.
50
+ * @param params.ref - The git reference (branch, tag, or commit SHA).
51
+ * @returns The content of the file as a string.
52
+ */
53
+ export async function fetchRawFileViaAPI({
54
+ octokit,
55
+ owner,
56
+ repo,
57
+ path,
58
+ ref,
59
+ }: {
60
+ octokit: Octokit;
61
+ owner: string;
62
+ repo: string;
63
+ path: string;
64
+ ref: string;
65
+ }): Promise<string> {
36
66
  const res = await octokit.repos.getContent({
37
67
  owner,
38
68
  repo,
@@ -41,112 +71,146 @@ async function fetchRawFileViaAPI(
41
71
  headers: {
42
72
  accept: "application/vnd.github.v3.raw",
43
73
  },
44
- })
74
+ });
75
+
76
+ if (typeof res.data === "string") {
77
+ return res.data;
78
+ }
45
79
 
46
- return typeof res.data === "string"
47
- ? res.data
48
- : Buffer.from((res.data as any).content, "base64").toString("utf-8")
80
+ if (
81
+ typeof res.data === "object" &&
82
+ res.data !== null &&
83
+ "content" in res.data &&
84
+ typeof (res.data as { content: unknown }).content === "string"
85
+ ) {
86
+ const { content } = res.data as FileContentResponse;
87
+ return Buffer.from(content, "base64").toString("utf-8");
88
+ }
89
+
90
+ throw new Error("Unexpected GitHub API response shape");
49
91
  }
50
92
 
51
- function extractMapBlocks(content: string): {
52
- uuid: string
53
- startLine: number
54
- endLine: number
93
+ /**
94
+ * Extracts all @mapStart and @mapEnd blocks from the given content.
95
+ *
96
+ * @param content - The content to extract blocks from.
97
+ *
98
+ * @returns An array of objects containing the UUID, start line, and end line of each block.
99
+ */
100
+ export function extractMapBlocks(content: string): {
101
+ uuid: string;
102
+ startLine: number;
103
+ endLine: number;
55
104
  }[] {
56
- const lines = content.split("\n")
105
+ const lines = content.split("\n");
57
106
  interface MapBlock {
58
- uuid: string
59
- startLine: number
60
- endLine: number
107
+ uuid: string;
108
+ startLine: number;
109
+ endLine: number;
61
110
  }
62
- const blocks: MapBlock[] = []
63
- const stack: { uuid: string; line: number }[] = []
111
+ const blocks: MapBlock[] = [];
112
+ const stack: { uuid: string; line: number }[] = [];
64
113
 
65
114
  lines.forEach((line, idx) => {
66
- const start = line.match(/@mapStart\s+([a-f0-9-]+)/)
67
- const end = line.match(/@mapEnd\s+([a-f0-9-]+)/)
115
+ const start = line.match(/@mapStart\s+([a-f0-9-]+)/);
116
+ const end = line.match(/@mapEnd\s+([a-f0-9-]+)/);
68
117
 
69
118
  if (start) {
70
- stack.push({ uuid: start[1], line: idx })
119
+ stack.push({ uuid: start[1], line: idx });
71
120
  } else if (end) {
72
- const last = stack.find(s => s.uuid === end[1])
121
+ const last = stack.find(s => s.uuid === end[1]);
73
122
  if (last) {
74
- blocks.push({ uuid: last.uuid, startLine: last.line, endLine: idx + 1 })
75
- stack.splice(stack.indexOf(last), 1)
123
+ blocks.push({ uuid: last.uuid, startLine: last.line, endLine: idx + 1 });
124
+ stack.splice(stack.indexOf(last), 1);
76
125
  }
77
126
  }
78
- })
127
+ });
79
128
 
80
- return blocks
129
+ return blocks;
81
130
  }
82
131
 
83
- function getChangedBlocks(oldText: string, newText: string): {
84
- uuid: string
85
- startLine: number
86
- endLine: number
132
+ /**
133
+ * Get the changed blocks between two versions of text.
134
+ *
135
+ * @param oldText The original text.
136
+ * @param newText The modified text.
137
+ *
138
+ * @returns An array of objects representing the changed blocks.
139
+ */
140
+ export function getChangedBlocks(
141
+ oldText: string,
142
+ newText: string,
143
+ ): {
144
+ uuid: string;
145
+ startLine: number;
146
+ endLine: number;
87
147
  }[] {
88
- const oldBlocks = extractMapBlocks(oldText)
89
- const newBlocks = extractMapBlocks(newText)
90
- const changed = []
148
+ const oldBlocks = extractMapBlocks(oldText);
149
+ const newBlocks = extractMapBlocks(newText);
150
+ const changed = [];
91
151
 
92
152
  for (const newBlock of newBlocks) {
93
- const oldMatch = oldBlocks.find(b => b.uuid === newBlock.uuid)
94
- if (!oldMatch) continue
153
+ const oldMatch = oldBlocks.find(b => b.uuid === newBlock.uuid);
154
+ if (!oldMatch) continue;
95
155
 
96
- const oldSegment = oldText.split("\n").slice(oldMatch.startLine, oldMatch.endLine).join("\n")
97
- const newSegment = newText.split("\n").slice(newBlock.startLine, newBlock.endLine).join("\n")
156
+ const oldSegment = oldText.split("\n").slice(oldMatch.startLine, oldMatch.endLine).join("\n");
157
+ const newSegment = newText.split("\n").slice(newBlock.startLine, newBlock.endLine).join("\n");
98
158
 
99
159
  if (oldSegment !== newSegment) {
100
- changed.push(newBlock)
160
+ changed.push(newBlock);
101
161
  }
102
162
  }
103
163
 
104
- return changed
164
+ return changed;
105
165
  }
106
-
166
+ /**
167
+ * Defines the "crawl" command for the CLI.
168
+ *
169
+ * @returns The configured Command instance.
170
+ */
107
171
  export default function (): Command {
108
172
  return new Command()
109
173
  .command("crawl")
110
174
  .description("Detect compliance-related changes between @mapStart and @mapEnd in PR files")
111
175
  .action(async () => {
112
- const { owner, repo, pull_number } = getPRContext()
113
- const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN })
176
+ const { owner, repo, pull_number } = getPRContext();
177
+ const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
114
178
 
115
- const pr = await octokit.pulls.get({ owner, repo, pull_number })
116
- const prBranch = pr.data.head.ref
179
+ const pr = await octokit.pulls.get({ owner, repo, pull_number });
180
+ const prBranch = pr.data.head.ref;
117
181
 
118
- const { data: files } = await octokit.pulls.listFiles({ owner, repo, pull_number })
182
+ const { data: files } = await octokit.pulls.listFiles({ owner, repo, pull_number });
119
183
 
120
184
  for (const file of files) {
121
- if (file.status === "added") continue
185
+ if (file.status === "added") continue;
122
186
  try {
123
187
  const [oldText, newText] = await Promise.all([
124
- fetchRawFileViaAPI(octokit, owner, repo, file.filename, "main"),
125
- fetchRawFileViaAPI(octokit, owner, repo, file.filename, prBranch),
126
- ])
188
+ fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: "main" }),
189
+ fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: prBranch }),
190
+ ]);
127
191
 
128
- const changedBlocks = getChangedBlocks(oldText, newText)
192
+ const changedBlocks = getChangedBlocks(oldText, newText);
129
193
 
130
194
  for (const block of changedBlocks) {
131
- const commentBody = `**Compliance Alert**: \`${file.filename}\` changed between lines ${block.startLine + 1}–${block.endLine}.\nUUID \`${block.uuid}\` may be out of compliance. Please review.`
132
- console.log(`Commenting on ${file.filename}: ${commentBody}`)
195
+ const commentBody = `**Compliance Alert**: \`${file.filename}\` changed between lines ${block.startLine + 1}–${block.endLine}.\nUUID \`${block.uuid}\` may be out of compliance. Please review.`;
196
+ console.log(`Commenting on ${file.filename}: ${commentBody}`);
133
197
  await octokit.issues.createComment({
134
198
  owner,
135
199
  repo,
136
200
  issue_number: pull_number,
137
201
  body: commentBody,
138
- })
139
- // await octokit.pulls.createReview({
140
- // owner,
141
- // repo,
142
- // pull_number,
143
- // body: commentBody,
144
- // event: "REQUEST_CHANGES",
145
- // })
202
+ });
203
+ // await octokit.pulls.createReview({
204
+ // owner,
205
+ // repo,
206
+ // pull_number,
207
+ // body: commentBody,
208
+ // event: "REQUEST_CHANGES",
209
+ // })
146
210
  }
147
211
  } catch (err) {
148
- console.error(`Error processing ${file.filename}: ${err}`)
212
+ console.error(`Error processing ${file.filename}: ${err}`);
149
213
  }
150
214
  }
151
- })
215
+ });
152
216
  }
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { Command } from "commander"
4
- import crawl from "./crawl.js"
3
+ import { Command } from "commander";
4
+ import crawl from "./crawl.js";
5
5
  // Define the program
6
- const program = new Command()
6
+ const program = new Command();
7
7
 
8
8
  // Set basic information
9
9
  program
@@ -12,18 +12,18 @@ program
12
12
  .option("-c, --config <path>", "path to config file", "compliance.json")
13
13
  .addCommand(crawl())
14
14
  .action(options => {
15
- console.log("Checking compliance status...")
15
+ console.log("Checking compliance status...");
16
16
  if (options.config) {
17
- console.log(`Using config file: ${options.config}`)
17
+ console.log(`Using config file: ${options.config}`);
18
18
  } else {
19
- console.log("Using default configuration")
19
+ console.log("Using default configuration");
20
20
  }
21
- console.log("Compliance check completed!")
22
- })
21
+ console.log("Compliance check completed!");
22
+ });
23
23
 
24
- program.parse(process.argv)
24
+ program.parse(process.argv);
25
25
 
26
26
  // If no command is provided, show help
27
27
  if (!process.argv.slice(1).length) {
28
- program.help()
28
+ program.help();
29
29
  }