mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.*
220 lines
14 KiB
Markdown
220 lines
14 KiB
Markdown
# Backend
|
||
|
||
This guide is designed to support both Coder engineers and community contributors in understanding our backend systems and getting started with development.
|
||
|
||
Coder’s backend powers the core infrastructure behind workspace provisioning, access control, and the overall developer experience. As the backbone of our platform, it plays a critical role in enabling reliable and scalable remote development environments.
|
||
|
||
The purpose of this guide is to help you:
|
||
|
||
* Understand how the various backend components fit together.
|
||
* Navigate the codebase with confidence and adhere to established best practices.
|
||
* Contribute meaningful changes - whether you're fixing bugs, implementing features, or reviewing code.
|
||
|
||
Need help or have questions? Join the conversation on our [Discord server](https://discord.com/invite/coder) — we’re always happy to support contributors.
|
||
|
||
## Platform Architecture
|
||
|
||
To understand how the backend fits into the broader system, we recommend reviewing the following resources:
|
||
|
||
* [General Concepts](../../admin/infrastructure/validated-architectures/index.md#general-concepts): Essential concepts and language used to describe how Coder is structured and operated.
|
||
|
||
* [Architecture](../../admin/infrastructure/architecture.md): A high-level overview of the infrastructure layout, key services, and how components interact.
|
||
|
||
These sections provide the necessary context for navigating and contributing to the backend effectively.
|
||
|
||
## Tech Stack
|
||
|
||
Coder's backend is built using a collection of robust, modern Go libraries and internal packages. Familiarity with these technologies will help you navigate the codebase and contribute effectively.
|
||
|
||
### Core Libraries & Frameworks
|
||
|
||
* [go-chi/chi](https://github.com/go-chi/chi): lightweight HTTP router for building RESTful APIs in Go
|
||
* [golang-migrate/migrate](https://github.com/golang-migrate/migrate): manages database schema migrations across environments
|
||
* [coder/terraform-config-inspect](https://github.com/coder/terraform-config-inspect) *(forked)*: used for parsing and analyzing Terraform configurations, forked to include [PR #74](https://github.com/hashicorp/terraform-config-inspect/pull/74)
|
||
* [coder/pq](https://github.com/coder/pq) *(forked)*: PostgreSQL driver forked to support rotating authentication tokens via `driver.Connector`
|
||
* [coder/tailscale](https://github.com/coder/tailscale) *(forked)*: enables secure, peer-to-peer connectivity, forked to apply internal patches pending upstreaming
|
||
* [coder/wireguard-go](https://github.com/coder/wireguard-go) *(forked)*: WireGuard networking implementation, forked to fix a data race and adopt the latest gVisor changes
|
||
* [coder/ssh](https://github.com/coder/ssh) *(forked)*: customized SSH server based on `gliderlabs/ssh`, forked to include Tailscale-specific patches and avoid complex subpath dependencies
|
||
* [coder/bubbletea](https://github.com/coder/bubbletea) *(forked)*: terminal UI framework for CLI apps, forked to remove an `init()` function that interfered with web terminal output
|
||
|
||
### Coder libraries
|
||
|
||
* [coder/terraform-provider-coder](https://github.com/coder/terraform-provider-coder): official Terraform provider for managing Coder resources via infrastructure-as-code
|
||
* [coder/websocket](https://github.com/coder/websocket): minimal WebSocket library for real-time communication
|
||
* [coder/serpent](https://github.com/coder/serpent): CLI framework built on `cobra`, used for large, complex CLIs
|
||
* [coder/guts](https://github.com/coder/guts): generates TypeScript types from Go for shared type definitions
|
||
* [coder/wgtunnel](https://github.com/coder/wgtunnel): WireGuard tunnel server for secure backend networking
|
||
|
||
## Repository Structure
|
||
|
||
The Coder backend is organized into multiple packages and directories, each with a specific purpose. Here's a high-level overview of the most important ones:
|
||
|
||
* [agent](../../../agent): core logic of a workspace agent, supports DevContainers, remote SSH, startup/shutdown script execution. Protobuf definitions for DRPC communication with `coderd` are kept in [proto](../../../agent/proto).
|
||
* [cli](../../../cli): CLI interface for `coder` command built on [coder/serpent](https://github.com/coder/serpent). Input controls are defined in [cliui](../../../cli/cliui), and [testdata](../../../cli/testdata) contains golden files for common CLI calls
|
||
* [cmd](../../../cmd): entry points for CLI and services, including `coderd`
|
||
* [coderd](../../../coderd): the main API server implementation with [chi](https://github.com/go-chi/chi) endpoints
|
||
* [audit](../../../coderd/audit): audit log logic, defines target resources, actions and extra fields
|
||
* [autobuild](../../../coderd/autobuild): core logic of the workspace autobuild executor, periodically evaluates workspaces for next transition actions
|
||
* [httpmw](../../../coderd/httpmw): HTTP middlewares mainly used to extract parameters from HTTP requests (e.g. current user, template, workspace, OAuth2 account, etc.) and storing them in the request context
|
||
* [prebuilds](../../../coderd/prebuilds): common interfaces for prebuild workspaces, feature implementation is in [enterprise/prebuilds](../../../enterprise/coderd/prebuilds)
|
||
* [provisionerdserver](../../../coderd/provisionerdserver): DRPC server for [provisionerd](../../../provisionerd) instances, used to validate and extract Terraform data and resources, and store them in the database.
|
||
* [rbac](../../../coderd/rbac): RBAC engine for `coderd`, including authz layer, role definitions and custom roles. Built on top of [Open Policy Agent](https://github.com/open-policy-agent/opa) and Rego policies.
|
||
* [telemetry](../../../coderd/telemetry): records a snapshot with various workspace data for telemetry purposes. Once recorded the reporter sends it to the configured telemetry endpoint.
|
||
* [tracing](../../../coderd/tracing): extends telemetry with tracing data consistent with [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md)
|
||
* [workspaceapps](../../../coderd/workspaceapps): core logic of a secure proxy to expose workspace apps deployed in a workspace
|
||
* [wsbuilder](../../../coderd/wsbuilder): wrapper for business logic of creating a workspace build. It encapsulates all database operations required to insert a build record in a transaction.
|
||
* [database](../../../coderd/database): schema migrations, query logic, in-memory database, etc.
|
||
* [db2sdk](../../../coderd/database/db2sdk): translation between database structures and [codersdk](../../../codersdk) objects used by coderd API.
|
||
* [dbauthz](../../../coderd/database/dbauthz): AuthZ wrappers for database queries, ideally, every query should verify first if the accessor is eligible to see the query results.
|
||
* [dbfake](../../../coderd/database/dbfake): helper functions to quickly prepare the initial database state for testing purposes (e.g. create N healthy workspaces and templates), operates on higher level than [dbgen](../../../coderd/database/dbgen)
|
||
* [dbgen](../../../coderd/database/dbgen): helper functions to insert raw records to the database store, used for testing purposes
|
||
* [dbmock](../../../coderd/database/dbmock): a store wrapper for database queries, useful to verify if the function has been called, used for testing purposes
|
||
* [dbpurge](../../../coderd/database/dbpurge): simple wrapper for periodic database cleanup operations
|
||
* [migrations](../../../coderd/database/migrations): an ordered list of up/down database migrations, use `./create_migration.sh my_migration_name` to modify the database schema
|
||
* [pubsub](../../../coderd/database/pubsub): PubSub implementation using PostgreSQL and in-memory drop-in replacement
|
||
* [queries](../../../coderd/database/queries): contains SQL files with queries, `sqlc` compiles them to [Go functions](../../../coderd/database/queries.sql.go)
|
||
* [sqlc.yaml](../../../coderd/database/sqlc.yaml): defines mappings between SQL types and custom Go structures
|
||
* [codersdk](../../../codersdk): user-facing API entities used by CLI and site to communicate with `coderd` endpoints
|
||
* [dogfood](../../../dogfood): Terraform definition of the dogfood cluster deployment
|
||
* [enterprise](../../../enterprise): enterprise-only features, notice similar file structure to repository root (`audit`, `cli`, `cmd`, `coderd`, etc.)
|
||
* [coderd](../../../enterprise/coderd)
|
||
* [prebuilds](../../../enterprise/coderd/prebuilds): core logic of prebuilt workspaces - reconciliation loop
|
||
* [provisioner](../../../provisioner): supported implementation of provisioners, Terraform and "echo" (for testing purposes)
|
||
* [provisionerd](../../../provisionerd): core logic of provisioner runner to interact provisionerd server, depending on a job acquired it calls template import, dry run or a workspace build
|
||
* [pty](../../../pty): terminal emulation for agent shell
|
||
* [support](../../../support): compile a support bundle with diagnostics
|
||
* [tailnet](../../../tailnet): core logic of Tailnet controller to maintain DERP maps, coordinate connections with agents and peers
|
||
* [vpn](../../../vpn): Coder Desktop (VPN) and tunneling components
|
||
|
||
## Testing
|
||
|
||
The Coder backend includes a rich suite of unit and end-to-end tests. A variety of helper utilities are used throughout the codebase to make testing easier, more consistent, and closer to real behavior.
|
||
|
||
### [clitest](../../../cli/clitest)
|
||
|
||
* Spawns an in-memory `serpent.Command` instance for unit testing
|
||
* Configures an authorized `codersdk` client
|
||
* Once a `serpent.Invocation` is created, tests can execute commands as if invoked by a real user
|
||
|
||
### [ptytest](../../../pty/ptytest)
|
||
|
||
* `ptytest` attaches to a `serpent.Invocation` and simulates TTY input/output
|
||
* `pty` provides matchers and "write" operations for interacting with pseudo-terminals
|
||
|
||
### [coderdtest](../../../coderd/coderdtest)
|
||
|
||
* Provides shortcuts to spin up an in-memory `coderd` instance
|
||
* Can start an embedded provisioner daemon
|
||
* Supports multi-user testing via `CreateFirstUser` and `CreateAnotherUser`
|
||
* Includes "busy wait" helpers like `AwaitTemplateVersionJobCompleted`
|
||
* [oidctest](../../../coderd/coderdtest/oidctest) can start a fake OIDC provider
|
||
|
||
### [testutil](../../../testutil)
|
||
|
||
* General-purpose testing utilities, including:
|
||
* [chan.go](../../../testutil/chan.go): helpers for sending/receiving objects from channels (`TrySend`, `RequireReceive`, etc.)
|
||
* [duration.go](../../../testutil/duration.go): set timeouts for test execution
|
||
* [eventually.go](../../../testutil/eventually.go): repeatedly poll for a condition using a ticker
|
||
* [port.go](../../../testutil/port.go): select a free random port
|
||
* [prometheus.go](../../../testutil/prometheus.go): validate Prometheus metrics with expected values
|
||
* [pty.go](../../../testutil/pty.go): read output from a terminal until a condition is met
|
||
* [wait_buffer.go](../../../testutil/wait_buffer.go): thread-safe `io.Writer` that blocks until accumulated output contains a signal (`WaitFor`, `WaitForNth`, `WaitForCond`)
|
||
|
||
### [dbtestutil](../../../coderd/database/dbtestutil)
|
||
|
||
* Allows choosing between real and in-memory database backends for tests
|
||
* `WillUsePostgres` is useful for skipping tests in CI environments that don't run Postgres
|
||
|
||
### [quartz](https://github.com/coder/quartz/tree/main)
|
||
|
||
* Provides a mockable clock or ticker interface
|
||
* Allows manual time advancement
|
||
* Useful for testing time-sensitive or timeout-related logic
|
||
|
||
## Quiz
|
||
|
||
Try to find answers to these questions before jumping into implementation work — having a solid understanding of how Coder works will save you time and help you contribute effectively.
|
||
|
||
1. When you create a template, what does that do exactly?
|
||
2. When you create a workspace, what exactly happens?
|
||
3. How does the agent get the required information to run?
|
||
4. How are provisioner jobs run?
|
||
|
||
## Recipes
|
||
|
||
### Adding database migrations and fixtures
|
||
|
||
#### Database migrations
|
||
|
||
Database migrations are managed with
|
||
[`migrate`](https://github.com/golang-migrate/migrate).
|
||
|
||
To add new migrations, use the following command:
|
||
|
||
```sh
|
||
./coderd/database/migrations/create_migration.sh my name
|
||
/home/coder/src/coder/coderd/database/migrations/000070_my_name.up.sql
|
||
/home/coder/src/coder/coderd/database/migrations/000070_my_name.down.sql
|
||
```
|
||
|
||
Then write queries into the generated `.up.sql` and `.down.sql` files and commit
|
||
them into the repository. The down script should make a best-effort to retain as
|
||
much data as possible.
|
||
|
||
Run `make gen` to generate models.
|
||
|
||
#### Database fixtures (for testing migrations)
|
||
|
||
There are two types of fixtures that are used to test that migrations don't
|
||
break existing Coder deployments:
|
||
|
||
* Partial fixtures
|
||
[`migrations/testdata/fixtures`](../../../coderd/database/migrations/testdata/fixtures)
|
||
* Full database dumps
|
||
[`migrations/testdata/full_dumps`](../../../coderd/database/migrations/testdata/full_dumps)
|
||
|
||
Both types behave like database migrations (they also
|
||
[`migrate`](https://github.com/golang-migrate/migrate)). Their behavior mirrors
|
||
Coder migrations such that when migration number `000022` is applied, fixture
|
||
`000022` is applied afterwards.
|
||
|
||
Partial fixtures are used to conveniently add data to newly created tables so
|
||
that we can ensure that this data is migrated without issue.
|
||
|
||
Full database dumps are for testing the migration of fully-fledged Coder
|
||
deployments. These are usually done for a specific version of Coder and are
|
||
often fixed in time. A full database dump may be necessary when testing the
|
||
migration of multiple features or complex configurations.
|
||
|
||
To add a new partial fixture, run the following command:
|
||
|
||
```sh
|
||
./coderd/database/migrations/create_fixture.sh my fixture
|
||
/home/coder/src/coder/coderd/database/migrations/testdata/fixtures/000070_my_fixture.up.sql
|
||
```
|
||
|
||
Then add some queries to insert data and commit the file to the repo. See
|
||
[`000024_example.up.sql`](../../../coderd/database/migrations/testdata/fixtures/000024_example.up.sql)
|
||
for an example.
|
||
|
||
To create a full dump, run a fully fledged Coder deployment and use it to
|
||
generate data in the database. Then shut down the deployment and take a snapshot
|
||
of the database.
|
||
|
||
```sh
|
||
mkdir -p coderd/database/migrations/testdata/full_dumps/v0.12.2 && cd $_
|
||
pg_dump "postgres://coder@localhost:..." -a --inserts >000069_dump_v0.12.2.up.sql
|
||
```
|
||
|
||
Make sure sensitive data in the dump is desensitized, for instance names,
|
||
emails, OAuth tokens and other secrets. Then commit the dump to the project.
|
||
|
||
To find out what the latest migration for a version of Coder is, use the
|
||
following command:
|
||
|
||
```sh
|
||
git ls-files v0.12.2 -- coderd/database/migrations/*.up.sql
|
||
```
|
||
|
||
This helps in naming the dump (e.g. `000069` above).
|