diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 558a1445a..869b94c30 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -132,6 +132,8 @@ jobs: VLT_REGISTRY_AUTH_TOKEN: ${{ secrets.VLT_REGISTRY_AUTH_TOKEN }} CLOUDSMITH_REGISTRY: ${{ secrets.CLOUDSMITH_REGISTRY }} CLOUDSMITH_AUTH_TOKEN: ${{ secrets.CLOUDSMITH_AUTH_TOKEN }} + GH_REGISTRY: ${{ secrets.GH_REGISTRY }} + GH_AUTH_TOKEN: ${{ secrets.GH_AUTH_TOKEN }} run: | ./bench run \ --fixtures="${{ matrix.fixture }}" \ diff --git a/app/src/components/header.tsx b/app/src/components/header.tsx index ac14b9c79..a688b59e0 100644 --- a/app/src/components/header.tsx +++ b/app/src/components/header.tsx @@ -289,7 +289,7 @@ const LeaderBoardItem = ({ {Icon && ( )} diff --git a/app/src/components/icons/github.tsx b/app/src/components/icons/github.tsx new file mode 100644 index 000000000..f8f33d228 --- /dev/null +++ b/app/src/components/icons/github.tsx @@ -0,0 +1,13 @@ +import { createLucideIcon } from "lucide-react"; + +export const Github = createLucideIcon("Github", [ + [ + "path", + { + d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12", + fill: "currentColor", + key: "1", + strokeWidth: "0", + }, + ], +]); diff --git a/app/src/components/icons/index.ts b/app/src/components/icons/index.ts index fcfbfd242..9a4575731 100644 --- a/app/src/components/icons/index.ts +++ b/app/src/components/icons/index.ts @@ -13,6 +13,7 @@ export * from "./bar-chart.tsx"; // ecosystem icons export * from "./astro.tsx"; export * from "./aws.tsx"; +export * from "./github.tsx"; export * from "./berry.tsx"; export * from "./bun.tsx"; export * from "./cloudsmith.tsx"; diff --git a/app/src/hooks/use-history-data.ts b/app/src/hooks/use-history-data.ts index 722ef7522..21f9d822e 100644 --- a/app/src/hooks/use-history-data.ts +++ b/app/src/hooks/use-history-data.ts @@ -21,6 +21,7 @@ const PACKAGE_MANAGERS = [ "node", "aws", "cloudsmith", + "github", ]; interface UseHistoryDataReturn { diff --git a/app/src/lib/get-icons.ts b/app/src/lib/get-icons.ts index 844a3f040..d987fbab8 100644 --- a/app/src/lib/get-icons.ts +++ b/app/src/lib/get-icons.ts @@ -6,6 +6,7 @@ import { Bun, Cloudsmith, Deno, + Github, Next, Node, Npm, @@ -26,6 +27,7 @@ const packageManagerMap: Partial> = { aws: Aws, bun: Bun, cloudsmith: Cloudsmith, + github: Github, deno: Deno, node: Node, npm: Npm, diff --git a/app/src/lib/utils.ts b/app/src/lib/utils.ts index c977eb0fe..44d84b7c5 100644 --- a/app/src/lib/utils.ts +++ b/app/src/lib/utils.ts @@ -466,12 +466,14 @@ export function getPackageManagerDisplayName( if (packageManager === "aws") return "codeartifact.us-east-1.amazonaws.com"; if (packageManager === "cloudsmith") return "npm.cloudsmith.io"; + if (packageManager === "github") return "npm.pkg.github.com"; } if (packageManager === "berry") return "yarn (berry)"; if (packageManager === "zpm") return "yarn (zpm)"; if (packageManager === "turbo") return "turborepo"; if (packageManager === "aws") return "AWS CodeArtifact"; if (packageManager === "cloudsmith") return "Cloudsmith"; + if (packageManager === "github") return "GitHub"; return packageManager; } diff --git a/app/src/types/chart-data.ts b/app/src/types/chart-data.ts index 99718c5c8..8fefe427c 100644 --- a/app/src/types/chart-data.ts +++ b/app/src/types/chart-data.ts @@ -11,7 +11,8 @@ export type PackageManager = | "turbo" | "node" | "aws" - | "cloudsmith"; + | "cloudsmith" + | "github"; export type Fixture = | "next" @@ -52,6 +53,7 @@ export interface PackageManagerVersions { node?: string; aws?: string; cloudsmith?: string; + github?: string; } export interface BaseFixtureResult { @@ -72,6 +74,7 @@ export interface PackageManagerData { node?: number; aws?: number; cloudsmith?: number; + github?: number; npm_stddev?: number; yarn_stddev?: number; @@ -86,6 +89,7 @@ export interface PackageManagerData { node_stddev?: number; aws_stddev?: number; cloudsmith_stddev?: number; + github_stddev?: number; npm_fill?: string; yarn_fill?: string; @@ -100,6 +104,7 @@ export interface PackageManagerData { node_fill?: string; aws_fill?: string; cloudsmith_fill?: string; + github_fill?: string; npm_count?: number; yarn_count?: number; @@ -114,6 +119,7 @@ export interface PackageManagerData { node_count?: number; aws_count?: number; cloudsmith_count?: number; + github_count?: number; npm_dnf?: boolean; yarn_dnf?: boolean; @@ -128,6 +134,7 @@ export interface PackageManagerData { node_dnf?: boolean; aws_dnf?: boolean; cloudsmith_dnf?: boolean; + github_dnf?: boolean; } export type FixtureResult = BaseFixtureResult & PackageManagerData; @@ -167,6 +174,7 @@ export interface PackageCountData { node?: PackageCountEntry; aws?: PackageCountEntry; cloudsmith?: PackageCountEntry; + github?: PackageCountEntry; } export interface PackageCountTableRow { diff --git a/bench b/bench index 933cf5e39..735a02f08 100755 --- a/bench +++ b/bench @@ -43,6 +43,7 @@ AVAILABLE_REGISTRIES=( vlt aws cloudsmith + github ) usage() { @@ -56,7 +57,7 @@ Usage: Options: --fixtures Comma or space-separated fixture names (default: next) --pms Comma or space-separated package managers (default: all) - --registries Comma-separated registries for registry-* variations (default: npm,vlt,aws,cloudsmith) + --registries Comma-separated registries for registry-* variations (default: npm,vlt,aws,cloudsmith,github) --variation Comma or space-separated benchmark variations (default: clean) --runs Hyperfine runs (default: scripts/variations/common.sh default) --warmup Hyperfine warmup runs (default: scripts/variations/common.sh default) @@ -78,6 +79,7 @@ Examples: ./bench run --variation=registry-lockfile --registries=npm,vlt CODEARTIFACT_AUTH_TOKEN= ./bench run --variation=registry-clean --fixtures=next --registries=aws CLOUDSMITH_REGISTRY= CLOUDSMITH_AUTH_TOKEN= ./bench run --variation=registry-clean --fixtures=next --registries=cloudsmith + GH_REGISTRY= GH_AUTH_TOKEN= ./bench run --variation=registry-clean --fixtures=next --registries=github ./bench chart --fixtures=next --variation=clean ./bench process EOF @@ -448,7 +450,7 @@ run_bench() { if [[ -n "$registries_env" ]]; then echo " registries: $registries_env" else - echo " registries: npm,vlt,aws,cloudsmith (default)" + echo " registries: npm,vlt,aws,cloudsmith,github (default)" fi fi diff --git a/scripts/generate-chart.js b/scripts/generate-chart.js index 22d171729..d95660122 100644 --- a/scripts/generate-chart.js +++ b/scripts/generate-chart.js @@ -40,6 +40,7 @@ const REGISTRY_COLORS = { vlt: "#000000", aws: "#ff9900", cloudsmith: "#2a6fe1", + github: "#6336b8", }; const parseNumeric = (value) => { diff --git a/scripts/registry/common.sh b/scripts/registry/common.sh index c1283ea92..e97aeae1a 100644 --- a/scripts/registry/common.sh +++ b/scripts/registry/common.sh @@ -68,6 +68,11 @@ BENCH_REGISTRY_AWS_NPMRC_KEY="${BENCH_REGISTRY_AWS_URL#http*://}" # The auth .npmrc key uses the URL as-is (without protocol). BENCH_REGISTRY_CLOUDSMITH_URL="https:${CLOUDSMITH_REGISTRY:-}" BENCH_REGISTRY_CLOUDSMITH_NPMRC_KEY="${CLOUDSMITH_REGISTRY#//}" +# GitHub registry URL is injected without the protocol prefix +# (e.g. "//npm.pkg.github.com/..."), so we prepend "https:" for the registry config. +# The auth .npmrc key uses the URL as-is (without protocol). +BENCH_REGISTRY_GITHUB_URL="https:${GH_REGISTRY:-}" +BENCH_REGISTRY_GITHUB_NPMRC_KEY="${GH_REGISTRY#//}" # Registry setup commands run in hyperfine --prepare (untimed, before each run). # Auth token is written as a literal placeholder so npm resolves it from env. @@ -81,6 +86,7 @@ BENCH_SETUP_REGISTRY_NPM="npm config set registry \"$BENCH_REGISTRY_NPM_URL\" -- BENCH_SETUP_REGISTRY_VLT="npm config set registry \"$BENCH_REGISTRY_VLT_URL\" --location=project && npm config set \"//${BENCH_REGISTRY_VLT_URL_NPMRC_KEY}:_authToken=\\\${VLT_REGISTRY_AUTH_TOKEN}:$(head -c 16 /dev/urandom | xxd -p)_\\\${HYPERFINE_ITERATION}\" --location=project" BENCH_SETUP_REGISTRY_AWS="npm config set registry \"$BENCH_REGISTRY_AWS_URL\" --location=project && npm config set \"//${BENCH_REGISTRY_AWS_NPMRC_KEY}:_authToken=\\\${CODEARTIFACT_AUTH_TOKEN}\" --location=project" BENCH_SETUP_REGISTRY_CLOUDSMITH="npm config set registry \"$BENCH_REGISTRY_CLOUDSMITH_URL\" --location=project && npm config set \"//${BENCH_REGISTRY_CLOUDSMITH_NPMRC_KEY}:_authToken=\\\${CLOUDSMITH_AUTH_TOKEN}\" --location=project" +BENCH_SETUP_REGISTRY_GITHUB="npm config set registry \"$BENCH_REGISTRY_GITHUB_URL\" --location=project && npm config set \"//${BENCH_REGISTRY_GITHUB_NPMRC_KEY}:_authToken=\\\${GH_AUTH_TOKEN}\" --location=project" # Registry verification helper runs in hyperfine --conclude (untimed, after each run). BENCH_VERIFY_REGISTRY="npm config get registry && ((grep -m3 '\"resolved\"' package-lock.json 2>/dev/null | sed 's/^[[:space:]]*//') || echo 'no lockfile yet') && echo ''" @@ -90,23 +96,26 @@ BENCH_CONCLUDE_NPM="{ $BENCH_VERIFY_REGISTRY; } >> $BENCH_OUTPUT_FOLDER/npm-veri BENCH_CONCLUDE_VLT_REG="{ $BENCH_VERIFY_REGISTRY; } >> $BENCH_OUTPUT_FOLDER/vlt-verify.log 2>&1" BENCH_CONCLUDE_AWS="{ $BENCH_VERIFY_REGISTRY; } >> $BENCH_OUTPUT_FOLDER/aws-verify.log 2>&1" BENCH_CONCLUDE_CLOUDSMITH="{ $BENCH_VERIFY_REGISTRY; } >> $BENCH_OUTPUT_FOLDER/cloudsmith-verify.log 2>&1" +BENCH_CONCLUDE_GITHUB="{ $BENCH_VERIFY_REGISTRY; } >> $BENCH_OUTPUT_FOLDER/github-verify.log 2>&1" # Registry commands are timed and should only run installs. BENCH_COMMAND_NPM="$BENCH_NPM_INSTALL >> $BENCH_OUTPUT_FOLDER/npm-output-\${HYPERFINE_ITERATION}.log 2>&1" BENCH_COMMAND_VLT_REG="$BENCH_NPM_INSTALL >> $BENCH_OUTPUT_FOLDER/vlt-output-\${HYPERFINE_ITERATION}.log 2>&1" BENCH_COMMAND_AWS="$BENCH_NPM_INSTALL >> $BENCH_OUTPUT_FOLDER/aws-output-\${HYPERFINE_ITERATION}.log 2>&1" BENCH_COMMAND_CLOUDSMITH="$BENCH_NPM_INSTALL >> $BENCH_OUTPUT_FOLDER/cloudsmith-output-\${HYPERFINE_ITERATION}.log 2>&1" +BENCH_COMMAND_GITHUB="$BENCH_NPM_INSTALL >> $BENCH_OUTPUT_FOLDER/github-output-\${HYPERFINE_ITERATION}.log 2>&1" # Registry include flags # If BENCH_INCLUDE_REGISTRY is not set, default to running all registries. if [ -z "${BENCH_INCLUDE_REGISTRY:-}" ]; then - BENCH_INCLUDE_REGISTRY="npm,vlt,aws,cloudsmith" + BENCH_INCLUDE_REGISTRY="npm,vlt,aws,cloudsmith,github" fi BENCH_INCLUDE_REG_NPM="" BENCH_INCLUDE_REG_VLT="" BENCH_INCLUDE_REG_AWS="" BENCH_INCLUDE_REG_CLOUDSMITH="" +BENCH_INCLUDE_REG_GITHUB="" for entry in $(echo "$BENCH_INCLUDE_REGISTRY" | tr ',' '\n'); do case "$entry" in @@ -115,6 +124,7 @@ for entry in $(echo "$BENCH_INCLUDE_REGISTRY" | tr ',' '\n'); do vlt) BENCH_INCLUDE_REG_VLT=1 ;; aws) BENCH_INCLUDE_REG_AWS=1 ;; cloudsmith) BENCH_INCLUDE_REG_CLOUDSMITH=1 ;; + github) BENCH_INCLUDE_REG_GITHUB=1 ;; *) echo "Error: Unknown registry '$entry' in BENCH_INCLUDE_REGISTRY" exit 1 @@ -142,6 +152,16 @@ if [ -n "$BENCH_INCLUDE_REG_CLOUDSMITH" ] && [ -z "${CLOUDSMITH_REGISTRY:-}" ]; exit 1 fi +if [ -n "$BENCH_INCLUDE_REG_GITHUB" ] && [ -z "${GH_AUTH_TOKEN:-}" ]; then + echo "Error: 'github' registry was requested, but GH_AUTH_TOKEN is not set" + exit 1 +fi + +if [ -n "$BENCH_INCLUDE_REG_GITHUB" ] && [ -z "${GH_REGISTRY:-}" ]; then + echo "Error: 'github' registry was requested, but GH_REGISTRY is not set" + exit 1 +fi + echo "Registry benchmarks will run: $BENCH_INCLUDE_REGISTRY" # Clean up & create the results directory diff --git a/scripts/variations/registry-clean.sh b/scripts/variations/registry-clean.sh index 035f537ef..a4c04eb17 100644 --- a/scripts/variations/registry-clean.sh +++ b/scripts/variations/registry-clean.sh @@ -28,4 +28,7 @@ hyperfine --ignore-failure \ ${BENCH_INCLUDE_REG_AWS:+--conclude="$BENCH_CONCLUDE_AWS"} \ ${BENCH_INCLUDE_REG_CLOUDSMITH:+--prepare="$BENCH_PREPARE_BASE && $BENCH_SETUP_REGISTRY_CLOUDSMITH"} \ ${BENCH_INCLUDE_REG_CLOUDSMITH:+--command-name="cloudsmith" "$BENCH_COMMAND_CLOUDSMITH"} \ - ${BENCH_INCLUDE_REG_CLOUDSMITH:+--conclude="$BENCH_CONCLUDE_CLOUDSMITH"} + ${BENCH_INCLUDE_REG_CLOUDSMITH:+--conclude="$BENCH_CONCLUDE_CLOUDSMITH"} \ + ${BENCH_INCLUDE_REG_GITHUB:+--prepare="$BENCH_PREPARE_BASE && $BENCH_SETUP_REGISTRY_GITHUB"} \ + ${BENCH_INCLUDE_REG_GITHUB:+--command-name="github" "$BENCH_COMMAND_GITHUB"} \ + ${BENCH_INCLUDE_REG_GITHUB:+--conclude="$BENCH_CONCLUDE_GITHUB"} diff --git a/scripts/variations/registry-lockfile.sh b/scripts/variations/registry-lockfile.sh index 04ddb5841..7d0557c96 100644 --- a/scripts/variations/registry-lockfile.sh +++ b/scripts/variations/registry-lockfile.sh @@ -29,4 +29,7 @@ hyperfine --ignore-failure \ ${BENCH_INCLUDE_REG_AWS:+--conclude="$BENCH_CONCLUDE_AWS"} \ ${BENCH_INCLUDE_REG_CLOUDSMITH:+--prepare="$BENCH_PREPARE_BASE && $BENCH_SETUP_REGISTRY_CLOUDSMITH"} \ ${BENCH_INCLUDE_REG_CLOUDSMITH:+--command-name="cloudsmith" "$BENCH_COMMAND_CLOUDSMITH"} \ - ${BENCH_INCLUDE_REG_CLOUDSMITH:+--conclude="$BENCH_CONCLUDE_CLOUDSMITH"} + ${BENCH_INCLUDE_REG_CLOUDSMITH:+--conclude="$BENCH_CONCLUDE_CLOUDSMITH"} \ + ${BENCH_INCLUDE_REG_GITHUB:+--prepare="$BENCH_PREPARE_BASE && $BENCH_SETUP_REGISTRY_GITHUB"} \ + ${BENCH_INCLUDE_REG_GITHUB:+--command-name="github" "$BENCH_COMMAND_GITHUB"} \ + ${BENCH_INCLUDE_REG_GITHUB:+--conclude="$BENCH_CONCLUDE_GITHUB"}