diff --git a/.github/workflows/dependency-submission/.gitignore b/.github/workflows/cosmic-detector/.gitignore similarity index 100% rename from .github/workflows/dependency-submission/.gitignore rename to .github/workflows/cosmic-detector/.gitignore diff --git a/.github/workflows/dependency-submission/action.yml b/.github/workflows/cosmic-detector/action.yml similarity index 90% rename from .github/workflows/dependency-submission/action.yml rename to .github/workflows/cosmic-detector/action.yml index fd1f8b1..2d73b71 100644 --- a/.github/workflows/dependency-submission/action.yml +++ b/.github/workflows/cosmic-detector/action.yml @@ -1,4 +1,4 @@ -name: "Cosmic Dependency Submission Action" +name: "Cosmic Dependency Detection Action" description: "Action using the dependency-submission-toolkit" inputs: token: diff --git a/.github/workflows/dependency-submission/cosmic-detector.test.ts b/.github/workflows/cosmic-detector/cosmic-detector.test.ts similarity index 67% rename from .github/workflows/dependency-submission/cosmic-detector.test.ts rename to .github/workflows/cosmic-detector/cosmic-detector.test.ts index 46f31dd..490cca4 100644 --- a/.github/workflows/dependency-submission/cosmic-detector.test.ts +++ b/.github/workflows/cosmic-detector/cosmic-detector.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "vitest"; import { parseCosmicPackages, createPackageManifests } from "./cosmic-detector"; import { PackageURL } from "packageurl-js"; -// Define a helper function to simulate a CosmicPackage +// Helper function to simulate a CosmicPackage const createCosmicPackage = () => ({ name: "example-package", url: "https://example.com", @@ -19,10 +19,8 @@ describe("parseCosmicPackages", () => { test("parses single package", () => { const stdout = JSON.stringify(createCosmicPackage()); const result = parseCosmicPackages(stdout); - if (result[0]) { - expect(result).toHaveLength(1); - expect(result[0].name).toBe("example-package"); - } + expect(result).toHaveLength(1); + expect(result[0]?.name).toBe("example-package"); }); test("parses multiple packages", () => { @@ -39,6 +37,16 @@ describe("parseCosmicPackages", () => { const result = parseCosmicPackages(stdout); expect(result).toHaveLength(0); }); + + test("handles mixed valid and invalid JSON", () => { + const stdout = [ + JSON.stringify(createCosmicPackage()), + "invalid-json", + JSON.stringify(createCosmicPackage()), + ].join("---"); + const result = parseCosmicPackages(stdout); + expect(result).toHaveLength(2); + }); }); describe("createPackageManifests", () => { @@ -51,19 +59,22 @@ describe("createPackageManifests", () => { const manifest = manifests[0]; if (manifest) { - expect(manifest.name).toBe(cosmicPackage.name); + expect(manifest?.name).toBe(cosmicPackage.name); const manifestDependencies = manifest.directDependencies(); expect(manifestDependencies).toHaveLength(1); const purl = PackageURL.fromString(cosmicPackage.purl); expect( - manifestDependencies - .map((p) => { - return p.packageURL; - }) - .join(" "), - ).toContain(purl); + manifestDependencies.map((p) => p.packageURL.toString()).join(" "), + ).toContain(purl.toString()); } }); + + test("handles empty package list", () => { + const cosmicPackages: any[] = []; + const manifests = createPackageManifests(cosmicPackages); + + expect(manifests).toHaveLength(0); + }); }); diff --git a/.github/workflows/cosmic-detector/cosmic-detector.ts b/.github/workflows/cosmic-detector/cosmic-detector.ts new file mode 100644 index 0000000..1278a06 --- /dev/null +++ b/.github/workflows/cosmic-detector/cosmic-detector.ts @@ -0,0 +1,115 @@ +import * as core from "@actions/core"; +import * as exec from "@actions/exec"; +import * as glob from "@actions/glob"; +import { + Manifest, + Package, + Snapshot, + submitSnapshot, +} from "@github/dependency-submission-toolkit"; +import { PackageURL } from "packageurl-js"; + +// Type definition for the top-level structure from the output of 'pkl eval' +type CosmicPackage = { + name: string; // Name of the package + url: string; // URL of the package repository + version: string; // Version of the package + hash: string; // Hash of the package + executablePath: string; // Path to the executable + testArgs: string[]; // Arguments for testing the package + type: string; // Type of the package + purl: string; // Package URL in purl format +}; + +/** + * Parses the stdout from the 'pkl eval' command to extract package information. + * @param stdout - The stdout from the 'pkl eval' command. + * @returns An array of CosmicPackage objects. + */ +export function parseCosmicPackages(stdout: string): CosmicPackage[] { + const packages: CosmicPackage[] = []; + + // Split the stdout by the '---' separator + const packageStrings = stdout + .split("---") + .map((pkgStr) => pkgStr.trim()) + .filter((pkgStr) => pkgStr.length > 0); + + // Parse each package string into an object + for (const pkgStr of packageStrings) { + try { + const cosmicPackage = JSON.parse(pkgStr) as CosmicPackage; + packages.push(cosmicPackage); + } catch (error) { + core.error(`Error parsing package: ${error}`); + } + } + + return packages; +} + +/** + * Creates package manifests from an array of CosmicPackage objects. + * @param cosmicPackages - An array of CosmicPackage objects. + * @returns An array of Manifest objects. + */ +export function createPackageManifests( + cosmicPackages: CosmicPackage[], +): Manifest[] { + return cosmicPackages.map((cosmicPackage) => { + const purl = PackageURL.fromString(cosmicPackage.purl); + const pkg = new Package(purl); + const manifest = new Manifest( + cosmicPackage.name, + `Packages/${cosmicPackage.name}.pkl`, + ); + manifest.addDirectDependency(pkg); + return manifest; + }); +} + +/** + * Main function that orchestrates the process of retrieving, parsing, and submitting package information. + */ +export async function main() { + try { + const cosmicPackageDirectory = core.getInput("cosmic-package-directory"); + + const globber = await glob.create(`${cosmicPackageDirectory}/*.pkl`); + const files = await globber.glob(); + + // Ensure there are some .pkl files to process. + if (files.length === 0) { + core.setFailed( + `No .pkl files found in directory: ${cosmicPackageDirectory}`, + ); + return; + } + + const prodPackages = await exec.getExecOutput( + "pkl", + ["eval", "-f", "json", ...files], + { cwd: cosmicPackageDirectory }, + ); + if (prodPackages.exitCode !== 0) { + core.error(prodPackages.stderr); + core.setFailed("'pkl eval' failed!"); + return; + } + const cosmicPackages = parseCosmicPackages(prodPackages.stdout); + const packageManifests = createPackageManifests(cosmicPackages); + const snapshot = new Snapshot({ + name: "cosmic-detector", + url: "https://github.com/willswire/cosmic/tree/main/.github/workflows/cosmic-detector", + version: "0.0.1", + }); + + for (const pm of packageManifests) { + snapshot.addManifest(pm); + } + + submitSnapshot(snapshot); + } catch (error) { + core.setFailed(`Action failed with error: ${error}`); + } +} diff --git a/.github/workflows/dependency-submission/index.ts b/.github/workflows/cosmic-detector/index.ts similarity index 100% rename from .github/workflows/dependency-submission/index.ts rename to .github/workflows/cosmic-detector/index.ts diff --git a/.github/workflows/dependency-submission/package-lock.json b/.github/workflows/cosmic-detector/package-lock.json similarity index 100% rename from .github/workflows/dependency-submission/package-lock.json rename to .github/workflows/cosmic-detector/package-lock.json diff --git a/.github/workflows/dependency-submission/package.json b/.github/workflows/cosmic-detector/package.json similarity index 81% rename from .github/workflows/dependency-submission/package.json rename to .github/workflows/cosmic-detector/package.json index 77b19d4..5b1eb9e 100644 --- a/.github/workflows/dependency-submission/package.json +++ b/.github/workflows/cosmic-detector/package.json @@ -1,7 +1,7 @@ { - "name": "dependency-submission", + "name": "cosmic-detector", "private": true, - "description": "[UNPUBLISHED PACKAGE!] Example using the Dependency Submission Toolkit and npm list", + "version": "0.0.1", "type": "module", "scripts": { "all": "npm run type-check && npm run build && npm run test", diff --git a/.github/workflows/dependency-submission/tsconfig.json b/.github/workflows/cosmic-detector/tsconfig.json similarity index 100% rename from .github/workflows/dependency-submission/tsconfig.json rename to .github/workflows/cosmic-detector/tsconfig.json diff --git a/.github/workflows/dependency-submission/cosmic-detector.ts b/.github/workflows/dependency-submission/cosmic-detector.ts deleted file mode 100644 index 4d96c6c..0000000 --- a/.github/workflows/dependency-submission/cosmic-detector.ts +++ /dev/null @@ -1,96 +0,0 @@ -import * as core from "@actions/core"; -import * as exec from "@actions/exec"; -import * as glob from "@actions/glob"; -import { - Manifest, - Package, - Snapshot, - submitSnapshot, -} from "@github/dependency-submission-toolkit"; -import { PackageURL } from "packageurl-js"; - -// top-level structure from the output of 'npm list' -type CosmicPackage = { - name: string; - url: string; - version: string; - hash: string; - executablePath: string; - testArgs: Array; - type: string; - purl: string; -}; - -export function parseCosmicPackages(stdout: string): CosmicPackage[] { - const packages: CosmicPackage[] = []; - - // Split the stdout by the '---' separator - const packageStrings = stdout - .split("---") - .map((pkgStr) => pkgStr.trim()) - .filter((pkgStr) => pkgStr.length > 0); - - // Parse each package string into an object - for (const pkgStr of packageStrings) { - try { - const cosmicPackage = JSON.parse(pkgStr) as CosmicPackage; - packages.push(cosmicPackage); - } catch (error) { - console.error("Error parsing package:", error); - } - } - - return packages; -} - -export function createPackageManifests( - cosmicPackages: CosmicPackage[], -): Manifest[] { - return cosmicPackages.map((cosmicPackage) => { - const purl = PackageURL.fromString(cosmicPackage.purl); - let pkg = new Package(purl); - let manifest = new Manifest( - cosmicPackage.name, - `Packages/${cosmicPackage.name}.pkl`, - ); - manifest.addDirectDependency(pkg); - return manifest; - }); -} - -// This program uses 'npm list' to provide a list of all production -// (non-development) dependencies and all transitive dependencies. This -// provides transitive relationships unlike package.json, and output can be -// configured to avoid issues present with parsing package-lock.json (such as -// inclusion of workspace packages). This is provided as example to help guide -// development. -export async function main() { - const cosmicPackageDirectory = core.getInput("cosmic-package-directory"); - - const globber = await glob.create(`${cosmicPackageDirectory}/*.pkl`); - const files = await globber.glob(); - - const prodPackages = await exec.getExecOutput( - "pkl", - ["eval", "-f", "json", ...files], - { cwd: cosmicPackageDirectory }, - ); - if (prodPackages.exitCode !== 0) { - core.error(prodPackages.stderr); - core.setFailed("'pkl eval' failed!"); - return; - } - const cosmicPackages = parseCosmicPackages(prodPackages.stdout); - const packageManifests = createPackageManifests(cosmicPackages); - const snapshot = new Snapshot({ - name: "cosmic detector", - url: "https://github.com/willswire/cosmic/tree/main/.github/workflows/dependency-submission", - version: "0.0.1", - }); - - for (const pm of packageManifests) { - snapshot.addManifest(pm); - } - - submitSnapshot(snapshot); -} diff --git a/.github/workflows/dependency-submission.yml b/.github/workflows/detect.yml similarity index 67% rename from .github/workflows/dependency-submission.yml rename to .github/workflows/detect.yml index 266adb4..ce427f9 100644 --- a/.github/workflows/dependency-submission.yml +++ b/.github/workflows/detect.yml @@ -1,9 +1,11 @@ -name: Submit Dependency Snapshot +name: Detect on: workflow_dispatch: pull_request: branches: [main] + push: + branches: [main] env: PKL_VERSION: 0.26.3 @@ -13,8 +15,10 @@ permissions: contents: write jobs: - submit-dependencies: + submit_dependencies: + name: Submit Dependencies runs-on: macos-14 + if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 @@ -30,10 +34,10 @@ jobs: node-version: 20 - name: Install NPM dependencies - run: npm ci --prefix .github/workflows/dependency-submission/ + run: npm ci --prefix .github/workflows/cosmic-detector/ - name: Run all NPM build/test actions - run: npm run all --prefix .github/workflows/dependency-submission/ + run: npm run all --prefix .github/workflows/cosmic-detector/ - name: Run dependency submission - uses: ./.github/workflows/dependency-submission/ + uses: ./.github/workflows/cosmic-detector/ diff --git a/Packages/age.pkl b/Packages/age.pkl index ac9b9f1..5a7a1a4 100644 --- a/Packages/age.pkl +++ b/Packages/age.pkl @@ -6,9 +6,9 @@ url = "https://github.com/FiloSottile/age/releases/download/v\(version)/age-v\(v purl = "pkg:golang/filippo.io/age@\(version)" -version = "1.1.0" +version = "1.0.0" -hash = "f9dbc0726394f509e3d515a0bef5ffc02d8e59a818bfffc0f4acd826405af292" +hash = "42aaf089081d338ba5eba508d31fe81fb68ec692f404cea996fcbb34690ec2f1" executablePath = "/age/age" diff --git a/Packages/k9s.pkl b/Packages/k9s.pkl index e9731f9..6e52816 100644 --- a/Packages/k9s.pkl +++ b/Packages/k9s.pkl @@ -6,9 +6,9 @@ url = "https://github.com/derailed/k9s/releases/download/v\(version)/k9s_Darwin_ purl = "pkg:golang/github.com/derailed/k9s@\(version)" -version = "0.32.5" +version = "0.26.0" -hash = "916a51cc8e0c48811a1b459cfad98201ba9e0b90e5741d8a889bed718169f17d" +hash = "43df569e527141dbfc53d859d7675b71c2cfc597ffa389a20f91297c6701f255" executablePath = "/k9s"