Go CLI: add Edge Workers command parity - #3018
Conversation
#### Purpose and Context Bring the Go runtime up to date with the Node Edge Workers command set. #### Key Changes Add all ten commands, project scaffolding and compilation, GraphQL operations, and deployment planning. Preserve activation safeguards, source and location semantics, terminal escaping, and error handling. #### Impact and Considerations New workers remain inactive unless explicitly enabled. Local builds still use the project's Node-based AssemblyScript compiler. SEA changes are excluded. #### Testing and Validation Add unit, real runtime differential, terminal prompt, and compiler smoke coverage. Go tests and vet, Node tests and type checks, and normal and hostile fixture parity pass. Local integration parity remains unverified because a required local API service is stopped.
Dependency ReviewThe following issues were found:
License Issuesinternal/edgeworkers/templates/package.json
OpenSSF Scorecard
Scanned Files
|
#### Purpose and Context Both runtimes print stored worker source through the single-line terminal sanitizer. It turns ordinary newlines and tabs into literal Unicode escape sequences, making get --source output unreadable. #### Key Changes Add source-specific escaping in Node and Go and use it only when rendering stored source. Preserve LF and horizontal tabs, normalize CRLF to LF, and continue escaping standalone CR, ANSI escapes, and other C0, DEL, and C1 controls. Keep literal backslash sequences intact. #### Impact and Considerations Names, metadata, errors, stored source, and deployment behavior remain unchanged. The fix is display-only; workers do not need redeployment. #### Testing and Validation Reproduce the failure before the fix in both unit suites and through the real CLIs. Add equivalent formatting and terminal-safety cases and an independent expected-output assertion to source parity so matching runtime bugs cannot pass. Verify Go tests/vet/build, 255 Node tests, type checking/lint/build, and normal and hostile fixture parity.
There was a problem hiding this comment.
Pull request overview
Ports the existing Node.js Edge Workers CLI command set to the Go runtime (vip-next), adds extensive Node-vs-Go parity coverage (scenarios, prompt handling, filesystem and API request comparisons), and fixes get --source rendering in both runtimes to preserve readable formatting while neutralizing unsafe terminal controls.
Changes:
- Add Go Edge Workers implementation (scaffold/build/validate/list/get/deploy/enable/disable/delete) with app/env resolution, GraphQL middleware, confirmations, and output formatting.
- Add comprehensive parity scenarios/fixtures plus differential and prompt-parity tests to compare Node vs Go behavior (stdout/stderr, requests, filesystem effects, prompts).
- Fix
get --sourceoutput formatting in Node and Go to preserve newlines/tabs and normalize CRLF→LF while escaping other terminal control characters.
Reviewed changes
Copilot reviewed 126 out of 128 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| testdata/parity/edge-workers-validate.yaml | Parity scenario for edge-workers validate happy path. |
| testdata/parity/edge-workers-validate-null.yaml | Parity scenario for null validation response handling. |
| testdata/parity/edge-workers-validate-no-name.yaml | Parity scenario for missing name validation error. |
| testdata/parity/edge-workers-validate-no-artifact.yaml | Parity scenario for missing prebuilt artifact error. |
| testdata/parity/edge-workers-validate-name-all.yaml | Parity scenario for conflicting name + --all. |
| testdata/parity/edge-workers-validate-invalid.yaml | Parity scenario for invalid worker validation. |
| testdata/parity/edge-workers-validate-all.yaml | Parity scenario for validate --all. |
| testdata/parity/edge-workers-unicode-order.yaml | Parity scenario covering unicode worker ordering behavior. |
| testdata/parity/edge-workers-table-control-name.yaml | Parity scenario for table output with control chars in names. |
| testdata/parity/edge-workers-short-equals.yaml | Parity scenario for short-flag -x=value parsing. |
| testdata/parity/edge-workers-repeated-type.yaml | Parity scenario for repeated --type flag behavior. |
| testdata/parity/edge-workers-repeated-path.yaml | Parity scenario for repeated --path flag behavior. |
| testdata/parity/edge-workers-read-null.yaml | Parity scenario for null read envelope behavior. |
| testdata/parity/edge-workers-new.yaml | Parity scenario for edge-workers new. |
| testdata/parity/edge-workers-new-location.yaml | Parity scenario for new --location. |
| testdata/parity/edge-workers-new-invalid-name.yaml | Parity scenario for invalid worker name handling. |
| testdata/parity/edge-workers-new-invalid-location.yaml | Parity scenario for invalid location handling. |
| testdata/parity/edge-workers-mutation-null.yaml | Parity scenario for null mutation response handling. |
| testdata/parity/edge-workers-mutation-graphql-error.yaml | Parity scenario for GraphQL error handling on mutation. |
| testdata/parity/edge-workers-list-table.yaml | Parity scenario for list table output. |
| testdata/parity/edge-workers-list-json.yaml | Parity scenario for list JSON output. |
| testdata/parity/edge-workers-list-empty.yaml | Parity scenario for empty list behavior. |
| testdata/parity/edge-workers-list-empty-json.yaml | Parity scenario for empty list in JSON mode. |
| testdata/parity/edge-workers-list-csv.yaml | Parity scenario for list CSV output. |
| testdata/parity/edge-workers-json-control-name.yaml | Parity scenario for JSON output escaping with control chars in names. |
| testdata/parity/edge-workers-init.yaml | Parity scenario for project init. |
| testdata/parity/edge-workers-init-nonempty.yaml | Parity scenario for init refusal on non-empty dir. |
| testdata/parity/edge-workers-init-invalid-type.yaml | Parity scenario for invalid init type handling. |
| testdata/parity/edge-workers-get.yaml | Parity scenario for get details. |
| testdata/parity/edge-workers-get-source.yaml | Parity scenario for get --source formatting + safety. |
| testdata/parity/edge-workers-get-no-source.yaml | Parity scenario when --source requested but none stored. |
| testdata/parity/edge-workers-get-missing.yaml | Parity scenario for missing worker handling. |
| testdata/parity/edge-workers-get-empty-source.yaml | Parity scenario for empty stored source handling. |
| testdata/parity/edge-workers-entry-escape.yaml | Parity scenario ensuring entry path traversal is rejected. |
| testdata/parity/edge-workers-enable.yaml | Parity scenario for enabling a worker. |
| testdata/parity/edge-workers-enable-production-refused.yaml | Parity scenario for production enable confirmation refusal. |
| testdata/parity/edge-workers-duplicate-names.yaml | Parity scenario for duplicate worker names detection. |
| testdata/parity/edge-workers-double-dash.yaml | Parity scenario for -- boundary parsing. |
| testdata/parity/edge-workers-disable.yaml | Parity scenario for disabling a worker. |
| testdata/parity/edge-workers-deploy-upload-failure.yaml | Parity scenario for partial deploy upload failure. |
| testdata/parity/edge-workers-deploy-source-empty.yaml | Parity scenario for deploying with empty source. |
| testdata/parity/edge-workers-deploy-skip-validate.yaml | Parity scenario for deploy --skip-validate. |
| testdata/parity/edge-workers-deploy-skip-source.yaml | Parity scenario for deploy --skip-source on update. |
| testdata/parity/edge-workers-deploy-skip-source-create.yaml | Parity scenario for --skip-source on create. |
| testdata/parity/edge-workers-deploy-production-skip.yaml | Parity scenario for prod deploy with --skip-confirmation. |
| testdata/parity/edge-workers-deploy-production-refused.yaml | Parity scenario for prod deploy refusal without confirmation. |
| testdata/parity/edge-workers-deploy-name-all.yaml | Parity scenario for deploy name + --all conflict. |
| testdata/parity/edge-workers-deploy-location-replace.yaml | Parity scenario for location replace behavior. |
| testdata/parity/edge-workers-deploy-location-preserve.yaml | Parity scenario for location preserve behavior. |
| testdata/parity/edge-workers-deploy-location-clear.yaml | Parity scenario for clearing location on update. |
| testdata/parity/edge-workers-deploy-inactive-update.yaml | Parity scenario for updating inactive worker. |
| testdata/parity/edge-workers-deploy-inactive-update-enable.yaml | Parity scenario for update + enable. |
| testdata/parity/edge-workers-deploy-enable-failure.yaml | Parity scenario for enable failure after upload. |
| testdata/parity/edge-workers-deploy-create.yaml | Parity scenario for create via deploy. |
| testdata/parity/edge-workers-deploy-create-enable.yaml | Parity scenario for create + enable via deploy. |
| testdata/parity/edge-workers-deploy-all-preparation-failure.yaml | Parity scenario ensuring prepare-before-write semantics. |
| testdata/parity/edge-workers-deploy-active-update.yaml | Parity scenario for updating active worker. |
| testdata/parity/edge-workers-deploy-active-update-enable.yaml | Parity scenario for active update with --enable. |
| testdata/parity/edge-workers-delete-rejected.yaml | Parity scenario for delete rejected by API. |
| testdata/parity/edge-workers-delete-force.yaml | Parity scenario for delete with --force. |
| testdata/parity/edge-workers-build-one.yaml | Parity scenario for building one worker. |
| testdata/parity/edge-workers-build-name-all.yaml | Parity scenario for build name + --all conflict. |
| testdata/parity/edge-workers-build-missing-compiler.yaml | Parity scenario for missing compiler error. |
| testdata/parity/edge-workers-build-empty.yaml | Parity scenario for build with no workers. |
| testdata/parity/edge-workers-build-compiler-error.yaml | Parity scenario for compiler failure diagnostics. |
| testdata/parity/edge-workers-build-all.yaml | Parity scenario for build --all. |
| testdata/parity/edge-workers-bare-type.yaml | Parity scenario for bare optional --type parsing. |
| testdata/parity/edge-workers-bare-path.yaml | Parity scenario for bare optional --path parsing. |
| testdata/parity/edge-workers-bare-location.yaml | Parity scenario for bare optional --location parsing. |
| testdata/parity/edge-workers-artifact-symlink.yaml | Parity scenario preventing artifact symlink escape. |
| testdata/parity-local/edge-workers/two-workers/workers/b/worker.json | Local fixture worker manifest. |
| testdata/parity-local/edge-workers/two-workers/workers/b/assembly/index.ts | Local fixture worker source. |
| testdata/parity-local/edge-workers/two-workers/workers/a/worker.json | Local fixture worker manifest. |
| testdata/parity-local/edge-workers/two-workers/workers/a/assembly/index.ts | Local fixture worker source. |
| testdata/parity-local/edge-workers/two-workers/edge-workers.json | Local fixture project descriptor. |
| testdata/parity-local/edge-workers/basic/workers/headers/worker.json | Local fixture worker manifest. |
| testdata/parity-local/edge-workers/basic/workers/headers/assembly/index.ts | Local fixture worker source. |
| testdata/parity-local/edge-workers/basic/edge-workers.json | Local fixture project descriptor. |
| src/lib/edge-workers/output.ts | Add escapeTerminalSource for safe readable source output. |
| src/bin/vip-edge-workers-get.js | Use source-specific escaping for get --source. |
| internal/parity/surface_differential_test.go | Exclude edge-worker scenarios from the generic surface inventory. |
| internal/parity/runner.go | Add per-run working directory support. |
| internal/parity/runner_test.go | Test runner working directory behavior. |
| internal/parity/edge_workers_prompt_test.go | Add PTY-based prompt parity tests (non-Windows). |
| internal/parity/edge_workers_differential_test.go | Add full Node-vs-Go differential harness for Edge Workers. |
| internal/parity/edge_workers_cases_test.go | Declare Edge Workers differential scenario inventory. |
| internal/parity/edge_workers_build_smoke_test.go | Opt-in real compiler smoke test for both runtimes. |
| internal/output/output_test.go | Add JSON control-character escaping test coverage. |
| internal/output/json.go | Escape DEL/C1 in rendered JSON to match Node terminal-safe behavior. |
| internal/gql/schema.gql | Extend schema with edge worker validation and updated mutation docs. |
| internal/gql/operations/edge_workers.graphql | Add Edge Workers queries/mutations used by Go runtime. |
| internal/gql/genqlient.yaml | Bind edge worker mutation inputs to custom marshaler types. |
| internal/gql/edgeworkerinput/input.go | Custom JSON marshaling to preserve omitted/null/empty semantics. |
| internal/gql/edgeworkerinput/input_test.go | Tests for presence/omission semantics in mutation inputs. |
| internal/edgeworkers/validation.go | Validation helpers for names/paths/location parsing and containment. |
| internal/edgeworkers/types.go | Define Edge Workers domain types and API interface. |
| internal/edgeworkers/templates/worker.ts | Scaffolded AssemblyScript worker template. |
| internal/edgeworkers/templates/tsconfig.json | Scaffolded tsconfig template. |
| internal/edgeworkers/templates/README.md | Scaffolded project README. |
| internal/edgeworkers/templates/package.json | Scaffolded package.json with pinned SDK/compiler deps. |
| internal/edgeworkers/templates/gitignore | Scaffolded .gitignore template. |
| internal/edgeworkers/templates/edge-workers.json | Scaffolded project descriptor template. |
| internal/edgeworkers/scaffold.go | Implement project/worker scaffolding in Go. |
| internal/edgeworkers/project.go | Implement project discovery + manifest/descriptor parsing in Go. |
| internal/edgeworkers/project_test.go | Tests for discovery, sorting, parsing, symlink safety. |
| internal/edgeworkers/output.go | Implement terminal-safe output formatting (incl. source). |
| internal/edgeworkers/output_test.go | Tests for output escaping + confirmation messaging. |
| internal/edgeworkers/deployment.go | Plan/prepare/apply deployment logic with prepare-before-write. |
| internal/edgeworkers/deployment_test.go | Tests for partial failure, presence, active state semantics. |
| internal/edgeworkers/confirmation.go | Implement production confirmations and deletion confirmation. |
| internal/edgeworkers/build.go | Build via AssemblyScript compiler and safe artifact/source reads. |
| internal/edgeworkers/build_test.go | Tests for scaffolding safety, compiler args, UTF-8 replacement, symlinks. |
| internal/edgeworkers/api.go | Go GraphQL client wrapper for Edge Workers operations. |
| internal/edgeworkers/api_test.go | Tests for payloads, read envelopes, rechallenge caching, retry rules. |
| go.mod | Promote golang.org/x/text to direct dependency (used by new code). |
| docs/EDGE-WORKERS.md | Document Go runtime command availability + source rendering rules. |
| cmd/vip-next/root.go | Register new edge-workers command in Go CLI. |
| cmd/vip-next/flags_node_parity_test.go | Add short-flag parity mappings for edge-workers commands. |
| cmd/vip-next/edge_workers_test.go | Root command wiring + parsing/help marker tests for edge-workers. |
| cmd/vip-next/commands/edge_workers.go | Core command wiring, shared helpers, app/env integration. |
| cmd/vip-next/commands/edge_workers_test.go | Go command-level tests for lifecycle, validation, telemetry, non-interactive behavior. |
| cmd/vip-next/commands/edge_workers_read.go | Implement list/get/validate commands. |
| cmd/vip-next/commands/edge_workers_mutation.go | Implement deploy/enable/disable/delete commands. |
| cmd/vip-next/commands/edge_workers_local.go | Implement init/new/build local commands. |
| cmd/vip-next/commands/edge_workers_flags.go | Implement optional-value flag handling for Node parity. |
| tests/lib/edge-workers/project.js | Extend Node tests for malformed UTF-8 source replacement. |
| tests/bin/vip-edge-workers-get.js | Add Node tests for safe readable get --source rendering. |
Suppressed comments (3)
cmd/vip-next/commands/edge_workers_local.go:49
- The command examples use
vip ...even though the Go binary root command isvip-next, which can confuse users reading--help.
c := &cobra.Command{Use: "new <name>", Short: "Add a new worker to an edge-workers project.", Example: " vip edge-workers new add-security-headers\n vip edge-workers new my-worker --path ./infra/edge\n vip edge-workers new api-auth --location starts_with:/api/"}
cmd/vip-next/commands/edge_workers_read.go:33
- This help example uses
vip ...even though the Go CLI entrypoint isvip-next. Since this is copy/paste guidance, it should match the actual binary name.
c := &cobra.Command{Use: "get <name>", Short: "Retrieve details for a single deployed edge worker.", Example: " vip @example-app.production edge-workers get my-worker\n vip @example-app.production edge-workers get my-worker --source"}
cmd/vip-next/commands/edge_workers_mutation.go:77
- This help example uses
vip ...even though the Go CLI root command isvip-next. Using the correct binary name prevents copy/paste mistakes from--help.
c := &cobra.Command{Use: action + " <name>", Short: verb + " a deployed edge worker.", Example: " vip @example-app.production edge-workers " + action + " my-worker"}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
#### Purpose and Context The Go Edge Workers examples and scaffold next steps point at the Node vip executable. Copying them can switch runtimes unintentionally. #### Key Changes Use vip-next in all ten Go help examples and the init/new next-step messages. Leave Node guidance and shared project templates unchanged. #### Impact and Considerations Document the approved executable-name difference in the cutover notes. Parity first checks each runtime's actual executable name, then normalizes only the known init/new guidance prefixes. Arguments, source contents, filesystem effects, and API requests still compare. #### Testing and Validation Add rendered-help coverage for all ten Go commands and next-step assertions in both runtimes. Verify expected failures before the fix, then run Go tests, vet/build, Node init/new tests and lint, and real Node-vs-Go fixture parity in normal and hostile environments.
|



