Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b7fcd04
Agents and Claude
rinatkhaziev Feb 12, 2026
61f1ee9
First pass
rinatkhaziev Feb 12, 2026
ce6a987
Migrate all commands
rinatkhaziev Feb 12, 2026
fc7ba9a
Finalize commander move
rinatkhaziev Feb 12, 2026
def09c5
Doc updates
rinatkhaziev Feb 12, 2026
7477bc1
Implement standalone executables
rinatkhaziev Feb 12, 2026
e93b8b2
First pass at SEA GH workflow
rinatkhaziev Feb 12, 2026
f9224a3
Pass 2 at GHA workflow
rinatkhaziev Feb 12, 2026
5a27d40
Update helpers/build-sea.js
rinatkhaziev Feb 13, 2026
453db7d
Update AGENTS.md
rinatkhaziev Feb 13, 2026
2fab276
Revert agents
rinatkhaziev Mar 9, 2026
6b19b3c
Lint
rinatkhaziev Mar 9, 2026
959f0b3
More lint
rinatkhaziev Mar 9, 2026
90da69c
Merge branch 'trunk' into commander-migration
rinatkhaziev Mar 12, 2026
7bc7729
Merge branch 'trunk' into commander-migration
rinatkhaziev Mar 13, 2026
8455959
Merge pull request #2736 from Automattic/commander-migration
rinatkhaziev Mar 13, 2026
d9e8c00
Merge branch 'next' into sea
rinatkhaziev Mar 13, 2026
a3ce33e
Fix merge fail
rinatkhaziev Mar 18, 2026
a75fe55
Lint
rinatkhaziev Mar 18, 2026
be7c2dd
Maybe fix tests
rinatkhaziev Mar 23, 2026
962dd39
Merge branch 'next' into sea
rinatkhaziev Mar 23, 2026
8aea4b8
Handle ENOENT in loadConfigFile
rinatkhaziev Mar 23, 2026
659ff58
Lint
rinatkhaziev Mar 23, 2026
ced464e
prettier fix for MD
rinatkhaziev Mar 23, 2026
49020e1
Merge pull request #2737 from Automattic/sea
rinatkhaziev Mar 23, 2026
20fc451
Merge branch 'trunk' into next
rinatkhaziev Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions .github/workflows/sea-build-sign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
name: Build SEA Artifacts

on:
workflow_dispatch:
inputs:
sign_artifacts:
description: 'Sign artifacts when signing secrets are configured.'
required: false
default: false
type: boolean

permissions:
contents: read

env:
NODE_OPTIONS: --unhandled-rejections=warn
DO_NOT_TRACK: '1'

jobs:
build-sea-native:
name: SEA Native (${{ matrix.target.name }})
runs-on: ${{ matrix.target.runs_on }}
env:
SIGN_ARTIFACTS: ${{ inputs.sign_artifacts }}
MACOS_CERTIFICATE_P12_BASE64: ${{ secrets.MACOS_CERTIFICATE_P12_BASE64 }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
WINDOWS_CERTIFICATE_PFX_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_PFX_BASE64 }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
WINDOWS_TIMESTAMP_URL: ${{ vars.WINDOWS_TIMESTAMP_URL }}
strategy:
fail-fast: false
matrix:
target:
- name: macOS
runs_on: macos-latest
binary_path: dist/sea/vip
artifact_name: vip-sea-macos
- name: Linux
runs_on: ubuntu-latest
binary_path: dist/sea/vip
artifact_name: vip-sea-linux
- name: Windows
runs_on: windows-latest
binary_path: dist/sea/vip.exe
artifact_name: vip-sea-windows

steps:
- name: Check out the source code
uses: actions/checkout@v6

- name: Set git to use LF
if: runner.os == 'Windows'
run: |
git config --global core.autocrlf false
git config --global core.eol lf

- name: Set up Node.js 22
uses: actions/setup-node@v6
with:
node-version: '22.x'
cache: npm
cache-dependency-path: npm-shrinkwrap.json

- name: Install dependencies
run: npm ci

- name: Build dist
run: npm run build

- name: Build SEA artifact
run: npm run build:sea

- name: Smoke test executable (Unix)
if: runner.os != 'Windows'
run: |
${{ matrix.target.binary_path }} --version
${{ matrix.target.binary_path }} whoami --help

- name: Smoke test executable (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
.\${{ matrix.target.binary_path }} --version
.\${{ matrix.target.binary_path }} whoami --help

- name: Import macOS signing certificate
if: runner.os == 'macOS' && env.SIGN_ARTIFACTS == 'true' && env.MACOS_CERTIFICATE_P12_BASE64 != '' && env.MACOS_CERTIFICATE_PASSWORD != '' && env.MACOS_SIGNING_IDENTITY != ''
run: |
KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain-db"
CERT_PATH="$RUNNER_TEMP/macos-cert.p12"

echo "$MACOS_CERTIFICATE_P12_BASE64" | base64 --decode > "$CERT_PATH"
security create-keychain -p "" "$KEYCHAIN_PATH"
security unlock-keychain -p "" "$KEYCHAIN_PATH"
security list-keychains -s "$KEYCHAIN_PATH"
security default-keychain -s "$KEYCHAIN_PATH"
security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN_PATH"

codesign --remove-signature ${{ matrix.target.binary_path }}
codesign --sign "$MACOS_SIGNING_IDENTITY" --force --options runtime ${{ matrix.target.binary_path }}
codesign --verify --strict --verbose=2 ${{ matrix.target.binary_path }}

- name: Sign Windows executable
if: runner.os == 'Windows' && env.SIGN_ARTIFACTS == 'true' && env.WINDOWS_CERTIFICATE_PFX_BASE64 != '' && env.WINDOWS_CERTIFICATE_PASSWORD != ''
shell: pwsh
run: |
$certPath = Join-Path $env:RUNNER_TEMP 'codesign.pfx'
[System.IO.File]::WriteAllBytes($certPath, [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_PFX_BASE64))
$timestampUrl = if ($env:WINDOWS_TIMESTAMP_URL) { $env:WINDOWS_TIMESTAMP_URL } else { 'http://timestamp.digicert.com' }

signtool sign /fd SHA256 /td SHA256 /tr $timestampUrl /f $certPath /p $env:WINDOWS_CERTIFICATE_PASSWORD .\${{ matrix.target.binary_path }}
signtool verify /pa /v .\${{ matrix.target.binary_path }}

- name: Generate checksum (Unix)
if: runner.os != 'Windows'
run: |
shasum -a 256 ${{ matrix.target.binary_path }} > ${{ matrix.target.binary_path }}.sha256

- name: Generate checksum (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$hash = (Get-FileHash -Algorithm SHA256 .\${{ matrix.target.binary_path }}).Hash.ToLower()
"${hash} *${{ matrix.target.binary_path }}" | Set-Content .\${{ matrix.target.binary_path }}.sha256 -NoNewline

- name: Upload SEA artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target.artifact_name }}
path: |
${{ matrix.target.binary_path }}
${{ matrix.target.binary_path }}.sha256
if-no-files-found: error

build-sea-windows-wsl:
name: SEA (Windows WSL)
runs-on: windows-latest

steps:
- name: Check out the source code
uses: actions/checkout@v6

- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf

- name: Build SEA inside WSL
shell: pwsh
run: |
$workspaceWsl = (wsl.exe wslpath -a "$env:GITHUB_WORKSPACE").Trim()
if (-not $workspaceWsl) {
throw 'Failed to resolve WSL workspace path.'
}

wsl.exe bash -lc "set -euo pipefail; export NVM_DIR=\$HOME/.nvm; if [ ! -s \"\$NVM_DIR/nvm.sh\" ]; then curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash; fi"
wsl.exe bash -lc "set -euo pipefail; export NVM_DIR=\$HOME/.nvm; . \"\$NVM_DIR/nvm.sh\"; nvm install 22; nvm use 22; cd \"$workspaceWsl\"; npm ci; npm run build; npm run build:sea; ./dist/sea/vip --version; ./dist/sea/vip whoami --help"
wsl.exe bash -lc "set -euo pipefail; cd \"$workspaceWsl\"; sha256sum dist/sea/vip > dist/sea/vip.sha256"

- name: Upload WSL SEA artifact
uses: actions/upload-artifact@v4
with:
name: vip-sea-windows-wsl
path: |
dist/sea/vip
dist/sea/vip.sha256
if-no-files-found: error
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ Guide for future agents working on this codebase. Focus on traps, cross-cutting
- `prepare` runs `npm run clean && npm run build`; npm package bins point to `dist/**`. Always rebuild before publishing so dist matches src.
- `helpers/prepublishOnly.js` enforces branch `trunk` for `npm publish --tag latest` and optionally reruns `npm test`. Release flows expect a clean node version that satisfies `engines.node`.

