diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 120000 index 000000000..be77ac83a --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1 @@ +../AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..bc69ef4a8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,168 @@ +# AGENTS.md + +This file provides guidance to AI coding assistants when working with code in this repository. + +## Project Overview + +The Coder Registry is a community-driven repository for Terraform modules and templates that extend Coder workspaces. It's organized with: + +- **Modules**: Individual components and tools (IDEs, auth integrations, dev tools) +- **Templates**: Complete workspace configurations for different platforms +- **Namespaces**: Each contributor has their own namespace under `/registry/[namespace]/` + +## Common Development Commands + +### Formatting + +```bash +bun run fmt # Format all code (Prettier + Terraform) +bun run fmt:ci # Check formatting (CI mode) +``` + +### Testing + +```bash +# Test all modules with .tftest.hcl files +bun run test + +# Test specific module (from module directory) +terraform init -upgrade +terraform test -verbose + +# Validate Terraform syntax +./scripts/terraform_validate.sh +``` + +### Module Creation + +```bash +# Generate new module scaffold +./scripts/new_module.sh namespace/module-name +``` + +### TypeScript Testing & Setup + +The repository uses Bun for TypeScript testing with utilities: + +- `test/test.ts` - Testing utilities for container management and Terraform operations +- `setup.ts` - Test cleanup (removes .tfstate files and test containers) +- Container-based testing with Docker for module validation + +## Architecture & Organization + +### Directory Structure + +``` +registry/[namespace]/ +├── README.md # Contributor info with frontmatter +├── .images/ # Namespace avatar (avatar.png/svg) +├── modules/ # Individual components +│ └── [module]/ # Each module has main.tf, README.md, tests +└── templates/ # Complete workspace configs + └── [template]/ # Each template has main.tf, README.md +``` + +### Key Components + +**Module Structure**: Each module contains: + +- `main.tf` - Terraform implementation +- `README.md` - Documentation with YAML frontmatter +- `.tftest.hcl` - Terraform test files (required) +- `run.sh` - Optional startup script + +**Template Structure**: Each template contains: + +- `main.tf` - Complete Coder template configuration +- `README.md` - Documentation with YAML frontmatter +- Additional configs, scripts as needed + +### README Frontmatter Requirements + +All modules/templates require YAML frontmatter: + +```yaml +--- +display_name: "Module Name" +description: "Brief description" +icon: "../../../../.icons/tool.svg" +verified: false +tags: ["tag1", "tag2"] +--- +``` + +## Testing Requirements + +### Module Testing + +- Every module MUST have `.tftest.hcl` test files +- Optional `main.test.ts` files for container-based testing or complex business logic validation +- Tests use Docker containers with `--network=host` flag +- Linux required for testing (Docker Desktop on macOS/Windows won't work) +- Use Colima or OrbStack on macOS instead of Docker Desktop + +### Test Utilities + +The `test/test.ts` file provides: + +- `runTerraformApply()` - Execute Terraform with variables +- `executeScriptInContainer()` - Run coder_script resources in containers +- `testRequiredVariables()` - Validate required variables +- Container management functions + +## Validation & Quality + +### Automated Validation + +The Go validation tool (`cmd/readmevalidation/`) checks: + +- Repository structure integrity +- Contributor README files +- Module and template documentation +- Frontmatter format compliance + +### Versioning + +Use semantic versioning for modules: + +- **Patch** (1.2.3 → 1.2.4): Bug fixes +- **Minor** (1.2.3 → 1.3.0): New features, adding inputs +- **Major** (1.2.3 → 2.0.0): Breaking changes + +## Dependencies & Tools + +### Required Tools + +- **Terraform** - Module development and testing +- **Docker** - Container-based testing +- **Bun** - JavaScript runtime for formatting/scripts +- **Go 1.23+** - Validation tooling + +### Development Dependencies + +- Prettier with Terraform and shell plugins +- TypeScript for test utilities +- Various npm packages for documentation processing + +## Workflow Notes + +### Contributing Process + +1. Create namespace (first-time contributors) +2. Generate module/template files using scripts +3. Implement functionality and tests +4. Run formatting and validation +5. Submit PR with appropriate template + +### Testing Workflow + +- All modules must pass `terraform test` +- Use `bun run test` for comprehensive testing +- Format code with `bun run fmt` before submission +- Manual testing recommended for templates + +### Namespace Management + +- Each contributor gets unique namespace +- Namespace avatar required (avatar.png/svg in .images/) +- Namespace README with contributor info and frontmatter diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/registry/coder/modules/kiro/main.test.ts b/registry/coder/modules/kiro/main.test.ts index 8d8bee636..2d268a844 100644 --- a/registry/coder/modules/kiro/main.test.ts +++ b/registry/coder/modules/kiro/main.test.ts @@ -99,19 +99,28 @@ describe("kiro", async () => { it("writes ~/.kiro/settings/mcp.json when mcp provided", async () => { const id = await runContainer("alpine"); try { - const mcp = JSON.stringify({ servers: { demo: { url: "http://localhost:1234" } } }); + const mcp = JSON.stringify({ + servers: { demo: { url: "http://localhost:1234" } }, + }); const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", mcp, }); - const script = findResourceInstance(state, "coder_script", "kiro_mcp").script; + const script = findResourceInstance( + state, + "coder_script", + "kiro_mcp", + ).script; const resp = await execContainer(id, ["sh", "-c", script]); if (resp.exitCode !== 0) { console.log(resp.stdout); console.log(resp.stderr); } expect(resp.exitCode).toBe(0); - const content = await readFileContainer(id, "/root/.kiro/settings/mcp.json"); + const content = await readFileContainer( + id, + "/root/.kiro/settings/mcp.json", + ); expect(content).toBe(mcp); } finally { await removeContainer(id); diff --git a/registry/coder/modules/windsurf/main.test.ts b/registry/coder/modules/windsurf/main.test.ts index 88e67f3cf..f5aa5e1f9 100644 --- a/registry/coder/modules/windsurf/main.test.ts +++ b/registry/coder/modules/windsurf/main.test.ts @@ -94,19 +94,28 @@ describe("windsurf", async () => { it("writes ~/.codeium/windsurf/mcp_config.json when mcp provided", async () => { const id = await runContainer("alpine"); try { - const mcp = JSON.stringify({ servers: { demo: { url: "http://localhost:1234" } } }); + const mcp = JSON.stringify({ + servers: { demo: { url: "http://localhost:1234" } }, + }); const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", mcp, }); - const script = findResourceInstance(state, "coder_script", "windsurf_mcp").script; + const script = findResourceInstance( + state, + "coder_script", + "windsurf_mcp", + ).script; const resp = await execContainer(id, ["sh", "-c", script]); if (resp.exitCode !== 0) { console.log(resp.stdout); console.log(resp.stderr); } expect(resp.exitCode).toBe(0); - const content = await readFileContainer(id, "/root/.codeium/windsurf/mcp_config.json"); + const content = await readFileContainer( + id, + "/root/.codeium/windsurf/mcp_config.json", + ); expect(content).toBe(mcp); } finally { await removeContainer(id);