code-provenance 0.1.3 → 0.1.5

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
@@ -27,11 +27,12 @@ npx code-provenance docker-compose.yml
27
27
  ```
28
28
 
29
29
  ```
30
- ┌─────────┬────────────────┬────────────────────────────┬──────────────┬──────────┬────────────┐
31
- │ SERVICE │ IMAGE │ REPO │ COMMIT │ STATUS │ CONFIDENCE │
32
- ├─────────┼────────────────┼────────────────────────────┼──────────────┼──────────┼────────────┤
33
- │ web │ traefik:v3.6.0 │ github.com/traefik/traefik │ 06db5168c0d9 │ resolved │ exact │
34
- └─────────┴────────────────┴────────────────────────────┴──────────────┴──────────┴────────────┘
30
+ web: traefik:v3.6.0
31
+ repo: github.com/traefik/traefik
32
+ commit: 06db5168c0d9
33
+ status: resolved
34
+ confidence: exact
35
+ url: https://github.com/traefik/traefik/commit/06db5168c0d9...
35
36
  ```
36
37
 
37
38
  ## Library Usage
package/dist/cli.js CHANGED
@@ -37,10 +37,17 @@ async function main() {
37
37
  "Create a token at https://github.com/settings/tokens with read:packages scope.\n");
38
38
  }
39
39
  const yamlContent = readFileSync(composeFile, "utf-8");
40
- const services = parseCompose(yamlContent);
40
+ let services;
41
+ try {
42
+ services = parseCompose(yamlContent);
43
+ }
44
+ catch (err) {
45
+ console.error(`Error: failed to parse ${composeFile} — ${err instanceof Error ? err.message : err}`);
46
+ return 1;
47
+ }
41
48
  if (services.length === 0) {
42
- console.error("No services with images found.");
43
- return 0;
49
+ console.error("No services with images found. Is this a valid docker-compose file?");
50
+ return 1;
44
51
  }
45
52
  // Resolve all images in parallel
46
53
  const results = await Promise.all(services.map(([serviceName, imageString]) => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -6,11 +6,21 @@ export function parseImageRef(imageString) {
6
6
  const raw = imageString;
7
7
  let tag;
8
8
  let namePart;
9
- // Handle digest references (image@sha256:...)
9
+ // Handle digest references (image@sha256:... or image:tag@sha256:...)
10
10
  if (imageString.includes("@")) {
11
11
  const atIdx = imageString.indexOf("@");
12
12
  namePart = imageString.slice(0, atIdx);
13
- tag = imageString.slice(atIdx + 1);
13
+ const digest = imageString.slice(atIdx + 1);
14
+ // Check if there's a tag before the digest (image:tag@sha256:...)
15
+ const lastSegment = namePart.split("/").pop();
16
+ if (lastSegment.includes(":")) {
17
+ const colonPos = namePart.lastIndexOf(":");
18
+ tag = namePart.slice(colonPos + 1);
19
+ namePart = namePart.slice(0, colonPos);
20
+ }
21
+ else {
22
+ tag = digest;
23
+ }
14
24
  }
15
25
  else {
16
26
  const lastSegment = imageString.split("/").pop();
@@ -1 +1 @@
1
- {"version":3,"file":"composeParser.js","sourceRoot":"","sources":["../src/composeParser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"composeParser.js","sourceRoot":"","sources":["../src/composeParser.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-provenance",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Resolve Docker images to their source code commits on GitHub",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/cli.ts CHANGED
@@ -47,11 +47,18 @@ async function main(): Promise<number> {
47
47
  }
48
48
 
49
49
  const yamlContent = readFileSync(composeFile, "utf-8");
50
- const services = parseCompose(yamlContent);
50
+
51
+ let services: Array<[string, string]>;
52
+ try {
53
+ services = parseCompose(yamlContent);
54
+ } catch (err) {
55
+ console.error(`Error: failed to parse ${composeFile} — ${err instanceof Error ? err.message : err}`);
56
+ return 1;
57
+ }
51
58
 
52
59
  if (services.length === 0) {
53
- console.error("No services with images found.");
54
- return 0;
60
+ console.error("No services with images found. Is this a valid docker-compose file?");
61
+ return 1;
55
62
  }
56
63
 
57
64
  // Resolve all images in parallel
@@ -9,11 +9,20 @@ export function parseImageRef(imageString: string): ImageRef {
9
9
  let tag: string;
10
10
  let namePart: string;
11
11
 
12
- // Handle digest references (image@sha256:...)
12
+ // Handle digest references (image@sha256:... or image:tag@sha256:...)
13
13
  if (imageString.includes("@")) {
14
14
  const atIdx = imageString.indexOf("@");
15
15
  namePart = imageString.slice(0, atIdx);
16
- tag = imageString.slice(atIdx + 1);
16
+ const digest = imageString.slice(atIdx + 1);
17
+ // Check if there's a tag before the digest (image:tag@sha256:...)
18
+ const lastSegment = namePart.split("/").pop()!;
19
+ if (lastSegment.includes(":")) {
20
+ const colonPos = namePart.lastIndexOf(":");
21
+ tag = namePart.slice(colonPos + 1);
22
+ namePart = namePart.slice(0, colonPos);
23
+ } else {
24
+ tag = digest;
25
+ }
17
26
  } else {
18
27
  const lastSegment = imageString.split("/").pop()!;
19
28
  if (lastSegment.includes(":")) {