## Standalone SEA Packaging

- Canonical runbook for standalone executable build/signing is in `docs/SEA-BUILD-SIGNING.md`. Use it for macOS, Linux, Windows native, and WSL-mediated Windows builds.
- SEA builds are Node 22 only (enforced in `helpers/build-sea.js`); always verify `node -v` before `npm run build:sea`.
- The executable is self-contained for Node runtime + JS deps, but `dev-env` commands still require host Docker/Compose availability.

## Common Pitfalls Checklist

- Running CLI without a token opens a browser (`open`) and waits for interactive input—pass `--help` or set `WPVIP_DEPLOY_TOKEN` in automation.
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# CLAUDE

For guidance on working in this repo, traps, and migration notes, see `AGENTS.md`.
For standalone SEA build/signing by platform, see `docs/SEA-BUILD-SIGNING.md`.
55 changes: 55 additions & 0 deletions docs/COMMANDER-MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Commander Migration Status

Goal: remove the abandoned `args` package, keep CLI behavior stable, and support packaging to a single bundled executable (Node SEA or similar). See `AGENTS.md` for broader architecture traps.

## Migration Outcome

- `src/lib/cli/command.js` is the active Commander-backed compatibility wrapper for all bins that call `command()`.
- `args` has been removed from `package.json` and `npm-shrinkwrap.json`.
- Root command flow (`src/bin/vip.js`) now dispatches via the shared Commander wrapper again, preserving login gating and subcommand chaining.
- Temporary side-path wrapper work has been removed (`src/lib/cli/command-commander.ts` deleted).

## Compatibility Behaviors Preserved

- Legacy command contract stays the same: `command(opts).option(...).argv(process.argv, handler)`.
- Alias behavior remains pre-parse: `@app` and `@app.env` are stripped before `--`; alias + `--app/--env` still errors.
- `_opts` controls are still honored: app/env context fetch, confirmation gating, output formatting, wildcard command handling, required positional args.
- Shared formatting/output and telemetry hooks are still in the wrapper path.
- Local nested subcommand dispatch still works via sibling executable resolution.

## Post-Migration Hardening

- Short-flag compatibility was restored for long options without explicit aliases:
- Example: `--elasticsearch` accepts `-e`, `--phpmyadmin` accepts `-p`, etc.
- Auto-short generation skips reserved global flags (`-h`, `-v`, `-d`) and avoids duplicate collisions.
- `vip dev-env exec` now performs bounded readiness checks before deciding an environment is not running.
- `startEnvironment()` now includes bounded post-start readiness checks and one recovery `landoStart` retry if the environment stays `DOWN` after rebuild/start.

## Remaining Technical Debt

- `_opts` is still module-level state in `src/lib/cli/command.js` and can leak between command instances in one process.
- Help text parity against historical `args` output is close but still a verification target for high-traffic commands.
- Full dev-env E2E can still show Docker/Lando infrastructure flakiness (network cleanup and startup latency), which is environment-level, not parser-level.

## Verification Commands

- `npm run build`
- `npm run check-types`
- `npm run test:e2e:dev-env -- --runInBand __tests__/devenv-e2e/001-create.spec.js __tests__/devenv-e2e/005-update.spec.js`
- `npm run test:e2e:dev-env -- --runInBand __tests__/devenv-e2e/008-exec.spec.js __tests__/devenv-e2e/010-import-sql.spec.js`

## Single-Bundle Direction

- Preferred: `esbuild` bundle rooted at `src/bin/vip.js`.
- Keep native deps external (`@postman/node-keytar`) for SEA/packaging workflows.
- Candidate build target:
- `dist/vip.bundle.cjs` for SEA ingestion or launcher wrapping.
- Example command:
- `esbuild src/bin/vip.js --bundle --platform=node --target=node20 --format=cjs --outfile=dist/vip.bundle.cjs --banner:js="#!/usr/bin/env node" --external:@postman/node-keytar`

## Next Refactor Steps

1. Remove global `_opts` state from `src/lib/cli/command.js` by moving to per-instance configuration.
2. Add parser contract tests for aliasing, wildcard behavior, and short/long boolean coercion.
3. Add stable startup/readiness integration checks around dev-env commands in CI environments with Docker.
4. Add bundling script(s) and SEA config proof-of-concept for a single-file executable artifact.
Loading
Loading