Description
Port the existing Node Edge Workers command set to the Go runtime:
init,new,build,validate,list,get,deploy,enable,disable, anddelete.The implementation reuses Go app/environment resolution and authenticated GraphQL middleware. It preserves inactive creation, explicit enablement, production confirmations, prepare-before-write deployment, source omission, location preservation/clearing, and partial-failure reporting. Local AssemblyScript builds still require Node.js and project npm dependencies.
Add equivalent fixtures and real Node-vs-Go comparisons for output, API requests, filesystem effects, parsing, and confirmations. Match Node's terminal-safe JSON escaping and malformed UTF-8 source decoding. The approved executable-name difference is documented in cutover note 1.28: Go Edge Workers help examples and
init/newnext steps invokevip-next; Node continues to invokevip. Shared project templates are unchanged. Node SEA changes are out of scope.Source display fix
Both runtimes now preserve newlines and tabs in
get --sourceoutput and normalize CRLF to LF. A source-specific formatter still escapes standalone carriage returns, ANSI escapes, and other terminal controls; metadata escaping and stored source remain unchanged. Literal backslash escape sequences are not decoded.Regression tests failed in both runtimes before the fix and passed afterward. The real CLI parity scenario also asserts the expected readable output independently, so a shared rendering bug cannot pass merely because both runtimes match.
Go executable guidance
Address Copilot's four review comments by correcting all ten Go help examples and the
init/newnext steps. Tests render each command's help, assert Node and Go guidance independently, then normalize only those known executable prefixes for parity comparison.Changelog Description
Added
Fixed
get --sourceoutput without allowing unsafe terminal controls.Verification
Passed locally on macOS:
make test,make lint, andmake verify-gql-stale.make test-parity-unitandmake test-parity-unit-hostile, including 70 Edge Workers differential scenarios and six terminal-prompt scenarios.allocandon_client_responsefunction exports.Not verified:
make test-paritywas attempted, but a required local API service was stopped. App-context discovery failed before any local integration scenario ran. No live Edge Worker was deployed or enabled. Windows execution and host-modifying dev-env E2E tests were not run.Pull request checklist
Steps to Test
make test,make lint, andmake verify-gql-stale.npm run build,npm run check-types,make require-node-vip-bin,make test-parity-unit, andmake test-parity-unit-hostile.NODE_VIP_BIN="$PWD/dist/bin/vip.js" go test -tags='parity edgeworkers_build_smoke' ./internal/parity -run '^TestEdgeWorkersRealCompilerSmoke$' -count=1 -v. This installs pinned compiler dependencies into temporary projects.make test-parity.