Skip to content

Migrate @azure-tools/typespec-go from autorest.go into this repo#4628

Merged
tadelesh merged 61 commits into
mainfrom
go-migration
Jul 17, 2026
Merged

Migrate @azure-tools/typespec-go from autorest.go into this repo#4628
tadelesh merged 61 commits into
mainfrom
go-migration

Conversation

@tadelesh

@tadelesh tadelesh commented Jun 15, 2026

Copy link
Copy Markdown
Member

Migrates @azure-tools/typespec-go from Azure/autorest.go into this monorepo. See Azure/autorest.go#1982 for full background and plan.

What's in this PR

Source code (Phase 3 of the migration plan)

  • New packages/typespec-go/ containing the emitter and its three previously-private workspace dependencies inlined:
    • codegen.gosrc/codegen/
    • codemodel.gosrc/codemodel/
    • naming.gosrc/naming/
  • Static assets: README.md, LICENSE, CHANGELOG.md, vitest.config.ts, tsconfig.json (mirrors typespec-python).
  • .chronus change entry.

Tests

The emitter is tested with three tiers, in order of preference (documented in docs/development.md):

  1. Emitter unit tests (scenarios) — the default. Markdown snapshot tests under test/unittest/scenarios/*.md: each .md compiles a small TypeSpec in memory and snapshots the generated Go, with no Go toolchain or mock server. ~29 focused scenarios cover naming, models/serialization, client & options shapes, polymorphism, client customizations (@@alternateType / @@clientName), containing-module, sample generation (example JSON input → *_example_test.go), and the former Regressions code-gen cases.
    • scenario-runner.ts — in-memory compile + snapshot harness (SCENARIOS_UPDATE=true regenerates expected blocks; ARM specs auto-routed to an ARM tester).
    • gen-scenario-suites.mjs — generates one vitest suite per .md; scenario-suites.guard.test.ts fails if they drift.
  2. External service specs — all Azure RM / data-plane service specs (17 modules) are sourced from Azure/azure-rest-api-specs at a pinned commit via a sparse, blobless, shallow clone:
    • .scripts/azure-rest-api-specs.json — pinned commit + sparse paths
    • .scripts/sync-azure-rest-api-specs.js — idempotent sync (skipped when cache marker matches)
    • .scripts/tspconfig.yaml — stub config that suppresses upstream tspconfig bleed (the per-language @azure-tools/typespec-go options that target azure-sdk-for-go)
  3. Local spec tests — kept only where the behavior can only be verified by executing generated Go at runtime. Just two remain:
    • gogenerate (test/tsp/GoGeneratetest/local/gogenerate) — the post-generation go generate hook.
    • fakeserver (test/tsp/FakeServertest/local/fakeserver) — fake-server runtime behavior (context cancellation, dispatch races, path/query decoding); a minimal 2-operation spec.

Removed local specs (migrated into scenarios): ClientOption, Internal.Pager, ModelsOnlyWithBaseTypes, NoOptionalBody, PageableLROs, Random.Management, RawJson, and the Test.Management ARM provider. The old Regressions grab-bag was split into scenarios plus the slimmed fakeserver runtime test. The local ExactName test was dropped (duplicated by an azure-http-specs scenario).

Build / regenerate

  • .scripts/tspcompile.js — Always invoked with --config=.scripts/tspconfig.yaml so upstream tspconfigs don't bleed.
  • .scripts/semaphore.js — 8-way parallel compile primitive.
  • .scripts/spector.js — reused start/stop wrapper around npx tsp-spector.

CI

  • .github/workflows/ci-go.yml — jobs: build, test (Go matrix 1.26.1/1.25.8 with regenerate + lint:go + spector-backed test:go:e2e), unit (vitest), docs (regen-docs).
  • .github/actions/setup-go/action.yml — composite wrapping actions/setup-go@v5.
  • eng/config/labels.ts — adds emitter:go area label + path mapping.
  • eng/pipelines/jobs/build-for-publish.yml — adds Go regen + e2e + upload-spector-coverage.yml template call (GeneratorName=@azure-tools/typespec-go) after the Python block.
  • tsconfig.ws.json includes the new package.
  • Root mise.toml pins go = "1.26.1" for local development; in CI Go is installed via actions/setup-go (GH Actions) and GoTool@0 (ADO release pipeline).
  • .gitignore ignores generated zz_*.go / go.mod / go.sum / LICENSE.txt / testdata under packages/typespec-go/test/.

Skipped per discussion

  • No nightly pipeline — all TypeSpec deps live in this repo now.
  • test/local/ stays in this repo — not relocated to azure-sdk-for-go.

Validation (local)

  • pnpm build
  • pnpm test (vitest unit) ✅ 47/47 (29 scenario suites + guard + emitter tests)
  • pnpm regenerate ✅ all tsp compiles
  • pnpm format:check ✅ clean for all packages/typespec-go/** files
  • pnpm lint:go0 issues (golangci-lint v2.11.4 + shadow, every generated module)
  • pnpm test:go:e2e ✅ spector start → hand-written test modules (azblob / azkeys / gogenerate / fakeserver) PASS → spector stop

Follow-ups (out of scope; tracked in autorest.go#1982)

  • Migrate remaining swagger-based data-plane SDKs to the latest autorest.go (Phase 1, in flight).
  • Stop maintaining codegen.go / codemodel.go / naming.go in autorest.go once Phase 4 lands.
  • Announce deprecation of autorest.go (after Phase 4).

Comment thread packages/typespec-go/src/codegen/fake/servers.ts Dismissed
@azure-sdk

azure-sdk commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

All changed packages have been documented.

  • @azure-tools/typespec-go
Show changes

@azure-tools/typespec-go - internal ✏️

Move @azure-tools/typespec-go from Azure/autorest.go into Azure/typespec-azure. The previously-private workspace packages @azure-tools/codegen.go, @azure-tools/codemodel.go, and @azure-tools/naming.go are now inlined into src/codegen, src/codemodel, and src/naming respectively. No behavior changes for emitter consumers.

@pkg-pr-new

pkg-pr-new Bot commented Jun 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-go@4628

commit: 439c537

@azure-sdk

azure-sdk commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

You can try these changes here

🛝 Playground 🌐 Website

tadelesh and others added 5 commits June 15, 2026 15:45
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix 13 spelling typos carried over from upstream source (acceptible,
  credendial, defef, deferenced, depracated, Disciminator, encounted,
  enveloipe, furture, hepler, Iterface, specifiy, uhandled).
- Rename formatValue's defef parameter to deref (callers pass positionally).
- Rename trackDisciminator function to trackDiscriminator.
- Add cspell ignorePaths for packages/typespec-go/{test,temp,.scripts}/**.
- Add legitimate Go SDK identifiers (azfake, azidentity, GOPATH, Errorf,
  Fatalf, polymorphics, Retriable, Unmarshaller, etc.) and Go stdlib
  package names (cmplx, fcgi, flate, gofmt, pkix, etc.) to dictionary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ran pnpm sync-labels to regenerate triage policy files and CONTRIBUTING.md
labels reference with the new emitter:go area label.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tadelesh and others added 4 commits June 15, 2026 16:27
The filtered install (--filter @azure-tools/typespec-go...) doesn't pull in
core's workspace-root devDependencies (prettier-plugin-organize-imports),
which @typespec/xml's gen-extern-signature -> tspd -> prettier requires
at build time. Match the build/test jobs and install everything.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- nooptionalbody/testdata/generate/transforms.go: hand-authored helper invoked by after_generate.go's //go:generate directive. Without it, the emit's post-step go generate fails, cleanGeneratedFiles wipes all zz_*.go except zz_version.go, and the orphan triggers a downstream golangci-lint 'unused const' error.

- rawjson/go.mod and go.sum: rawjson uses containing-module=rawjson/v2 and emits into subpkg/. The module root (one level up) must exist for the emit's post-step go mod tidy to find go.mod.

Also: surface emit failures in tspcompile.js by setting process.exitCode = 1. Previously a failed emit only logged 'exec error' and let the script exit 0, hiding the failure until a downstream lint job complained.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tadelesh and others added 2 commits June 15, 2026 17:16
verify-labels CI runs pnpm sync-labels --github --check which requires the banner emitted by core/eng/common/scripts/labels/definitions.ts:295 to match exactly. PR #4563 had hand-patched the banner to a different path that the script never reproduces, so any PR touching CONTRIBUTING.md or eng/config/labels.ts fails the check. Re-running pnpm sync-labels produces this content; committing verbatim.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…seline

After pnpm regenerate finishes, the locally regenerated test artifacts under packages/typespec-go/test/{local,http-specs,azure-http-specs}/ are automatically mirrored into a sparse checkout of Azure/azure-sdk-assets@typespec-go in packages/typespec-go/temp/baseline/. Developers can then inspect codegen deltas with a plain git -C temp/baseline status / git diff — no separate command needed.

- New .scripts/sync-baseline.js: idempotent shallow+blobless sparse clone (test/local, test/http-specs, test/azure-http-specs); mirror copies the local tree into the checkout after regen.

- tspcompile.js: kicks off the sync at startup and runs the mirror in beforeExit so it fires after every emit's async callback has drained. Skipped on regen failure (process.exitCode != 0) so partial output doesn't pollute the baseline.

- ci-go.yml: TYPESPEC_GO_SKIP_BASELINE=1 on the Regenerate step so CI doesn't need network access to azure-sdk-assets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread .chronus/changes/typespec-go-move-into-typespec-azure-2026-06-11-14-30-00.md Outdated
Comment thread .github/actions/setup-go/action.yml
Comment thread packages/typespec-go/package.json Outdated
Comment thread packages/typespec-go/package.json Outdated
Comment thread .github/workflows/ci-go.yml
Comment thread packages/typespec-go/.scripts/azure-rest-api-specs.json
@jhendrixMSFT

Copy link
Copy Markdown
Member

Are there plans to get more granular WRT what runs in CI? At present it looks like quite a few things ran that's not germane to this emitter.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tadelesh and others added 6 commits July 9, 2026 12:07
Collapse wrapped prose paragraphs to single lines and correct the lint:go
description to note it covers test/local, test/http-specs and test/azure-http-specs
(not just test/local).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The old intro claimed everything under test/ is generated from specs. Describe the
actual mix (in-memory unit tests, local spec tests, external Spector specs) and note
that regenerate only writes the Go fixtures under test/local, test/http-specs and
test/azure-http-specs, while test/unittest is updated via pnpm test:update.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… vs tests

The old Step 3 (Regenerate) and Step 4 (Test) were both loosely "about tests" and
awkwardly ordered, while the closely-related Step 5 (Review the generated-code diff)
sat after them. Restructure so the steps follow the actual workflow:

- Step 3 "Regenerate and validate the generated code" now groups everything about
  the generated artifacts: regenerate, review the baseline diff (merged from the old
  Step 5), run the Go tests, lint the generated Go, and debug.
- Step 4 "Add or update tests" is now purely about authoring tests: choosing the
  right tier and writing an emitter unit-test scenario.
- Renumber the remaining steps and fix all cross-references and the TOC.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Regenerating fixtures, running the Go tests and linting are all part of the same
testing story as the unit-test scenarios (they exercise tiers 2 and 3 of the test
taxonomy), so splitting them across two top-level steps was artificial. Merge them
into one "Step 3: Test your changes" ordered from cheapest to heaviest: choose the
tier, write an in-memory scenario, then (for the generated-Go tiers) regenerate,
review the diff, run the Go tests, and lint. Renumber docs/PR to Steps 4/5 and fix
the TOC and cross-references.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ports Azure/autorest.go#2022 into the migrated emitter: emit
`fmt.Errorf("unmarshalling type %T: %s", recv, err.Error())` instead of the
`%v` + err form in the three JSON-unmarshaller code paths. This makes the intent
to propagate the error message explicit and avoids tripping errorlint in the
generated code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bump the package version to 0.14.3 and add the 0.14.3 changelog section to match
the upstream Azure/autorest.go release (adapting Access.internal polymorphic
returns; JSON unmarshalling errors now use %s + err.Error()).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tadelesh tadelesh closed this Jul 10, 2026
@tadelesh tadelesh reopened this Jul 10, 2026
Resolve conflict in eng/pipelines/jobs/build-for-publish.yml: main (#4824)
decoupled emitter e2e + spector-coverage from the publish critical path by moving
those steps into eng/pipelines/jobs/spector-coverage.yml. Take main's version of
build-for-publish.yml and add the Go e2e steps as a new `spector_go` job in
spector-coverage.yml, matching the Python/Java/TS jobs (turbo-cache restore +
GoTool + regenerate + test:go:e2e + upload-spector-coverage).
Comment thread packages/typespec-go/docs/development.md Outdated
Comment thread packages/typespec-go/package.json Outdated
Comment thread packages/typespec-go/docs/development.md Outdated
Comment thread packages/typespec-go/docs/development.md
@Azure Azure deleted a comment from github-actions Bot Jul 16, 2026
tadelesh and others added 3 commits July 16, 2026 11:21
… fix scenario UX

- Rename the npm script `regenerate` back to `tspcompile` (matches the original
  name and the `.scripts/tspcompile.js` file); update ci-go.yml and the Go
  spector-coverage job to call `pnpm run tspcompile`.
- Remove the azure-sdk-assets baseline diff scheme entirely: delete
  .scripts/sync-baseline.js, drop the sync/mirror calls from tspcompile.js, the
  `TYPESPEC_GO_SKIP_BASELINE` env, and the "Review the generated-code diff" doc
  section (decided not to use this approach).
- Scenario usability: `test:update` now regenerates the per-scenario suites
  first so a newly added `.md` is picked up automatically; the harness now fails
  explicitly when a scenario has a `tsp` block but no `go <name>` output block
  (previously it silently passed producing no Go); make gen-scenario-suites emit
  prettier-stable output so regenerating never drifts; document the output-block
  requirement.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wrap the verbose `turbo run build --filter=@azure-tools/typespec-go...` (build
the emitter plus its workspace deps) in a `build:deps` package script. Update
the development guide's Step 2 to `pnpm build:deps` and the four ci-go.yml build
steps to `pnpm --filter "@azure-tools/typespec-go" run build:deps`, giving a
single source of truth for how to build the emitter. Addresses the PR review
comment asking for a package.json script.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread packages/typespec-go/test/unittest/scenarios/discriminated-base-no-subtypes.md Outdated
tadelesh and others added 2 commits July 17, 2026 11:37
…o-output error

Addresses two PR review comments on the scenario harness:

- Format generated Go with `gofmt -s` when snapshotting (the emitter runs the
  same after emit), so snapshots match the shipped, formatted code instead of
  the raw pre-format output — fixes the unindented struct-field comments Joel
  flagged. Reformats all existing scenario snapshots accordingly. The `unit` CI
  job now sets up Go so gofmt is available; documented the toolchain requirement.
- When a scenario has a tsp block but no output block, the failure now lists the
  `go <name>` block names its input actually produces, so the author can copy
  one in.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
oxlint's preserve-caught-error flagged the ENOENT re-throw in the scenario
harness gofmt helper for dropping the caught error. Attach it via the Error
cause option.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tadelesh
tadelesh added this pull request to the merge queue Jul 17, 2026
Merged via the queue into main with commit 0e66bb8 Jul 17, 2026
35 checks passed
@tadelesh
tadelesh deleted the go-migration branch July 17, 2026 05:24
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:go Issues for @azure-tools/typespec-go emitter label Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:go Issues for @azure-tools/typespec-go emitter eng meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants