diff --git a/.agents/notes/proposed/architecture/2026-10-23-three-package-workspaces.md b/.agents/notes/proposed/architecture/2026-10-23-three-package-workspaces.md index ece483bf..2528e3e1 100644 --- a/.agents/notes/proposed/architecture/2026-10-23-three-package-workspaces.md +++ b/.agents/notes/proposed/architecture/2026-10-23-three-package-workspaces.md @@ -1,4 +1,4 @@ -# Three packages: `gcb-cli`, `gcb-client`, `gcb-host` +# Three packages: `gcb-core`, `gcb-client`, `gcb-host` - **Date:** 2026-10-23 - **Status:** proposed; supersedes the single-package + esbuild-bundle plan @@ -10,19 +10,19 @@ Split the repository into Yarn workspaces under `packages/`: ```text packages/ - cli/ gcb-cli shared CLI runtime, argument parsing, protocol, types - client/ gcb-client container side; depends on gcb-cli - host/ gcb-host host side; depends on gcb-cli and yaml + core/ gcb-core shared command runtime, argument parsing, protocol, types + client/ gcb-client container side; depends on gcb-core + host/ gcb-host host side; depends on gcb-core and yaml ``` Dependency graph: ```text -gcb-client ──> gcb-cli -gcb-host ──> gcb-cli, yaml +gcb-client ──> gcb-core +gcb-host ──> gcb-core, yaml ``` -There is no dependency from `gcb-cli` to either side, and no dependency from +There is no dependency from `gcb-core` to either side, and no dependency from `gcb-client` to `gcb-host`. The container installs only `gcb-client`; the host installs only `gcb-host`. Both top-level packages expose the same `gcb` bin, so the external command is still one name. @@ -31,7 +31,7 @@ name. - npm installs peers in ways that are easy to get wrong; a package boundary is enforced by the dependency graph instead of by documentation. -- `gcb-cli` is a base dependency, not a dispatcher that owns both backends. It must not be able to +- `gcb-core` is a base dependency, not a dispatcher that owns both backends. It must not be able to load `yaml`. - A missing `yaml` must be impossible on a host and irrelevant in a container, not a runtime surprise. @@ -39,10 +39,10 @@ name. ## Bin ownership `gcb-client` and `gcb-host` each declare `"bin": { "gcb": "./bin/gcb.js" }`. The bin is a thin -wrapper: it imports the shared runner from `gcb-cli`, passes its own command backend, and exits with +wrapper: it imports the shared runner from `gcb-core`, passes its own command backend, and exits with the result. -`gcb-cli` may carry a development bin, but it is not the published entry point. Relying on npm to +`gcb-core` may carry a development bin, but it is not the published entry point. Relying on npm to link a dependency's bin into the global prefix is not something to build a release on. Only one of the two top-level packages should be installed in a given environment. Installing both @@ -53,7 +53,7 @@ globally would race for the same `gcb` link; that is documented rather than work - `gcb-client` (implemented): `git-credential-*`, `setup`, `probe`, `logs`, `pr`. - `gcb-host` (implemented): `app`, `host`, `daemon`, `init`, `stage`, `compose`, `diagnose`, `authorize`, `host-opener`. -- `gcb-cli`: help/version, argument parsing, command lookup, error formatting, and the shared +- `gcb-core`: help/version, argument parsing, command lookup, error formatting, and the shared wire/types. `gh` and `config` are roadmap commands, not implemented yet. When `gcb gh` lands it will bypass the @@ -72,8 +72,8 @@ self-contained artifact. That is a separate decision from this package split. ## Packaging and tests - Root is private; `workspaces: ["packages/*"]`. -- Each package has its own `package.json`, `tsconfig.json`, `src/`, `dist/`, and `files`. -- Versions stay in lockstep; `gcb-client` and `gcb-host` depend on the exact `gcb-cli` version. +- Each package has its own `package.json`, `tsconfig.json`, `src/`, `lib/`, and `files`. +- Versions stay in lockstep; `gcb-client` and `gcb-host` depend on the exact `gcb-core` version. - CI adds a real package test: 1. `npm pack` all three; 2. install `gcb-client` into a temporary prefix, assert `gcb --help` and `gcb setup --help` @@ -81,7 +81,7 @@ self-contained artifact. That is a separate decision from this package split. 3. install `gcb-host` into another prefix, assert `gcb app --help` and `gcb daemon --help` work and `yaml` is present. - Unit tests may continue to import `packages/*/src` through a development export condition; the - packaged entry points use `dist`. + packaged entry points use `lib`. ## Consequences diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 00000000..23db17c2 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,5 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a tool to manage versioning and changelogs. Read the full documentation at https://changesets.dev. + +We also have a quick list of common questions to get you started engaging with this project in our [FAQ](https://changesets.dev/faq). diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000..3a467af4 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://unpkg.com/@changesets/config/schema.json", + "changelog": [ + "@changesets/changelog-github", + { + "repo": "code-vaults/git-credential-broker" + } + ], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "fixed": [ + [ + "gcb-core", + "gcb-client", + "gcb-host" + ] + ] +} diff --git a/.changeset/initial-release.md b/.changeset/initial-release.md new file mode 100644 index 00000000..b2b1589a --- /dev/null +++ b/.changeset/initial-release.md @@ -0,0 +1,7 @@ +--- +'gcb-core': patch +'gcb-client': patch +'gcb-host': patch +--- + +Prepare the first public release of the renamed packages. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98bf1821..37834e43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: run: | $ErrorActionPreference = 'Continue' $log = Join-Path $env:RUNNER_TEMP 'daemon.txt' - node --conditions=gcb-development packages/host/bin/gcb.js daemon --check *> $log + node --conditions=development packages/host/bin/gcb.js daemon --check *> $log $code = $LASTEXITCODE $out = Get-Content $log -Raw Write-Host "exit=$code" @@ -109,7 +109,7 @@ jobs: run: | $ErrorActionPreference = 'Continue' $log = Join-Path $env:RUNNER_TEMP 'setup.txt' - node --conditions=gcb-development packages/client/bin/gcb.js setup *> $log + node --conditions=development packages/client/bin/gcb.js setup *> $log $code = $LASTEXITCODE $out = Get-Content $log -Raw Write-Host "exit=$code" @@ -126,7 +126,7 @@ jobs: run: | $ErrorActionPreference = 'Continue' $log = Join-Path $env:RUNNER_TEMP 'compose.txt' - node --conditions=gcb-development packages/host/bin/gcb.js compose --socket-dir C:\sock *> $log + node --conditions=development packages/host/bin/gcb.js compose --socket-dir C:\sock *> $log $code = $LASTEXITCODE $out = Get-Content $log -Raw Write-Host "exit=$code" @@ -142,7 +142,7 @@ jobs: - name: help still works shell: pwsh - run: node --conditions=gcb-development packages/client/bin/gcb.js --help + run: node --conditions=development packages/client/bin/gcb.js --help wsl: timeout-minutes: 20 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..0abd39d6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,132 @@ +name: Release + +on: + push: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + # A publish that has started has to finish: cancelling it can leave some packages on npm and the + # rest not. + cancel-in-progress: false + +permissions: + contents: read + +jobs: + release: + name: Release + runs-on: ubuntu-latest + permissions: + # `id-token` is npm trusted publishing; `contents` and `pull-requests` are the version commit + # and the release pull request. + contents: write + id-token: write + pull-requests: write + outputs: + version: ${{ steps.version.outputs.version }} + published: ${{ steps.changesets.outputs.published }} + steps: + - name: Checkout Repo + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # Changesets writes each changelog from the commits since the last release. + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: lts/* + cache: yarn + + - name: Enable Corepack + run: corepack enable + + - name: Install Dependencies + run: yarn install --immutable + + - name: Build + run: yarn build + + - name: Read the package version + id: version + run: echo "version=$(jq -r .version packages/core/package.json)" >> "$GITHUB_OUTPUT" + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@ae32849d5ba541f9ae29e40e22a623bc13562f51 # v2.1.2 + with: + commit-message: 'chore: release packages' + pr-title: 'chore: release packages' + version-script: yarn run version + publish-script: yarn release + + image: + name: Publish gcb-${{ matrix.target }} + needs: release + if: needs.release.outputs.published == 'true' + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + target: [client, host] + steps: + - name: Checkout Repo + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Setup QEMU + uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0 + with: + platforms: arm64 + + - name: Setup Buildx + uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 + + - name: Log in to GHCR + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Work out the tags + id: tags + env: + VERSION: ${{ needs.release.outputs.version }} + IMAGE: gcb-${{ matrix.target }} + run: | + { + echo "ghcr.io/code-vaults/$IMAGE:latest" + echo "ghcr.io/code-vaults/$IMAGE:sha-${GITHUB_SHA}" + echo "ghcr.io/code-vaults/$IMAGE:${VERSION}" + } > "$RUNNER_TEMP/tags" + { + echo 'tags<> "$GITHUB_OUTPUT" + + - name: Build and push + uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0 + with: + context: . + target: ${{ matrix.target }} + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.tags.outputs.tags }} + labels: | + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.version=${{ needs.release.outputs.version }} + org.opencontainers.image.title=gcb-${{ matrix.target }} + provenance: true + sbom: true + cache-from: type=gha,scope=${{ matrix.target }} + cache-to: type=gha,mode=max,scope=${{ matrix.target }} diff --git a/AGENTS.md b/AGENTS.md index cce0db6e..a4331463 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,8 +60,8 @@ corepack yarn pack:check # build, then show exactly what npm would publish The CLI runs from source too, so there is no need to build to try a command: ```sh -node --conditions=gcb-development packages/client/bin/gcb.js --help -node --conditions=gcb-development packages/host/bin/gcb.js compose --socket-dir /tmp/sock # reads --config, $GIT_BROKER_CONFIG, else ./broker.config.yml +node --conditions=development packages/client/bin/gcb.js --help +node --conditions=development packages/host/bin/gcb.js compose --socket-dir /tmp/sock # reads --config, $GIT_BROKER_CONFIG, else ./broker.config.yml ``` `yarn test` builds first because the end-to-end suite execs `packages/client/bin/gcb.js` as a **real** @@ -79,7 +79,7 @@ sources must stay erasable (`erasableSyntaxOnly` is on: no enums, no parameter p `setup` cannot know the PATH of a later git process; do not pretend a setup-time check is a guarantee. If a review finding depends on an unsupported shape, answer it in the PR and leave the code alone. -- **The gh action catalog is the one source for an action.** `packages/cli/src/actions.ts` +- **The gh action catalog is the one source for an action.** `packages/core/src/actions.ts` defines its command, flags, positionals, permissions and timeout; the token mint, the creation preflight, the command table and the docs must read it rather than keep a second list. The broker rebuilds a canonical argv from validated values and never forwards the caller’s argv. Add an @@ -310,7 +310,7 @@ Full detail and the measurements behind them: | Path | What | |---|---| -| `packages/cli/src/` | shared parser, help/version, protocol, types, platform, paths and the gh action catalog | +| `packages/core/src/` | shared parser, help/version, protocol, types, platform, paths and the gh action catalog | | `packages/client/src/helper.ts` | the container-side credential helper | | `packages/client/src/commands/` | setup, probe, logs, pr, gh and remotes | | `packages/host/src/broker.ts` | unix socket server, refusal codes, audit records | diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f462e260..820d73b1 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -34,9 +34,9 @@ Node strips the types, so the package sources are directly runnable with the dev condition: ```sh -node --conditions=gcb-development packages/client/bin/gcb.js --help -node --conditions=gcb-development packages/host/bin/gcb.js compose --socket-dir /tmp/sock --config /tmp/deploy/broker.config.yml -node --conditions=gcb-development packages/host/bin/gcb.js daemon --config /tmp/deploy/broker.config.yml --check +node --conditions=development packages/client/bin/gcb.js --help +node --conditions=development packages/host/bin/gcb.js compose --socket-dir /tmp/sock --config /tmp/deploy/broker.config.yml +node --conditions=development packages/host/bin/gcb.js daemon --config /tmp/deploy/broker.config.yml --check ``` Commands find the configuration by convention — `--config`, else `$GIT_BROKER_CONFIG`, else @@ -52,7 +52,7 @@ Two consequences: - The `helper` command must resolve to an executable. `setup` records `!gcb`, so git resolves the globally installed bin through PATH; a source checkout can use the same config if it has a `gcb` shim on PATH, or spell the interpreter out explicitly with - `git config --global credential.helper '!node --conditions=gcb-development /path/packages/client/bin/gcb.js'`. + `git config --global credential.helper '!node --conditions=development /path/packages/client/bin/gcb.js'`. ## Build @@ -71,15 +71,15 @@ exec-bit detection), so the build applies it every time. As the CLI, without installing anything: ```sh -node --conditions=gcb-development packages/host/bin/gcb.js daemon --config /tmp/deploy/broker.config.yml +node --conditions=development packages/host/bin/gcb.js daemon --config /tmp/deploy/broker.config.yml ``` As the commands a user of the package gets: ```sh mkdir -p /tmp/gcb-packs -npm pack ./packages/cli ./packages/host --pack-destination /tmp/gcb-packs -npm install -g /tmp/gcb-packs/gcb-cli-*.tgz /tmp/gcb-packs/gcb-host-*.tgz +npm pack ./packages/core ./packages/host --pack-destination /tmp/gcb-packs +npm install -g /tmp/gcb-packs/gcb-core-*.tgz /tmp/gcb-packs/gcb-host-*.tgz gcb --version ``` @@ -140,7 +140,7 @@ If you add tests, three traps are already paid for in this suite: ```sh corepack yarn pack:check # shows exactly what each of the three packages would ship -npm pack ./packages/cli # the tarball itself +npm pack ./packages/core # the tarball itself npm pack ./packages/client npm pack ./packages/host ``` @@ -152,17 +152,32 @@ the checkout of that version beside them. ## Releasing -1. Bump the same `version` in all three package manifests and keep the exact `gcb-cli` dependency in - client/host in lockstep. -2. `corepack yarn check`. -3. Publish in dependency order: `npm publish packages/cli`, then `packages/client` and `packages/host`. -4. Re-render any sidecar you generated: `compose` pins `gcb-host@`, so it takes +Published changes are versioned with Changesets: + +1. Add a changeset with `corepack yarn changeset` in the pull request that changes a published package. + There is no CI gate for this; with no changesets, `changeset publish` only publishes versions npm + does not have yet. +2. The release workflow uses `changesets/action` to open or update `chore: release packages`. Merging + that pull request runs `changeset publish`. +3. `@changesets/changelog-github` writes the changelog entries; each package's `prepack` runs + `clean-pkg-json`, so the published manifest omits the workspace-only `development` export. +4. The same release builds and publishes the `gcb-client` and `gcb-host` images. +5. Re-render any sidecar you generated: `compose` pins `gcb-host@`, so it takes the new version only when it is rendered again. +The release workflow uses npm trusted publishing (OIDC): `id-token: write` is granted, no +`NPM_TOKEN` secret is read. Configure the npm package's trusted publisher for this repository first. +The two images are published to GHCR only. + +Also configure: + +- **Settings → Actions → General → Allow GitHub Actions to create and approve pull requests** on; + `changesets/action` cannot open the version pull request without it + ## Layout ``` -packages/cli/src/ parser, help/version, protocol, types, platform and paths +packages/core/src/ parser, help/version, protocol, types, platform and paths packages/client/src/ credential helper, setup, probe, logs and pr packages/host/src/ YAML config, providers, broker, daemon and host commands packages/*/bin/gcb.js the two installed bins (client and host) diff --git a/Dockerfile b/Dockerfile index 1275574e..e6b97170 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,8 +5,8 @@ # host the broker, with gh, for running `gcb daemon` # # Local build: -# docker build --target client -t code-vaults/gcb-client:dev . -# docker build --target host -t code-vaults/gcb-host:dev . +# docker build --target client -t ghcr.io/code-vaults/gcb-client:dev . +# docker build --target host -t ghcr.io/code-vaults/gcb-host:dev . FROM node:24-slim AS build WORKDIR /src @@ -17,11 +17,11 @@ COPY scripts ./scripts RUN corepack yarn install --immutable \ && corepack yarn build \ && mkdir -p /packs \ - && npm pack ./packages/cli ./packages/client ./packages/host --pack-destination /packs + && npm pack ./packages/core ./packages/client ./packages/host --pack-destination /packs FROM node:24-slim AS client COPY --from=build /packs /packs -RUN npm install -g --omit=dev /packs/gcb-cli-*.tgz /packs/gcb-client-*.tgz \ +RUN npm install -g --omit=dev /packs/gcb-core-*.tgz /packs/gcb-client-*.tgz \ && rm -rf /packs /root/.npm /tmp/* \ && find /usr/local/lib/node_modules/gcb-*/lib -type f -name '*.map' -delete \ && npm cache clean --force @@ -50,7 +50,7 @@ RUN --mount=type=cache,id=apt_cache,target=/var/cache/apt,sharing=locked \ FROM host-base AS host COPY --from=build /packs /packs -RUN npm install -g --omit=dev /packs/gcb-cli-*.tgz /packs/gcb-host-*.tgz \ +RUN npm install -g --omit=dev /packs/gcb-core-*.tgz /packs/gcb-host-*.tgz \ && rm -rf /packs /root/.npm /tmp/* \ && find /usr/local/lib/node_modules/gcb-*/lib -type f -name '*.map' -delete \ && npm cache clean --force diff --git a/README.md b/README.md index b016b56b..f4dfec71 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,8 @@ dependencies: ```sh git clone https://github.com/code-vaults/git-credential-broker /opt/gcb cd /opt/gcb && corepack yarn install -node --conditions=gcb-development packages/client/bin/gcb.js --help -node --conditions=gcb-development packages/host/bin/gcb.js --help +node --conditions=development packages/client/bin/gcb.js --help +node --conditions=development packages/host/bin/gcb.js --help ``` Keep the checkout outside every container mount. @@ -101,11 +101,11 @@ Keep the checkout outside every container mount. ## GitHub actions The action path is wired through the broker; the host image must include `gh` before these commands -can run. The container never receives the token. Build the image, then pass `--image code-vaults/gcb-host:dev` to +can run. The container never receives the token. Build the image, then pass `--image ghcr.io/code-vaults/gcb-host:dev` to the compose command in [Quick start](#quick-start-sidecar): ```sh -docker build --target host -t code-vaults/gcb-host:dev . +docker build --target host -t ghcr.io/code-vaults/gcb-host:dev . ``` The image's `CMD` starts `gcb daemon`, but `compose` still renders the registry-fetching `npx` @@ -137,7 +137,7 @@ Inside a checkout, `--repo` can be omitted only when `origin` names a usable Git host matches `--host`; otherwise pass `--repo`, or the matching `--host`. The exact command, flags and required values come from -[`packages/cli/src/actions.ts`](packages/cli/src/actions.ts); `gcb gh --help` renders that catalog. +[`packages/core/src/actions.ts`](packages/core/src/actions.ts); `gcb gh --help` renders that catalog. ## Set up the GitHub App first @@ -146,7 +146,7 @@ The exact command, flags and required values come from should open pull requests, **Actions: Read** for `logs`, and **Checks: Read** / **Statuses: Read** / **Issues: Read and write** for the corresponding `gcb gh` actions. Grant them in the app, not only in the request. The per-action source of truth is the catalog in - [`packages/cli/src/actions.ts`](packages/cli/src/actions.ts). + [`packages/core/src/actions.ts`](packages/core/src/actions.ts). 3. Install the app on the account that owns the repositories, granting access to those alone. 4. Download the **private key**; note the **App ID** and **Client ID**. 5. Ignore the client secret — this tool never uses it. Installation tokens are obtained by signing a @@ -293,7 +293,7 @@ path, because a relative one is resolved against the current directory, which is checkout: ```sh -node --conditions=gcb-development /srv/git-cred-broker/packages/client/bin/gcb.js logs \ +node --conditions=development /srv/git-cred-broker/packages/client/bin/gcb.js logs \ --socket /srv/git-cred-broker/broker.sock \ --host github.com --repo owner/repo --job 1234567890 ``` @@ -578,7 +578,7 @@ this working, and the traps it already paid for, are in [AGENTS.md](AGENTS.md). ## Layout ``` -packages/cli/src/ shared parser, protocol, types, platform helpers and the gh action catalog +packages/core/src/ shared parser, protocol, types, platform helpers and the gh action catalog packages/client/src/ credential helper, setup, probe, logs, pr, gh packages/host/src/ YAML config, providers, broker, daemon and host commands packages/*/bin/ the two installed gcb bins (client and host) @@ -605,43 +605,43 @@ The contract between the pushing container and the broker is deliberately small: ## Images -Two images, in separate registries/repositories, mirror the two packages: +Two GHCR repositories mirror the two packages: | Image | Contents | Use | |---|---|---| -| `code-vaults/gcb-client:dev` | `gcb` client and Node runtime only | idsh base / `COPY --from` | -| `code-vaults/gcb-host:dev` | broker, `gh`, and broker dependencies | run `gcb daemon` on the host | +| `ghcr.io/code-vaults/gcb-client:dev` | `gcb` client and Node runtime only | idsh base / `COPY --from` | +| `ghcr.io/code-vaults/gcb-host:dev` | broker, `gh`, and broker dependencies | run `gcb daemon` on the host | -Published equivalents are the same names on GHCR: -`ghcr.io/code-vaults/gcb-client:dev` and `ghcr.io/code-vaults/gcb-host:dev`. A -GitHub repository can publish both packages; they share the source repository without sharing a tag. +The release publishes both repositories with `latest`, `` and `sha-` tags. The +`:dev` tags are local build tags and are not published; do not pull them from GHCR. -For local development, build and reuse the same tags: +For local development, build and reuse the `:dev` tags: ```sh -docker build --target client -t code-vaults/gcb-client:dev . -docker build --target host -t code-vaults/gcb-host:dev . +docker build --target client -t ghcr.io/code-vaults/gcb-client:dev . +docker build --target host -t ghcr.io/code-vaults/gcb-host:dev . ``` -While the image exists locally, Docker uses it instead of pulling from the registry; another machine -or CI pulls the same tags. +While the image exists locally, Docker uses it instead of pulling from the registry. Another machine +or CI builds the same Dockerfile and tags, rather than pulling `:dev`. For idsh's dev image, name the client image as a stage and copy only the gcb packages into the base: ```dockerfile ARG BASE=devockr/idsh:base -ARG GCB_CLIENT_IMAGE=code-vaults/gcb-client:dev +ARG GCB_CLIENT_IMAGE=ghcr.io/code-vaults/gcb-client:dev FROM ${GCB_CLIENT_IMAGE} AS gcb-client FROM ${BASE} -COPY --from=gcb-client /usr/local/lib/node_modules/gcb-cli /usr/local/lib/node_modules/gcb-cli +COPY --from=gcb-client /usr/local/lib/node_modules/gcb-core /usr/local/lib/node_modules/gcb-core COPY --from=gcb-client /usr/local/lib/node_modules/gcb-client /usr/local/lib/node_modules/gcb-client RUN ln -s /usr/local/lib/node_modules/gcb-client/bin/gcb.js /usr/local/bin/gcb ``` Copy the two package directories, not all of `/usr/local/lib/node_modules`: the idsh base already has -its own `corepack` and `npm`, and a whole-directory copy would replace them. A CI build passes -`--build-arg GCB_CLIENT_IMAGE=ghcr.io/code-vaults/gcb-client:dev` instead. +its own `corepack` and `npm`, and a whole-directory copy would replace them. That default is for a +local build; CI and production pass a published version instead, e.g. +`--build-arg GCB_CLIENT_IMAGE=ghcr.io/code-vaults/gcb-client:`. ## App permissions by action diff --git a/ROADMAP.md b/ROADMAP.md index f691d75c..b538a3e1 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -34,7 +34,7 @@ host-user delegation/live reload are not implemented. not a boundary. - **Configuration becomes human-editable** (YAML, see Phase 1), with groups and globs. `yaml` is a dependency of the host package, not a bundled artifact. -- **Three packages, one command.** `gcb-cli` is the shared runtime; `gcb-client` and `gcb-host` are the +- **Three packages, one command.** `gcb-core` is the shared runtime; `gcb-client` and `gcb-host` are the installed entry points and both expose `gcb`. The container never installs host dependencies. - **The dsh approval plugin lives in `../idsh`.** This repository only carries its roadmap item and the container-facing skill. @@ -92,9 +92,9 @@ The configuration is the source of truth and must be comfortable to edit by hand - [x] Use YAML. `yaml` is the parser: `parseDocument` preserves comments and formatting, it is pure JavaScript, and the Document API is what lets `init` update one value without rewriting the file. - [x] Split the repository into Yarn workspaces under `packages/`: - - `gcb-cli`: shared argument parsing, help, protocol and types; no `yaml`; - - `gcb-client`: container side; depends on `gcb-cli`; no host dependencies; - - `gcb-host`: host side; depends on `gcb-cli` and `yaml`; + - `gcb-core`: shared argument parsing, help, protocol and types; no `yaml`; + - `gcb-client`: container side; depends on `gcb-core`; no host dependencies; + - `gcb-host`: host side; depends on `gcb-core` and `yaml`; - both client and host expose the same `gcb` bin; only one is installed per environment. - [x] Do **not** bundle. npm installs dependencies; remove esbuild and the staged bundle build. `stage`, if kept, exports a commit and does not build a self-contained artifact. diff --git a/examples/docker-compose.snippet.yml b/examples/docker-compose.snippet.yml index 3e4f74db..a66ee43e 100644 --- a/examples/docker-compose.snippet.yml +++ b/examples/docker-compose.snippet.yml @@ -91,8 +91,9 @@ services: - /srv/git-broker-socket:/run/git-broker ``` -Pin a version (`npx --yes --package 'gcb-host@0.1.0'`) if you would rather not -resolve `latest` on every start; `compose` pins the version it was generated from. +Pin a released version (`npx --yes --package 'gcb-host@'`) if you would rather not +resolve `latest` on every start; `compose` pins the version it was generated from. The first +functional release is `0.0.1`; `0.0.0` is an empty placeholder. ## 2. DSH container: reach the socket and configure git diff --git a/package.json b/package.json index cad319ef..1b90ce04 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "gcb-workspace", - "version": "0.1.0", + "version": "0.0.0", "private": true, - "description": "Workspace for gcb-cli, gcb-client and gcb-host.", + "description": "Workspace for gcb-core, gcb-client and gcb-host.", "license": "MIT", "author": "JounQin ", "homepage": "https://github.com/code-vaults/git-credential-broker#readme", @@ -22,17 +22,22 @@ "packages/*" ], "scripts": { - "build": "node scripts/clean-build.mjs && tsc -p packages/cli/tsconfig.build.json && tsc -p packages/client/tsconfig.build.json && tsc -p packages/host/tsconfig.build.json && node scripts/postbuild.mjs", + "build": "node scripts/clean-build.mjs && tsc -p packages/core/tsconfig.build.json && tsc -p packages/client/tsconfig.build.json && tsc -p packages/host/tsconfig.build.json && node scripts/postbuild.mjs", "typecheck": "tsc -p tsconfig.json", - "test": "yarn build && node --conditions=gcb-development --disable-warning=ExperimentalWarning --test test/unit/*.test.ts test/e2e/*.test.ts", - "test:unit": "node --conditions=gcb-development --disable-warning=ExperimentalWarning --test test/unit/*.test.ts", - "test:e2e": "yarn build && node --conditions=gcb-development --disable-warning=ExperimentalWarning --test test/e2e/*.test.ts", + "test": "yarn build && node --conditions=development --disable-warning=ExperimentalWarning --test test/unit/*.test.ts test/e2e/*.test.ts", + "test:unit": "node --conditions=development --disable-warning=ExperimentalWarning --test test/unit/*.test.ts", + "test:e2e": "yarn build && node --conditions=development --disable-warning=ExperimentalWarning --test test/e2e/*.test.ts", "check": "yarn typecheck && yarn test", "pack:check": "yarn build && node scripts/pack-check.mjs", - "prepublishOnly": "yarn check" + "prepublishOnly": "yarn check", + "version": "changeset version && yarn install --mode=update-lockfile", + "release": "changeset publish" }, "devDependencies": { + "@changesets/changelog-github": "^1.0.1", + "@changesets/cli": "^3.0.3", "@types/node": "^24.19.0", + "clean-pkg-json": "^2.0.0", "typescript": "^7.0.2", "yaml": "^2.9.1" } diff --git a/packages/client/bin/gcb.js b/packages/client/bin/gcb.js index 77064999..e17f8be2 100644 --- a/packages/client/bin/gcb.js +++ b/packages/client/bin/gcb.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { runCli } from 'gcb-cli'; +import { runCli } from 'gcb-core'; import { clientBackend, runHelper } from 'gcb-client'; const argv = process.argv.slice(2); diff --git a/packages/client/package.json b/packages/client/package.json index ad593a86..063f77a5 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "gcb-client", - "version": "0.1.0", + "version": "0.0.0", "description": "Container-side gcb client: credential helper, setup, and socket-backed commands.", "license": "MIT", "author": "JounQin ", @@ -22,16 +22,19 @@ ], "exports": { ".": { - "gcb-development": "./src/index.ts", + "development": "./src/index.ts", "types": "./lib/index.d.ts", "default": "./lib/index.js" } }, "dependencies": { - "gcb-cli": "0.1.0" + "gcb-core": "0.0.0" }, "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" + }, + "scripts": { + "prepack": "clean-pkg-json" } } diff --git a/packages/client/src/commands/gh.ts b/packages/client/src/commands/gh.ts index f1a39735..ec4a2b52 100644 --- a/packages/client/src/commands/gh.ts +++ b/packages/client/src/commands/gh.ts @@ -4,7 +4,7 @@ * The action catalog defines the command, flags, positionals and permissions. The client only * parses names and values; the broker rebuilds the canonical argv and runs gh with its own token. */ -import { GH_ACTIONS, getGhAction, parseArgs, say, fail, type ActionValues } from 'gcb-cli'; +import { GH_ACTIONS, getGhAction, parseArgs, say, fail, type ActionValues } from 'gcb-core'; import { requestOverSocket, resolveSocketPath } from '../helper.ts'; import { remoteRepo } from './remotes.ts'; diff --git a/packages/client/src/commands/logs.ts b/packages/client/src/commands/logs.ts index 7b4bc287..16bad269 100644 --- a/packages/client/src/commands/logs.ts +++ b/packages/client/src/commands/logs.ts @@ -8,7 +8,7 @@ * Exit codes: 0 read, 1 refused, 3 broker unreachable. */ import { requestOverSocket, resolveSocketPath } from '../helper.ts'; -import { fail, parseArgs, say } from 'gcb-cli'; +import { fail, parseArgs, say } from 'gcb-core'; /** * How long to wait for the broker. diff --git a/packages/client/src/commands/pr.ts b/packages/client/src/commands/pr.ts index ec3d1956..fb5471f4 100644 --- a/packages/client/src/commands/pr.ts +++ b/packages/client/src/commands/pr.ts @@ -21,11 +21,11 @@ import { removeResult, waitForResult, writeRequest, -} from 'gcb-cli'; +} from 'gcb-core'; import { requestOverSocket, resolveSocketPath } from '../helper.ts'; import { baseBranchFor, qualifiedBranch, remoteRepo } from './remotes.ts'; import { runGh } from './gh.ts'; -import { fail, parseArgs, say } from 'gcb-cli'; +import { fail, parseArgs, say } from 'gcb-core'; /** Every flag the flag-only lifecycle understands. */ const KNOWN_FLAGS = new Set([ diff --git a/packages/client/src/commands/probe.ts b/packages/client/src/commands/probe.ts index 8c0b286e..1ab911b9 100644 --- a/packages/client/src/commands/probe.ts +++ b/packages/client/src/commands/probe.ts @@ -5,9 +5,9 @@ * reports the decision with the credential reduced to a fingerprint, so the output is safe to * paste anywhere. Exit codes: 0 allowed, 1 denied, 3 broker unreachable. */ -import { tokenFingerprint } from 'gcb-cli'; +import { tokenFingerprint } from 'gcb-core'; import { requestOverSocket, resolveSocketPath } from '../helper.ts'; -import { fail, parseArgs, say } from 'gcb-cli'; +import { fail, parseArgs, say } from 'gcb-core'; /** Usage text for `probe`. */ export const PROBE_USAGE = `Usage: gcb probe [options] diff --git a/packages/client/src/commands/setup.ts b/packages/client/src/commands/setup.ts index 4db4f9fe..abdb35a8 100644 --- a/packages/client/src/commands/setup.ts +++ b/packages/client/src/commands/setup.ts @@ -32,7 +32,7 @@ import { warn, writeNodeCaBundle, writeSecretFile, -} from 'gcb-cli'; +} from 'gcb-core'; /** Everything `setup` needs, resolved. */ export interface SetupInput { diff --git a/packages/client/src/helper.ts b/packages/client/src/helper.ts index 77a73231..526ed989 100644 --- a/packages/client/src/helper.ts +++ b/packages/client/src/helper.ts @@ -35,8 +35,8 @@ import { homedir } from 'node:os'; import path from 'node:path'; import type { Readable, Writable } from 'node:stream'; -import { asWireResponse, encodeMessage, parseMessage } from 'gcb-cli'; -import type { WireResponse } from 'gcb-cli'; +import { asWireResponse, encodeMessage, parseMessage } from 'gcb-core'; +import type { WireResponse } from 'gcb-core'; /** Ceiling for the description git sends us. */ const MAX_INPUT_BYTES = 8 * 1024; diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 39e730ca..8a388511 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -3,8 +3,8 @@ * * The host commands are not imported here; installing `gcb-client` never pulls `yaml`. */ -import { GH_ACTIONS } from 'gcb-cli'; -import type { CommandBackend } from 'gcb-cli'; +import { GH_ACTIONS } from 'gcb-core'; +import type { CommandBackend } from 'gcb-core'; export { runHelper } from './helper.ts'; diff --git a/packages/cli/package.json b/packages/core/package.json similarity index 82% rename from packages/cli/package.json rename to packages/core/package.json index 8829c89e..5dded5d9 100644 --- a/packages/cli/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { - "name": "gcb-cli", - "version": "0.1.0", + "name": "gcb-core", + "version": "0.0.0", "description": "Shared command runtime and protocol for gcb-client and gcb-host.", "license": "MIT", "author": "JounQin ", @@ -18,7 +18,7 @@ ], "exports": { ".": { - "gcb-development": "./src/index.ts", + "development": "./src/index.ts", "types": "./lib/index.d.ts", "default": "./lib/index.js" } @@ -26,5 +26,8 @@ "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" + }, + "scripts": { + "prepack": "clean-pkg-json" } } diff --git a/packages/cli/src/actions.ts b/packages/core/src/actions.ts similarity index 100% rename from packages/cli/src/actions.ts rename to packages/core/src/actions.ts diff --git a/packages/cli/src/errors.ts b/packages/core/src/errors.ts similarity index 100% rename from packages/cli/src/errors.ts rename to packages/core/src/errors.ts diff --git a/packages/cli/src/fingerprint.ts b/packages/core/src/fingerprint.ts similarity index 100% rename from packages/cli/src/fingerprint.ts rename to packages/core/src/fingerprint.ts diff --git a/packages/cli/src/host-request.ts b/packages/core/src/host-request.ts similarity index 100% rename from packages/cli/src/host-request.ts rename to packages/core/src/host-request.ts diff --git a/packages/cli/src/index.ts b/packages/core/src/index.ts similarity index 100% rename from packages/cli/src/index.ts rename to packages/core/src/index.ts diff --git a/packages/cli/src/paths.ts b/packages/core/src/paths.ts similarity index 100% rename from packages/cli/src/paths.ts rename to packages/core/src/paths.ts diff --git a/packages/cli/src/platform.ts b/packages/core/src/platform.ts similarity index 100% rename from packages/cli/src/platform.ts rename to packages/core/src/platform.ts diff --git a/packages/cli/src/socket-protocol.ts b/packages/core/src/socket-protocol.ts similarity index 100% rename from packages/cli/src/socket-protocol.ts rename to packages/core/src/socket-protocol.ts diff --git a/packages/cli/src/support.ts b/packages/core/src/support.ts similarity index 100% rename from packages/cli/src/support.ts rename to packages/core/src/support.ts diff --git a/packages/cli/src/types.ts b/packages/core/src/types.ts similarity index 100% rename from packages/cli/src/types.ts rename to packages/core/src/types.ts diff --git a/packages/cli/src/version.ts b/packages/core/src/version.ts similarity index 100% rename from packages/cli/src/version.ts rename to packages/core/src/version.ts diff --git a/packages/cli/tsconfig.build.json b/packages/core/tsconfig.build.json similarity index 100% rename from packages/cli/tsconfig.build.json rename to packages/core/tsconfig.build.json diff --git a/packages/cli/tsconfig.json b/packages/core/tsconfig.json similarity index 100% rename from packages/cli/tsconfig.json rename to packages/core/tsconfig.json diff --git a/packages/host/bin/gcb.js b/packages/host/bin/gcb.js index 7c09900e..8d1834fe 100644 --- a/packages/host/bin/gcb.js +++ b/packages/host/bin/gcb.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { runCli } from 'gcb-cli'; +import { runCli } from 'gcb-core'; import { hostBackend } from 'gcb-host'; process.exitCode = await runCli(process.argv.slice(2), hostBackend); diff --git a/packages/host/package.json b/packages/host/package.json index 070fc905..7c1a3fd5 100644 --- a/packages/host/package.json +++ b/packages/host/package.json @@ -1,6 +1,6 @@ { "name": "gcb-host", - "version": "0.1.0", + "version": "0.0.0", "description": "Host-side gcb broker, configuration, providers and administration commands.", "license": "MIT", "author": "JounQin ", @@ -22,13 +22,13 @@ ], "exports": { ".": { - "gcb-development": "./src/index.ts", + "development": "./src/index.ts", "types": "./lib/index.d.ts", "default": "./lib/index.js" } }, "dependencies": { - "gcb-cli": "0.1.0", + "gcb-core": "0.0.0", "node-fetch-native": "^1.6.7", "x-fetch": "^0.3.0", "yaml": "^2.9.1" @@ -36,5 +36,8 @@ "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" + }, + "scripts": { + "prepack": "clean-pkg-json" } } diff --git a/packages/host/src/audit.ts b/packages/host/src/audit.ts index 15cb5cbb..ea235a2e 100644 --- a/packages/host/src/audit.ts +++ b/packages/host/src/audit.ts @@ -10,7 +10,7 @@ import { chmodSync, closeSync, createWriteStream, mkdirSync, openSync } from 'no import type { WriteStream } from 'node:fs'; import { dirname } from 'node:path'; -import type { AuditSink } from 'gcb-cli'; +import type { AuditSink } from 'gcb-core'; /** * Keys whose values must never reach the audit log. diff --git a/packages/host/src/broker.ts b/packages/host/src/broker.ts index c4e614ae..4dfe3d3a 100644 --- a/packages/host/src/broker.ts +++ b/packages/host/src/broker.ts @@ -21,6 +21,7 @@ import fs from 'node:fs'; import { parseProxy, withProxy, type ProxyChoice } from './http.ts'; import { buildGhArgv, + PACKAGE_VERSION, getGhAction, MAX_BODY_CHARS, MAX_MESSAGE_BYTES, @@ -33,15 +34,15 @@ import { parseMessage, socketPathRefusal, tokenFingerprint, -} from 'gcb-cli'; +} from 'gcb-core'; import net from 'node:net'; import path from 'node:path'; import { hostConfig, normalizeRepoPath, repoAllowed } from './policy.ts'; -import type { ActionValues, AuditSink, BrokerConfig, Provider, WireResponse } from 'gcb-cli'; +import type { ActionValues, AuditSink, BrokerConfig, Provider, WireResponse } from 'gcb-core'; /** Reported by the `ping` operation so the container side can prove what it reached. */ -export const BROKER_VERSION = '0.1.0'; +export const BROKER_VERSION = PACKAGE_VERSION; /** How long one socket connection may stay idle before it is dropped. */ // How long a connection may stay silent before it is dropped. It has to outlast the longest wait a client diff --git a/packages/host/src/commands/authorize.ts b/packages/host/src/commands/authorize.ts index b1e65ee8..9c433e22 100644 --- a/packages/host/src/commands/authorize.ts +++ b/packages/host/src/commands/authorize.ts @@ -19,7 +19,7 @@ import { dirname, join, resolve as resolvePath } from 'node:path'; import { USER_TOKEN_FILE, userTokenPath, loadConfig, resolveConfigPath } from '../config.ts'; import { collectUserToken, startDeviceFlow, type Fetcher } from '../device-flow.ts'; import { fetcherFor, parseProxy } from '../http.ts'; -import { fail, insideMountedPath, isInsideContainer, parseArgs, say, writeSecretFile } from 'gcb-cli'; +import { fail, insideMountedPath, isInsideContainer, parseArgs, say, writeSecretFile } from 'gcb-core'; /** Usage text for `authorize`. */ export const AUTHORIZE_USAGE = `Usage: gcb authorize [options] diff --git a/packages/host/src/commands/compose.ts b/packages/host/src/commands/compose.ts index 1a66f396..5f4bef30 100644 --- a/packages/host/src/commands/compose.ts +++ b/packages/host/src/commands/compose.ts @@ -13,8 +13,8 @@ import fs from 'node:fs'; import path from 'node:path'; import { inferMode, loadConfig, resolveConfigPath, deploymentDir, SIDECAR } from '../config.ts'; -import { PACKAGE_VERSION } from 'gcb-cli'; -import { fail, parseArgs, say, warn } from 'gcb-cli'; +import { PACKAGE_VERSION } from 'gcb-core'; +import { fail, parseArgs, say, warn } from 'gcb-core'; import { USER_TOKEN_FILE } from '../config.ts'; /** Everything `compose` needs, resolved. */ @@ -29,7 +29,7 @@ export interface ComposeInput { readonly user: string; /** Base image. */ readonly image: string; - /** npm spec to run, e.g. `gcb@0.1.0`. */ + /** npm spec to run, e.g. `gcb@0.0.0`. */ readonly packageSpec: string; /** Compose service and container name. */ readonly name: string; @@ -96,7 +96,7 @@ export function renderCompose(input: ComposeInput): string { : '\n # No user.refresh yet: run `gcb authorize` and render this again. A mount' + '\n # for a path that does not exist would become a directory, and the broker would read that.'; const start = fromCode - ? `exec node --conditions=gcb-development ${CODE_DIR}/packages/host/bin/gcb.js daemon --config ${SIDECAR.configPath}` + ? `exec node --conditions=development ${CODE_DIR}/packages/host/bin/gcb.js daemon --config ${SIDECAR.configPath}` : `exec npx --yes --package '${input.packageSpec}' gcb daemon --config ${SIDECAR.configPath}`; const command = ` - sh - -c diff --git a/packages/host/src/commands/diagnose.ts b/packages/host/src/commands/diagnose.ts index 66be0439..e5e1d53f 100644 --- a/packages/host/src/commands/diagnose.ts +++ b/packages/host/src/commands/diagnose.ts @@ -18,8 +18,8 @@ import { readFileSync } from 'node:fs'; import { assertKeysReadable, loadConfig, resolveConfigPath } from '../config.ts'; import { nextLink, signAppJwt } from '../providers/github-app.ts'; import { fetcherFor, parseProxy } from '../http.ts'; -import type { GithubAppHostConfig } from 'gcb-cli'; -import { fail, parseArgs, say, warn } from 'gcb-cli'; +import type { GithubAppHostConfig } from 'gcb-core'; +import { fail, parseArgs, say, warn } from 'gcb-core'; /** One installation, as far as this command cares. */ interface Installation { diff --git a/packages/host/src/commands/host-opener.ts b/packages/host/src/commands/host-opener.ts index d87ac6a1..d4d883ab 100644 --- a/packages/host/src/commands/host-opener.ts +++ b/packages/host/src/commands/host-opener.ts @@ -29,8 +29,8 @@ import { writeResult, type HostOpenRequest, type HostOpenResult, -} from 'gcb-cli'; -import { fail, listFlag, parseArgs, say, warn } from 'gcb-cli'; +} from 'gcb-core'; +import { fail, listFlag, parseArgs, say, warn } from 'gcb-core'; import { applyProxyChoice, parseProxy, type ProxyChoice } from '../http.ts'; const run = promisify(execFile); diff --git a/packages/host/src/commands/init.ts b/packages/host/src/commands/init.ts index 3eb9a7ba..70b81acb 100644 --- a/packages/host/src/commands/init.ts +++ b/packages/host/src/commands/init.ts @@ -28,7 +28,7 @@ import { type DeploymentMode, } from '../config.ts'; import { parseAllowEntry } from '../policy.ts'; -import type { BrokerConfig, GithubAppHostConfig } from 'gcb-cli'; +import type { BrokerConfig, GithubAppHostConfig } from 'gcb-core'; import { brokerPaths, DEPLOYMENT_MODES, @@ -37,7 +37,7 @@ import { requireFixedInSidecar, } from './deployment.ts'; import type { BrokerPaths } from './deployment.ts'; -import { fail, insideMountedPath, isInsideContainer, parseArgs, say, writeSecretFile } from 'gcb-cli'; +import { fail, insideMountedPath, isInsideContainer, parseArgs, say, writeSecretFile } from 'gcb-core'; /** The environment `init` reasons about, injectable so the guard rails can be tested. */ export interface InitEnvironment { diff --git a/packages/host/src/commands/stage.ts b/packages/host/src/commands/stage.ts index b3c3cbc9..26288d4f 100644 --- a/packages/host/src/commands/stage.ts +++ b/packages/host/src/commands/stage.ts @@ -21,8 +21,8 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import { canonicalPath } from 'gcb-cli'; -import { fail, insideMountedPath, parseArgs, say, warn, writeSecretFile } from 'gcb-cli'; +import { canonicalPath } from 'gcb-core'; +import { fail, insideMountedPath, parseArgs, say, warn, writeSecretFile } from 'gcb-core'; /** The record `stage` leaves behind, so the running code is identifiable afterwards. */ export const STAGED_RECORD = 'STAGED.json'; @@ -178,7 +178,7 @@ agent can write to is a repository whose commits the agent can rewrite. Then run it from there — Node strips types, so there is nothing to build: corepack yarn install # in ; stage itself does not run commit code - node --conditions=gcb-development /packages/host/bin/gcb.js daemon --config /broker.config.yml + node --conditions=development /packages/host/bin/gcb.js daemon --config /broker.config.yml `; /** diff --git a/packages/host/src/config.ts b/packages/host/src/config.ts index 1f16db9e..eeaea59b 100644 --- a/packages/host/src/config.ts +++ b/packages/host/src/config.ts @@ -9,7 +9,7 @@ import path, { posix } from 'node:path'; import { parseDocument } from 'yaml'; import { parseAllowEntry } from './policy.ts'; -import type { BrokerConfig, GithubAppHostConfig, HostConfig, StaticHostConfig } from 'gcb-cli'; +import type { BrokerConfig, GithubAppHostConfig, HostConfig, StaticHostConfig } from 'gcb-core'; /** The file every command looks for when no configuration path is given. */ export const DEFAULT_CONFIG_FILE = 'broker.config.yml'; diff --git a/packages/host/src/daemon.ts b/packages/host/src/daemon.ts index 67a40508..f7a8f185 100644 --- a/packages/host/src/daemon.ts +++ b/packages/host/src/daemon.ts @@ -14,7 +14,7 @@ import { startBroker } from './broker.ts'; import { assertKeysReadable, assertUserTokensReadable, loadConfig, resolveConfigPath } from './config.ts'; import { createProvider } from './providers/index.ts'; import type { ProviderDeps } from './providers/index.ts'; -import type { BrokerConfig, Provider } from 'gcb-cli'; +import type { BrokerConfig, Provider } from 'gcb-core'; /** Usage text. */ const USAGE = diff --git a/packages/host/src/gh.ts b/packages/host/src/gh.ts index 9cfaff6f..c95acc49 100644 --- a/packages/host/src/gh.ts +++ b/packages/host/src/gh.ts @@ -11,7 +11,7 @@ import { tmpdir } from 'node:os'; import { StringDecoder } from 'node:string_decoder'; import path from 'node:path'; -import { buildGhArgv, getGhAction, type ActionValues } from 'gcb-cli'; +import { buildGhArgv, getGhAction, type ActionValues } from 'gcb-core'; import { applyProxyChoice, PROXY_ENV_KEYS } from './http.ts'; /** The default stdout/stderr ceiling, in bytes per stream. */ diff --git a/packages/host/src/http.ts b/packages/host/src/http.ts index 7d39355e..40268686 100644 --- a/packages/host/src/http.ts +++ b/packages/host/src/http.ts @@ -14,7 +14,7 @@ import https from 'node:https'; import { createProxy } from 'node-fetch-native/proxy'; import { fetch as directFetch } from 'node-fetch-native/node'; import { createXFetch, isXFetchError, type XFetchMiddleware } from 'x-fetch'; -import type { FetchLike } from 'gcb-cli'; +import type { FetchLike } from 'gcb-core'; /** A command's proxy choice: omitted keeps the host environment, null is direct. */ export type ProxyChoice = string | null | undefined; diff --git a/packages/host/src/index.ts b/packages/host/src/index.ts index 45744176..e8caf537 100644 --- a/packages/host/src/index.ts +++ b/packages/host/src/index.ts @@ -3,7 +3,7 @@ * * This is the only side that imports `yaml` (through config.ts) and holds the App key. */ -import type { CommandBackend } from 'gcb-cli'; +import type { CommandBackend } from 'gcb-core'; import { assertProxyEnabled } from './proxy.ts'; export * from './gh.ts'; diff --git a/packages/host/src/policy.ts b/packages/host/src/policy.ts index e6a24362..20f9a7fd 100644 --- a/packages/host/src/policy.ts +++ b/packages/host/src/policy.ts @@ -12,7 +12,7 @@ * - a wildcard is allowed only as a whole segment, never inside one, so a malformed entry * matches nothing and therefore fails closed. */ -import type { BrokerConfig, HostConfig, RepoRef } from 'gcb-cli'; +import type { BrokerConfig, HostConfig, RepoRef } from 'gcb-core'; /** One `owner` or `repo` segment: starts alphanumeric, then letters/digits/._- */ const SEGMENT_RE = /^[a-z0-9][a-z0-9._-]*$/; diff --git a/packages/host/src/providers/github-app.ts b/packages/host/src/providers/github-app.ts index 49c56861..64ee2669 100644 --- a/packages/host/src/providers/github-app.ts +++ b/packages/host/src/providers/github-app.ts @@ -20,15 +20,15 @@ import { userTokenPath } from '../config.ts'; import { currentProxyKey, proxyFetch } from '../http.ts'; import { createSign } from 'node:crypto'; -import { getGhAction, ProviderConfigError, tokenFingerprint, type ActionRunResult } from 'gcb-cli'; +import { getGhAction, ProviderConfigError, tokenFingerprint, type ActionRunResult } from 'gcb-core'; import { runGhAction } from '../gh.ts'; import { existsSync, readFileSync, writeFileSync } from 'node:fs'; import { refreshUserToken } from '../device-flow.ts'; -import type { Credential, FetchLike, FetchResponseLike, GithubAppHostConfig, Provider } from 'gcb-cli'; -import type { JobLog, JobLogRequest } from 'gcb-cli'; -import type { PullRequest, PullRequestRequest } from 'gcb-cli'; +import type { Credential, FetchLike, FetchResponseLike, GithubAppHostConfig, Provider } from 'gcb-core'; +import type { JobLog, JobLogRequest } from 'gcb-core'; +import type { PullRequest, PullRequestRequest } from 'gcb-core'; /** REST API origin. Overridable for GitHub Enterprise. */ const DEFAULT_API = 'https://api.github.com'; diff --git a/packages/host/src/providers/index.ts b/packages/host/src/providers/index.ts index f00f47ae..27b0910e 100644 --- a/packages/host/src/providers/index.ts +++ b/packages/host/src/providers/index.ts @@ -5,7 +5,7 @@ * broker, the helper, the socket protocol, the allowlist and the audit trail are all * provider-agnostic. */ -import type { FetchLike, HostConfig, Provider } from 'gcb-cli'; +import type { FetchLike, HostConfig, Provider } from 'gcb-core'; import { createGithubAppProvider } from './github-app.ts'; import { createStaticProvider } from './static.ts'; diff --git a/packages/host/src/providers/static.ts b/packages/host/src/providers/static.ts index e9075eb2..57fa18bf 100644 --- a/packages/host/src/providers/static.ts +++ b/packages/host/src/providers/static.ts @@ -12,7 +12,7 @@ */ import { readFileSync } from 'node:fs'; -import type { Credential, Provider, StaticHostConfig } from 'gcb-cli'; +import type { Credential, Provider, StaticHostConfig } from 'gcb-core'; /** Options for {@link createStaticProvider}. */ export interface StaticProviderOptions { diff --git a/scripts/clean-build.mjs b/scripts/clean-build.mjs index e582918f..715a826b 100644 --- a/scripts/clean-build.mjs +++ b/scripts/clean-build.mjs @@ -3,6 +3,6 @@ import { rmSync } from 'node:fs'; import path from 'node:path'; const root = path.resolve(import.meta.dirname, '..'); -for (const name of ['cli', 'client', 'host']) { +for (const name of ['core', 'client', 'host']) { rmSync(path.join(root, 'packages', name, 'lib'), { recursive: true, force: true }); } diff --git a/scripts/pack-check.mjs b/scripts/pack-check.mjs index c3c5c711..b3dd9e21 100644 --- a/scripts/pack-check.mjs +++ b/scripts/pack-check.mjs @@ -12,7 +12,7 @@ import path from 'node:path'; const root = path.resolve(import.meta.dirname, '..'); const scratch = mkdtempSync(path.join(os.tmpdir(), 'gcb-pack-check-')); try { - for (const name of ['cli', 'client', 'host']) { + for (const name of ['core', 'client', 'host']) { console.log(`\n== packages/${name}`); execFileSync('npm', ['pack', path.join(root, 'packages', name), '--dry-run', '--pack-destination', scratch], { cwd: root, diff --git a/test/e2e/packages.test.ts b/test/e2e/packages.test.ts index 68033244..e8da06e0 100644 --- a/test/e2e/packages.test.ts +++ b/test/e2e/packages.test.ts @@ -22,8 +22,13 @@ const hostPrefix = path.join(scratch, 'host'); after(() => fs.rmSync(scratch, { recursive: true, force: true })); /** Run a command and return stdout. */ -function run(command: string, args: readonly string[]): string { - return execFileSync(command, args, { cwd: ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); +function run(command: string, args: readonly string[], env?: NodeJS.ProcessEnv): string { + return execFileSync(command, args, { + cwd: ROOT, + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'pipe'], + ...(env === undefined ? {} : { env }), + }); } /** Run a command that is expected to fail, returning its stderr. */ @@ -40,7 +45,17 @@ function runFailure(command: string, args: readonly string[]): string { function pack(name: string): string { const target = path.join(packs, name); fs.mkdirSync(target, { recursive: true }); - const output = run('npm', ['pack', path.join(ROOT, 'packages', name), '--pack-destination', target]); + const source = path.join(ROOT, 'packages', name); + const copy = path.join(scratch, 'sources', name); + fs.mkdirSync(path.dirname(copy), { recursive: true }); + fs.cpSync(source, copy, { + recursive: true, + filter: (entry) => !entry.includes(`${path.sep}node_modules`), + }); + const output = run('npm', ['pack', copy, '--pack-destination', target], { + ...process.env, + PATH: `${path.join(ROOT, 'node_modules', '.bin')}${path.delimiter}${process.env['PATH'] ?? ''}`, + }); const file = output.trim().split('\n').pop(); assert.ok(file, `npm pack produced no filename for ${name}`); return path.join(target, file); @@ -71,12 +86,12 @@ function bin(prefix: string): string { describe('packed npm packages', () => { before(() => { fs.mkdirSync(packs, { recursive: true }); - const cli = pack('cli'); + const core = pack('core'); const client = pack('client'); const host = pack('host'); - run('npm', ['install', '-g', '--prefix', clientPrefix, '--no-audit', '--no-fund', cli, client]); - run('npm', ['install', '-g', '--prefix', hostPrefix, '--no-audit', '--no-fund', cli, host]); + run('npm', ['install', '-g', '--prefix', clientPrefix, '--no-audit', '--no-fund', core, client]); + run('npm', ['install', '-g', '--prefix', hostPrefix, '--no-audit', '--no-fund', core, host]); }); it('installs a working client without the host parser', () => { diff --git a/test/unit/actions.test.ts b/test/unit/actions.test.ts index 305272d5..4a8ea1d1 100644 --- a/test/unit/actions.test.ts +++ b/test/unit/actions.test.ts @@ -7,8 +7,8 @@ import { GH_ACTIONS, buildGhArgv, getGhAction, -} from '../../packages/cli/src/actions.ts'; -import { MAX_BODY_CHARS, MAX_TITLE_CHARS } from '../../packages/cli/src/host-request.ts'; +} from '../../packages/core/src/actions.ts'; +import { MAX_BODY_CHARS, MAX_TITLE_CHARS } from '../../packages/core/src/host-request.ts'; describe('gh action catalog', () => { it('has the roadmap actions and no merge action', () => { diff --git a/test/unit/broker-lifecycle.test.ts b/test/unit/broker-lifecycle.test.ts index cc9d5d86..d36fec78 100644 --- a/test/unit/broker-lifecycle.test.ts +++ b/test/unit/broker-lifecycle.test.ts @@ -6,9 +6,9 @@ import path from 'node:path'; import { describe, it } from 'node:test'; import { CODES, startBroker } from '../../packages/host/src/broker.ts'; -import { MAX_MESSAGE_BYTES } from '../../packages/cli/src/socket-protocol.ts'; +import { MAX_MESSAGE_BYTES } from '../../packages/core/src/socket-protocol.ts'; import { createStaticProvider } from '../../packages/host/src/providers/static.ts'; -import type { AuditSink, BrokerConfig, Provider, StaticHostConfig, WireResponse } from '../../packages/cli/src/types.ts'; +import type { AuditSink, BrokerConfig, Provider, StaticHostConfig, WireResponse } from '../../packages/core/src/types.ts'; const HOST = 'github.com'; diff --git a/test/unit/broker.test.ts b/test/unit/broker.test.ts index 90f0c192..34ed11e7 100644 --- a/test/unit/broker.test.ts +++ b/test/unit/broker.test.ts @@ -12,12 +12,13 @@ import path from 'node:path'; import { after, describe, it } from 'node:test'; import { redact } from '../../packages/host/src/audit.ts'; -import { tokenFingerprint } from '../../packages/cli/src/fingerprint.ts'; +import { tokenFingerprint } from '../../packages/core/src/fingerprint.ts'; +import { PACKAGE_VERSION } from '../../packages/core/src/version.ts'; import { CODES, createRequestHandler, prepareSocketPath } from '../../packages/host/src/broker.ts'; -import { MAX_BODY_CHARS } from '../../packages/cli/src/host-request.ts'; +import { MAX_BODY_CHARS } from '../../packages/core/src/host-request.ts'; import { createStaticProvider } from '../../packages/host/src/providers/static.ts'; -import type { AuditSink, BrokerConfig, Provider, StaticHostConfig, WireResponse } from '../../packages/cli/src/types.ts'; -import { ProviderConfigError } from '../../packages/cli/src/errors.ts'; +import type { AuditSink, BrokerConfig, Provider, StaticHostConfig, WireResponse } from '../../packages/core/src/types.ts'; +import { ProviderConfigError } from '../../packages/core/src/errors.ts'; const HOST = 'github.com'; const SECRET = 'unit-secret-value'; @@ -107,7 +108,7 @@ describe('broker request handling', () => { const { handle } = makeHarness(); const response = await handle({ op: 'ping' }); assert.equal(response.ok, true); - assert.equal(response.version, '0.1.0'); + assert.equal(response.version, PACKAGE_VERSION); assert.deepEqual(response.hosts, [HOST]); }); diff --git a/test/unit/commands.test.ts b/test/unit/commands.test.ts index a46103d5..a651f301 100644 --- a/test/unit/commands.test.ts +++ b/test/unit/commands.test.ts @@ -19,11 +19,11 @@ import { renderCompose, runCompose } from '../../packages/host/src/commands/comp import { runDiagnose } from '../../packages/host/src/commands/diagnose.ts'; import { SIDECAR, loadConfig, resolveConfigPath, deploymentDir } from '../../packages/host/src/config.ts'; import { appBlock, buildBrokerConfig, mergeAllowList, parsePermissions, performInit, resolveInitSelection } from '../../packages/host/src/commands/init.ts'; -import { parseArgs, listFlag, insideMountedPath, mountedPaths } from '../../packages/cli/src/support.ts'; +import { parseArgs, listFlag, insideMountedPath, mountedPaths } from '../../packages/core/src/support.ts'; import { performSetup } from '../../packages/client/src/commands/setup.ts'; -import type { BrokerConfig, GithubAppHostConfig } from '../../packages/cli/src/types.ts'; +import type { BrokerConfig, GithubAppHostConfig } from '../../packages/core/src/types.ts'; import { runProbe } from '../../packages/client/src/commands/probe.ts'; -import { encodeMessage, parseMessage } from '../../packages/cli/src/socket-protocol.ts'; +import { encodeMessage, parseMessage } from '../../packages/core/src/socket-protocol.ts'; import { runAsync } from '../common/run.ts'; /** Scratch space for the whole file. */ @@ -932,7 +932,7 @@ describe('compose', () => { socketDir: '/srv/shared/git-broker', user: '1026:100', image: 'node:24-slim', - packageSpec: 'gcb-host@0.1.0', + packageSpec: 'gcb-host@0.0.0', name: 'git-cred-broker', }); @@ -1022,7 +1022,7 @@ describe('compose', () => { socketDir: '/srv/shared/git-broker', user: '1026:100', image: 'node:24-slim', - packageSpec: 'gcb-host@0.1.0', + packageSpec: 'gcb-host@0.0.0', name: 'git-cred-broker', }); assert.match(custom, /\/srv\/custom\/broker\.yml:\/etc\/git-cred-broker\/broker\.config\.yml:ro/); @@ -1036,7 +1036,7 @@ describe('compose', () => { }); it('runs the daemon from the published package, not from a copied checkout', () => { - assert.match(rendered, /npx --yes --package 'gcb-host@0\.1\.0' gcb daemon/); + assert.match(rendered, /npx --yes --package 'gcb-host@0\.0\.0' gcb daemon/); assert.match(rendered, new RegExp(`--config ${SIDECAR.configPath}`)); }); @@ -1046,13 +1046,13 @@ describe('compose', () => { socketDir: '/srv/shared/git-broker', user: '1026:100', image: 'node:24-slim', - packageSpec: 'gcb-host@0.1.0', + packageSpec: 'gcb-host@0.0.0', name: 'git-cred-broker', code: '/volume1/docker/git-cred-broker/app', }); assert.match(fromCode, /- \/volume1\/docker\/git-cred-broker\/app:\/opt\/gcb:ro/); - assert.match(fromCode, /exec node --conditions=gcb-development \/opt\/gcb\/packages\/host\/bin\/gcb\.js daemon/); + assert.match(fromCode, /exec node --conditions=development \/opt\/gcb\/packages\/host\/bin\/gcb\.js daemon/); assert.equal(/npx/.test(fromCode), false, 'no registry access at start'); assert.equal(/npm_config_cache/.test(fromCode), false, 'and so no cache to write'); assert.match(fromCode, /STAGED\.json/, 'it points at the record of which commit this is'); @@ -1121,7 +1121,7 @@ describe('the anchor flags, at the CLI boundary', () => { const cli = (args: readonly string[]): { status: number; stdout: string; stderr: string } => { try { - execFileSync('node', ['--conditions=gcb-development', 'packages/client/bin/gcb.js', 'pr', ...args], { + execFileSync('node', ['--conditions=development', 'packages/client/bin/gcb.js', 'pr', ...args], { cwd: path.resolve('.'), encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], @@ -1320,7 +1320,7 @@ describe('the anchor flags, at the CLI boundary', () => { await new Promise((resolve) => server.listen(socketPath, resolve)); try { const result = await runAsync(process.execPath, [ - '--conditions=gcb-development', + '--conditions=development', path.resolve('packages/client/bin/gcb.js'), 'pr', '--number', '7', '--status', '--socket', socketPath, ], { @@ -1351,7 +1351,7 @@ describe('the anchor flags, at the CLI boundary', () => { await new Promise((resolve) => server.listen(socketPath, resolve)); try { const result = await runAsync(process.execPath, [ - '--conditions=gcb-development', + '--conditions=development', 'packages/client/bin/gcb.js', 'pr', '--number', '7', '--title', 'a title', '--repo', 'acme/widget', '--socket', socketPath, ], { @@ -1385,7 +1385,7 @@ describe('the anchor flags, at the CLI boundary', () => { await new Promise((resolve) => server.listen(socketPath, resolve)); try { const result = await runAsync(process.execPath, [ - '--conditions=gcb-development', + '--conditions=development', 'packages/client/bin/gcb.js', 'pr', '--number', '7', '--body-file', bodyFile, '--repo', 'acme/widget', '--socket', socketPath, ], { @@ -1415,7 +1415,7 @@ describe('the anchor flags, at the CLI boundary', () => { await new Promise((resolve) => server.listen(socketPath, resolve)); try { const result = await runAsync(process.execPath, [ - '--conditions=gcb-development', + '--conditions=development', 'packages/client/bin/gcb.js', 'pr', '--repo', 'acme/widget', @@ -1438,7 +1438,7 @@ describe('the help path', () => { it('routes gcb help pr to gcb pr --help', () => { const home = fs.mkdtempSync(path.join(os.tmpdir(), 'gcb-help-path-')); try { - const result = execFileSync('node', ['--conditions=gcb-development', 'packages/client/bin/gcb.js', 'help', 'pr'], { + const result = execFileSync('node', ['--conditions=development', 'packages/client/bin/gcb.js', 'help', 'pr'], { cwd: path.resolve('.'), encoding: 'utf8', env: { ...process.env, HOME: home, GIT_BROKER_SOCKET: '', GIT_BROKER_SOCKET_FILE: '' }, diff --git a/test/unit/gh-command.test.ts b/test/unit/gh-command.test.ts index 7ad7b1b7..9d6ad85f 100644 --- a/test/unit/gh-command.test.ts +++ b/test/unit/gh-command.test.ts @@ -8,7 +8,7 @@ import { describe, it } from 'node:test'; import { startBroker } from '../../packages/host/src/broker.ts'; import { tryRunAsync, type RunResult } from '../common/run.ts'; -import type { AuditSink, BrokerConfig, Provider, StaticHostConfig } from '../../packages/cli/src/types.ts'; +import type { AuditSink, BrokerConfig, Provider, StaticHostConfig } from '../../packages/core/src/types.ts'; /** Run the client from source, next to this file rather than from the cwd. */ const CLIENT_BIN = fileURLToPath(new URL('../../packages/client/bin/gcb.js', import.meta.url)); @@ -17,7 +17,7 @@ const CLIENT_BIN = fileURLToPath(new URL('../../packages/client/bin/gcb.js', imp function runClient(args: readonly string[], cwd?: string): Promise { return tryRunAsync( process.execPath, - ['--conditions=gcb-development', CLIENT_BIN, ...args], + ['--conditions=development', CLIENT_BIN, ...args], { cwd, env: process.env, timeoutMs: 5000 }, ); } diff --git a/test/unit/github-app.test.ts b/test/unit/github-app.test.ts index a79357dc..841bf527 100644 --- a/test/unit/github-app.test.ts +++ b/test/unit/github-app.test.ts @@ -33,9 +33,9 @@ import { describe, it } from 'node:test'; import { createGithubAppProvider, nextLink, signAppJwt } from '../../packages/host/src/providers/github-app.ts'; import { createProvider } from '../../packages/host/src/providers/index.ts'; -import { tokenFingerprint } from '../../packages/cli/src/fingerprint.ts'; -import type { FetchLike, FetchResponseLike, GithubAppHostConfig } from '../../packages/cli/src/types.ts'; -import { ProviderConfigError } from '../../packages/cli/src/errors.ts'; +import { tokenFingerprint } from '../../packages/core/src/fingerprint.ts'; +import type { FetchLike, FetchResponseLike, GithubAppHostConfig } from '../../packages/core/src/types.ts'; +import { ProviderConfigError } from '../../packages/core/src/errors.ts'; const { privateKey, publicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 }); const PRIVATE_PEM = privateKey.export({ type: 'pkcs8', format: 'pem' }).toString(); diff --git a/test/unit/helper.test.ts b/test/unit/helper.test.ts index f828ac80..c317587f 100644 --- a/test/unit/helper.test.ts +++ b/test/unit/helper.test.ts @@ -15,7 +15,7 @@ import { Readable, Writable } from 'node:stream'; import { after, describe, it } from 'node:test'; import { parseArgs, parseCredentialInput, requestOverSocket, resolveSocketPath, runHelper } from '../../packages/client/src/helper.ts'; -import type { WireResponse } from '../../packages/cli/src/types.ts'; +import type { WireResponse } from '../../packages/core/src/types.ts'; const CLIENT_REQUEST = 'protocol=https\nhost=github.com\npath=acme/widget.git\n\n'; diff --git a/test/unit/host-opener.test.ts b/test/unit/host-opener.test.ts index 2dc8641f..fa196bf1 100644 --- a/test/unit/host-opener.test.ts +++ b/test/unit/host-opener.test.ts @@ -13,7 +13,7 @@ import { join } from 'node:path'; import { after, before, describe, it } from 'node:test'; import { runHostOpener } from '../../packages/host/src/commands/host-opener.ts'; -import { channelDir, listRequests, readResult, writeRequest } from '../../packages/cli/src/host-request.ts'; +import { channelDir, listRequests, readResult, writeRequest } from '../../packages/core/src/host-request.ts'; describe('the opener, once', () => { let root = ''; diff --git a/test/unit/host-request.test.ts b/test/unit/host-request.test.ts index 2d8e9e94..0f782d75 100644 --- a/test/unit/host-request.test.ts +++ b/test/unit/host-request.test.ts @@ -30,7 +30,7 @@ import { writeOpener, writeRequest, writeResult, -} from '../../packages/cli/src/host-request.ts'; +} from '../../packages/core/src/host-request.ts'; /** A good request, which each test varies one field of. */ const GOOD = { head: 'feat/thing', base: 'main', title: 'a title', body: 'a body' }; diff --git a/test/unit/http.test.ts b/test/unit/http.test.ts index 6023681a..190f98a9 100644 --- a/test/unit/http.test.ts +++ b/test/unit/http.test.ts @@ -79,7 +79,7 @@ describe('startup proxy environment', () => { const response = await fetcherFor(null)('http://127.0.0.1:${address.port}/', { method: 'GET', headers: {} }); console.log(response.status, await response.text()); `; - const child = spawn(process.execPath, ['--conditions=gcb-development', '--input-type=module', '-e', script], { + const child = spawn(process.execPath, ['--conditions=development', '--input-type=module', '-e', script], { cwd: process.cwd(), env: { ...process.env, diff --git a/test/unit/platform.test.ts b/test/unit/platform.test.ts index c3d8cb7b..62350518 100644 --- a/test/unit/platform.test.ts +++ b/test/unit/platform.test.ts @@ -13,7 +13,7 @@ import path from 'node:path'; import { after, describe, it } from 'node:test'; import { prepareSocketPath } from '../../packages/host/src/broker.ts'; -import { isNativeWindows, isWindowsBackedPath, isWsl, platformRefusal, socketPathRefusal } from '../../packages/cli/src/platform.ts'; +import { isNativeWindows, isWindowsBackedPath, isWsl, platformRefusal, socketPathRefusal } from '../../packages/core/src/platform.ts'; /** Scratch space for the one test that touches the filesystem. */ const scratch = fs.mkdtempSync(path.join(os.tmpdir(), 'gcb-platform-')); diff --git a/test/unit/policy.test.ts b/test/unit/policy.test.ts index ded9b0d7..94923e42 100644 --- a/test/unit/policy.test.ts +++ b/test/unit/policy.test.ts @@ -6,7 +6,7 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; import { hostConfig, normalizeRepoPath, parseAllowEntry, repoAllowed } from '../../packages/host/src/policy.ts'; -import type { BrokerConfig } from '../../packages/cli/src/types.ts'; +import type { BrokerConfig } from '../../packages/core/src/types.ts'; describe('normalizeRepoPath', () => { it('accepts what git actually sends and strips the .git suffix', () => { diff --git a/test/unit/socket-protocol.test.ts b/test/unit/socket-protocol.test.ts index 4a843e58..69073a12 100644 --- a/test/unit/socket-protocol.test.ts +++ b/test/unit/socket-protocol.test.ts @@ -1,8 +1,8 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; -import { MAX_BODY_CHARS } from '../../packages/cli/src/host-request.ts'; -import { MAX_MESSAGE_BYTES, createLineReader } from '../../packages/cli/src/socket-protocol.ts'; +import { MAX_BODY_CHARS } from '../../packages/core/src/host-request.ts'; +import { MAX_MESSAGE_BYTES, createLineReader } from '../../packages/core/src/socket-protocol.ts'; describe('createLineReader', () => { it('splits lines across chunks and ignores blank lines', () => { diff --git a/tsconfig.json b/tsconfig.json index 312c1237..2210847f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,7 @@ "noEmit": true, "paths": { - "gcb-cli": ["./packages/cli/src/index.ts"], + "gcb-core": ["./packages/core/src/index.ts"], "gcb-client": ["./packages/client/src/index.ts"], "gcb-host": ["./packages/host/src/index.ts"] } diff --git a/yarn.lock b/yarn.lock index 44464940..1a73d627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,265 @@ __metadata: version: 10 cacheKey: 10c0 +"@changesets/apply-release-plan@npm:^8.1.1": + version: 8.1.1 + resolution: "@changesets/apply-release-plan@npm:8.1.1" + dependencies: + "@changesets/config": "npm:^4.0.1" + "@changesets/format": "npm:^0.1.2" + "@changesets/git": "npm:^4.0.1" + "@changesets/should-skip-package": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + import-meta-resolve: "npm:^4.2.0" + jsonc-parser: "npm:^3.3.1" + semver: "npm:^7.8.1" + checksum: 10c0/2a1cfb9e4e3feb2c76bcec646e116ebebc81271fed21a3e77d5f170963f88347a34e5d1474f8b87258448182cfa651c047282c8b1a741613a7f7d3fefc2eb9a2 + languageName: node + linkType: hard + +"@changesets/assemble-release-plan@npm:^7.0.0": + version: 7.0.0 + resolution: "@changesets/assemble-release-plan@npm:7.0.0" + dependencies: + "@changesets/errors": "npm:^1.0.0" + "@changesets/get-dependents-graph": "npm:^3.0.0" + "@changesets/should-skip-package": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + semver: "npm:^7.8.1" + checksum: 10c0/2544759583889865487aec744e948c6d84206a42aa593430436ace83003fe00d3880ef623114c396cd5fd883eccb1e03fc4a719ba5c33038a8556df8fca4b9b7 + languageName: node + linkType: hard + +"@changesets/changelog-git@npm:^1.0.0": + version: 1.0.0 + resolution: "@changesets/changelog-git@npm:1.0.0" + dependencies: + "@changesets/types": "npm:^7.0.0" + checksum: 10c0/f0f0ab31e6e6ac35ecdae46a521d4c84aab77bbb035898e364d8f9082391b2b8064ba33d9f97d4f1526195f8278f41910c72382b12fcc0092d5bb9ff3ae05310 + languageName: node + linkType: hard + +"@changesets/changelog-github@npm:^1.0.1": + version: 1.0.1 + resolution: "@changesets/changelog-github@npm:1.0.1" + dependencies: + "@changesets/get-github-info": "npm:^1.0.1" + "@changesets/types": "npm:^7.0.0" + checksum: 10c0/d1538b48d8cfa8846ff5428f7c98301342378c5d8fe0c077679dfdcf373f53e989553783159e5e594cf292b61d303560d32de4abb57b77453cc0c872acc8420b + languageName: node + linkType: hard + +"@changesets/cli@npm:^3.0.3": + version: 3.0.3 + resolution: "@changesets/cli@npm:3.0.3" + dependencies: + "@changesets/apply-release-plan": "npm:^8.1.1" + "@changesets/assemble-release-plan": "npm:^7.0.0" + "@changesets/changelog-git": "npm:^1.0.0" + "@changesets/config": "npm:^4.0.1" + "@changesets/errors": "npm:^1.0.0" + "@changesets/get-dependents-graph": "npm:^3.0.0" + "@changesets/git": "npm:^4.0.1" + "@changesets/pre": "npm:^3.0.0" + "@changesets/read": "npm:^1.0.1" + "@changesets/should-skip-package": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + "@changesets/write": "npm:^1.0.1" + "@clack/prompts": "npm:^1.7.0" + "@manypkg/get-packages": "npm:^3.1.0" + "@pnpm/deps.graph-sequencer": "npm:^1100.0.1" + cac: "npm:^7.0.0" + import-meta-resolve: "npm:^4.2.0" + launch-editor: "npm:^2.14.1" + package-manager-detector: "npm:^1.6.0" + semver: "npm:^7.8.1" + tinyexec: "npm:^1.3.1" + bin: + changeset: bin.js + checksum: 10c0/238b98c590bfe33e794cf5ab47e0fa6eb46fc587da9498af49037877f1043b3e91dac65c990ebd1675115d82f2a3a2b3e7aa1b5d385369b0322a24e858eb1313 + languageName: node + linkType: hard + +"@changesets/config@npm:^4.0.1": + version: 4.0.1 + resolution: "@changesets/config@npm:4.0.1" + dependencies: + "@changesets/get-dependents-graph": "npm:^3.0.0" + "@changesets/should-skip-package": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + "@manypkg/get-packages": "npm:^3.1.0" + picomatch: "npm:^4.0.7" + checksum: 10c0/959dbbb3ab9fab0427a8990cbe7d4465d9b67042c96108209c8110b7c5ccb2fc3303b75d5c024e911d3a51ca082d13d49a5091edf52014a2b8d69e89b58188ed + languageName: node + linkType: hard + +"@changesets/errors@npm:^1.0.0": + version: 1.0.0 + resolution: "@changesets/errors@npm:1.0.0" + checksum: 10c0/502439fb046b9916e8a0745374c75fa80883b0bdeea92aa2e85be07b8675dcdb50df5bd108ce66eddbda1f8863be750bf817301c9d4904c2168305df870e3f9f + languageName: node + linkType: hard + +"@changesets/format@npm:^0.1.1, @changesets/format@npm:^0.1.2": + version: 0.1.3 + resolution: "@changesets/format@npm:0.1.3" + dependencies: + package-manager-detector: "npm:^1.8.0" + tinyexec: "npm:^1.3.1" + checksum: 10c0/49819e75c753a5ce1249f7b52948692b1f678e1be3721cbfb1904da9319e6eedc277273deefb783afe87a16dd53f908addc1378d331194e50c40627ce824b0c4 + languageName: node + linkType: hard + +"@changesets/get-dependents-graph@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/get-dependents-graph@npm:3.0.0" + dependencies: + "@changesets/types": "npm:^7.0.0" + semver: "npm:^7.8.1" + checksum: 10c0/ab675098db0b92f61115952fb793620bb5b76e502bad5f7f63bcc85a50e5515f70e08957be87381a58141ab2078bf94dd92df86efa55e73227e7604ba6a3968b + languageName: node + linkType: hard + +"@changesets/get-github-info@npm:^1.0.1": + version: 1.0.1 + resolution: "@changesets/get-github-info@npm:1.0.1" + dependencies: + dataloader: "npm:^2.2.3" + checksum: 10c0/7b45b5ebc97b297e1c373ec782c501c3b6cc911badf43e4ebaaf46ce1d8b94f62e4d758705e03d3b9df06b730ab85b9dab5ad76ff070f8ff65ef2fb21647d61b + languageName: node + linkType: hard + +"@changesets/git@npm:^4.0.1": + version: 4.0.1 + resolution: "@changesets/git@npm:4.0.1" + dependencies: + "@changesets/errors": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + "@manypkg/get-packages": "npm:^3.1.0" + picomatch: "npm:^4.0.4" + tinyexec: "npm:^1.3.0" + checksum: 10c0/b548ecfafb238ff477a793e4ee91c1fe818274b9ea5b6d5a9d619f75a915ad27831f2accf2edce77da57f918bf1009b59cca2c5aaa7288db4b266f87872c2c23 + languageName: node + linkType: hard + +"@changesets/parse@npm:^1.0.0": + version: 1.0.0 + resolution: "@changesets/parse@npm:1.0.0" + dependencies: + "@changesets/types": "npm:^7.0.0" + yaml: "npm:^2.9.0" + checksum: 10c0/76e93b099015420dfc08f3e3a9321ea2512659d8946d1ed86de64899b52d37faa87173cc80ead5d313ffce2f829ce380a0188c0a1cccaad48350e7c6a83720d0 + languageName: node + linkType: hard + +"@changesets/pre@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/pre@npm:3.0.0" + dependencies: + "@changesets/errors": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + "@manypkg/get-packages": "npm:^3.1.0" + checksum: 10c0/56e49668f25cabf50dcab12b6ae20fd7dbeba628390149d38a9075b05c41b954d4fbcebe7535878087c5f0b707ce96b90b727286850c71d6d321477bd1a1c18e + languageName: node + linkType: hard + +"@changesets/read@npm:^1.0.1": + version: 1.0.1 + resolution: "@changesets/read@npm:1.0.1" + dependencies: + "@changesets/git": "npm:^4.0.1" + "@changesets/parse": "npm:^1.0.0" + "@changesets/types": "npm:^7.0.0" + checksum: 10c0/125de7132b71e9c184f35ec0ad4d23b9accb0aa04d178c835ef575fbf12afbed2fd2d975e987ebb70c007c9a08dc97a267123ba515a4c2f4f070279ad8193f46 + languageName: node + linkType: hard + +"@changesets/should-skip-package@npm:^1.0.0": + version: 1.0.0 + resolution: "@changesets/should-skip-package@npm:1.0.0" + dependencies: + "@changesets/types": "npm:^7.0.0" + checksum: 10c0/9beb51e7a6a6d678fbfe60efca4646d7daf117ffb90d3dbe3e8b07806f87383cf2a49b0e15b5fe2b827b69f61c0cf7cb77c4bf27b403c2ce835c5ba7990ed0e5 + languageName: node + linkType: hard + +"@changesets/types@npm:^7.0.0": + version: 7.0.0 + resolution: "@changesets/types@npm:7.0.0" + checksum: 10c0/494e09ff94968c1c81521f5ac8c6ab60a1e30d7d0cd9ea7f83c2cbac92efba38b03e008ee6fb4592d90b05d69bad864b6ae8155827d52a51c652f5c24d36ec83 + languageName: node + linkType: hard + +"@changesets/write@npm:^1.0.1": + version: 1.0.1 + resolution: "@changesets/write@npm:1.0.1" + dependencies: + "@changesets/format": "npm:^0.1.1" + "@changesets/types": "npm:^7.0.0" + human-id: "npm:^4.2.0" + checksum: 10c0/c9cb074a8c524db1327e54dc1379ff4b50d3a4915409a3e5abe1edaf1ce45f6dafc6c8aced17a1f3eebfa162241b5fd8ea74fc751d2e24df56c2966e4169fcaf + languageName: node + linkType: hard + +"@clack/core@npm:1.5.1": + version: 1.5.1 + resolution: "@clack/core@npm:1.5.1" + dependencies: + fast-wrap-ansi: "npm:^0.2.0" + sisteransi: "npm:^1.0.5" + checksum: 10c0/6dca93ff5a34bfe8c150367519bc40a847e9172cb1a78b18c88da0507cb6ad899debe1ad5cfcb9796e439108f12f003cf06fd002e2293bc85ff500975e45ff13 + languageName: node + linkType: hard + +"@clack/prompts@npm:^1.7.0": + version: 1.8.1 + resolution: "@clack/prompts@npm:1.8.1" + dependencies: + "@clack/core": "npm:1.5.1" + fast-string-width: "npm:^3.0.2" + fast-wrap-ansi: "npm:^0.2.0" + sisteransi: "npm:^1.0.5" + checksum: 10c0/ed38748acde0cb1e7ebdac1242470c78bd90380cbdde1e5560e0828881e3c74e2676de666086cf8183c8d4d3f1fc6e489f15a004f0d9f8ee294a3aa744de2093 + languageName: node + linkType: hard + +"@manypkg/find-root@npm:^3.1.0": + version: 3.1.0 + resolution: "@manypkg/find-root@npm:3.1.0" + dependencies: + "@manypkg/tools": "npm:^2.1.0" + checksum: 10c0/15b3f5c5c66881af88c1c70dcec805237a2b7e1d541ca7687aade00978680024f8e77ca2f4bac1415e00377f2e78a998d842c345c288d3e69383d50280620b1c + languageName: node + linkType: hard + +"@manypkg/get-packages@npm:^3.1.0": + version: 3.1.0 + resolution: "@manypkg/get-packages@npm:3.1.0" + dependencies: + "@manypkg/find-root": "npm:^3.1.0" + "@manypkg/tools": "npm:^2.1.0" + checksum: 10c0/e8baabd85a13f4537ae22124d5e53f1523ba0653f33006da45fc8bd642e0134786a6aad9d0a7ed99282ae20a80687ef5700bd72980441627b5c96658503ad83d + languageName: node + linkType: hard + +"@manypkg/tools@npm:^2.1.0": + version: 2.1.2 + resolution: "@manypkg/tools@npm:2.1.2" + dependencies: + jju: "npm:^1.4.0" + tinyglobby: "npm:^0.2.13" + yaml: "npm:^2.9.0" + checksum: 10c0/05c8ece3b3b3ff170765ecf230f0a5408543f1ad43f8b5dc97651adff0ffed3d860dabdd1e2d1068aa247832d473c4de583791675b8f3d07568da4cab2a0ebc3 + languageName: node + linkType: hard + +"@pnpm/deps.graph-sequencer@npm:^1100.0.1": + version: 1100.0.1 + resolution: "@pnpm/deps.graph-sequencer@npm:1100.0.1" + checksum: 10c0/b38a152e1184055a358e7c522f068572e84759a88dfc56c98a349125b11d3cce72e452424c235af5cf18258a5034f88fe203c72ba57ffbe70b297afc50d08dea + languageName: node + linkType: hard + "@types/node@npm:^24.19.0": version: 24.19.0 resolution: "@types/node@npm:24.19.0" @@ -154,27 +413,87 @@ __metadata: languageName: node linkType: hard -"gcb-cli@npm:0.1.0, gcb-cli@workspace:packages/cli": - version: 0.0.0-use.local - resolution: "gcb-cli@workspace:packages/cli" - languageName: unknown - linkType: soft +"cac@npm:^7.0.0": + version: 7.1.0 + resolution: "cac@npm:7.1.0" + checksum: 10c0/8bfeef75404cf7d1799abdf6e07b276f3bb646caacdef4d492c64dcff6d4277ec81254612343d041e00ede588fd57117d1a46238b6db18770461dcb2cb1f7487 + languageName: node + linkType: hard + +"clean-pkg-json@npm:^2.0.0": + version: 2.0.0 + resolution: "clean-pkg-json@npm:2.0.0" + bin: + clean-pkg-json: dist/index.mjs + checksum: 10c0/fe8828c0e788dcc20fec97f02d4f182becca30817896fe350095c01b5e22cbc5c02f912e5ce4f9ad509d11ff60e52803bbdfb153a8291df72ae1b80a0ce9aa53 + languageName: node + linkType: hard + +"dataloader@npm:^2.2.3": + version: 2.2.3 + resolution: "dataloader@npm:2.2.3" + checksum: 10c0/9b9a056fbc863ca86da87d59e053e871e263b4966aa4d55e40d61a65e96815fae5530ca220629064ca5f8e3000c0c4ec93292e170c38ff393fb34256b4d7c1aa + languageName: node + linkType: hard + +"fast-string-truncated-width@npm:^3.0.2": + version: 3.0.3 + resolution: "fast-string-truncated-width@npm:3.0.3" + checksum: 10c0/043b8663397d14a3880ce4f3407bcda60b40db9bbeafe62863a35d1f9c69ea17c8da3fcd72de235553e6c9cd053128cde9e24ca0d4a7463208f48db3cd23d981 + languageName: node + linkType: hard + +"fast-string-width@npm:^3.0.2": + version: 3.0.2 + resolution: "fast-string-width@npm:3.0.2" + dependencies: + fast-string-truncated-width: "npm:^3.0.2" + checksum: 10c0/c8822d175315bb353ebe782b65214ac53b13e3bf704e03b132ea7bdfa8de6a636375b3ab7a4097545393d109381c37c4f387c72a462c90b61412dbc4632f39a7 + languageName: node + linkType: hard + +"fast-wrap-ansi@npm:^0.2.0": + version: 0.2.2 + resolution: "fast-wrap-ansi@npm:0.2.2" + dependencies: + fast-string-width: "npm:^3.0.2" + checksum: 10c0/1aa7be4f7cb86f4bdb14691cb6bcc0b8df8b3b89df142ade3ae1602332dcf6f990cd750a923cd581ca0847808cb4ec1aa5afaafa7a72f849e87a2a62c98fa370 + languageName: node + linkType: hard + +"fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f + languageName: node + linkType: hard "gcb-client@workspace:packages/client": version: 0.0.0-use.local resolution: "gcb-client@workspace:packages/client" dependencies: - gcb-cli: "npm:0.1.0" + gcb-core: "npm:0.0.0" bin: gcb: ./bin/gcb.js languageName: unknown linkType: soft +"gcb-core@npm:0.0.0, gcb-core@workspace:packages/core": + version: 0.0.0-use.local + resolution: "gcb-core@workspace:packages/core" + languageName: unknown + linkType: soft + "gcb-host@workspace:packages/host": version: 0.0.0-use.local resolution: "gcb-host@workspace:packages/host" dependencies: - gcb-cli: "npm:0.1.0" + gcb-core: "npm:0.0.0" node-fetch-native: "npm:^1.6.7" x-fetch: "npm:^0.3.0" yaml: "npm:^2.9.1" @@ -187,12 +506,55 @@ __metadata: version: 0.0.0-use.local resolution: "gcb-workspace@workspace:." dependencies: + "@changesets/changelog-github": "npm:^1.0.1" + "@changesets/cli": "npm:^3.0.3" "@types/node": "npm:^24.19.0" + clean-pkg-json: "npm:^2.0.0" typescript: "npm:^7.0.2" yaml: "npm:^2.9.1" languageName: unknown linkType: soft +"human-id@npm:^4.2.0": + version: 4.2.2 + resolution: "human-id@npm:4.2.2" + bin: + human-id: dist/cli.js + checksum: 10c0/7bf51bf2cec8c26129d3f6ea068b18eca702130641afe5c475cb92270015e403be5bdd35f53b2da38a058a3c1c2632c2d0576c026ad78dc33d30af53eb7d426d + languageName: node + linkType: hard + +"import-meta-resolve@npm:^4.2.0": + version: 4.2.0 + resolution: "import-meta-resolve@npm:4.2.0" + checksum: 10c0/3ee8aeecb61d19b49d2703987f977e9d1c7d4ba47db615a570eaa02fe414f40dfa63f7b953e842cbe8470d26df6371332bfcf21b2fd92b0112f9fea80dde2c4c + languageName: node + linkType: hard + +"jju@npm:^1.4.0": + version: 1.4.0 + resolution: "jju@npm:1.4.0" + checksum: 10c0/f3f444557e4364cfc06b1abf8331bf3778b26c0c8552ca54429bc0092652172fdea26cbffe33e1017b303d5aa506f7ede8571857400efe459cb7439180e2acad + languageName: node + linkType: hard + +"jsonc-parser@npm:^3.3.1": + version: 3.3.1 + resolution: "jsonc-parser@npm:3.3.1" + checksum: 10c0/269c3ae0a0e4f907a914bf334306c384aabb9929bd8c99f909275ebd5c2d3bc70b9bcd119ad794f339dec9f24b6a4ee9cd5a8ab2e6435e730ad4075388fc2ab6 + languageName: node + linkType: hard + +"launch-editor@npm:^2.14.1": + version: 2.14.2 + resolution: "launch-editor@npm:2.14.2" + dependencies: + picocolors: "npm:^1.1.1" + shell-quote: "npm:^1.10.0" + checksum: 10c0/cf66c75534170142269bfc1749df8a4b5178ad644d358aa08d4feda9ecb1ba7a26191a76ea2cecea95c59235c142486b928b58eaf0cd77377d21e42ed5c3e100 + languageName: node + linkType: hard + "node-fetch-native@npm:^1.6.7": version: 1.6.7 resolution: "node-fetch-native@npm:1.6.7" @@ -200,6 +562,67 @@ __metadata: languageName: node linkType: hard +"package-manager-detector@npm:^1.6.0, package-manager-detector@npm:^1.8.0": + version: 1.9.0 + resolution: "package-manager-detector@npm:1.9.0" + checksum: 10c0/c901b08e9d284e9b517d27be1783fc279f3e814fac9de4c30441129a3a4b1475b16314ff95b98268daf49e20d5076478c50bc7b1b3ff8a591eb39f03f02dbb16 + languageName: node + linkType: hard + +"picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 + languageName: node + linkType: hard + +"picomatch@npm:^4.0.4, picomatch@npm:^4.0.7": + version: 4.0.7 + resolution: "picomatch@npm:4.0.7" + checksum: 10c0/beb6ae02c43ae44e84883b90830196d9046b1726ead292adcf7f57945e0bb0d992d68563d87e03b484b6f3c9a5c6defda7523477f047d7f0e663f126cc01787f + languageName: node + linkType: hard + +"semver@npm:^7.8.1": + version: 7.8.5 + resolution: "semver@npm:7.8.5" + bin: + semver: bin/semver.js + checksum: 10c0/b1f3127a5be8125a94f37188b361c212466c292c6910adce3ec106cff5dc211ccaedc4739c11bb70fda59d6fc1f040a9bca289f4e093451521a2372e5231fe0c + languageName: node + linkType: hard + +"shell-quote@npm:^1.10.0": + version: 1.12.0 + resolution: "shell-quote@npm:1.12.0" + checksum: 10c0/1605a4ed6a758bf13de7cb8197a4184d8015f7a4dbdcd6cd4a717d5b30b3ae7666300cc4ae7f3155cf80ace9739e9e82061ee5aa1a648f53f5fab31a220816d0 + languageName: node + linkType: hard + +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: 10c0/230ac975cca485b7f6fe2b96a711aa62a6a26ead3e6fb8ba17c5a00d61b8bed0d7adc21f5626b70d7c33c62ff4e63933017a6462942c719d1980bb0b1207ad46 + languageName: node + linkType: hard + +"tinyexec@npm:^1.3.0, tinyexec@npm:^1.3.1": + version: 1.3.1 + resolution: "tinyexec@npm:1.3.1" + checksum: 10c0/c590369cb3fa73cc18a3998caec8a00f9712d91309c881be3ac52b160fb2f80c7b1fbf3591858ab6abab47ad55385b0c86ec19982e32441a01f55298dab9ccd2 + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.13": + version: 0.2.17 + resolution: "tinyglobby@npm:0.2.17" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.4" + checksum: 10c0/7f7bb0f197c88bc4b20c231e0deca4240ca3bf313a88f5a7fee93a872b84966a4d50220947c0455ad07a60b3b360961c5b7fd979222aeb716a9f99b412002e4c + languageName: node + linkType: hard + "typescript@npm:^7.0.2": version: 7.0.2 resolution: "typescript@npm:7.0.2" @@ -356,7 +779,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.9.1": +"yaml@npm:^2.9.0, yaml@npm:^2.9.1": version: 2.9.1 resolution: "yaml@npm:2.9.1" bin: