ghcr-cleanup-manager-visualizer 1.1.2 → 1.1.4

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
@@ -15,8 +15,8 @@ Download the test scenario DB from the latest release and try the visualizer wit
15
15
  The DB contains dozens of scenario packages with different graphs and before/after views of cleanup operations on them.
16
16
 
17
17
  ```sh
18
- curl -LO https://github.com/ghcr-manager/ghcr-cleanup-manager/releases/latest/download/ghcr-cleanup-manager([^/s]*.sqlite)
19
- npx ghcr-cleanup-manager-visualizer --db ./ghcr-cleanup-manager([^/s]*.sqlite)
18
+ curl -LO https://github.com/ghcr-manager/ghcr-cleanup-manager/releases/latest/download/ghcr-cleanup-manager-release-scenarios.sqlite
19
+ npx ghcr-cleanup-manager-visualizer --db ./ghcr-cleanup-manager-release-scenarios.sqlite
20
20
  ```
21
21
 
22
22
  Or run the release image:
@@ -24,8 +24,8 @@ Or run the release image:
24
24
  ```sh
25
25
  docker run --rm -p 8080:8080 \
26
26
  -v "$PWD:/data:ro" \
27
- ghcr.io/ghcr-manager/ghcr-manager-visualizer:latest \
28
- --db /data/ghcr-cleanup-manager([^/s]*.sqlite)
27
+ ghcr.io/ghcr-manager/ghcr-cleanup-manager-visualizer:latest \
28
+ --db /data/ghcr-cleanup-manager-release-scenarios.sqlite
29
29
  ```
30
30
 
31
31
  Open the local URL printed by the command and select:
@@ -79,7 +79,7 @@ Example:
79
79
  ```sh
80
80
  docker run --rm -p 8080:8080 \
81
81
  -v "$PWD:/data:ro" \
82
- ghcr.io/ghcr-manager/ghcr-manager-visualizer:v1.0.6 \
82
+ ghcr.io/ghcr-manager/ghcr-cleanup-manager-visualizer:v1.1.3 \
83
83
  --db /data/acme__demo.sqlite
84
84
  ```
85
85
 
@@ -349,6 +349,9 @@ function buildNodeLabel(node) {
349
349
 
350
350
  if (node.tags.length > 0) {
351
351
  for (const tag of node.tags) {
352
+ if (tag.isDigestTag) {
353
+ continue;
354
+ }
352
355
  secondaryLines.push(`tag: ${buildTagDisplayText(tag)}`);
353
356
  }
354
357
  } else {
@@ -785,7 +788,15 @@ function renderTagList(container, tags) {
785
788
  }
786
789
 
787
790
  container.classList.add("tag-list");
788
- for (const tag of tags) {
791
+ const orderedTags = [...tags].sort((left, right) => {
792
+ if (left.isDigestTag !== right.isDigestTag) {
793
+ return left.isDigestTag ? 1 : -1;
794
+ }
795
+
796
+ return left.name.localeCompare(right.name);
797
+ });
798
+
799
+ for (const tag of orderedTags) {
789
800
  const tagElement = document.createElement("span");
790
801
  tagElement.className = `tag ${tag.changeStatus}`;
791
802
  tagElement.textContent = buildTagDisplayText(tag);
@@ -286,7 +286,8 @@ export class GraphRepository {
286
286
  manifest.artifact_type,
287
287
  manifest.subject_digest,
288
288
  ${payloadColumn} AS raw_json,
289
- tag.tag
289
+ tag.tag,
290
+ tag.is_digest_tag
290
291
  FROM manifests manifest
291
292
  JOIN package_versions package_version
292
293
  ON package_version.scan_id = manifest.scan_id
@@ -297,7 +298,6 @@ export class GraphRepository {
297
298
  LEFT JOIN tags tag
298
299
  ON tag.scan_id = manifest.scan_id
299
300
  AND tag.version_id = manifest.version_id
300
- AND tag.is_digest_tag = 0
301
301
  LEFT JOIN ranked_platforms platform
302
302
  ON platform.scan_id = manifest.scan_id
303
303
  AND platform.child_digest = manifest.digest
@@ -344,21 +344,25 @@ export class GraphRepository {
344
344
  tags = new Map();
345
345
  tagsByDigest.set(row.digest, tags);
346
346
  }
347
- let tagScans = tags.get(row.tag);
348
- if (!tagScans) {
349
- tagScans = new Set();
350
- tags.set(row.tag, tagScans);
347
+ let tagEntry = tags.get(row.tag);
348
+ if (!tagEntry) {
349
+ tagEntry = {
350
+ isDigestTag: row.is_digest_tag === 1,
351
+ scanIds: new Set()
352
+ };
353
+ tags.set(row.tag, tagEntry);
351
354
  }
352
- tagScans.add(row.scan_id);
355
+ tagEntry.scanIds.add(row.scan_id);
353
356
  }
354
357
  }
355
358
  for (const [digest, manifest] of manifests) {
356
359
  const tagMap = tagsByDigest.get(digest) ?? new Map();
357
360
  manifest.changeStatus = _resolveChangeStatus(scanMemberships.get(digest) ?? new Set(), newerScanId, olderScanId);
358
361
  manifest.tags = [...tagMap.entries()]
359
- .map(([name, tagScans]) => ({
362
+ .map(([name, tagEntry]) => ({
360
363
  name,
361
- changeStatus: _resolveChangeStatus(tagScans, newerScanId, olderScanId)
364
+ isDigestTag: tagEntry.isDigestTag,
365
+ changeStatus: _resolveChangeStatus(tagEntry.scanIds, newerScanId, olderScanId)
362
366
  }))
363
367
  .sort((left, right) => left.name.localeCompare(right.name));
364
368
  }
@@ -15,6 +15,7 @@ export interface TagOption {
15
15
  }
16
16
  export interface GraphTag {
17
17
  name: string;
18
+ isDigestTag: boolean;
18
19
  changeStatus: ChangeStatus;
19
20
  }
20
21
  export interface GraphNode {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "ghcr-cleanup-manager-visualizer",
3
3
  "description": "Inspect GHCR Cleanup Manager SQLite scan databases in a local browser graph visualizer.",
4
4
  "homepage": "https://github.com/ghcr-manager/ghcr-cleanup-manager#readme",
5
- "version": "v1.1.2",
5
+ "version": "v1.1.4",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
8
  "keywords": [