diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2426773..b573697 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,3 +34,15 @@ jobs: - run: deno fmt --check . - run: deno lint . - run: deno check ./app.ts + + test: + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: denolib/setup-deno@v2 + with: + deno-version: v2.x + - run: deno test --allow-read --allow-write --allow-env diff --git a/deno.lock b/deno.lock index f505d6b..8d8f2d1 100644 --- a/deno.lock +++ b/deno.lock @@ -1,25 +1,41 @@ { "version": "4", "specifiers": { + "jsr:@std/assert@*": "0.224.0", "jsr:@std/assert@0.224": "0.224.0", + "jsr:@std/assert@^1.0.6": "1.0.6", "jsr:@std/bytes@^1.0.2": "1.0.2", "jsr:@std/crypto@1": "1.0.3", "jsr:@std/encoding@1": "1.0.5", "jsr:@std/flags@*": "0.224.0", + "jsr:@std/fmt@0.224": "0.224.0", "jsr:@std/fs@1": "1.0.8", + "jsr:@std/internal@0.224": "0.224.0", + "jsr:@std/internal@^1.0.4": "1.0.4", "jsr:@std/io@*": "0.225.0", "jsr:@std/io@0.225": "0.225.0", "jsr:@std/json@1": "1.0.0", "jsr:@std/jsonc@*": "1.0.1", "jsr:@std/path@1": "1.0.8", "jsr:@std/path@^1.0.8": "1.0.8", + "jsr:@std/testing@*": "1.0.3", "jsr:@std/yaml@*": "1.0.5", "jsr:@std/yaml@1": "1.0.5", "npm:@types/node@*": "22.5.4" }, "jsr": { "@std/assert@0.224.0": { - "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f" + "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", + "dependencies": [ + "jsr:@std/fmt", + "jsr:@std/internal@0.224" + ] + }, + "@std/assert@1.0.6": { + "integrity": "1904c05806a25d94fe791d6d883b685c9e2dcd60e4f9fc30f4fc5cf010c72207", + "dependencies": [ + "jsr:@std/internal@^1.0.4" + ] }, "@std/bytes@1.0.2": { "integrity": "fbdee322bbd8c599a6af186a1603b3355e59a5fb1baa139f8f4c3c9a1b3e3d57" @@ -33,15 +49,27 @@ "@std/flags@0.224.0": { "integrity": "d40eaf58c356b2e1313c6d4e62dc28b614aad2ddae6f5ff72a969e0b1f5ad689", "dependencies": [ - "jsr:@std/assert" + "jsr:@std/assert@0.224" ] }, + "@std/fmt@0.224.0": { + "integrity": "e20e9a2312a8b5393272c26191c0a68eda8d2c4b08b046bad1673148f1d69851" + }, "@std/fs@1.0.8": { "integrity": "161c721b6f9400b8100a851b6f4061431c538b204bb76c501d02c508995cffe0", "dependencies": [ "jsr:@std/path@^1.0.8" ] }, + "@std/internal@0.224.0": { + "integrity": "afc50644f9cdf4495eeb80523a8f6d27226b4b36c45c7c195dfccad4b8509291", + "dependencies": [ + "jsr:@std/fmt" + ] + }, + "@std/internal@1.0.4": { + "integrity": "62e8e4911527e5e4f307741a795c0b0a9e6958d0b3790716ae71ce085f755422" + }, "@std/io@0.225.0": { "integrity": "c1db7c5e5a231629b32d64b9a53139445b2ca640d828c26bf23e1c55f8c079b3", "dependencies": [ @@ -60,6 +88,12 @@ "@std/path@1.0.8": { "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" }, + "@std/testing@1.0.3": { + "integrity": "f98c2bee53860a5916727d7e7d3abe920dd6f9edace022e2d059f00d05c2cf42", + "dependencies": [ + "jsr:@std/assert@^1.0.6" + ] + }, "@std/yaml@1.0.5": { "integrity": "71ba3d334305ee2149391931508b2c293a8490f94a337eef3a09cade1a2a2742" } diff --git a/fixtures/.node-version b/fixtures/.node-version new file mode 100644 index 0000000..f274881 --- /dev/null +++ b/fixtures/.node-version @@ -0,0 +1 @@ +v16.16.0 diff --git a/fixtures/.ruby-version b/fixtures/.ruby-version new file mode 100644 index 0000000..e4604e3 --- /dev/null +++ b/fixtures/.ruby-version @@ -0,0 +1 @@ +3.2.1 diff --git a/fixtures/.terraform-version b/fixtures/.terraform-version new file mode 100644 index 0000000..9c6d629 --- /dev/null +++ b/fixtures/.terraform-version @@ -0,0 +1 @@ +1.6.1 diff --git a/fixtures/.yarnrc b/fixtures/.yarnrc new file mode 100644 index 0000000..ff41eed --- /dev/null +++ b/fixtures/.yarnrc @@ -0,0 +1,7 @@ +# --- +# dependencies: +# zlib.net: ^1.2 +# env: +# FOO: BAR +# BAR: 1 +# --- diff --git a/fixtures/.yarnrc.yml b/fixtures/.yarnrc.yml new file mode 100644 index 0000000..e797da6 --- /dev/null +++ b/fixtures/.yarnrc.yml @@ -0,0 +1,6 @@ +#--- +# dependencies: +# zlib.net: ^1.2 +# env: +# FOO: BAR +#--- diff --git a/fixtures/Cargo.toml b/fixtures/Cargo.toml new file mode 100644 index 0000000..4a41bdd --- /dev/null +++ b/fixtures/Cargo.toml @@ -0,0 +1,13 @@ +# --- +# pkgx: +# dependencies: +# - zlib.net^1.2 +# env: +# FOO: BAR +# --- + +[package] +name = "pkgx example" +version = "0.0.1" +authors = ["mxcl"] +autobins = false diff --git a/fixtures/Gemfile b/fixtures/Gemfile new file mode 100644 index 0000000..b19bbcb --- /dev/null +++ b/fixtures/Gemfile @@ -0,0 +1,8 @@ +# --- +# dependencies: +# zlib.net: ^1.2 +# env: +# FOO: BAR +# --- +gem 'rails', '5.0.0' +gem 'sqlite3' diff --git a/fixtures/action.yml/empty/action.yml b/fixtures/action.yml/empty/action.yml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/fixtures/action.yml/empty/action.yml @@ -0,0 +1 @@ + diff --git a/fixtures/action.yml/not-node/action.yml b/fixtures/action.yml/not-node/action.yml new file mode 100644 index 0000000..8f3c557 --- /dev/null +++ b/fixtures/action.yml/not-node/action.yml @@ -0,0 +1,19 @@ +name: Elixir Script +author: Jon Lauridsen +description: Run simple Elixir scripts +branding: + color: orange + icon: code +inputs: + script: + description: The script to run + required: true + debug: + description: Whether to tell the GitHub client to log details of its requests. true or false. Default is to run in debug mode when the GitHub Actions step debug logging is turned on. + default: ${{ runner.debug == '1' }} +outputs: + result: + description: The stringified return value of the script +runs: + using: docker + image: Dockerfile diff --git a/fixtures/action.yml/std/action.yml b/fixtures/action.yml/std/action.yml new file mode 100644 index 0000000..2ef7fed --- /dev/null +++ b/fixtures/action.yml/std/action.yml @@ -0,0 +1,9 @@ +runs: + using: "node16" + main: "main.js" + +pkgx: + dependencies: + zlib.net^1.2 + env: + FOO: BAR diff --git a/fixtures/bun.lockb b/fixtures/bun.lockb new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/cdk.json b/fixtures/cdk.json new file mode 100644 index 0000000..e8ccd94 --- /dev/null +++ b/fixtures/cdk.json @@ -0,0 +1,64 @@ +{ + "app": "npx ts-node --prefer-ts-exts bin/cdk.ts", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true + } +} diff --git a/fixtures/deno.json/arr/deno.json b/fixtures/deno.json/arr/deno.json new file mode 100644 index 0000000..022b113 --- /dev/null +++ b/fixtures/deno.json/arr/deno.json @@ -0,0 +1,3 @@ +{ + "pkgx": ["zlib.net^1.2"] +} diff --git a/fixtures/deno.json/std/deno.json b/fixtures/deno.json/std/deno.json new file mode 100644 index 0000000..35f2a11 --- /dev/null +++ b/fixtures/deno.json/std/deno.json @@ -0,0 +1,10 @@ +{ + "pkgx": { + "dependencies": { + "zlib.net": "^1.2" + }, + "env": { + "FOO": "BAR" + } + } +} diff --git a/fixtures/deno.jsonc b/fixtures/deno.jsonc new file mode 100644 index 0000000..35f2a11 --- /dev/null +++ b/fixtures/deno.jsonc @@ -0,0 +1,10 @@ +{ + "pkgx": { + "dependencies": { + "zlib.net": "^1.2" + }, + "env": { + "FOO": "BAR" + } + } +} diff --git a/fixtures/go.mod b/fixtures/go.mod new file mode 100644 index 0000000..688d517 --- /dev/null +++ b/fixtures/go.mod @@ -0,0 +1,17 @@ +// --- +// dependencies: +// zlib.net: ^1.2 +// testing.org: 1.2.3 +// env: +// FOO: BAR +// --- + +module github.com/pkgxdev/go-mod-example + +require ( + github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect + github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect + github.com/gorilla/mux v1.6.2 + github.com/sirupsen/logrus v1.2.0 + gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect +) diff --git a/fixtures/package.json/arr/package.json b/fixtures/package.json/arr/package.json new file mode 100644 index 0000000..bfdf568 --- /dev/null +++ b/fixtures/package.json/arr/package.json @@ -0,0 +1,3 @@ +{ + "pkgx": ["zlib.net^1.2", "deno@1.33"] +} diff --git a/fixtures/package.json/engines/package.json b/fixtures/package.json/engines/package.json new file mode 100644 index 0000000..f69e7ee --- /dev/null +++ b/fixtures/package.json/engines/package.json @@ -0,0 +1,8 @@ +{ + "engines": { + "node": "~16.16.1", + "npm": "~9.7.1", + "yarn": "~1.22.10", + "pnpm": "~7.33.7" + } +} diff --git a/fixtures/package.json/packageManager/package.json b/fixtures/package.json/packageManager/package.json new file mode 100644 index 0000000..20414b5 --- /dev/null +++ b/fixtures/package.json/packageManager/package.json @@ -0,0 +1,3 @@ +{ + "packageManager": "pnpm@7.33.7+sha256.d1581d46ed10f54ff0cbdd94a2373b1f070202b0fbff29f27c2ce01460427043" +} diff --git a/fixtures/package.json/std/package.json b/fixtures/package.json/std/package.json new file mode 100644 index 0000000..35f2a11 --- /dev/null +++ b/fixtures/package.json/std/package.json @@ -0,0 +1,10 @@ +{ + "pkgx": { + "dependencies": { + "zlib.net": "^1.2" + }, + "env": { + "FOO": "BAR" + } + } +} diff --git a/fixtures/package.json/str/package.json b/fixtures/package.json/str/package.json new file mode 100644 index 0000000..a2b62b5 --- /dev/null +++ b/fixtures/package.json/str/package.json @@ -0,0 +1,3 @@ +{ + "pkgx": "zlib.net^1.2 python.org@latest" +} diff --git a/fixtures/package.json/volta/package.json b/fixtures/package.json/volta/package.json new file mode 100644 index 0000000..9f5fc4a --- /dev/null +++ b/fixtures/package.json/volta/package.json @@ -0,0 +1,8 @@ +{ + "volta": { + "node": "16.16.1", + "npm": "9.7.1", + "yarn": "1.22.10", + "pnpm": "7.33.7" + } +} diff --git a/fixtures/pixi.toml b/fixtures/pixi.toml new file mode 100644 index 0000000..b6e9717 --- /dev/null +++ b/fixtures/pixi.toml @@ -0,0 +1,7 @@ +# --- +# dependencies: +# zlib.net: ^1.2 +# python.org: '@latest' +# env: +# FOO: BAR +# --- diff --git a/fixtures/pkgx.yml b/fixtures/pkgx.yml new file mode 100644 index 0000000..3240f75 --- /dev/null +++ b/fixtures/pkgx.yml @@ -0,0 +1,5 @@ +dependencies: + zlib.net: ^1.2 + python.org: latest +env: + FOO: BAR diff --git a/fixtures/pyproject.toml/poetry-yaml-fm/pyproject.toml b/fixtures/pyproject.toml/poetry-yaml-fm/pyproject.toml new file mode 100644 index 0000000..ababfd6 --- /dev/null +++ b/fixtures/pyproject.toml/poetry-yaml-fm/pyproject.toml @@ -0,0 +1,12 @@ +# pyproject. toml +# --- +# pkgx: +# python@3.10 +# --- + +[tool-poetry] +name = "magicaitrainer" +version = "0.1.0" +description = +authors = ["jlphilli"] +readme = "README. md" diff --git a/fixtures/pyproject.toml/poetry/pyproject.toml b/fixtures/pyproject.toml/poetry/pyproject.toml new file mode 100644 index 0000000..6031d92 --- /dev/null +++ b/fixtures/pyproject.toml/poetry/pyproject.toml @@ -0,0 +1,13 @@ +# --- +# dependencies: +# zlib.net: ^1.2 +# env: +# FOO: BAR +# --- + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool-poetry.dependencies] +python = "3.11.4" diff --git a/fixtures/pyproject.toml/std/pyproject.toml b/fixtures/pyproject.toml/std/pyproject.toml new file mode 100644 index 0000000..7e7c305 --- /dev/null +++ b/fixtures/pyproject.toml/std/pyproject.toml @@ -0,0 +1,9 @@ +# --- +# dependencies: +# zlib.net: ^1.2 +# env: +# FOO: BAR +# --- + +[project] +name = "pkgx example" diff --git a/fixtures/python-version/broken/.python-version b/fixtures/python-version/broken/.python-version new file mode 100644 index 0000000..86a410d --- /dev/null +++ b/fixtures/python-version/broken/.python-version @@ -0,0 +1 @@ +broken \ No newline at end of file diff --git a/fixtures/python-version/commented/.python-version b/fixtures/python-version/commented/.python-version new file mode 100644 index 0000000..5de512a --- /dev/null +++ b/fixtures/python-version/commented/.python-version @@ -0,0 +1,3 @@ +# hi + +3.11 diff --git a/fixtures/python-version/std/.python-version b/fixtures/python-version/std/.python-version new file mode 100644 index 0000000..c8cfe39 --- /dev/null +++ b/fixtures/python-version/std/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/fixtures/requirements.txt b/fixtures/requirements.txt new file mode 100644 index 0000000..ff764d5 --- /dev/null +++ b/fixtures/requirements.txt @@ -0,0 +1,9 @@ +# --- +# dependencies: +# zlib.net: ^1.2 +# env: +# FOO: BAR +# --- +tensorflow==2.3.1 +uvicorn==0.12.2 +fastapi==0.63.0 diff --git a/fixtures/skaffold.yaml/empty/skaffold.yaml b/fixtures/skaffold.yaml/empty/skaffold.yaml new file mode 100644 index 0000000..53eb66c --- /dev/null +++ b/fixtures/skaffold.yaml/empty/skaffold.yaml @@ -0,0 +1,4 @@ +apiVersion: v4beta7 +kind: Config +metadata: + name: skaffold-fixture diff --git a/fixtures/skaffold.yaml/manifests/skaffold.yaml b/fixtures/skaffold.yaml/manifests/skaffold.yaml new file mode 100644 index 0000000..11bb4ed --- /dev/null +++ b/fixtures/skaffold.yaml/manifests/skaffold.yaml @@ -0,0 +1,9 @@ +apiVersion: v4beta7 +kind: Config +metadata: + name: skaffold-fixture +manifests: + kpt: [] + kustomize: {} + helm: + releases: [] diff --git a/fixtures/skaffold.yaml/std/skaffold.yaml b/fixtures/skaffold.yaml/std/skaffold.yaml new file mode 100644 index 0000000..5d55591 --- /dev/null +++ b/fixtures/skaffold.yaml/std/skaffold.yaml @@ -0,0 +1,22 @@ +apiVersion: v4beta7 +kind: Config +metadata: + name: skaffold-fixture +build: + local: + useDockerCLI: true +deploy: + kubeContext: minikube + kubectl: {} + helm: {} + kpt: {} + docker: + images: [] +manifests: + kpt: [] + kustomize: {} + helm: + releases: [] + +profiles: + - name: skaffold-fixture diff --git a/fixtures/yarn.lock b/fixtures/yarn.lock new file mode 100644 index 0000000..e69de29 diff --git a/src/sniff.test.ts b/src/sniff.test.ts new file mode 100644 index 0000000..117945f --- /dev/null +++ b/src/sniff.test.ts @@ -0,0 +1,253 @@ +// deno-lint-ignore-file require-await +import { + assert, + assertEquals, + assertRejects, + assertThrows, +} from "jsr:@std/assert"; +import specimen, { _internals } from "./sniff.ts"; +import * as mock from "jsr:@std/testing/mock"; +import { Path, utils } from "libpkgx"; + +export const fixturesd = new Path(new URL(import.meta.url).pathname).parent() + .parent().join("fixtures"); + +Deno.test("devenv.ts", async (runner) => { + // const stub = mock.stub(_internals, "find", async pkg => utils.pkg.parse(pkg)) + + try { + await runner.step("supplementable fixtures", async (test) => { + // each of the files in this list must have a zlib.net^1.2 dependency and a FOO=BAR env + const keyfiles = [ + ["pkgx.yml"], + ["deno.json/std/deno.json", "deno.land"], + ["deno.json/arr/deno.json", "deno.land"], + ["deno.jsonc", "deno.land"], + ["package.json/std/package.json", "nodejs.org"], + ["package.json/str/package.json", "nodejs.org"], + ["package.json/arr/package.json", "nodejs.org"], + ["Cargo.toml", "rust-lang.org"], + ["Gemfile", "ruby-lang.org"], + ["pyproject.toml/std/pyproject.toml", "pip.pypa.io"], + ["pyproject.toml/poetry/pyproject.toml", "python-poetry.org"], + ["go.mod", "go.dev"], + ["requirements.txt", "pip.pypa.io"], + [".yarnrc", "classic.yarnpkg.com"], + ["pixi.toml", "prefix.dev"], + ["action.yml/std/action.yml", "nodejs.org^16"], + [".yarnrc.yml", "yarnpkg.com"], + ]; + + for (const [keyfile, dep] of keyfiles) { + await test.step(`${keyfile}`, async () => { + const go = async (file: Path) => { + const { env, pkgs } = await specimen(file.parent()); + assert( + pkgs.find((pkg) => utils.pkg.str(pkg) == "zlib.net^1.2"), + "should dep zlib^1.2", + ); + if (dep) { + assert( + pkgs.find((pkg) => utils.pkg.str(pkg) == dep), + `should dep ${dep}`, + ); + } + + switch (keyfile) { + case "package.json/str/package.json": + case "package.json/arr/package.json": + case "deno.json/arr/deno.json": + break; // testing the short form for deps with these files + default: + assertEquals(env.FOO, "BAR"); + } + }; + + const target = fixturesd.join(keyfile).cp({ into: Path.mktemp() }); + await go(target); + await go(Path.mktemp().join(target.basename()).ln("s", { target })); + }); + } + }); + + await runner.step("fixed fixtures", async (test) => { + const keyfiles = [ + [ + "package.json/engines/package.json", + "nodejs.org~16.16.1", + "npmjs.com~9.7.1", + "yarnpkg.com~1.22.10", + "pnpm.io~7.33.7", + ], + [ + "package.json/packageManager/package.json", + "pnpm.io@7.33.7", + "nodejs.org", + ], + [ + "package.json/volta/package.json", + "nodejs.org@16.16.1", + "npmjs.com@9.7.1", + "yarnpkg.com@1.22.10", + "pnpm.io@7.33.7", + ], + [".node-version", "nodejs.org@16.16.0"], + ["python-version/std/.python-version", "python.org~3.10"], + ["python-version/commented/.python-version", "python.org~3.11"], + [".ruby-version", "ruby-lang.org@3.2.1"], + [".terraform-version", "terraform.io@1.6.1"], + ["yarn.lock", "yarnpkg.com"], + ["bun.lockb", "bun.sh>=1"], + [ + "pyproject.toml/poetry-yaml-fm/pyproject.toml", + "pip.pypa.io", + "python~3.10", + ], + ["cdk.json", "aws.amazon.com/cdk"], + ]; + + for (const [keyfile, ...deps] of keyfiles) { + await test.step(keyfile, async () => { + const file = fixturesd.join(keyfile).cp({ into: Path.mktemp() }); + const { env, pkgs } = await specimen(file.parent()); + + assertEquals(pkgs.length, deps.length); + + pkgs.forEach((pkg, i) => { + assertEquals(Object.keys(env).length, 0); + assertEquals(utils.pkg.str(pkg), deps[i]); + }); + }); + } + }); + + await runner.step("broken .python-version", async () => { + const file = fixturesd.join("python-version/broken/.python-version").cp({ + into: Path.mktemp(), + }); + const { pkgs } = await specimen(file.parent()); + assertEquals(pkgs.length, 0); //NOTE this seems like dumb behavior + }); + + await runner.step("vcs", async (test) => { + const vcss = [ + ["hg", "mercurial-scm.org"], + ["svn", "apache.org/subversion"], + ]; + + if (Deno.build.os !== "darwin") { + vcss.push(["git", "git-scm.org"]); + } + + for (const [vcs, dep] of vcss) { + await test.step(vcs, async () => { + const d = Path.mktemp().join(`.${vcs}`).mkdir(); + const { env, pkgs } = await specimen(d.parent()); + assertEquals(Object.keys(env).length, 0); + assertEquals(utils.pkg.str(pkgs[0]), dep); + }); + } + }); + + await runner.step("empty action.yml has no deps", async () => { + const { pkgs } = await specimen(fixturesd.join("action.yml/empty")); + assertEquals(pkgs.length, 0); + + const { pkgs: pkgs2 } = await specimen( + fixturesd.join("action.yml/not-node"), + ); + assertEquals(pkgs2.length, 0); + }); + + await runner.step("no dir error", async () => { + await assertRejects(() => specimen(new Path("/a/b/c/pkgx"))); + }); + + await runner.step("not error if no yaml fm", async () => { + const f = Path.mktemp().join("pyproject.toml").touch(); + await specimen(f.parent()); + + f.rm().write({ text: "#---\n#---" }); + await specimen(f.parent()); + + // we don’t support invalid json just like npm won’t + f.parent().join("package.json").touch(); + await assertRejects(() => specimen(f.parent())); + + f.parent().join("package.json").rm().write({ text: "{}" }); + await specimen(f.parent()); + }); + + await runner.step("skips invalid deps node", async () => { + const f = Path.mktemp().join("package.json").rm().write({ + text: '{"pkgx": {"dependencies": true}}', + }); + const { pkgs } = await specimen(f.parent()); + assertEquals(pkgs.length, 1); + assertEquals(pkgs[0].project, "nodejs.org"); + }); + + await runner.step("skffold.yaml", async () => { + // test invalid skffold.yaml + const f = Path.mktemp().join("skaffold.yaml").touch(); + f.parent().join("skaffold.yaml").rm().write({ text: "" }); + const { env, pkgs } = await specimen(f.parent()); + // only skafflold.dev, no other dep expected + assert( + pkgs.length === 1, + "invalid skaffold.yaml should not return any dep", + ); + + const keyfiles = [ + [ + "skaffold.yaml/std/skaffold.yaml", + "skaffold.dev", + "kubernetes.io/kubectl", + "helm.sh", + "kpt.dev", + "kubernetes.io/minikube", + "docker.com/cli", + "kubernetes.io/kustomize", + ], + [ + "skaffold.yaml/empty/skaffold.yaml", + "skaffold.dev", + ], + [ + "skaffold.yaml/manifests/skaffold.yaml", + "skaffold.dev", + "helm.sh", + "kpt.dev", + "kubernetes.io/kustomize", + ], + ]; + + for (const [keyfile, ...deps] of keyfiles) { + const file = fixturesd.join(keyfile).cp({ into: Path.mktemp() }); + const { env, pkgs } = await specimen(file.parent()); + assert( + pkgs.length === deps.length, + `dependencies length differ, required: ${deps.length}, actual: ${pkgs.length}`, + ); + deps.every((dep) => { + assert( + pkgs.find((pkg) => utils.pkg.str(pkg) == dep), + "should dep " + dep, + ); + }); + } + }); + } finally { + // stub.restore() + } + + await runner.step("validateDollarSignUsage", () => { + assertThrows(() => _internals.validateDollarSignUsage("foo $(bar) baz")); + assertThrows(() => _internals.validateDollarSignUsage("foo $123 baz")); + + _internals.validateDollarSignUsage("foo $bar baz"); + _internals.validateDollarSignUsage("foo $BAR baz"); + _internals.validateDollarSignUsage("foo $B0AR baz"); + _internals.validateDollarSignUsage("foo z${FOO}s baz"); + }); +});