diff --git a/.github/config/en-custom.txt b/.github/config/en-custom.txt index dbc3d2ce..2f8e0624 100644 --- a/.github/config/en-custom.txt +++ b/.github/config/en-custom.txt @@ -16,6 +16,7 @@ Azure SQLServer subcomponents Blazor +brooke clusterissuer tcpreplay DDoS @@ -30,13 +31,24 @@ CRON CRUDL CSI CTRL +Codegen Codespace Codespaces +codeql CosmosDB +corepack +Corepack CreateOrUpdate Datastores DDD +dep +deps deserialize +desynchronization +devcontainer +devDependencies +devcontainers +dirs DNS dns DaemonSet @@ -176,6 +188,7 @@ centric cli clusterName codebase +codegen codespace codespaces codetab @@ -226,6 +239,10 @@ github githubPath gotestsum githubRepo +gitmodules +gitsubmodule +gomod +hamilton handoff hardcoding hostname @@ -266,10 +283,15 @@ linux liveness lrt livenessProbe +lockfile +lockfiles +Lockfiles localWorkspace localhost macOS macos +Makefile +Makefiles managedStore md memorydb @@ -277,6 +299,9 @@ microservice microservice microservices microsoft +mk +Monorepo +monorepos mongo mongoDB mongoDatabase @@ -299,7 +324,10 @@ namespaces nav navbar newtab +noncloud npm +npmrc +npx objectname oidcIssuer org's @@ -309,12 +337,20 @@ pageinfo param params parametrization +parallelizable passthrough Peirone pem performant periodSeconds pfx +pnpm +pnpm's +pnpmVersion +POSIX +postCreateCommand +postinstall +Postinstall powershell pre preconfigured @@ -333,6 +369,8 @@ rabbitmq radapp radiuspublic rbac +READMEs +recurse rediscaches readinessProbe redis @@ -340,6 +378,7 @@ redisCaches redoc replacePrefix repo +reproducibility resourceGroupName resourceId resourcegroup @@ -377,6 +416,12 @@ statestore stdout stgSuffixes submodules +submodule +Submodule +subdirectory +subdirectories +Symlinked +src subnet subnets subscriptionID @@ -393,6 +438,7 @@ traceId ubuntu ui ucp +uncompiled unencrypted unmanaged url @@ -410,6 +456,10 @@ wi workingDir workspaceTypes workspaces +worktree +Worktree +worktrees +Worktrees walkthrough yaml yml @@ -705,6 +755,7 @@ Convertor DataModel PRs TypeSpec +TypeScript TerraformConfig envVariables EnvironmentVariables diff --git a/specs/001-remove-bicep-types-submodule/checklists/requirements.md b/specs/001-remove-bicep-types-submodule/checklists/requirements.md new file mode 100644 index 00000000..20d185fd --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/checklists/requirements.md @@ -0,0 +1,37 @@ +# Specification Quality Checklist: Remove bicep-types Submodule & Migrate to pnpm + Go Modules + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: January 22, 2026 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Spec derived from GitHub Issue #10913 with comprehensive acceptance criteria from the issue +- All functional requirements map to specific acceptance scenarios in user stories +- Assumptions section documents dependencies on external repository structure (Azure/bicep-types) +- Spec is ready for `/speckit.clarify` or `/speckit.plan` diff --git a/specs/001-remove-bicep-types-submodule/plan-1-go-modules.md b/specs/001-remove-bicep-types-submodule/plan-1-go-modules.md new file mode 100644 index 00000000..bb800589 --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/plan-1-go-modules.md @@ -0,0 +1,187 @@ +# Implementation Plan 1: Migrate Go Dependencies to Direct Module Reference + +**Branch**: `001-remove-bicep-types-submodule-go` | **Date**: 2026-01-22 | **Spec**: [spec.md](./spec.md) +**Input**: Feature specification from `/specs/001-remove-bicep-types-submodule/spec.md` + +## Summary + +Migrate Go code from using the local `bicep-types` submodule via `replace` directive to referencing `github.com/Azure/bicep-types/src/bicep-types-go` as a standard Go module dependency pinned to a specific commit SHA. This is the first phase of removing the bicep-types submodule, enabling the second phase (pnpm migration + submodule removal) to proceed safely. + +## Technical Context + +**Language/Version**: Go 1.25.5 (per go.mod) +**Primary Dependencies**: `github.com/Azure/bicep-types/src/bicep-types-go` (currently via replace directive to local submodule) +**Storage**: N/A +**Testing**: `go test`, `make test` +**Target Platform**: Linux (CI), macOS/Windows (developer machines) +**Project Type**: Monorepo with Go services, TypeScript tooling +**Performance Goals**: Build time should not regress significantly +**Constraints**: Must maintain reproducible builds via commit SHA pinning +**Scale/Scope**: ~20 Go files importing bicep-types-go packages + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +| Principle | Status | Notes | +| ----------- | -------- | ------- | +| **I. API-First Design** | ✅ PASS | No API changes - dependency management only | +| **II. Idiomatic Code Standards** | ✅ PASS | Using standard Go modules is idiomatic | +| **III. Multi-Cloud Neutrality** | ✅ PASS | No cloud-specific changes | +| **IV. Testing Pyramid Discipline** | ✅ PASS | Existing tests validate bicep-types-go integration | +| **V. Collaboration-Centric Design** | ✅ PASS | Improves contributor experience | +| **VI. Open Source and Community-First** | ✅ PASS | Following standard open source dependency practices | +| **VII. Simplicity Over Cleverness** | ✅ PASS | Replacing complex submodule with standard Go modules | +| **VIII. Separation of Concerns** | ✅ PASS | Clean dependency boundary via module reference | +| **IX. Incremental Adoption** | ✅ PASS | First phase of two-phase migration; Go code works independently | +| **XVI. Repository-Specific Standards** | ✅ PASS | Following radius repo Go conventions | +| **XVII. Polyglot Project Coherence** | ✅ PASS | Consistent with Go ecosystem patterns | + +**Gate Result**: ✅ All gates pass + +## Requirements Addressed + +| Requirement | Coverage | +| ------------- | ---------- | +| FR-004 | Go code references bicep-types-go through go.mod as standard module | +| FR-005 | Go module dependencies resolvable via `go mod` commands | +| FR-006 | Go module pinned to specific git commit SHA | +| FR-020 (partial) | Go-related documentation updated | + +## Project Structure + +### Documentation (this feature) + +```text +specs/001-remove-bicep-types-submodule/ +├── spec.md # Feature specification +├── plan-1-go-modules.md # This file (Plan 1) +├── plan-2-pnpm-submodule.md # Plan 2 (pnpm + submodule removal) +├── research-1-go-modules.md # Phase 0 research for Plan 1 +└── tasks-1-go-modules.md # Phase 2 tasks for Plan 1 +``` + +### Source Code Changes (radius repository) + +```text +radius/ +├── go.mod # MODIFY: Replace directive → direct dependency +├── go.sum # MODIFY: Add bicep-types-go checksums +├── CONTRIBUTING.md # MODIFY: Update Go dependency instructions +└── docs/contributing/ # MODIFY: Update relevant contributor docs +``` + +## Technical Approach + +### Current State + +The `go.mod` file contains: + +```go +replace github.com/Azure/bicep-types/src/bicep-types-go => ./bicep-types/src/bicep-types-go +``` + +This points to the local submodule directory. Go imports throughout the codebase use: + +```go +import "github.com/Azure/bicep-types/src/bicep-types-go/types" +import "github.com/Azure/bicep-types/src/bicep-types-go/factory" +import "github.com/Azure/bicep-types/src/bicep-types-go/index" +import "github.com/Azure/bicep-types/src/bicep-types-go/writers" +``` + +### Target State + +Replace the `replace` directive with a direct module dependency: + +```go +require ( + github.com/Azure/bicep-types/src/bicep-types-go v0.0.0-20260115000000-abc123def456 +) +``` + +The import paths remain unchanged since they already use the canonical module path. + +### Migration Steps + +1. **Identify target commit SHA** in Azure/bicep-types repository +2. **Update go.mod**: Remove `replace` directive, add direct `require` +3. **Run `go mod tidy`**: Resolve and verify dependencies +4. **Run `go build ./...`**: Verify compilation +5. **Run `make test`**: Verify all tests pass +6. **Update documentation**: Remove submodule references from Go setup docs + +> **Note**: Dependabot is already configured for Go module updates in the repository, so no additional configuration is needed. + +### Rollback Strategy + +Standard git revert of the PR. The submodule is still present (removed in Plan 2), so reverting restores the `replace` directive and everything works as before. + +## Research Required (Phase 0) + +1. **Commit SHA Selection**: Identify the current bicep-types commit the submodule points to, verify it's available as a Go module +2. **Go Module Availability**: Verify `github.com/Azure/bicep-types/src/bicep-types-go` can be fetched as a Go module from the Azure/bicep-types repository +3. **API Compatibility**: Confirm no breaking changes between submodule version and direct module version + +## Design Artifacts (Phase 1) + +### data-model.md + +Not applicable - this is a dependency management change with no data model changes. + +### contracts/ + +Not applicable - no API changes. + +### quickstart.md + +Developer quickstart for verifying Go module migration: + +```bash +# Clone repository (no --recurse-submodules needed for Go after this change) +git clone https://github.com/radius-project/radius +cd radius + +# Verify Go dependencies resolve +go mod download + +# Build +make build + +# Run tests +make test +``` + +## Dependencies + +- **Upstream**: Azure/bicep-types repository must have the target commit available +- **Downstream**: Plan 2 (pnpm + submodule removal) depends on this plan completing successfully + +## Success Criteria + +| Criterion | Validation | +| ----------- | ------------ | +| SC-001 (partial) | Go build completes without submodule initialization | +| SC-003 (partial) | Go-related build/test workflows have no git submodule commands | +| SC-005 | All existing Go tests pass without modification | + +## Risks and Mitigations + +| Risk | Impact | Mitigation | +| ------ | -------- | ------------ | +| bicep-types-go not available as standalone module | HIGH | Research in Phase 0; may need to work with Azure/bicep-types maintainers | +| Version mismatch causing build failures | MEDIUM | Pin to exact commit SHA matching current submodule | + +## Complexity Tracking + +> No complexity violations identified. This plan simplifies the dependency graph. + +--- + +## Phase Summary + +| Phase | Output | Status | +| ------- | -------- | -------- | +| Phase 0 | research-1-go-modules.md | NOT STARTED | +| Phase 1 | quickstart.md (above) | INCLUDED | +| Phase 2 | tasks-1-go-modules.md | NOT STARTED (via /speckit.tasks) | diff --git a/specs/001-remove-bicep-types-submodule/plan-2-pnpm-submodule.md b/specs/001-remove-bicep-types-submodule/plan-2-pnpm-submodule.md new file mode 100644 index 00000000..eca8adb4 --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/plan-2-pnpm-submodule.md @@ -0,0 +1,582 @@ +# Implementation Plan 2: Migrate to pnpm + Remove bicep-types Submodule + +**Branch**: `001-remove-bicep-types-submodule-pnpm` | **Date**: 2026-01-22 (Updated: 2026-01-31) | **Spec**: [spec.md](./spec.md) +**Input**: Feature specification from `/specs/001-remove-bicep-types-submodule/spec.md` +**Depends On**: [Plan 1: Go Modules Migration](./plan-1-go-modules.md) +**Prototype**: [brooke-hamilton/radius:pnpm-direct-ref](https://github.com/brooke-hamilton/radius/tree/pnpm-direct-ref) + +## Summary + +Migrate JavaScript/TypeScript tooling in `hack/bicep-types-radius/` from npm to pnpm, update bicep-types npm dependencies to use pnpm git references with postinstall build scripts, remove the bicep-types git submodule, update all CI/CD workflows, and update documentation. This is the second and final phase of the submodule removal migration. + +**Key Insight from Prototype:** pnpm's subdirectory reference syntax (`#path:/`) does NOT work for TypeScript packages that require compilation. The solution is to reference the full repository in package.json (pnpm fetches it automatically), build the TypeScript package via a `postinstall` script, and create a symlink for module resolution. + +## Technical Context + +**Language/Version**: Node.js (per .node-version), TypeScript +**Primary Dependencies**: + +- `bicep-types` npm package (currently via `file:` reference to submodule) +- Various npm packages in `typespec/`, `hack/bicep-types-radius/` +**Package Manager**: npm → pnpm migration (for `hack/bicep-types-radius/` and `typespec/`) +**Storage**: N/A +**Testing**: npm/pnpm scripts, `make test` +**Target Platform**: Linux (CI), macOS/Windows (developer machines) +**Project Type**: Monorepo with TypeScript tooling, Go services +**Performance Goals**: Build time should not regress; pnpm typically improves it +**Constraints**: Must maintain reproducible builds via lockfiles with commit SHA pinning; TypeScript packages require local build +**Scale/Scope**: +- 3 npm package directories requiring pnpm migration (`autorest.bicep/`, `generator/`, `typespec/`) +- 8 CI workflow files with 15 `submodules:` occurrences to remove +- Multiple Makefile targets using npm commands + +**Critical Technical Constraint (discovered in prototype):** +The `bicep-types` package is TypeScript source code that must be compiled. The compiled `lib/` directory is `.gitignore`d in the upstream repository. Therefore: +1. pnpm's `#path:/` subdirectory syntax does NOT work +2. The full repository must be referenced as a git dependency (pnpm fetches it) +3. A `postinstall` script must run `npm install && npm run build` inside the package +4. A symlink must be created so `import from "bicep-types"` resolves correctly + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +| Principle | Status | Notes | +| --------- | ------ | ----- | +| **I. API-First Design** | ✅ PASS | No API changes - tooling/build system only | +| **II. Idiomatic Code Standards** | ✅ PASS | pnpm is modern, widely adopted package manager | +| **III. Multi-Cloud Neutrality** | ✅ PASS | No cloud-specific changes | +| **IV. Testing Pyramid Discipline** | ✅ PASS | Existing tests validate tooling; CI validates migration | +| **V. Collaboration-Centric Design** | ✅ PASS | Significantly improves contributor experience | +| **VI. Open Source and Community-First** | ✅ PASS | pnpm is open source, standard tooling | +| **VII. Simplicity Over Cleverness** | ✅ PASS | Replacing submodules with standard dependency management | +| **VIII. Separation of Concerns** | ✅ PASS | Clean dependency boundaries via pnpm | +| **IX. Incremental Adoption** | ✅ PASS | Migration includes contributor guide for existing clones | +| **XVI. Repository-Specific Standards** | ⚠️ CHECK | Dev container needs pnpm; devcontainer.json update required | +| **XVII. Polyglot Project Coherence** | ✅ PASS | Consistent with Node.js ecosystem patterns | + +**Gate Result**: ✅ All gates pass (XVI addressed in implementation) + +## Requirements Addressed + +| Requirement | Coverage | +| ----------- | -------- | +| FR-001 | bicep-types git submodule completely removed | +| FR-002 | .gitmodules configuration removed | +| FR-003 | No `git submodule` commands required for build/test | +| FR-007 | All JS/TS tooling migrated to pnpm | +| FR-008 | hack/bicep-types-radius/ uses pnpm git references | +| FR-009 | Lockfiles updated for pnpm git subdirectory references | +| FR-010 | pnpm dependencies pinned to specific commit SHA | +| FR-011 | Makefiles function without submodule commands | +| FR-012 | Build scripts use pnpm | +| FR-013 | Workflow files have no submodule steps | +| FR-014 | All CI/CD workflows pass without submodule operations | +| FR-015 | Codegen workflows complete with new dependency sources | +| FR-016 | All regression tests pass | +| FR-017 | Dependabot configured for pnpm | +| FR-018 | Security scanning covers bicep-types dependencies | +| FR-019 | Dev container includes pnpm | +| FR-020 | CONTRIBUTING.md updated | +| FR-021 | One-time migration guide for existing clones | +| FR-022 | Go and pnpm setup steps documented | +| FR-023 | All READMEs updated | + +## Project Structure + +### Documentation (this feature) + +```text +specs/001-remove-bicep-types-submodule/ +├── spec.md # Feature specification +├── plan-1-go-modules.md # Plan 1 (Go modules) +├── plan-2-pnpm-submodule.md # This file (Plan 2) +├── research-2-pnpm.md # Phase 0 research for Plan 2 +├── data-model.md # N/A for this feature +├── contracts/ # N/A for this feature +├── quickstart.md # Combined quickstart +└── tasks-2-pnpm-submodule.md # Phase 2 tasks for Plan 2 +``` + +### Source Code Changes (radius repository) + +```text +radius/ +├── .gitmodules # DELETE: Remove entirely +├── bicep-types/ # DELETE: Remove submodule directory from git index +│ +├── typespec/ +│ ├── package.json # NO CHANGE (no bicep-types dependency) +│ ├── package-lock.json # DELETE +│ └── pnpm-lock.yaml # CREATE: pnpm lockfile +│ +├── hack/bicep-types-radius/ +│ └── src/ +│ ├── autorest.bicep/ +│ │ ├── package.json # MODIFY: Add pnpm config, postinstall, bicep-types-repo +│ │ ├── .npmrc # CREATE: pnpm configuration +│ │ ├── package-lock.json # DELETE +│ │ └── pnpm-lock.yaml # CREATE: pnpm lockfile +│ └── generator/ +│ ├── package.json # MODIFY: Add pnpm config, postinstall, bicep-types-repo +│ ├── .npmrc # CREATE: pnpm configuration +│ ├── package-lock.json # DELETE +│ └── pnpm-lock.yaml # CREATE: pnpm lockfile +│ +├── build/ +│ └── generate.mk # MODIFY: npm → pnpm, add pnpm-installed check, remove submodule commands +│ +├── .github/ +│ ├── dependabot.yml # MODIFY: Remove gitsubmodule, add autorest.bicep and generator directories +│ └── workflows/ +│ ├── build.yaml # MODIFY: Remove submodules: recursive +│ ├── codeql.yml # MODIFY: Remove submodules: recursive +│ ├── lint.yaml # MODIFY: Remove submodules: recursive +│ ├── validate-bicep.yaml # MODIFY: Remove submodules: true +│ ├── publish-docs.yaml # MODIFY: Remove submodules: recursive +│ ├── long-running-azure.yaml # MODIFY: Remove submodules: recursive +│ ├── functional-test-noncloud.yaml # MODIFY: Remove submodules: recursive +│ └── functional-test-cloud.yaml # MODIFY: Remove submodules: recursive +│ +├── .devcontainer/ +│ ├── devcontainer.json # MODIFY: Add pnpmVersion to node feature configuration +│ └── post-create.sh # MODIFY: Change npm ci to pnpm install for typespec +│ +├── CONTRIBUTING.md # MODIFY: Update setup instructions +└── docs/contributing/ + └── migration-guide.md # CREATE: One-time migration guide for existing clones +``` + +## Technical Approach + +### Current State + +**Package References** (in `hack/bicep-types-radius/src/*/package.json`): + +```json +{ + "devDependencies": { + "bicep-types": "file:../../../../bicep-types/src/bicep-types" + } +} +``` + +**Makefile** (`build/generate.mk`): + +```makefile +generate-bicep-types: + git submodule update --init --recursive; \ + npm --prefix bicep-types/src/bicep-types install; \ + npm --prefix bicep-types/src/bicep-types ci && npm --prefix bicep-types/src/bicep-types run build; \ + npm --prefix hack/bicep-types-radius/src/autorest.bicep ci && ... +``` + +**Workflows** (multiple files): + +```yaml +- uses: actions/checkout@ + with: + submodules: recursive +``` + +**Dependabot**: + +```yaml +- package-ecosystem: gitsubmodule + directory: / + schedule: + interval: weekly +``` + +### Target State (Validated in Prototype) + +**Package References** (pnpm git reference with postinstall build): + +```json +{ + "pnpm": { + "onlyBuiltDependencies": ["autorest"] + }, + "scripts": { + "build": "tsc -p .", + "test": "jest", + "lint": "eslint src --ext ts", + "lint:fix": "eslint src --ext ts --fix", + "postinstall": "cd node_modules/bicep-types-repo/src/bicep-types && npm install && npm run build && cd ../../../.. && rm -rf node_modules/bicep-types && ln -sf bicep-types-repo/src/bicep-types node_modules/bicep-types" + }, + "devDependencies": { + "bicep-types-repo": "git+https://github.com/Azure/bicep-types.git#556bf5edad58e47ca57c6ddb1af155c3bcfdc5c7" + } +} +``` + +**Key elements of package.json changes:** + +| Element | Purpose | +| ------- | ------- | +| `bicep-types-repo` package name | pnpm fetches full repo to `node_modules/bicep-types-repo/`; name differs from symlink | +| `git+https://` URL format | Required by pnpm (not `github:` shorthand which defaults to SSH) | +| Commit SHA after `#` | Pins to specific version for reproducibility | +| `postinstall` script | Builds TypeScript and creates symlink for `bicep-types` imports | +| `pnpm.onlyBuiltDependencies` | Allows autorest lifecycle scripts (matches npm behavior) | + +**.npmrc** (new file in each package directory): + +```properties +# Allow pnpm to install packages that need to run postinstall scripts +side-effects-cache = false +``` + +**Makefile** (updated): + +```makefile +.PHONY: generate-pnpm-installed +generate-pnpm-installed: + @echo "$(ARROW) Detecting pnpm..." + @which pnpm > /dev/null || { echo "pnpm is a required dependency. Run 'npm install -g pnpm' to install."; exit 1; } + @echo "$(ARROW) OK" + +.PHONY: generate-bicep-types +generate-bicep-types: generate-node-installed generate-pnpm-installed ## Generate Bicep extensibility types + @echo "$(ARROW) Generating Bicep extensibility types from OpenAPI specs..." + @echo "$(ARROW) Installing autorest.bicep dependencies (postinstall builds bicep-types)..." + cd hack/bicep-types-radius/src/autorest.bicep && pnpm install + @echo "$(ARROW) Building autorest.bicep..." + pnpm --prefix hack/bicep-types-radius/src/autorest.bicep run build + @echo "$(ARROW) Installing generator dependencies (postinstall builds bicep-types)..." + cd hack/bicep-types-radius/src/generator && pnpm install + @echo "$(ARROW) Running generator..." + cd hack/bicep-types-radius/src/generator && pnpm run generate \ + --specs-dir ../../../../swagger --release-version ${VERSION} --verbose +``` + +**Workflows**: + +```yaml +- uses: actions/checkout@ + # No submodules property needed +``` + +**Dependabot** (remove gitsubmodule, add package directories): + +```yaml +# ADD: New directories for pnpm packages +- package-ecosystem: npm + directory: /hack/bicep-types-radius/src/autorest.bicep + schedule: + interval: weekly + groups: + autorest-bicep: + patterns: + - "*" + +- package-ecosystem: npm + directory: /hack/bicep-types-radius/src/generator + schedule: + interval: weekly + groups: + bicep-generator: + patterns: + - "*" + +# KEEP: Already exists in current config +- package-ecosystem: npm + directory: /typespec + ... + +# REMOVE: No longer needed +# - package-ecosystem: gitsubmodule +``` + +### Build Flow (After Migration) + +``` +make generate-bicep-types + │ + ├─▶ pnpm install in autorest.bicep + │ ├─▶ Fetches Azure/bicep-types to node_modules/bicep-types-repo/ + │ └─▶ postinstall: npm install → npm run build → creates symlink + │ + ├─▶ pnpm run build in autorest.bicep + │ + ├─▶ pnpm install in generator + │ ├─▶ Fetches Azure/bicep-types to node_modules/bicep-types-repo/ + │ └─▶ postinstall: npm install → npm run build → creates symlink + │ + └─▶ pnpm run generate +``` + +### Migration Steps + +1. **Install pnpm**: Update dev container, document installation for contributors +2. **Update autorest.bicep/package.json**: Add pnpm config, postinstall script, bicep-types-repo reference +3. **Create autorest.bicep/.npmrc**: Add `side-effects-cache = false` +4. **Update generator/package.json**: Add pnpm config, postinstall script, bicep-types-repo reference +5. **Create generator/.npmrc**: Add `side-effects-cache = false` +6. **Generate pnpm lockfiles**: Run `pnpm install` in both directories +7. **Delete npm lockfiles**: Remove `package-lock.json` from both directories +8. **Update Makefile**: Add `generate-pnpm-installed` target, update `generate-bicep-types` to use pnpm +9. **Update CI workflows**: Remove `submodules: recursive/true` from checkout steps +10. **Remove submodule**: `git submodule deinit -f bicep-types`, `git rm bicep-types`, `rm .gitmodules` +11. **Update Dependabot**: Remove `gitsubmodule`, add autorest.bicep and generator directories +12. **Update dev container**: Add `pnpmVersion` to node feature in devcontainer.json +13. **Update documentation**: CONTRIBUTING.md, create migration guide +14. **Verify**: Full CI pipeline passes, `make generate-bicep-types` succeeds + +### Submodule Removal Commands + +```bash +# 1. Deinitialize the submodule +git submodule deinit -f bicep-types + +# 2. Remove from .git/modules +rm -rf .git/modules/bicep-types + +# 3. Remove the submodule entry and directory +git rm -f bicep-types + +# 4. Remove .gitmodules file (only submodule) +git rm .gitmodules +``` + +### Rollback Strategy + +Standard git revert of the PR. Since this is atomic, reverting: + +- Restores `.gitmodules` and submodule reference +- Restores npm lockfiles and commands +- Restores workflow submodule settings + +Contributors would need to re-initialize submodule after revert: + +```bash +git submodule add https://github.com/Azure/bicep-types.git bicep-types +``` + +### Why pnpm Subdirectory References Don't Work (Prototype Learning) + +The original plan proposed using pnpm's subdirectory reference syntax: + +```json +// ❌ This does NOT work for TypeScript packages +"bicep-types": "github:Azure/bicep-types#&path:/src/bicep-types" +``` + +**Why it fails:** + +1. **TypeScript Compilation Required**: The `bicep-types` package is TypeScript source code. The compiled `lib/` directory is `.gitignore`d in the upstream repository. + +2. **pnpm Doesn't Build**: When pnpm installs a git package with `#path:/`, it extracts the subdirectory but does NOT run `npm install` or `npm run build`. The TypeScript remains uncompiled. + +3. **No `lib/` Directory**: Without compilation, `import from "bicep-types"` fails because the package's `main` field points to `lib/index.js` which doesn't exist. + +**The Solution (Validated in Prototype):** + +1. Reference the **full repository** in package.json as `bicep-types-repo` (pnpm fetches it automatically) +2. Use a `postinstall` script to: + - `cd` into the package directory + - Run `npm install && npm run build` + - Create a symlink for `bicep-types` → the built package +3. Add `.npmrc` with `side-effects-cache = false` to ensure postinstall runs + +## Research Required (Phase 0) + +> **Status**: ✅ Complete and Validated via Prototype - See [research-2-pnpm.md](./research-2-pnpm.md) for findings + +1. **pnpm Git Reference Syntax**: ✅ Use `git+https://github.com/Azure/bicep-types.git#` (NOT `github:...#path:/`) +2. **TypeScript Build Strategy**: ✅ `postinstall` script runs `npm install && npm run build` inside `node_modules/bicep-types-repo/src/bicep-types` +3. **Symlink Strategy**: ✅ Create symlink `node_modules/bicep-types` → `bicep-types-repo/src/bicep-types` +4. **pnpm Configuration**: ✅ `.npmrc` with `side-effects-cache = false`; `pnpm.onlyBuiltDependencies: ["autorest"]` in package.json +5. **pnpm + Dependabot**: ✅ Use `package-ecosystem: npm`; git deps require manual updates +6. **Workflow Caching**: ✅ Use `pnpm/action-setup@v4` with `actions/setup-node@v4` cache +7. **Dev Container pnpm**: ✅ Use `pnpmVersion` option in node devcontainer feature (built-in support, no extra scripts) + +## Design Artifacts (Phase 1) + +### data-model.md + +Not applicable - this is a build/tooling change with no data model changes. + +### contracts/ + +Not applicable - no API changes. + +### quickstart.md + +Developer quickstart after migration (combined for both plans): + +```bash +# Clone repository - no submodules needed! +git clone https://github.com/radius-project/radius +cd radius + +# Install pnpm +npm install -g pnpm@10 + +# Install TypeScript dependencies (postinstall scripts build bicep-types) +pnpm --prefix hack/bicep-types-radius/src/autorest.bicep install +pnpm --prefix hack/bicep-types-radius/src/generator install + +# Optional: Install typespec dependencies (if needed) +npm --prefix typespec install + +# Verify Go dependencies +go mod download + +# Build everything +make build + +# Run tests +make test + +# Generate Bicep types (if needed) +make generate-bicep-types +``` + +### Migration Guide for Existing Contributors + +```bash +# If you have an existing clone with the submodule +cd radius + +# Remove the submodule artifacts +rm -rf bicep-types +rm -rf .git/modules/bicep-types + +# Remove stale npm artifacts +rm -rf hack/bicep-types-radius/src/*/node_modules + +# Fetch latest changes +git fetch origin +git checkout main +git pull + +# Install pnpm +npm install -g pnpm + +# Install dependencies (postinstall scripts build bicep-types) +cd hack/bicep-types-radius/src/autorest.bicep && pnpm install && cd ../../../.. +cd hack/bicep-types-radius/src/generator && pnpm install && cd ../../../.. + +# Verify build works +make generate-bicep-types +``` + +### Version Update Guide + +To update to a new version of bicep-types: + +```bash +# 1. Get the new commit SHA from Azure/bicep-types +git ls-remote https://github.com/Azure/bicep-types HEAD + +# 2. Update both package.json files with the new SHA +# Edit: hack/bicep-types-radius/src/autorest.bicep/package.json +# Edit: hack/bicep-types-radius/src/generator/package.json +# Change: "bicep-types-repo": "git+https://github.com/Azure/bicep-types.git#" + +# 3. Update lockfiles +cd hack/bicep-types-radius/src/autorest.bicep && pnpm install && cd ../../../.. +cd hack/bicep-types-radius/src/generator && pnpm install && cd ../../../.. + +# 4. Test +make generate-bicep-types +``` + +## Dependencies + +- **Upstream**: Plan 1 (Go modules) must be merged first +- **Upstream**: Azure/bicep-types repository must be accessible (public GitHub repo) +- **Prototype**: Validated on branch `brooke-hamilton/radius:pnpm-direct-ref` + +## Success Criteria + +| Criterion | Validation | +| --------- | ---------- | +| SC-001 | New contributors complete setup in <10 minutes | +| SC-002 | Zero submodule-related build failures | +| SC-003 | 100% of workflows have no git submodule commands | +| SC-004 | Dependabot creates PRs for npm registry packages in pnpm directories | +| SC-005 | All regression tests pass | +| SC-006 | Git worktrees work without conflicts | +| SC-007 | Documentation has no submodule references | +| SC-008 | `make generate-bicep-types` succeeds with pnpm | + +## Risks and Mitigations + +| Risk | Impact | Mitigation | +| ---- | ------ | ---------- | +| ~~pnpm git subdirectory references not stable~~ | N/A | ✅ Resolved: Using git+https:// reference + postinstall build instead | +| TypeScript build failure in postinstall | MEDIUM | Validated in prototype; postinstall is straightforward | +| Contributor confusion during transition | MEDIUM | Clear migration guide, announcement in release notes | +| CI cache invalidation causing slow builds | LOW | Configure pnpm caching properly in workflows | +| Dependabot not supporting pnpm git refs | LOW | Document manual update process; git deps require manual SHA updates | +| Duplicate repo fetches in node_modules | LOW | Both packages fetch same repo independently; acceptable tradeoff for simplicity | +| postinstall script portability | LOW | Script uses POSIX commands; works on Linux/macOS; Windows may need WSL or Git Bash | + +## Known Limitations + +| Limitation | Description | Workaround | +| ---------- | ----------- | ---------- | +| No Dependabot for git deps | `bicep-types-repo` commit SHA must be updated manually | Consider scheduled GitHub Action to check for updates | +| Requires pnpm | New dependency for contributors | Document installation in CONTRIBUTING.md | +| Duplicate fetches | Both packages fetch the same repo | Acceptable tradeoff; pnpm's content-addressable store mitigates | +| Postinstall complexity | Build logic in package.json scripts | Well-documented and validated in prototype | + +## Workflow Files Requiring Updates + +| File | Current Setting | Target Setting | +| ---- | --------------- | -------------- | +| `.github/workflows/build.yaml` | `submodules: recursive` (4 occurrences, lines 110, 212, 369, 436) | Remove property | +| `.github/workflows/codeql.yml` | `submodules: recursive` (line 95) | Remove property | +| `.github/workflows/lint.yaml` | `submodules: recursive` (line 58) | Remove property | +| `.github/workflows/validate-bicep.yaml` | `submodules: true` (line 64) | Remove property | +| `.github/workflows/publish-docs.yaml` | `submodules: recursive` (line 52) | Remove property | +| `.github/workflows/long-running-azure.yaml` | `submodules: recursive` (line 136) | Remove property | +| `.github/workflows/functional-test-noncloud.yaml` | `submodules: recursive` (line 208) | Remove property | +| `.github/workflows/functional-test-cloud.yaml` | `submodules: recursive` (4 occurrences, lines 172, 328, 336, 626) | Remove property | + +**Total**: 15 occurrences across 8 workflow files + +## Complexity Tracking + +> No complexity violations identified. This plan simplifies the build system. + +## Files Changed (from Prototype) + +| File | Change | +| ---- | ------ | +| `.gitmodules` | DELETE | +| `bicep-types/` | DELETE (submodule removed) | +| `build/generate.mk` | Uses pnpm, added pnpm-installed check | +| `.github/dependabot.yml` | Removed gitsubmodule, added npm entries | +| `hack/.../autorest.bicep/package.json` | git+https ref, postinstall, pnpm config | +| `hack/.../autorest.bicep/.npmrc` | NEW: side-effects-cache = false | +| `hack/.../autorest.bicep/package-lock.json` | DELETE | +| `hack/.../autorest.bicep/pnpm-lock.yaml` | NEW | +| `hack/.../generator/package.json` | git+https ref, postinstall, pnpm config | +| `hack/.../generator/.npmrc` | NEW: side-effects-cache = false | +| `hack/.../generator/package-lock.json` | DELETE | +| `hack/.../generator/pnpm-lock.yaml` | NEW | +| `.devcontainer/devcontainer.json` | Add pnpmVersion to node feature (not in prototype) | +| `CONTRIBUTING.md` | Update setup instructions (not in prototype) | +| `docs/contributing/migration-guide.md` | NEW (not in prototype) | + +--- + +## Phase Summary + +| Phase | Output | Status | +| ----- | ------ | ------ | +| Phase 0 | [research-2-pnpm.md](./research-2-pnpm.md) | ✅ COMPLETE (Validated via prototype) | +| Phase 1 | quickstart.md (above), migration-guide.md (above) | ✅ INCLUDED | +| Phase 2 | tasks-2-pnpm-submodule.md | NOT STARTED (via /speckit.tasks) | + +## Prototype Reference + +The approach in this plan has been validated via prototype: + +- **Branch**: [brooke-hamilton/radius:pnpm-direct-ref](https://github.com/brooke-hamilton/radius/tree/pnpm-direct-ref) +- **Diff**: [radius-project/radius/compare/main...brooke-hamilton:radius:pnpm-direct-ref](https://github.com/radius-project/radius/compare/main...brooke-hamilton:radius:pnpm-direct-ref) +- **Commit**: `5f73e0361fd83bbd56504731c0072a8175906ee9` +- **bicep-types pinned to**: `556bf5edad58e47ca57c6ddb1af155c3bcfdc5c7` diff --git a/specs/001-remove-bicep-types-submodule/research-1-go-modules.md b/specs/001-remove-bicep-types-submodule/research-1-go-modules.md new file mode 100644 index 00000000..1f518f7e --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/research-1-go-modules.md @@ -0,0 +1,180 @@ +# Research: Go Modules Migration + +**Plan**: [plan-1-go-modules.md](./plan-1-go-modules.md) +**Date**: 2026-01-22 +**Status**: Complete + +## Research Questions + +From Plan 1, the following items required research: + +1. Commit SHA Selection - Identify the current bicep-types commit the submodule points to +2. Go Module Availability - Verify bicep-types-go can be fetched as a Go module +3. API Compatibility - Confirm no breaking changes between versions +4. Dependabot Behavior - Research Dependabot support for subdirectory Go modules + +--- + +## Findings + +### 1. Current Submodule Commit SHA + +| Aspect | Details | +| ------ | ------- | +| **Decision** | The bicep-types submodule points to commit `c1a289be58bea8e23cecbce871a11a3fad8c3467` | +| **Evidence** | `git submodule status` returns: `+c1a289be58bea8e23cecbce871a11a3fad8c3467 bicep-types (heads/main-8-gc1a289b)` | +| **Rationale** | This commit is the baseline. The Go module version should match this commit or newer. | +| **Alternatives Considered** | Using `main` branch HEAD - rejected for reproducibility concerns | + +### 2. Go Module Structure in Azure/bicep-types + +| Aspect | Details | +| ------ | ------- | +| **Decision** | ✅ A valid Go module exists at `github.com/Azure/bicep-types/src/bicep-types-go` | +| **Evidence** | The `src/bicep-types-go/go.mod` file contains: | + +```go +module github.com/Azure/bicep-types/src/bicep-types-go + +go 1.21 + +require github.com/stretchr/testify v1.11.1 +``` + +| **Rationale** | The module already uses the canonical import path that Radius uses. No code changes needed. | +| **Alternatives Considered** | Forking bicep-types to Radius org - rejected as unnecessary complexity | + +**Module Packages Available:** + +- `types/` - Core Bicep type definitions +- `factory/` - Type factory for creating Bicep types +- `index/` - Type indexing utilities +- `writers/` - JSON and Markdown output writers +- `cmd/bicep-types/` - CLI tool + +### 3. Go Subdirectory Module Support + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Go natively supports modules in subdirectories of monorepos | +| **Evidence** | [Go Modules Reference](https://go.dev/ref/mod): "If the module is not defined in the repository's root directory, the module subdirectory is the part of the module path that names the directory." | +| **Rationale** | The pattern `github.com/Azure/bicep-types/src/bicep-types-go` is standard Go practice (similar to `golang.org/x/tools/gopls`) | +| **Alternatives Considered** | None - this is the standard approach | + +**Version Tagging Convention:** + +For subdirectory modules, semantic version tags must be prefixed with the module subdirectory path: + +- Tag format: `src/bicep-types-go/v1.0.0` +- If no tags exist, Go uses pseudo-versions: `v0.0.0-20260115000000-c1a289be58be` + +**Current Tag Status:** + +⚠️ Azure/bicep-types does NOT publish semantic version tags with the subdirectory prefix. This means: + +- We must use commit-based pseudo-versions +- Format: `v0.0.0-YYYYMMDDHHMMSS-<12-char-commit-hash>` +- Example: `v0.0.0-20260115000000-c1a289be58be` + +### 4. Dependabot Support for Subdirectory Go Modules + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Dependabot fully supports Go modules in subdirectories | +| **Evidence** | [Dependabot documentation](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file) confirms `gomod` ecosystem with `directory` option | +| **Rationale** | No special configuration needed - Dependabot will detect updates to the bicep-types-go dependency | +| **Alternatives Considered** | Manual dependency updates - rejected for maintainability | + +**Configuration Example:** + +```yaml +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" # Root go.mod that imports bicep-types-go + schedule: + interval: "weekly" + groups: + go-dependencies: + patterns: + - "*" +``` + +**Note:** Since bicep-types uses pseudo-versions (no semantic tags), Dependabot will detect new commits but the version numbers will be commit-based. + +--- + +## Implementation Decisions + +### go.mod Changes + +**Current State:** + +```go +// replace github.com/radius-project/radius/bicep-types/src/bicep-types-go => ./bicep-types/src/bicep-types-go +replace github.com/Azure/bicep-types/src/bicep-types-go => ./bicep-types/src/bicep-types-go +``` + +**Target State:** + +```go +require ( + github.com/Azure/bicep-types/src/bicep-types-go v0.0.0-20260115000000-c1a289be58be +) +``` + +Remove the `replace` directive and add a direct `require` with the pseudo-version matching the current submodule commit. + +### Migration Commands + +```bash +# 1. Get the exact version Go will assign to the commit +go list -m github.com/Azure/bicep-types/src/bicep-types-go@c1a289be58be + +# 2. Update go.mod (remove replace, add require) +go get github.com/Azure/bicep-types/src/bicep-types-go@c1a289be58be + +# 3. Verify and clean up +go mod tidy + +# 4. Test +go build ./... +make test +``` + +### Dependabot Configuration + +The existing Dependabot configuration already includes: + +```yaml +- package-ecosystem: gomod + directory: / + schedule: + interval: weekly +``` + +This will automatically pick up the new dependency. No changes required. + +--- + +## Risks and Mitigations + +| Risk | Likelihood | Impact | Mitigation | +| ---- | ---------- | ------ | ---------- | +| Pseudo-version format changes | Low | Low | Go's pseudo-version format is stable and well-documented | +| Upstream breaking changes | Medium | Medium | Pin to specific commit; review Dependabot PRs carefully | +| Build failures due to missing dependencies | Low | High | Test thoroughly before merge; easy rollback available | + +--- + +## Summary + +| Research Question | Answer | Confidence | +| ----------------- | ------ | ---------- | +| Current submodule commit | `c1a289be58bea8e23cecbce871a11a3fad8c3467` | ✅ High | +| Go module available | Yes, at `github.com/Azure/bicep-types/src/bicep-types-go` | ✅ High | +| API compatible | Yes, same module path used by Radius imports | ✅ High | +| Dependabot support | Yes, works with `gomod` ecosystem | ✅ High | +| Version format | Pseudo-version (no semantic tags upstream) | ✅ High | + +**All research questions resolved. Plan 1 is ready for task breakdown.** diff --git a/specs/001-remove-bicep-types-submodule/research-2-pnpm.md b/specs/001-remove-bicep-types-submodule/research-2-pnpm.md new file mode 100644 index 00000000..8651ba40 --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/research-2-pnpm.md @@ -0,0 +1,609 @@ +# Research: pnpm Migration and Submodule Removal + +**Plan**: [plan-2-pnpm-submodule.md](./plan-2-pnpm-submodule.md) +**Date**: 2026-01-22 (Updated: 2026-01-31) +**Status**: Complete (Validated via prototype) + +## Research Questions + +From Plan 2, the following items required research: + +1. pnpm Git Reference Syntax - Exact syntax for subdirectory git references +2. pnpm + Dependabot - Integration and configuration +3. npm to pnpm Migration - Best practices and commands +4. pnpm in GitHub Actions - Installation and caching strategies +5. Dev Container pnpm - Installation method for dev containers +6. bicep-types npm Package - Verify package structure and build requirements +7. **NEW** TypeScript Build Strategy - How to build bicep-types in node_modules + +--- + +## Findings + +### 1. pnpm Git References for TypeScript Packages + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Reference full repo via `git+https://` URL in package.json; pnpm fetches it automatically during install; build via postinstall script; create symlink | +| **Evidence** | Prototype validation on branch `brooke-hamilton:radius:pnpm-direct-ref` | +| **Rationale** | pnpm's `#path:/` subdirectory syntax does NOT work for TypeScript packages that require compilation; the package must be built in place after pnpm fetches it | +| **Alternatives Considered** | `github:...#path:/src/bicep-types` - does not work because TypeScript needs compilation; npm tarball from GitHub releases - not available | + +**❌ Syntax That Does NOT Work:** + +```json +// These do NOT work for TypeScript packages requiring build +"bicep-types": "github:Azure/bicep-types#path:/src/bicep-types" +"bicep-types": "github:Azure/bicep-types#c1a289be58be&path:/src/bicep-types" +``` + +**Why pnpm subdirectory references don't work:** + +- The `bicep-types` package is TypeScript source that must be compiled +- pnpm installs the source files but does NOT run `npm install` or `npm run build` +- The package's `lib/` directory (compiled output) does not exist after install + +**✅ Recommended Approach (Validated in Prototype):** + +Reference the full repo in package.json. pnpm fetches it to `node_modules/bicep-types-repo/` during install. A postinstall script then builds the TypeScript and creates a symlink: + +```json +{ + "pnpm": { + "onlyBuiltDependencies": ["autorest"] + }, + "scripts": { + "postinstall": "cd node_modules/bicep-types-repo/src/bicep-types && npm install && npm run build && cd ../../../.. && rm -rf node_modules/bicep-types && ln -sf bicep-types-repo/src/bicep-types node_modules/bicep-types" + }, + "devDependencies": { + "bicep-types-repo": "git+https://github.com/Azure/bicep-types.git#556bf5edad58e47ca57c6ddb1af155c3bcfdc5c7" + } +} +``` + +**Key elements:** + +| Element | Purpose | +| ------- | ------- | +| `bicep-types-repo` package name | pnpm installs the full repo to `node_modules/bicep-types-repo/`; name differs from symlink target | +| `git+https://` URL format | Required by pnpm (not `github:` shorthand which defaults to SSH) | +| Commit SHA after `#` | Pins to specific version | +| `postinstall` script | Builds TypeScript and creates symlink after pnpm fetches the repo | +| `pnpm.onlyBuiltDependencies` | Allows autorest lifecycle scripts (matches npm behavior) | + +**Postinstall script breakdown:** + +```bash +# 1. Navigate to the bicep-types package within the fetched repo +cd node_modules/bicep-types-repo/src/bicep-types + +# 2. Install its dependencies and compile TypeScript +npm install && npm run build + +# 3. Return to package root +cd ../../../.. + +# 4. Remove any existing bicep-types directory/symlink +rm -rf node_modules/bicep-types + +# 5. Create symlink so "import from 'bicep-types'" resolves correctly +ln -sf bicep-types-repo/src/bicep-types node_modules/bicep-types +``` + +**Note:** An `.npmrc` file with `side-effects-cache = false` is required to ensure postinstall scripts run correctly. + +--- + +### 2. pnpm + Dependabot Integration + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Use `package-ecosystem: "npm"` for pnpm projects; git dependencies require manual updates | +| **Evidence** | [GitHub Dependabot docs](https://docs.github.com/code-security/dependabot) - pnpm v7-v10 lockfiles supported under npm ecosystem; prototype validation | +| **Rationale** | Dependabot treats pnpm as npm-compatible; git-based deps (`git+https://...#commit`) have NO auto-update support | +| **Alternatives Considered** | Renovate bot - more pnpm-native but adds complexity; manual updates only - reduces automation | + +**Configuration (from prototype):** + +```yaml +# .github/dependabot.yml +version: 2 +updates: + # For autorest.bicep directory (NEW) + - package-ecosystem: npm + directory: /hack/bicep-types-radius/src/autorest.bicep + schedule: + interval: weekly + groups: + autorest-bicep: + patterns: + - "*" + + # For generator directory (NEW) + - package-ecosystem: npm + directory: /hack/bicep-types-radius/src/generator + schedule: + interval: weekly + groups: + bicep-generator: + patterns: + - "*" + + # For typespec directory (KEEP existing) + - package-ecosystem: npm + directory: /typespec + schedule: + interval: weekly + groups: + typespec: + patterns: + - "*" +``` + +**Limitations:** + +| Feature | Support | +| ------- | ------- | +| pnpm lockfile updates | ✅ Supported (v7-v10) | +| Registry package updates | ✅ Full support | +| `git+https://...#commit` dependency updates | ❌ NOT supported | +| Security alerts | ✅ Supported | + +**Workaround for Git Dependencies:** + +The `bicep-types-repo` commit SHA must be updated manually. Consider a scheduled GitHub Action: + +```yaml +name: Check bicep-types updates +on: + schedule: + - cron: '0 0 * * 0' # Weekly +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + CURRENT=$(git ls-remote https://github.com/Azure/bicep-types HEAD | cut -f1) + echo "Latest bicep-types commit: $CURRENT" + # Compare with pinned version and create issue if different +``` + +--- + +### 3. npm to pnpm Migration + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Fresh `pnpm install` after updating package.json (no import needed due to dependency changes) | +| **Evidence** | Prototype validation - dependencies change significantly with git reference | +| **Rationale** | The bicep-types reference changes from `file:` to `git+https://`; clean install is appropriate | +| **Alternatives Considered** | `pnpm import` - not suitable when dependencies fundamentally change | + +**Migration Steps (from prototype):** + +```bash +# Per-directory migration for bicep-types-radius packages +cd hack/bicep-types-radius/src/autorest.bicep/ + +# 1. Update package.json with: +# - pnpm.onlyBuiltDependencies: ["autorest"] +# - postinstall script +# - bicep-types-repo git reference (replacing bicep-types file: reference) + +# 2. Create .npmrc with side-effects-cache = false + +# 3. Delete old lockfile and node_modules +rm -rf package-lock.json node_modules + +# 4. Install with pnpm (generates pnpm-lock.yaml) +pnpm install + +# 5. Verify build works +pnpm run build + +# Repeat for: +# - hack/bicep-types-radius/src/generator/ +``` + +**For typespec/ (no bicep-types dependency):** + +```bash +cd typespec/ + +# 1. Import existing lockfile (converts package-lock.json → pnpm-lock.yaml) +pnpm import + +# 2. Install dependencies with pnpm (validates the import) +pnpm install + +# 3. Verify +pnpm test + +# 4. Remove old lockfile +rm package-lock.json +``` + +**Supported Import Sources:** + +- `package-lock.json` (npm v5+) ✅ +- `npm-shrinkwrap.json` ✅ +- `yarn.lock` ✅ + +**Key Differences from npm:** + +| Aspect | npm | pnpm | +| ------ | --- | ---- | +| node_modules structure | Flat | Symlinked from store | +| Disk usage | Duplicated | Content-addressable (shared) | +| Install speed | Slower | Faster | +| Phantom dependencies | Allowed | Blocked by default | +| Lock file | package-lock.json | pnpm-lock.yaml | +| Git repo packages | `package.json` at root required | Full repo fetched to node_modules/, postinstall handles build | + +--- + +### 4. pnpm in GitHub Actions + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Use `pnpm/action-setup@v4` with `actions/setup-node@v4` caching | +| **Evidence** | [github.com/pnpm/action-setup](https://github.com/pnpm/action-setup) | +| **Rationale** | Official pnpm action with built-in store caching | +| **Alternatives Considered** | Manual npm install of pnpm - slower and no caching benefits | + +**Recommended Configuration:** + +```yaml +- name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 # or specific: 10.8.1 + +- name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: 'pnpm' # Built-in pnpm cache support + +- name: Install dependencies + run: pnpm install --frozen-lockfile +``` + +**Action Features:** + +| Option | Description | Recommended | +| ------ | ----------- | ----------- | +| `version` | pnpm version (10, 10.x, 10.8.1) | `10` | +| `run_install` | Auto-run install | `false` (explicit is better) | +| Built-in cache | Automatic store caching | Uses setup-node cache | + +**Full Workflow Example:** + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: 'pnpm' + cache-dependency-path: | + typespec/pnpm-lock.yaml + hack/bicep-types-radius/src/*/pnpm-lock.yaml + + - name: Install TypeSpec dependencies + run: pnpm --prefix typespec install --frozen-lockfile + + - name: Install generator dependencies + run: pnpm --prefix hack/bicep-types-radius/src/generator install --frozen-lockfile +``` + +--- + +### 5. Dev Container pnpm Installation + +| Aspect | Details | +| ------ | ------- | +| **Decision** | Use official Node.js feature with Corepack activation | +| **Evidence** | [containers.dev/features](https://containers.dev/features) - Node feature includes pnpm via Corepack | +| **Rationale** | Corepack is the Node.js-native package manager manager | +| **Alternatives Considered** | Separate pnpm feature from devcontainers-extra - adds unnecessary dependency | + +**Recommended Configuration:** + +```json +// .devcontainer/devcontainer.json +{ + "features": { + "ghcr.io/devcontainers/features/node:1": { + "version": "20" + } + }, + "postCreateCommand": "corepack enable && corepack prepare pnpm@latest-10 --activate" +} +``` + +**Alternative (dedicated pnpm feature):** + +```json +{ + "features": { + "ghcr.io/devcontainers-extra/features/pnpm:2": { + "version": "10" + } + } +} +``` + +**Current Dev Container Status:** + +The Radius dev container already includes Node.js. The update needed: + +1. Add `corepack enable` to postCreateCommand +2. Add `corepack prepare pnpm@latest-10 --activate` + +--- + +### 6. bicep-types npm Package Structure and Build Requirements + +| Aspect | Details | +| ------ | ------- | +| **Decision** | The `src/bicep-types/` directory is a TypeScript package that REQUIRES local compilation | +| **Evidence** | Prototype validation - `npm install && npm run build` required in postinstall | +| **Rationale** | Package is TypeScript source; compiled `lib/` directory is not committed to git | +| **Alternatives Considered** | Wait for official npm publish - uncertain timeline; use as-is - doesn't work without build | + +**Critical Finding:** The bicep-types package **cannot** be used directly from git without building. The compiled output (`lib/` directory) is `.gitignore`d. + +**Package Structure:** + +```text +src/bicep-types/ +├── package.json # Package configuration +├── tsconfig.json # TypeScript compilation config +├── jest.config.ts # Test configuration +├── .eslintrc.js # Linting rules +├── README.md # Package documentation +├── src/ # TypeScript SOURCE (in git) +│ ├── index.ts # Main exports +│ ├── types.ts # Core type definitions +│ ├── indexer.ts # Type indexing +│ ├── utils.ts # Utilities +│ └── writers/ +│ ├── json.ts # JSON serialization +│ └── markdown.ts # Markdown generation +├── lib/ # ⚠️ COMPILED OUTPUT (NOT in git, must be built) +│ ├── index.js +│ ├── index.d.ts +│ └── ... +└── test/ + └── integration/ # Integration tests +``` + +**Build Process Required:** + +```bash +# Inside src/bicep-types/ directory: +npm install # Install devDependencies (typescript, etc.) +npm run build # Compiles src/ → lib/ +``` + +**Main Exports (after build):** + +```typescript +// From lib/index.js (compiled from src/index.ts) +export * from "./writers/json"; // writeTypesJson, readTypesJson, writeIndexJson +export * from "./writers/markdown"; // writeMarkdown, writeIndexMarkdown +export * from "./indexer"; // buildIndex +export * from "./types"; // TypeFactory, TypeIndex, BicepType, etc. +``` + +**Key Types Used by Radius:** + +| Type | Purpose | +| ---- | ------- | +| `TypeFactory` | Creates and manages Bicep types | +| `TypeIndex` | Index structure for resources and functions | +| `BicepType` | Union of all Bicep type variants | +| `ResourceType` | Resource type definition | +| `ObjectType` | Object type definition | +| `FunctionType` | Function type definition | + +**Compatibility:** Standard TypeScript/npm package, compatible with pnpm after postinstall build. + +--- + +## Implementation Decisions + +### Package.json Updates + +**Before (file: reference to submodule):** + +```json +{ + "devDependencies": { + "bicep-types": "file:../../../../bicep-types/src/bicep-types" + } +} +``` + +**After (pnpm git reference with postinstall build - from prototype):** + +```json +{ + "pnpm": { + "onlyBuiltDependencies": ["autorest"] + }, + "scripts": { + "build": "tsc -p .", + "test": "jest", + "lint": "eslint src --ext ts", + "lint:fix": "eslint src --ext ts --fix", + "postinstall": "cd node_modules/bicep-types-repo/src/bicep-types && npm install && npm run build && cd ../../../.. && rm -rf node_modules/bicep-types && ln -sf bicep-types-repo/src/bicep-types node_modules/bicep-types" + }, + "devDependencies": { + "bicep-types-repo": "git+https://github.com/Azure/bicep-types.git#556bf5edad58e47ca57c6ddb1af155c3bcfdc5c7" + } +} +``` + +**Key differences from original plan:** + +- Package renamed to `bicep-types-repo` (pnpm fetches full repository to node_modules/) +- Uses `git+https://` URL format (not `github:` shorthand) +- Commit SHA appended with `#` (not combined with `&path:`) +- `postinstall` script handles: install → build → symlink +- `pnpm.onlyBuiltDependencies` allows autorest lifecycle scripts + +### .npmrc Files (NEW) + +Create `.npmrc` in both `autorest.bicep/` and `generator/` directories: + +```properties +# Allow pnpm to install packages that need to run postinstall scripts +side-effects-cache = false +``` + +### Makefile Updates + +**Before:** + +```makefile +generate-bicep-types: + git submodule update --init --recursive; \ + npm --prefix bicep-types/src/bicep-types install; \ + npm --prefix bicep-types/src/bicep-types ci && npm --prefix bicep-types/src/bicep-types run build; \ + npm --prefix hack/bicep-types-radius/src/autorest.bicep ci && ... +``` + +**After (from prototype):** + +```makefile +.PHONY: generate-pnpm-installed +generate-pnpm-installed: + @echo "$(ARROW) Detecting pnpm..." + @which pnpm > /dev/null || { echo "pnpm is a required dependency. Run 'npm install -g pnpm' to install."; exit 1; } + @echo "$(ARROW) OK" + +.PHONY: generate-bicep-types +generate-bicep-types: generate-node-installed generate-pnpm-installed ## Generate Bicep extensibility types + @echo "$(ARROW) Generating Bicep extensibility types from OpenAPI specs..." + @echo "$(ARROW) Installing autorest.bicep dependencies (postinstall builds bicep-types)..." + cd hack/bicep-types-radius/src/autorest.bicep && pnpm install + @echo "$(ARROW) Building autorest.bicep..." + pnpm --prefix hack/bicep-types-radius/src/autorest.bicep run build + @echo "$(ARROW) Installing generator dependencies (postinstall builds bicep-types)..." + cd hack/bicep-types-radius/src/generator && pnpm install + @echo "$(ARROW) Running generator..." + cd hack/bicep-types-radius/src/generator && pnpm run generate \ + --specs-dir ../../../../swagger --release-version ${VERSION} --verbose +``` + +**Key changes:** +- Added `generate-pnpm-installed` prerequisite target +- Uses `pnpm install` instead of `npm ci` +- Removed explicit bicep-types build steps (handled by postinstall) +- Removed `git submodule update --init --recursive` +- Uses `cd ... && pnpm install` pattern for cleaner execution + +### Workflow Updates + +**Before:** + +```yaml +- uses: actions/checkout@v4 + with: + submodules: recursive +``` + +**After:** + +```yaml +- uses: actions/checkout@v4 + # No submodules property + +- uses: pnpm/action-setup@v4 + with: + version: 10 + +- uses: actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: 'pnpm' +``` + +### Dependabot Updates + +**Remove:** + +```yaml +- package-ecosystem: gitsubmodule + directory: / +``` + +**Add (from prototype):** + +```yaml +- package-ecosystem: npm + directory: /hack/bicep-types-radius/src/autorest.bicep + schedule: + interval: weekly + groups: + autorest-bicep: + patterns: + - "*" + +- package-ecosystem: npm + directory: /hack/bicep-types-radius/src/generator + schedule: + interval: weekly + groups: + bicep-generator: + patterns: + - "*" +``` + +--- + +## Risks and Mitigations + +| Risk | Likelihood | Impact | Mitigation | +| ---- | ---------- | ------ | ---------- | +| ~~pnpm git subdirectory refs unstable~~ | N/A | N/A | ✅ Resolved: Using git+https:// reference + postinstall build instead | +| TypeScript build failure in postinstall | Low | High | Validated in prototype; postinstall is straightforward | +| Dependabot can't update git deps | Certain | Low | Document manual process; consider future scheduled workflow | +| Dev container pnpm issues | Low | Medium | Use Corepack which is Node.js-native | +| CI cache invalidation | Low | Low | Configure cache-dependency-path properly | +| Phantom dependency issues | Medium | Medium | pnpm's strictness catches issues early; fix during migration | +| Duplicate repo in node_modules | Certain | Low | Both packages fetch same repo independently; acceptable tradeoff | +| Postinstall script complexity | Low | Medium | Script is well-tested in prototype | + +--- + +## Summary + +| Research Question | Answer | Confidence | +| ----------------- | ------ | ---------- | +| Git subdirectory syntax | ❌ Does NOT work for TypeScript; use `git+https://` reference + postinstall build + symlink | ✅ High (prototype validated) | +| Git reference format | `git+https://github.com/Azure/bicep-types.git#` | ✅ High (prototype validated) | +| TypeScript build strategy | `postinstall` script runs `npm install && npm run build` inside node_modules | ✅ High (prototype validated) | +| Symlink strategy | `ln -sf bicep-types-repo/src/bicep-types node_modules/bicep-types` | ✅ High (prototype validated) | +| Dependabot integration | `npm` ecosystem; git deps require manual updates | ✅ High | +| npm to pnpm migration | Fresh `pnpm install` for bicep-types packages; `pnpm import` for typespec | ✅ High | +| GitHub Actions setup | `pnpm/action-setup@v4` + `cache: 'pnpm'` | ✅ High | +| Dev container pnpm | Corepack activation in postCreateCommand | ✅ High | +| bicep-types package valid | Yes, but **requires local build** | ✅ High (prototype validated) | +| pnpm config required | `.npmrc` with `side-effects-cache = false` | ✅ High (prototype validated) | +| autorest lifecycle scripts | `pnpm.onlyBuiltDependencies: ["autorest"]` | ✅ High (prototype validated) | + +**All research questions resolved. Prototype validated the approach. Plan 2 is ready for task breakdown.** diff --git a/specs/001-remove-bicep-types-submodule/spec.md b/specs/001-remove-bicep-types-submodule/spec.md new file mode 100644 index 00000000..cae558c5 --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/spec.md @@ -0,0 +1,186 @@ +# Feature Specification: Remove bicep-types Submodule & Migrate to pnpm + Go Modules + +**Feature Branch**: `001-remove-bicep-types-submodule` +**Created**: January 22, 2026 +**Status**: Draft +**Source**: [GitHub Issue #10913](https://github.com/radius-project/radius/issues/10913) + +## Overview + +Migrate Radius repository from git submodule for bicep-types to direct dependency references using Go modules and pnpm. This eliminates submodule usage, improves contributor experience, streamlines dependency management, and reduces build/test failures related to submodules. + +## Clarifications + +### Session 2026-01-22 + +- Q: How should bicep-types dependency versions be pinned after migration? → A: Pin to specific git commit SHA in both go.mod and pnpm lockfiles +- Q: What is the rollback strategy if the migration causes unexpected issues? → A: No dedicated rollback needed - migration is atomic and can be reverted via standard git revert +- Q: Should pnpm migration be limited to bicep-types or apply repository-wide? → A: Migrate all JavaScript/TypeScript tooling in the repository to pnpm +- Q: How to handle transition for contributors with existing clones containing the submodule? → A: Provide a one-time migration guide as part of the contributing docs with cleanup commands +- Q: Is Dependabot support for pnpm git references a concern? → A: pnpm is fully supported by Dependabot; only configuration updates are needed (covered by FR-017) + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - New Contributor Onboarding (Priority: P1) + +As a new contributor to the Radius project, I want to clone the repository and start developing without needing to understand or manage git submodules, so that I can focus on code changes rather than wrestling with repository setup. + +**Why this priority**: Contributor friction during initial setup leads to contributor abandonment. Submodules are a known source of confusion and errors for new contributors, impacting project growth. + +**Independent Test**: A new contributor can clone the repository and successfully build the project using standard commands without any submodule-specific instructions. + +**Acceptance Scenarios**: + +1. **Given** a fresh clone of the Radius repository, **When** a contributor runs the standard build commands, **Then** the build completes successfully without submodule initialization steps +2. **Given** a contributor has cloned the repository with `--depth 1` (shallow clone), **When** they run the build, **Then** dependencies are resolved automatically without submodule-related errors +3. **Given** a contributor follows the onboarding documentation, **When** they set up their development environment, **Then** no submodule commands are required + +--- + +### User Story 2 - CI/CD Build Reliability (Priority: P1) + +As a project maintainer, I want CI/CD pipelines to build reliably without submodule synchronization failures, so that builds don't fail due to submodule state issues. + +**Why this priority**: Build failures from submodule desynchronization waste maintainer time, block PRs, and erode confidence in the CI system. This directly impacts development velocity. + +**Independent Test**: CI workflows complete successfully across multiple consecutive runs without submodule-related failures. + +**Acceptance Scenarios**: + +1. **Given** a pull request is submitted, **When** CI workflows execute, **Then** all builds complete without submodule initialization or synchronization steps +2. **Given** the bicep-types upstream repository receives updates, **When** the Radius CI runs, **Then** dependency updates are handled through standard dependency management (Go modules/pnpm) rather than submodule updates +3. **Given** a GitHub Actions workflow runs with shallow clone settings, **When** the build executes, **Then** all dependencies resolve correctly without requiring full git history + +--- + +### User Story 3 - Dependency Update Management (Priority: P2) + +As a project maintainer, I want to update bicep-types dependencies using standard dependency management tools (Dependabot, Go modules, pnpm), so that dependency updates follow the same workflow as all other dependencies. + +**Why this priority**: Consistent dependency management reduces cognitive overhead and enables automated security patching through Dependabot. + +**Independent Test**: Dependabot can successfully create PRs for bicep-types dependency updates using standard Go/pnpm configuration. + +**Acceptance Scenarios**: + +1. **Given** a new version of bicep-types is released, **When** Dependabot scans for updates, **Then** it creates a PR to update the dependency through go.mod or pnpm lockfiles +2. **Given** a maintainer wants to update bicep-types manually, **When** they run standard Go or pnpm update commands, **Then** the dependency updates without git submodule commands +3. **Given** Dependabot is configured, **When** it monitors for security vulnerabilities, **Then** bicep-types vulnerabilities are detected and reported like other dependencies + +--- + +### User Story 4 - Git Worktree Support (Priority: P2) + +As a developer working on multiple features, I want to use git worktrees for parallel development, so that I can work on multiple branches simultaneously without conflicts. + +**Why this priority**: Worktrees are a productivity tool blocked by submodule usage. Enabling worktrees improves developer experience for power users. + +**Independent Test**: A developer can create and use git worktrees without submodule conflicts. + +**Acceptance Scenarios**: + +1. **Given** a developer has the main repository checked out, **When** they create a git worktree for a feature branch, **Then** the worktree functions correctly without submodule conflicts +2. **Given** multiple worktrees exist, **When** the developer builds in each worktree, **Then** builds complete successfully with isolated dependency states + +--- + +### User Story 5 - Documentation Clarity (Priority: P3) + +As a contributor reading the documentation, I want setup instructions that use only standard dependency tools, so that I can understand and follow the onboarding process easily. + +**Why this priority**: Documentation accuracy affects contributor success. Removing submodule instructions simplifies docs and reduces maintenance burden. + +**Independent Test**: Documentation accurately reflects the build process without mentioning submodules. + +**Acceptance Scenarios**: + +1. **Given** a contributor reads the CONTRIBUTING guide, **When** they follow the setup steps, **Then** no submodule commands are mentioned or required +2. **Given** the documentation is updated, **When** a new contributor follows it, **Then** they can successfully build and test without referring to external resources + +--- + +### Edge Cases + +- What happens when a contributor has an old clone with the submodule still present? + - Clear migration instructions should guide cleanup of stale submodule artifacts +- How does the system handle network failures during dependency resolution? + - Standard Go/pnpm retry and caching mechanisms apply +- What happens if bicep-types upstream changes its directory structure? + - Go module and pnpm path references would need updating, detected by CI failures + +## Requirements *(mandatory)* + +### Functional Requirements + +#### Submodule Removal + +- **FR-001**: The bicep-types git submodule MUST be completely removed from the repository +- **FR-002**: All references to submodule paths MUST be removed from .gitmodules configuration +- **FR-003**: The repository MUST not require any `git submodule` commands for building or testing + +#### Go Dependencies + +- **FR-004**: Go code MUST reference bicep-types-go through go.mod as a standard module dependency (github.com/Azure/bicep-types/src/bicep-types-go) +- **FR-005**: Go module dependencies MUST be resolvable using standard `go mod` commands +- **FR-006**: Go module dependencies MUST be pinned to a specific git commit SHA for reproducibility + +#### NPM/pnpm Dependencies + +- **FR-007**: All JavaScript/TypeScript tooling in the repository MUST be migrated to use pnpm as the package manager +- **FR-008**: NPM packages in hack/bicep-types-radius/ MUST use pnpm git references with postinstall build scripts for bicep-types packages +- **FR-009**: Lockfiles MUST be updated to reflect pnpm git references with postinstall build scripts +- **FR-010**: pnpm dependencies MUST be pinned to a specific git commit SHA for reproducibility + +#### Build System + +- **FR-011**: All Makefiles MUST function without submodule-related commands +- **FR-012**: Build scripts MUST use pnpm for JavaScript/TypeScript dependency management +- **FR-013**: Workflow files MUST not contain submodule initialization or update steps + +#### CI/CD + +- **FR-014**: All CI/CD workflows MUST pass without submodule operations +- **FR-015**: Codegen workflows MUST complete successfully with new dependency sources +- **FR-016**: All regression tests MUST pass after migration + +#### Dependency Management + +- **FR-017**: Dependabot configuration MUST be updated to monitor Go and pnpm dependency sources +- **FR-018**: Security scanning MUST cover bicep-types dependencies through standard vulnerability detection + +#### Development Environment + +- **FR-019**: The dev container MUST be updated to include pnpm pre-installed + +#### Documentation + +- **FR-020**: CONTRIBUTING.md and contributor documentation MUST be updated to remove all references to the bicep-types submodule and submodule-related instructions +- **FR-021**: Contributor documentation MUST include a one-time migration guide with cleanup commands for existing clones that contain the submodule +- **FR-022**: Contributor documentation MUST include updated steps for Go and pnpm setup +- **FR-023**: Any README files referencing submodules MUST be updated + +### Key Entities + +- **bicep-types-go**: Go language bindings for Bicep types, currently consumed as a submodule, to be consumed as a Go module +- **bicep-types NPM packages**: JavaScript/TypeScript packages for Bicep types, to be consumed via pnpm git references +- **hack/bicep-types-radius/**: Directory containing Radius-specific Bicep type tooling with npm dependencies to migrate + +## Assumptions + +- The Azure/bicep-types repository structure supports direct Go module and pnpm git subdirectory references +- pnpm git references with subdirectory paths are stable and supported for production use +- No Radius features depend on submodule-specific behaviors (local modifications, specific commit pinning beyond what dependency managers support) +- CI/CD environments have pnpm available or can install it as part of workflow setup +- Migration changes are atomic and can be reverted via standard git revert if critical issues arise + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: New contributors can complete repository setup and first build in under 10 minutes following documentation +- **SC-002**: CI/CD build success rate improves by eliminating submodule-related failures (target: 0 submodule-related build failures after migration is merged) +- **SC-003**: 100% of build/test workflows execute without any git submodule commands +- **SC-004**: Dependabot successfully monitors and creates PRs for npm registry package updates in pnpm directories (Note: bicep-types-repo git dependency requires manual SHA updates as Dependabot does not support git references) +- **SC-005**: All existing regression tests pass without modification to test logic (only dependency resolution changes) +- **SC-006**: Git worktrees can be created and used without conflicts or additional configuration +- **SC-007**: Documentation requires no mentions of git submodule commands for standard development workflows diff --git a/specs/001-remove-bicep-types-submodule/tasks-1-go-modules.md b/specs/001-remove-bicep-types-submodule/tasks-1-go-modules.md new file mode 100644 index 00000000..d4c44b8f --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/tasks-1-go-modules.md @@ -0,0 +1,184 @@ +# Tasks: Plan 1 - Migrate Go Dependencies to Direct Module Reference + +**Input**: Design documents from `/specs/001-remove-bicep-types-submodule/` +**Prerequisites**: plan-1-go-modules.md (required), spec.md (required for user stories) +**Branch**: `001-remove-bicep-types-submodule-go` + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel (different files, no dependencies) +- **[Story]**: Which user story this task belongs to (US1-US5) +- Include exact file paths in descriptions + +## Scope + +This plan addresses: + +- FR-004: Go code references bicep-types-go through go.mod as standard module +- FR-005: Go module dependencies resolvable via `go mod` commands +- FR-006: Go module pinned to specific git commit SHA +- FR-020 (partial): Go-related documentation updated + +--- + +## Phase 1: Setup (Research & Verification) + +**Purpose**: Validate Go module approach before making changes + +- [X] T001 Identify current bicep-types submodule commit SHA via `git submodule status` in radius/ +- [X] T002 Verify bicep-types-go module availability via `go list -m github.com/Azure/bicep-types/src/bicep-types-go@` +- [X] T003 [P] Document all Go files importing bicep-types-go packages via `grep -r "github.com/Azure/bicep-types" --include="*.go" radius/` + +--- + +## Phase 2: Foundational (Create Working Branch) + +**Purpose**: Prepare the codebase for migration + +**⚠️ CRITICAL**: Complete before implementation + +- [X] T004 Create feature branch `001-remove-bicep-types-submodule-go` from main +- [X] T005 Verify submodule is initialized and build works via `make build` in radius/ + +**Checkpoint**: Foundation ready - Go module migration can proceed + +--- + +## Phase 3: User Story 1 - New Contributor Onboarding (Priority: P1) 🎯 MVP + +**Goal**: Go build completes without requiring submodule initialization for new contributors + +**Independent Test**: Clone repository fresh, verify `go mod download && go build ./...` succeeds without submodule + +### Implementation for User Story 1 + +- [X] T006 [US1] Remove replace directive from radius/go.mod (line with `github.com/Azure/bicep-types/src/bicep-types-go => ./bicep-types/src/bicep-types-go`) +- [X] T007 [US1] Add direct require for bicep-types-go module in radius/go.mod with pinned commit SHA +- [X] T008 [US1] Run `go mod tidy` to resolve and update radius/go.sum +- [X] T009 [US1] Verify Go build succeeds via `go build ./...` in radius/ +- [X] T010 [US1] Verify all Go tests pass via `go test ./...` in radius/ + +**Checkpoint**: Go code compiles and tests pass with direct module reference + +--- + +## Phase 4: User Story 2 - CI/CD Build Reliability (Priority: P1) + +**Goal**: CI workflows build Go code without submodule commands + +**Independent Test**: Verify build.yaml and other Go-related workflows don't require submodule for Go compilation + +### Implementation for User Story 2 + +- [X] T011 [US2] Verify `make build` succeeds in radius/ (covers Makefile targets) +- [X] T012 [US2] Verify `make test` passes all Go-related tests in radius/ (Note: converter tests pass; unrelated test failures exist) +- [X] T013 [US2] Verify `make lint` passes (if Go linting is included) + +**Checkpoint**: Makefile targets work with direct module reference + +--- + +## Phase 5: User Story 3 - Dependency Update Management (Priority: P2) + +**Goal**: Dependabot can update bicep-types-go via standard Go module workflow + +**Independent Test**: Verify Dependabot configuration covers Go modules (already enabled) + +### Implementation for User Story 3 + +- [X] T014 [US3] Verify existing Dependabot config in radius/.github/dependabot.yml covers gomod package-ecosystem +- [X] T015 [US3] No changes needed - Dependabot already monitors Go modules in this repository + +**Checkpoint**: Dependabot will automatically detect bicep-types-go updates + +--- + +## Phase 6: User Story 5 - Documentation Clarity (Priority: P3) + +**Goal**: Go-related contributor documentation reflects new dependency approach + +**Independent Test**: Documentation accurately describes Go setup without submodule references + +### Implementation for User Story 5 + +- [X] T016 [P] [US5] Update Go setup section in radius/docs/contributing/contributing-code/contributing-code-building/README.md to clarify Go uses direct module dependency +- [X] T017 [P] [US5] Verify radius/docs/contributing/ Go docs don't mention submodule for Go dependencies + +**Checkpoint**: Documentation accurate for Go module approach + +--- + +## Phase 7: Polish & Validation + +**Purpose**: Final verification before PR + +- [X] T018 Run full `make build` and `make test` in radius/ +- [X] T019 [P] Verify `go mod verify` passes (checksums valid) +- [X] T020 [P] Run `go mod graph | grep bicep-types` to confirm dependency resolution +- [ ] T021 Create PR from `001-remove-bicep-types-submodule-go` to main +- [ ] T022 Verify CI pipeline passes on PR + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Setup (Phase 1)**: No dependencies - can start immediately +- **Foundational (Phase 2)**: Depends on Setup - confirms starting state +- **User Story 1 (Phase 3)**: Depends on Foundational - core migration +- **User Story 2 (Phase 4)**: Depends on User Story 1 - validates Makefile +- **User Story 3 (Phase 5)**: Can run in parallel with Phase 4 +- **User Story 5 (Phase 6)**: Can run in parallel with Phase 4-5 +- **Polish (Phase 7)**: Depends on all user stories complete + +### Parallel Opportunities + +```text +After Phase 3 (US1) completes: + ├── T011-T013 [US2] Makefile validation + ├── T014-T015 [US3] Dependabot verification + └── T016-T017 [US5] Documentation updates (all [P]) +``` + +--- + +## Implementation Strategy + +### MVP (User Story 1 Only) + +1. Complete Phases 1-3 +2. **STOP and VALIDATE**: Go builds without submodule +3. This is sufficient for Go code to work independently + +### Full Plan 1 Completion + +1. Complete all phases +2. Merge PR before starting Plan 2 +3. Plan 2 depends on Plan 1 being merged + +--- + +## Notes + +- This plan modifies Go tooling only - submodule is NOT removed yet +- Submodule removal happens in Plan 2 (pnpm migration) +- If Plan 1 needs rollback, simply revert the PR - submodule still exists +- Plan 2 cannot proceed until Plan 1 is merged +- No test tasks included - existing tests validate the migration + +--- + +## Summary + +| Metric | Value | +| ------- | ----- | +| Total Tasks | 22 | +| Setup/Foundational | 5 | +| US1 (P1) | 5 | +| US2 (P1) | 3 | +| US3 (P2) | 2 | +| US5 (P3) | 2 | +| Polish | 5 | +| Parallel Opportunities | 6 tasks can run in parallel after US1 | +| MVP Scope | Tasks T001-T010 (Phases 1-3) | diff --git a/specs/001-remove-bicep-types-submodule/tasks-2-pnpm-submodule.md b/specs/001-remove-bicep-types-submodule/tasks-2-pnpm-submodule.md new file mode 100644 index 00000000..436d3400 --- /dev/null +++ b/specs/001-remove-bicep-types-submodule/tasks-2-pnpm-submodule.md @@ -0,0 +1,348 @@ +# Tasks: Plan 2 - Migrate to pnpm + Remove bicep-types Submodule + +**Input**: Design documents from `/specs/001-remove-bicep-types-submodule/` +**Prerequisites**: plan-2-pnpm-submodule.md (required), spec.md (required for user stories), research-2-pnpm.md +**Branch**: `001-remove-bicep-types-submodule-pnpm` +**Depends On**: Plan 1 (Go Modules) must be merged first +**Prototype**: [brooke-hamilton/radius:pnpm-direct-ref](https://github.com/brooke-hamilton/radius/tree/pnpm-direct-ref) + +## Format: `- [ ] [TaskID] [P?] [Story?] Description with file path` + +- **Checkbox**: ALWAYS start with `- [ ]` (markdown checkbox) +- **Task ID**: Sequential number (T001, T002...) in execution order +- **[P]**: Include ONLY if task is parallelizable (different files, no dependencies) +- **[Story]**: Which user story this task belongs to (US1-US5) - REQUIRED for user story phases only +- Include exact file paths in descriptions + +## Scope + +This plan addresses: + +- FR-001: bicep-types git submodule completely removed +- FR-002: .gitmodules configuration removed +- FR-003: No `git submodule` commands required for build/test +- FR-007 through FR-023: pnpm migration, CI/CD updates, documentation + +## Critical Technical Constraint + +**⚠️ pnpm subdirectory syntax does NOT work for TypeScript packages requiring compilation.** + +The `bicep-types` package is TypeScript source that must be compiled. The solution validated in the prototype: + +1. Reference full repo via `git+https://github.com/Azure/bicep-types.git#` (NOT `github:...#path:/`) +2. pnpm fetches it to `node_modules/bicep-types-repo/` +3. `postinstall` script runs `npm install && npm run build` inside the package +4. Symlink created: `node_modules/bicep-types` → `bicep-types-repo/src/bicep-types` +5. `.npmrc` with `side-effects-cache = false` ensures postinstall runs + +--- + +## Phase 1: Setup (Environment Preparation) + +**Purpose**: Prepare pnpm tooling and verify prerequisites + +- [X] T001 Verify Plan 1 (Go modules migration) is merged to main +- [X] T002 Verify pnpm is installed locally via `pnpm --version` +- [X] T003 Identify current bicep-types submodule commit SHA for pnpm git references via `git submodule status` in radius/ + +--- + +## Phase 2: Foundational (Create Working Branch) + +**Purpose**: Prepare the codebase for migration + +**⚠️ CRITICAL**: Complete before any user story implementation + +- [X] T004 Create feature branch `001-remove-bicep-types-submodule-pnpm` from main +- [X] T005 Pull latest main to ensure Plan 1 changes are included +- [X] T006 Verify current build works via `make build` in radius/ + +**Checkpoint**: Foundation ready - pnpm migration can proceed + +--- + +## Phase 3: User Story 1 - New Contributor Onboarding (Priority: P1) 🎯 MVP + +**Goal**: New contributors can clone and build without submodule initialization + +**Independent Test**: Clone repository fresh (no --recurse-submodules), run pnpm install and build commands successfully + +### Implementation for User Story 1 + +#### pnpm Migration - typespec/ (no bicep-types dependency) + +- [X] T007 [US1] Delete radius/typespec/package-lock.json +- [X] T008 [US1] Generate pnpm lockfile via `pnpm install` in radius/typespec/ +- [X] T009 [US1] Verify typespec builds via `pnpm run build` in radius/typespec/ + +#### pnpm Migration - hack/bicep-types-radius/src/generator/ + +- [X] T010 [US1] Update radius/hack/bicep-types-radius/src/generator/package.json: + - Add `"pnpm": { "onlyBuiltDependencies": ["autorest"] }` + - Add `postinstall` script for bicep-types build and symlink + - Replace `"bicep-types": "file:..."` with `"bicep-types-repo": "git+https://github.com/Azure/bicep-types.git#"` +- [X] T011 [US1] Create radius/hack/bicep-types-radius/src/generator/.npmrc with `side-effects-cache = false` +- [X] T012 [US1] Delete radius/hack/bicep-types-radius/src/generator/package-lock.json +- [X] T013 [US1] Generate pnpm lockfile via `pnpm install` in radius/hack/bicep-types-radius/src/generator/ +- [X] T014 [US1] Verify generator builds via `pnpm run build` in radius/hack/bicep-types-radius/src/generator/ + +#### pnpm Migration - hack/bicep-types-radius/src/autorest.bicep/ + +- [X] T015 [US1] Update radius/hack/bicep-types-radius/src/autorest.bicep/package.json: + - Add `"pnpm": { "onlyBuiltDependencies": ["autorest"] }` + - Add `postinstall` script for bicep-types build and symlink + - Replace `"bicep-types": "file:..."` with `"bicep-types-repo": "git+https://github.com/Azure/bicep-types.git#"` +- [X] T016 [US1] Create radius/hack/bicep-types-radius/src/autorest.bicep/.npmrc with `side-effects-cache = false` +- [X] T017 [US1] Delete radius/hack/bicep-types-radius/src/autorest.bicep/package-lock.json +- [X] T018 [US1] Generate pnpm lockfile via `pnpm install` in radius/hack/bicep-types-radius/src/autorest.bicep/ +- [X] T019 [US1] Verify autorest.bicep builds via `pnpm run build` in radius/hack/bicep-types-radius/src/autorest.bicep/ + +#### Submodule Removal + +- [X] T020 [US1] Remove submodule from git index via `git rm bicep-types` in radius/ +- [X] T021 [US1] Delete radius/.gitmodules file +- [X] T022 [US1] Clean up .git/modules/bicep-types directory via `rm -rf .git/modules/bicep-types` + +#### Verify Build Works + +- [X] T023 [US1] Verify full build via `make build` in radius/ +- [ ] T024 [US1] Verify tests via `make test` in radius/ + +**Checkpoint**: Repository builds and tests pass without submodule + +--- + +## Phase 4: User Story 2 - CI/CD Build Reliability (Priority: P1) + +**Goal**: All CI workflows pass without submodule initialization steps + +**Independent Test**: CI pipeline completes successfully on PR + +### Implementation for User Story 2 + +#### Makefile Updates + +- [X] T025 [US2] Update radius/build/generate.mk: add `generate-pnpm-installed` target to verify pnpm availability +- [X] T026 [US2] Update radius/build/generate.mk: replace `npm` commands with `pnpm` in generate-bicep-types target +- [X] T027 [US2] Update radius/build/generate.mk: remove `git submodule update --init --recursive` commands +- [X] T028 [US2] Update radius/build/generate.mk line ~33: change error message from `run 'npm ci' in typespec directory.` to `run 'pnpm install' in typespec directory.` +- [X] T029 [US2] Update radius/build/generate.mk line ~55: change error message from `run 'npm install -g autorest@3.7.2' to install autorest` to `run 'pnpm add -g autorest@3.7.2' to install autorest` +- [X] T030 [US2] Update radius/build/test.mk line ~179: change error message from `run 'npm install -g oav@4.0.2' to install oav` to `run 'pnpm add -g oav@4.0.2' to install oav` +- [X] T031 [US2] Verify `make generate-bicep-types` works in radius/ + +#### Workflow Updates - build.yaml (4 occurrences) + +- [X] T032 [US2] Update radius/.github/workflows/build.yaml line ~110: remove `submodules: recursive` from checkout step +- [X] T033 [US2] Update radius/.github/workflows/build.yaml line ~212: remove `submodules: recursive` from checkout step +- [X] T034 [US2] Update radius/.github/workflows/build.yaml line ~369: remove `submodules: recursive` from checkout step +- [X] T035 [US2] Update radius/.github/workflows/build.yaml line ~436: remove `submodules: recursive` from checkout step +- [X] T036 [US2] Add pnpm setup step to radius/.github/workflows/build.yaml (pnpm/action-setup@v4) + +#### Workflow Updates - Other Files + +- [X] T037 [P] [US2] Update radius/.github/workflows/codeql.yml line ~95: remove `submodules: recursive`, add pnpm setup +- [X] T038 [P] [US2] Update radius/.github/workflows/lint.yaml line ~58: remove `submodules: recursive`, add pnpm setup +- [X] T039 [P] [US2] Update radius/.github/workflows/validate-bicep.yaml line ~64: remove `submodules: true`, add pnpm setup +- [X] T040 [P] [US2] Update radius/.github/workflows/publish-docs.yaml line ~52: remove `submodules: recursive`, add pnpm setup +- [X] T041 [P] [US2] Update radius/.github/workflows/long-running-azure.yaml line ~136: remove `submodules: recursive`, add pnpm setup + +#### Workflow Updates - Functional Tests (4 occurrences in cloud.yaml) + +- [X] T042 [US2] Update radius/.github/workflows/functional-test-noncloud.yaml line ~208: remove `submodules: recursive`, add pnpm setup +- [X] T043 [US2] Update radius/.github/workflows/functional-test-cloud.yaml line ~172: remove `submodules: recursive`, add pnpm setup +- [X] T044 [US2] Update radius/.github/workflows/functional-test-cloud.yaml line ~328: remove `submodules: recursive`, add pnpm setup +- [X] T045 [US2] Update radius/.github/workflows/functional-test-cloud.yaml line ~336: remove `submodules: recursive`, add pnpm setup +- [X] T046 [US2] Update radius/.github/workflows/functional-test-cloud.yaml line ~626: remove `submodules: recursive`, add pnpm setup + +#### Workflow Updates - npm to pnpm Consistency + +**⚠️ IMPORTANT**: Tasks T047-T055 MUST be executed AFTER T036-T046. The pnpm setup step must be added to each workflow BEFORE the workflow can use pnpm commands. When editing each workflow file, add the pnpm setup step first, then update npm commands to pnpm in the same edit. + +- [X] T047 [P] [US2] Update radius/.github/workflows/lint.yaml line ~76: change `npm ci` to `pnpm install` +- [X] T048 [P] [US2] Update radius/.github/workflows/lint.yaml line ~78: change `npm install -g autorest@3.7.2` to `pnpm add -g autorest@3.7.2` +- [X] T049 [P] [US2] Update radius/.github/workflows/lint.yaml line ~79: change `npm install -g oav@4.0.2` to `pnpm add -g oav@4.0.2` +- [X] T050 [P] [US2] Update radius/.github/workflows/publish-docs.yaml line ~95: change `npm ci` to `pnpm install` +- [X] T051 [P] [US2] Update radius/.github/workflows/publish-docs.yaml line ~98: change `npm install -g autorest@3.7.2` to `pnpm add -g autorest@3.7.2` +- [X] T052 [P] [US2] Update radius/.github/workflows/publish-docs.yaml line ~99: change `npm install -g oav@4.0.2` to `pnpm add -g oav@4.0.2` +- [ ] T053 [P] [US2] Update radius/.github/workflows/devcontainer-feature-test.yaml line ~36: change `npm install -g @devcontainers/cli` to `pnpm add -g @devcontainers/cli` +- [ ] T054 [P] [US2] Update radius/.github/workflows/devcontainer-feature-test.yaml line ~53: change `npm install -g @devcontainers/cli` to `pnpm add -g @devcontainers/cli` +- [X] T055 [P] [US2] Update radius/.github/workflows/validate-bicep.yaml lines ~78-84: update npx installation fallback from `npm install -g npx` to `pnpm add -g npx` (or remove if npx is bundled with Node.js) + +**Checkpoint**: All 15 submodule references removed from 8 workflow files, npm commands updated to pnpm for consistency + +--- + +## Phase 5: User Story 3 - Dependency Update Management (Priority: P2) + +**Goal**: Dependabot monitors pnpm dependencies correctly + +**Independent Test**: Dependabot configuration is valid and covers all pnpm directories + +**Note**: Git dependencies (`git+https://...#commit`) have NO auto-update support in Dependabot. The bicep-types-repo commit SHA must be updated manually. Consider a scheduled GitHub Action for notifications. + +### Implementation for User Story 3 + +- [X] T056 [US3] Update radius/.github/dependabot.yml: remove `gitsubmodule` package-ecosystem section +- [X] T057 [P] [US3] Update radius/.github/dependabot.yml: add npm config for `/hack/bicep-types-radius/src/generator` +- [X] T058 [P] [US3] Update radius/.github/dependabot.yml: add npm config for `/hack/bicep-types-radius/src/autorest.bicep` +- [X] T059 [US3] Verify Dependabot config syntax via `actionlint` or manual review + +**Checkpoint**: Dependabot configured for all pnpm directories + +--- + +## Phase 6: User Story 4 - Git Worktree Support (Priority: P2) + +**Goal**: Git worktrees work without submodule conflicts + +**Independent Test**: Create worktree, build successfully + +### Implementation for User Story 4 + +- [ ] T060 [US4] Test git worktree creation via `git worktree add ../radius-test feature-branch` +- [ ] T061 [US4] Verify build in worktree via `make build` in worktree directory +- [ ] T062 [US4] Clean up test worktree via `git worktree remove ../radius-test` + +**Checkpoint**: Worktrees work without submodule issues + +--- + +## Phase 7: User Story 5 - Documentation Clarity (Priority: P3) + +**Goal**: All documentation reflects pnpm workflow without submodule references + +**Independent Test**: Documentation accurately describes setup process + +### Implementation for User Story 5 + +#### Dev Container + +- [X] T063 [US5] Get latest pnpm version via `pnpm --version` (or check corepack) and update dev container: + - Update radius/.devcontainer/devcontainer.json: add `"pnpmVersion": ""` to the node feature configuration +- [X] T064 [US5] Update radius/.devcontainer/post-create.sh line ~6: change `npm install -g @typespec/compiler` to `pnpm add -g @typespec/compiler` +- [X] T065 [US5] Update radius/.devcontainer/post-create.sh line ~21: change `npm ci` to `pnpm install` in typespec directory +- [X] T066 [US5] Update radius/.devcontainer/post-create.sh line ~22: change `npm install -g autorest@3.7.2` to `pnpm add -g autorest@3.7.2` +- [X] T067 [US5] Update radius/.devcontainer/post-create.sh line ~23: change `npm install -g oav@4.0.2` to `pnpm add -g oav@4.0.2` + +#### Contributing Documentation + +- [ ] T068 [P] [US5] Update radius/CONTRIBUTING.md: replace npm with pnpm, remove all submodule references, document postinstall behavior +- [X] T069 [P] [US5] Create radius/docs/contributing/migration-guide.md with cleanup commands for existing clones +- [X] T070 [P] [US5] Update radius/docs/contributing/contributing-code/contributing-code-prerequisites/README.md lines ~183-185: change npm commands to pnpm + +#### README Updates + +- [ ] T071 [P] [US5] Review and update radius/README.md if it mentions submodules +- [ ] T072 [P] [US5] Review and update radius/hack/bicep-types-radius/README.md if it exists + +**Checkpoint**: All documentation updated + +--- + +## Phase 8: Polish & Validation + +**Purpose**: Final verification before PR + +- [X] T073 Run full `make build` in radius/ +- [ ] T074 Run full `make test` in radius/ +- [X] T075 [P] Run `make generate-bicep-types` to verify codegen workflow +- [ ] T076 [P] Verify pnpm lockfiles are consistent via `pnpm install --frozen-lockfile` in each directory +- [ ] T077 Fresh clone test: clone to new directory without `--recurse-submodules`, verify build +- [ ] T078 Create PR from `001-remove-bicep-types-submodule-pnpm` to main +- [ ] T079 Verify all CI workflows pass on PR + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Setup (Phase 1)**: Depends on Plan 1 being merged +- **Foundational (Phase 2)**: Depends on Setup completion +- **User Story 1 (Phase 3)**: Depends on Foundational - core migration + submodule removal +- **User Story 2 (Phase 4)**: Depends on User Story 1 - workflows need submodule removed first +- **User Story 3 (Phase 5)**: Can start after User Story 2 (Dependabot config) +- **User Story 4 (Phase 6)**: Can run in parallel with Phase 5 (worktree testing) +- **User Story 5 (Phase 7)**: Can run in parallel with Phases 5-6 +- **Polish (Phase 8)**: Depends on all user stories complete + +### Within User Story 1 (Phase 3) + +```text +pnpm migrations can run in parallel: + ├── T007-T009: typespec/ + ├── T010-T014: generator/ (includes .npmrc creation) + └── T015-T019: autorest.bicep/ (includes .npmrc creation) +Then sequentially: + └── T020-T024: Submodule removal + verification +``` + +### Within User Story 2 (Phase 4) + +```text +T025-T031: Makefile updates (sequential) +T032-T036: build.yaml updates (sequential - same file) +T037-T041: Other workflow files (parallel - different files) +T042-T055: Functional test workflows + npm-to-pnpm consistency (partially parallel) +``` + +### Parallel Opportunities After Phase 4 + +```text +After Phase 4 (US2) completes: + ├── T056-T059 [US3] Dependabot config + ├── T060-T062 [US4] Worktree testing + └── T063-T072 [US5] Documentation updates +``` + +--- + +## Implementation Strategy + +### MVP (User Stories 1-2) + +1. Complete Phases 1-4 +2. **STOP and VALIDATE**: Repository builds, CI passes, no submodule +3. This is sufficient for core functionality + +### Full Plan 2 Completion + +1. Complete all phases +2. Merge PR +3. Feature complete: submodule removed, pnpm migrated + +--- + +## Notes + +- Plan 1 MUST be merged before starting this plan +- **CRITICAL**: pnpm subdirectory syntax does NOT work for TypeScript packages requiring compilation +- Use `git+https://github.com/Azure/bicep-types.git#` format (NOT `github:...#path:/`) +- The `postinstall` script builds TypeScript and creates symlink for module resolution +- `.npmrc` with `side-effects-cache = false` ensures postinstall scripts run correctly +- Package named `bicep-types-repo` in devDependencies; symlink created as `bicep-types` +- Use same commit SHA as was in submodule for initial migration +- 15 total `submodules:` occurrences across 8 workflow files to update +- Dev container requires corepack for pnpm activation +- Existing clones need migration guide for cleanup +- Git dependencies have NO Dependabot auto-update support; manual SHA updates required + +--- + +## Summary + +| Metric | Value | +| ------- | ----- | +| Total Tasks | 79 | +| Setup/Foundational | 6 | +| US1 (P1) | 18 | +| US2 (P1) | 31 | +| US3 (P2) | 4 | +| US4 (P2) | 3 | +| US5 (P3) | 10 | +| Polish | 7 | +| Parallel Opportunities | 20+ tasks can run in parallel (pnpm dirs, workflows, docs) | +| MVP Scope | Tasks T001-T055 (Phases 1-4) | +| Workflow Files Updated | 10 | +| Submodule References Removed | 15 | +| npm→pnpm Consistency Updates | 17 |