CONTRIBUTING.md
Rama main · réplica de lectura del repositorio original.
# Contributing
Thank you for your interest in contributing to Coder.
This guide covers how to set up a development environment, the day-to-day workflow, and what we expect from pull requests.
All participation is governed by the [Code of Conduct](./CODE_OF_CONDUCT.md).
Area-specific guides live in [`contributing/`](./contributing/):
- [Backend](./contributing/backend.md): how the Go services fit together and how to test them.
- [Frontend](./contributing/frontend.md): the React codebase and its conventions.
- [Documentation](./contributing/documentation.md): the style guide for `docs/`.
- [Modules](./contributing/modules.md) and [templates](./contributing/templates.md): contributing to the Coder Registry.
- [AI contribution guidelines](./contributing/AI_CONTRIBUTING.md): rules for pull requests where an AI system is the primary author.
To report a security vulnerability, follow the [security policy](./SECURITY.md) instead of opening an issue.
## Requirements
To get started with Coder, the easiest way to set up the required environment is to use the provided [Nix environment](./flake.nix).
Learn more [how Nix works](https://nixos.org/guides/how-nix-works).
### Nix
1. [Install Nix](https://nix.dev/install-nix#install-nix)
1. After you've installed Nix, instantiate the development with the `nix-shell`
command:
```sh
cd ~/code/coder
# https://nix.dev/tutorials/declarative-and-reproducible-developer-environments
nix-shell
...
copying path '/nix/store/3ms6cs5210n8vfb5a7jkdvzrzdagqzbp-iana-etc-20210225' from 'https://cache.nixos.org'...
copying path '/nix/store/dxg5aijpyy36clz05wjsyk90gqcdzbam-iana-etc-20220520' from 'https://cache.nixos.org'...
copying path '/nix/store/v2gvj8whv241nj4lzha3flq8pnllcmvv-ignore-5.2.0.tgz' from 'https://cache.nixos.org'...
...
```
1. Optional: If you have [direnv](https://direnv.net/) installed with
[hooks configured](https://direnv.net/docs/hook.html), you can add `use nix`
to `.envrc` to automatically instantiate the development environment:
```sh
cd ~/code/coder
echo "use nix" >.envrc
direnv allow
```
Now, whenever you enter the project folder,
[`direnv`](https://direnv.net/docs/hook.html) will prepare the environment
for you:
```sh
cd ~/code/coder
direnv: loading ~/code/coder/.envrc
direnv: using nix
direnv: export +AR +AS +CC +CONFIG_SHELL +CXX +HOST_PATH +IN_NIX_SHELL +LD +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_BUILD_CORES +NIX_BUILD_TOP +NIX_CC +NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_CFLAGS_COMPILE +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_INDENT_MAKE +NIX_LDFLAGS +NIX_STORE +NM +NODE_PATH +OBJCOPY +OBJDUMP +RANLIB +READELF +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +TEMP +TEMPDIR +TMP +TMPDIR +XDG_DATA_DIRS +buildInputs +buildPhase +builder +cmakeFlags +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +mesonFlags +name +nativeBuildInputs +out +outputs +patches +phases +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH
🎉
```
- If you encounter a `creating directory` error on macOS, check the
[troubleshooting](#troubleshooting) section below.
### Without Nix
If you're not using the Nix environment, you can launch a local [DevContainer](./.devcontainer) to get a fully configured development environment.
DevContainers are supported in tools like **VS Code** and **GitHub Codespaces**, and come preloaded with all required dependencies: Docker, Go, Node.js with `pnpm`, `mise`, and `make`.
For manual setup outside Nix and DevContainers, install Docker, `mise`, and
`make`. Run `mise install` from the repository root to install Go, Node.js
with `pnpm`, and development tools at the versions pinned in `mise.toml`.
## Development workflow
Use the following `make` commands and scripts in development:
- `./scripts/develop.sh` runs the frontend and backend development server
- `make build` compiles binaries and release packages
- `make install` installs binaries to `$GOPATH/bin`
- `make test`
- `make pre-commit` runs gen, fmt, lint, typos, and builds a slim binary
- `make pre-commit-light` runs fmt and lint for shell, terraform, markdown,
helm, actions, and typos (skips gen, Go/TS lint+fmt, and binary build)
- `make pre-push` runs heavier CI checks including tests (allowlisted)
Install the git hooks to run these automatically:
```sh
git config core.hooksPath scripts/githooks
```
Hook checks are opt-in. Enable them with `git config coder.pre-commit true`
and `git config coder.pre-push true`; developers allowlisted in the hook
scripts run them by default.
The hooks classify staged/changed files and select the appropriate target.
Commits that only touch docs, shell, terraform, or other lightweight files
run `make pre-commit-light` instead of the full `make pre-commit`, and
`pre-push` is skipped entirely. Changes to Go, TypeScript, SQL, proto, or
the Makefile trigger the full targets as before.
### Running Coder on development mode
1. Run the development script to spin up the local environment:
```sh
./scripts/develop.sh
```
This will start two processes:
- http://localhost:3000: the backend API server. Primarily used for backend development and also serves the *static* frontend build.
- http://localhost:8080: the Node.js frontend development server. Supports *hot reloading* and is useful if you're working on the frontend as well.
Additionally, it starts a local PostgreSQL instance, creates both an admin and a member user account, and installs a default Docker-based template.
1. Verify Your Session
Confirm that you're logged in by running:
```sh
./scripts/coder-dev.sh list
```
This should return an empty list of workspaces. If you encounter an error, review the output from the [develop.sh](./scripts/develop.sh) script for issues.
> [!NOTE]
> `coder-dev.sh` is a helper script that behaves like the regular coder CLI, but uses the binary built from your local source and shares the same configuration directory set up by `develop.sh`. This ensures your local changes are reflected when testing.
>
> The default user is `admin@coder.com` and the default password is `SomeSecurePassword!`
1. Create Your First Workspace
A template named `docker` is created automatically. To spin up a workspace quickly, use:
```sh
./scripts/coder-dev.sh create my-workspace -t docker
```
## Styling
- [Documentation style guide](./contributing/documentation.md)
- [Frontend styling guide](./contributing/frontend.md#styling)
## Pull Requests
We welcome pull requests (PRs) from community members including (but not limited to) open source users, enthusiasts, and enterprise customers.
We will ask that you sign a Contributor License Agreement before we accept any contributions into our repo.
Please keep PRs small and self-contained. This allows code reviewers (see below) to focus and fully understand the PR. A good rule of thumb is less than 1000 lines changed. (One exception is a mechanistic refactor, like renaming, that is conceptually trivial but might have a large line count.)
If your intended feature or refactor will be larger than this:
1. Open an issue explaining what you intend to build, how it will work, and that you are volunteering to do the development. Include `@coder/community-triage` in the body.
2. Give the maintainers a chance to respond. Changes to the visual, interaction, or software design are easier to adjust before you start laying down code.
3. Break your work up into a series of smaller PRs.
Stacking tools like [Graphite](https://www.graphite.dev) are useful for keeping a series of PRs that build on each other up to date as they are reviewed and merged.
Each PR:
- Must individually build and pass all tests, including formatting and linting.
- Must not introduce regressions or backward-compatibility issues, even if a subsequent PR in your series would resolve the issue.
- Should be a conceptually coherent change set.
In practice, many of these smaller PRs will be invisible to end users, and that is ok. For example, you might introduce
a new Go package that implements the core business logic of a feature in one PR, but only later actually "wire it up"
to a new API route in a later PR. Or, you might implement a new React component in one PR, and only in a later PR place it on a page.
## Reviews
The following information has been borrowed from [Go's review philosophy](https://go.dev/doc/contribute#reviews).
Coder values thorough reviews. For each review comment that you receive, please
"close" it by implementing the suggestion or providing an explanation on why the
suggestion isn't the best option.
Be sure to do this for each comment; you can select **Done** to indicate that you've implemented the suggestion, or you can add a comment explaining why you aren't implementing the suggestion (or what you chose to implement instead).
It is perfectly normal for changes to go through several rounds of reviews, with
one or more reviewers making new comments every time, then waiting for an
updated change before reviewing again. All contributors, including those from
maintainers, are subject to the same review cycle; this process is not meant to
be applied selectively or to discourage anyone from contributing.
## Releases
Coder releases are managed entirely through the
[`release.yaml`](./.github/workflows/release.yaml)
GitHub Actions workflow, triggered manually via "Run workflow" in the Actions
tab. Release notes are automatically generated from commit titles and PR
metadata.
### Release types
| Type | Tag | Source | Purpose |
|------------------------|---------------|------------------|---------------------------------------|
| RC (release candidate) | `vX.Y.0-rc.W` | `main` or branch | Pre-release for testing |
| Create release branch | `vX.Y.0-rc.W` | `main` | Cut `release/X.Y` + tag RC atomically |
| Release | `vX.Y.0` | `release/X.Y` | First release of a minor version |
| Patch | `vX.Y.Z` | `release/X.Y` | Bug fixes and security patches |
### Workflow
RC tags can be created from `main` or from a release branch. The
`create-release-branch` type creates `release/X.Y` and tags the next RC in one
step, continuing the RC numbering sequence.
```txt
main: --*--*--*--*--*--*--*--*--*--
| rc.0 rc.1 |
| +--- create-release-branch ---+
| |
| release/2.34: --*-- rc.2 -- rc.3 -- v2.34.0
|
+-- (more RCs on main for next cycle)
```
1. **RC:** Go to [Actions > Release](https://github.com/coder/coder/actions/workflows/release.yaml),
select "Run workflow", select `main` (or a release branch) from the "Use
workflow from" dropdown, choose `rc`, and optionally provide a commit SHA
(defaults to HEAD). The workflow calculates the next RC version
automatically.
2. **Create release branch:** Select `main` in the dropdown, choose
`create-release-branch`, and optionally provide a commit SHA. This creates
`release/X.Y` and tags the next RC atomically.
3. **Release:** Select the release branch (e.g. `release/2.34`) from the
dropdown and choose `release`. No other inputs needed.
4. **Patch:** Cherry-pick fixes onto `release/X.Y` (see
[Backporting fixes to release branches](#backporting-fixes-to-release-branches)),
select that branch from the dropdown, and choose `release`.
The workflow validates that commits are on the expected branch for each release
type.
### Retrying a failed release
If the
[`release.yaml`](https://github.com/coder/coder/actions/workflows/release.yaml)
workflow fails after the tag has been pushed, re-run the failed jobs from the
GitHub Actions UI. The `prepare-release` job is idempotent and will detect
the existing tag.
To test the workflow without publishing, select dry-run.
### Commit messages
Commit messages should follow the
[Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/)
specification.
Allowed commit types (`feat`, `fix`, etc.) are listed in
[conventional-commit-types](https://github.com/commitizen/conventional-commit-types/blob/c3a9be4c73e47f2e8197de775f41d981701407fb/index.json).
Note that these types are also used to automatically sort and organize the
release notes.
A good commit message title uses the imperative, present tense and is ~50
characters long (no more than 72).
Examples:
- Good: `feat(coderd): add feature X`
- Bad: `feat(coderd): added feature X` (past tense)
Scopes must reference a real path in the repository (a directory or file stem)
and must contain all changed files, except files under `docs/`. For example,
use `coderd/database` if all changes are within that directory. If changes
span multiple top-level directories, omit the scope.
A good rule of thumb for writing good commit messages is to recite:
[If applied, this commit will ...](https://cbea.ms/git-commit/).
**Note:** We lint PR titles to ensure they follow the Conventional Commits
specification, however, it's still possible to merge PRs on GitHub with a badly
formatted title. Take care when merging single-commit PRs as GitHub may prefer
to use the original commit title instead of the PR title.
### Backporting fixes to release branches
Changes land on `main` first. To ship a change in an existing release, add
one of these labels to its PR against `main`:
| Label | Targets | Use when |
|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
| `cherry-pick` | The latest `release/2.X` branch (mainline) only | The fix only needs to ship in the next mainline patch |
| `backport` | The latest three `release/2.X` branches (mainline, stable, security) plus the ESR branches in [`esr_versions.txt`](./scripts/release_channels/esr_versions.txt) | The fix must reach every supported release, including ESR |
The label can be added before or after the PR merges. Nothing happens until
the PR is merged. After that, the
[cherry-pick](./.github/workflows/cherry-pick.yaml) or
[backport](./.github/workflows/backport.yaml) workflow:
1. Creates a `backport/<pr>-to-<version>` branch from each target release
branch and runs `git cherry-pick -x -m1 <merge commit>`.
2. Opens a PR against each release branch. The PR reuses the original title
with the PR number appended, e.g.
`fix(site): correct button alignment (#12345)`, so release notes stay
meaningful.
3. Labels each PR `cherry-pick/v2.X` or `backport/v2.X` so all PRs for a
release can be filtered together.
4. Assigns you and requests your review, since you added the label.
5. Comments on the original PR with a link to each new PR.
You are then responsible for getting each generated PR reviewed, green, and
merged. Close any PR that should not ship to a given branch.
If the cherry-pick conflicts, the PR is still opened, but it contains only an
empty placeholder commit. No conflict markers are committed. The title is
prefixed with `[CONFLICT]` (cherry-pick) or suffixed with `(conflicts)`
(backport). To resolve it, check out the branch, start from the release
branch, and cherry-pick by hand:
```sh
git fetch origin backport/<pr>-to-<version>
git checkout backport/<pr>-to-<version>
git reset --hard origin/release/<version>
git cherry-pick -x -m1 <merge commit>
# resolve conflicts, then
git push --force-with-lease origin backport/<pr>-to-<version>
```
Things to know:
- Only bug fixes belong on release branches. A PR against `release/*` whose
title does not start with `fix:` or `fix(scope):` gets a warning comment
from the [cherry-pick check](./.github/workflows/pr-cherry-pick-check.yaml).
- Dependabot security updates are labeled `backport` automatically.
- Re-running a workflow is safe. Branches and PRs that already exist are
skipped.
- To backport by hand instead, open a PR against `release/2.X` with the same
title and a `git cherry-pick -x` of the merge commit.
### Breaking changes
Breaking changes can be triggered in two ways:
- Add `!` to the commit message title, e.g.
`feat(coderd)!: remove deprecated endpoint /test`
- Add the
[`release/breaking`](https://github.com/coder/coder/issues?q=sort%3Aupdated-desc+label%3Arelease%2Fbreaking)
label to a PR that has, or will be, merged into `main`.
### Generative AI
Using AI to help with contributions is acceptable, but only if the [AI Contribution Guidelines](./contributing/AI_CONTRIBUTING.md)
are followed. If most of your PR was generated by AI, please read and comply with these rules before submitting.
### Security
> [!CAUTION]
> If you find a vulnerability, **DO NOT FILE AN ISSUE**. Instead, send an email
> to <security@coder.com>.
The
[`security`](https://github.com/coder/coder/issues?q=sort%3Aupdated-desc+label%3Asecurity)
label can be added to PRs that have, or will be, merged into `main`. Doing so
will make sure the change stands out in the release notes.
### Experimental
The
[`release/experimental`](https://github.com/coder/coder/issues?q=sort%3Aupdated-desc+label%3Arelease%2Fexperimental)
label can be used to move the note to the bottom of the release notes under a
separate title.
## Troubleshooting
### Database migration mismatch after switching branches
If `./scripts/develop.sh` exits with a "database migration conflict" error,
it means the database has migrations from another branch that don't exist
on the current one. You have two options:
```sh
# Roll back the mismatched migrations (preserves your dev data):
./scripts/develop.sh --db-rollback
# Or wipe the database and start fresh:
./scripts/develop.sh --db-reset
```
### Nix on macOS: `error: creating directory`
On macOS, a [direnv bug](https://github.com/direnv/direnv/issues/1345) can cause
`nix-shell` to fail to build or run `coder`. If you encounter
`error: creating directory` when you attempt to run, build, or test, add a
`mkdir` line to your `.envrc`:
```sh
use nix
mkdir -p "$TMPDIR"
```