mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
docs: reorganize the About section (#18236)
As part of an information architecture overhaul, this PR reorganizes the About section and adds a Support section (but not content to it yet) [preview](https://coder.com/docs/@docs-ia-about/about) this PR is intentionally limited in scope so that we can ship meaningful changes faster and followup PRs should include: - [ ] edit + overhaul the About page - [ ] decide on the `start` directory - [ ] ~screenshots page updates~ (this should happen July or later) redirects PR: https://github.com/coder/coder.com/pull/944 --------- Co-authored-by: EdwardAngert <17991901+EdwardAngert@users.noreply.github.com>
This commit is contained in:
co-authored by
EdwardAngert
parent
5944b1c595
commit
f1cca03ed3
@@ -0,0 +1,77 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and
|
||||
expression, level of experience, education, socio-economic status, nationality,
|
||||
personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, or to ban temporarily or permanently any
|
||||
contributor for other behaviors that they deem inappropriate, threatening,
|
||||
offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at <opensource@coder.com>. All complaints
|
||||
will be reviewed and investigated and will result in a response that is deemed
|
||||
necessary and appropriate to the circumstances. The project team is obligated to
|
||||
maintain confidentiality with regard to the reporter of an incident. Further
|
||||
details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at
|
||||
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
<https://www.contributor-covenant.org/faq>
|
||||
@@ -0,0 +1,268 @@
|
||||
# Contributing
|
||||
|
||||
## Requirements
|
||||
|
||||
<div class="tabs">
|
||||
|
||||
To get started with Coder, the easiest way to set up the required environment is to use the provided [Nix environment](https://github.com/coder/coder/tree/main/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:
|
||||
|
||||
```shell
|
||||
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:
|
||||
|
||||
```shell
|
||||
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:
|
||||
|
||||
```shell
|
||||
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](https://github.com/coder/coder/tree/main/.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`, and `make`.
|
||||
|
||||
</div>
|
||||
|
||||
## 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`
|
||||
|
||||
### 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](https://github.com/coder/coder/blob/main/scripts/develop.sh) script for issues.
|
||||
|
||||
> `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
|
||||
```
|
||||
|
||||
### Deploying a PR
|
||||
|
||||
You need to be a member or collaborator of the [coder](https://github.com/coder) GitHub organization to be able to deploy a PR.
|
||||
|
||||
You can test your changes by creating a PR deployment. There are two ways to do
|
||||
this:
|
||||
|
||||
- Run `./scripts/deploy-pr.sh`
|
||||
- Manually trigger the
|
||||
[`pr-deploy.yaml`](https://github.com/coder/coder/actions/workflows/pr-deploy.yaml)
|
||||
GitHub Action workflow:
|
||||
|
||||
<Image src="./images/deploy-pr-manually.png" alt="Deploy PR manually" height="348px" align="center" />
|
||||
|
||||
#### Available options
|
||||
|
||||
- `-d` or `--deploy`, force deploys the PR by deleting the existing deployment.
|
||||
- `-b` or `--build`, force builds the Docker image. (generally not needed as we
|
||||
are intelligently checking if the image needs to be built)
|
||||
- `-e EXPERIMENT1,EXPERIMENT2` or `--experiments EXPERIMENT1,EXPERIMENT2`, will
|
||||
enable the specified experiments. (defaults to `*`)
|
||||
- `-n` or `--dry-run` will display the context without deployment. e.g., branch
|
||||
name and PR number, etc.
|
||||
- `-y` or `--yes`, will skip the CLI confirmation prompt.
|
||||
|
||||
> [!NOTE]
|
||||
> PR deployment will be re-deployed automatically when the PR is updated.
|
||||
> It will use the last values automatically for redeployment.
|
||||
|
||||
Once the deployment is finished, a unique link and credentials will be posted in
|
||||
the [#pr-deployments](https://codercom.slack.com/archives/C05DNE982E8) Slack
|
||||
channel.
|
||||
|
||||
## Styling
|
||||
|
||||
- [Documentation style guide](./documentation.md)
|
||||
|
||||
- [Frontend styling guide](./frontend.md#styling)
|
||||
|
||||
## 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
|
||||
click **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 initiated via
|
||||
[`./scripts/release.sh`](https://github.com/coder/coder/blob/main/scripts/release.sh)
|
||||
and automated via GitHub Actions. Specifically, the
|
||||
[`release.yaml`](https://github.com/coder/coder/blob/main/.github/workflows/release.yaml)
|
||||
workflow. They are created based on the current
|
||||
[`main`](https://github.com/coder/coder/tree/main) branch.
|
||||
|
||||
The release notes for a release are automatically generated from commit titles
|
||||
and metadata from PRs that are merged into `main`.
|
||||
|
||||
### Creating a release
|
||||
|
||||
The creation of a release is initiated via
|
||||
[`./scripts/release.sh`](https://github.com/coder/coder/blob/main/scripts/release.sh).
|
||||
This script will show a preview of the release that will be created, and if you
|
||||
choose to continue, create and push the tag which will trigger the creation of
|
||||
the release via GitHub Actions.
|
||||
|
||||
See `./scripts/release.sh --help` for more information.
|
||||
|
||||
### Creating a release (via workflow dispatch)
|
||||
|
||||
Typically the workflow dispatch is only used to test (dry-run) a release,
|
||||
meaning no actual release will take place. The workflow can be dispatched
|
||||
manually from
|
||||
[Actions: Release](https://github.com/coder/coder/actions/workflows/release.yaml).
|
||||
Simply press "Run workflow" and choose dry-run.
|
||||
|
||||
If a release has failed after the tag has been created and pushed, it can be
|
||||
retried by again, pressing "Run workflow", changing "Use workflow from" from
|
||||
"Branch: main" to "Tag: vX.X.X" and not selecting 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(api): add feature X`
|
||||
- Bad: `feat(api): added feature X` (past tense)
|
||||
|
||||
A good rule of thumb for writing good commit messages is to recite:
|
||||
[If applied, this commit will ...](https://reflectoring.io/meaningful-commit-messages/).
|
||||
|
||||
**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.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Breaking changes can be triggered in two ways:
|
||||
|
||||
- Add `!` to the commit message title, e.g.
|
||||
`feat(api)!: 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`.
|
||||
|
||||
### 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
|
||||
|
||||
### 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`:
|
||||
|
||||
```shell
|
||||
use nix
|
||||
mkdir -p "$TMPDIR"
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
# Security Policy
|
||||
|
||||
Coder welcomes feedback from security researchers and the general public to help improve our security.
|
||||
If you believe you have discovered a vulnerability, privacy issue, exposed data, or other security issues
|
||||
in any of our assets, we want to hear from you.
|
||||
|
||||
If you find a vulnerability, **DO NOT FILE AN ISSUE**.
|
||||
Instead, send an email to
|
||||
<security@coder.com>.
|
||||
|
||||
Refer to the [Security policy](https://coder.com/security/policy) for more information.
|
||||
@@ -0,0 +1,219 @@
|
||||
# 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](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/agent/proto).
|
||||
* [cli](https://github.com/coder/coder/tree/main/cli): CLI interface for `coder` command built on [coder/serpent](https://github.com/coder/serpent). Input controls are defined in [cliui](https://github.com/coder/coder/tree/docs-backend-contrib-guide/cli/cliui), and [testdata](https://github.com/coder/coder/tree/docs-backend-contrib-guide/cli/testdata) contains golden files for common CLI calls
|
||||
* [cmd](https://github.com/coder/coder/tree/main/cmd): entry points for CLI and services, including `coderd`
|
||||
* [coderd](https://github.com/coder/coder/tree/main/coderd): the main API server implementation with [chi](https://github.com/go-chi/chi) endpoints
|
||||
* [audit](https://github.com/coder/coder/tree/main/coderd/audit): audit log logic, defines target resources, actions and extra fields
|
||||
* [autobuild](https://github.com/coder/coder/tree/main/coderd/autobuild): core logic of the workspace autobuild executor, periodically evaluates workspaces for next transition actions
|
||||
* [httpmw](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/coderd/prebuilds): common interfaces for prebuild workspaces, feature implementation is in [enterprise/prebuilds](https://github.com/coder/coder/tree/main/enterprise/coderd/prebuilds)
|
||||
* [provisionerdserver](https://github.com/coder/coder/tree/main/coderd/provisionerdserver): DRPC server for [provisionerd](https://github.com/coder/coder/tree/main/provisionerd) instances, used to validate and extract Terraform data and resources, and store them in the database.
|
||||
* [rbac](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/coderd/telemetry): records a snapshot with various workspace data for telemetry purposes. Once recorded the reporter sends it to the configured telemetry endpoint.
|
||||
* [tracing](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/coderd/workspaceapps): core logic of a secure proxy to expose workspace apps deployed in a workspace
|
||||
* [wsbuilder](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/coderd/database): schema migrations, query logic, in-memory database, etc.
|
||||
* [db2sdk](https://github.com/coder/coder/tree/main/coderd/database/db2sdk): translation between database structures and [codersdk](https://github.com/coder/coder/tree/main/codersdk) objects used by coderd API.
|
||||
* [dbauthz](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/coderd/database/dbgen)
|
||||
* [dbgen](https://github.com/coder/coder/tree/main/coderd/database/dbgen): helper functions to insert raw records to the database store, used for testing purposes
|
||||
* [dbmem](https://github.com/coder/coder/tree/main/coderd/database/dbmem): in-memory implementation of the database store, ideally, every real query should have a complimentary Go implementation
|
||||
* [dbmock](https://github.com/coder/coder/tree/main/coderd/database/dbmock): a store wrapper for database queries, useful to verify if the function has been called, used for testing purposes
|
||||
* [dbpurge](https://github.com/coder/coder/tree/main/coderd/database/dbpurge): simple wrapper for periodic database cleanup operations
|
||||
* [migrations](https://github.com/coder/coder/tree/main/coderd/database/migrations): an ordered list of up/down database migrations, use `./create_migration.sh my_migration_name` to modify the database schema
|
||||
* [pubsub](https://github.com/coder/coder/tree/main/coderd/database/pubsub): PubSub implementation using PostgreSQL and in-memory drop-in replacement
|
||||
* [queries](https://github.com/coder/coder/tree/main/coderd/database/queries): contains SQL files with queries, `sqlc` compiles them to [Go functions](https://github.com/coder/coder/blob/docs-backend-contrib-guide/coderd/database/queries.sql.go)
|
||||
* [sqlc.yaml](https://github.com/coder/coder/tree/main/coderd/database/sqlc.yaml): defines mappings between SQL types and custom Go structures
|
||||
* [codersdk](https://github.com/coder/coder/tree/main/codersdk): user-facing API entities used by CLI and site to communicate with `coderd` endpoints
|
||||
* [dogfood](https://github.com/coder/coder/tree/main/dogfood): Terraform definition of the dogfood cluster deployment
|
||||
* [enterprise](https://github.com/coder/coder/tree/main/enterprise): enterprise-only features, notice similar file structure to repository root (`audit`, `cli`, `cmd`, `coderd`, etc.)
|
||||
* [coderd](https://github.com/coder/coder/tree/main/enterprise/coderd)
|
||||
* [prebuilds](https://github.com/coder/coder/tree/main/enterprise/coderd/prebuilds): core logic of prebuilt workspaces - reconciliation loop
|
||||
* [provisioner](https://github.com/coder/coder/tree/main/provisioner): supported implementation of provisioners, Terraform and "echo" (for testing purposes)
|
||||
* [provisionerd](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/pty): terminal emulation for agent shell
|
||||
* [support](https://github.com/coder/coder/tree/main/support): compile a support bundle with diagnostics
|
||||
* [tailnet](https://github.com/coder/coder/tree/main/tailnet): core logic of Tailnet controller to maintain DERP maps, coordinate connections with agents and peers
|
||||
* [vpn](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/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](https://github.com/coder/coder/tree/main/coderd/coderdtest/oidctest) can start a fake OIDC provider
|
||||
|
||||
### [testutil](https://github.com/coder/coder/tree/main/testutil)
|
||||
|
||||
* General-purpose testing utilities, including:
|
||||
* [chan.go](https://github.com/coder/coder/blob/main/testutil/chan.go): helpers for sending/receiving objects from channels (`TrySend`, `RequireReceive`, etc.)
|
||||
* [duration.go](https://github.com/coder/coder/blob/main/testutil/duration.go): set timeouts for test execution
|
||||
* [eventually.go](https://github.com/coder/coder/blob/main/testutil/eventually.go): repeatedly poll for a condition using a ticker
|
||||
* [port.go](https://github.com/coder/coder/blob/main/testutil/port.go): select a free random port
|
||||
* [prometheus.go](https://github.com/coder/coder/blob/main/testutil/prometheus.go): validate Prometheus metrics with expected values
|
||||
* [pty.go](https://github.com/coder/coder/blob/main/testutil/pty.go): read output from a terminal until a condition is met
|
||||
|
||||
### [dbtestutil](https://github.com/coder/coder/tree/main/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:
|
||||
|
||||
```shell
|
||||
./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:
|
||||
|
||||
```shell
|
||||
./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.
|
||||
|
||||
```shell
|
||||
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:
|
||||
|
||||
```shell
|
||||
git ls-files v0.12.2 -- coderd/database/migrations/*.up.sql
|
||||
```
|
||||
|
||||
This helps in naming the dump (e.g. `000069` above).
|
||||
@@ -0,0 +1,149 @@
|
||||
# Documentation
|
||||
|
||||
This style guide is primarily for use with authoring documentation.
|
||||
|
||||
## General guidelines
|
||||
|
||||
- Use sentence case, even in titles (do not punctuate the title, though)
|
||||
- Use the second person
|
||||
- Use the active voice
|
||||
- Use plural nouns and pronouns (_they_, _their_, or _them_), especially when
|
||||
the specific number is uncertain (i.e., "Set up your environments" even though
|
||||
you don't know if the user will have one or many environments)
|
||||
- When writing documentation titles, use the noun form, not the gerund form
|
||||
(e.g., "Environment Management" instead of "Managing Environments")
|
||||
- Context matters when you decide whether to capitalize something or not. For
|
||||
example,
|
||||
["A Job creates one or more Pods..."](https://kubernetes.io/docs/concepts/workloads/controllers/job/)
|
||||
is correct when writing about Kubernetes. However, in other contexts, neither
|
||||
_job_ nor _pods_ would be capitalized. Please follow the conventions set forth
|
||||
by the relevant companies and open source communities.
|
||||
|
||||
## Third-party references
|
||||
|
||||
If you have questions that aren't explicitly covered by this guide, consult the
|
||||
following third-party references:
|
||||
|
||||
| **Type of guidance** | **Third-party reference** |
|
||||
|----------------------|----------------------------------------------------------------------------------------|
|
||||
| Spelling | [Merriam-Webster.com](https://www.merriam-webster.com/) |
|
||||
| Style - nontechnical | [The Chicago Manual of Style](https://www.chicagomanualofstyle.org/home.html) |
|
||||
| Style - technical | [Microsoft Writing Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/) |
|
||||
|
||||
## Tools
|
||||
|
||||
The following are tools that you can use to edit your writing. However, take the
|
||||
suggestions provided with a grain of salt.
|
||||
|
||||
- [alex.js](https://alexjs.com/)
|
||||
- [Grammarly](https://app.grammarly.com/)
|
||||
- [Hemingway Editor](https://hemingwayapp.com/)
|
||||
|
||||
## How to format text
|
||||
|
||||
Below summarizes the text-formatting conventions you should follow.
|
||||
|
||||
### Bold
|
||||
|
||||
Use **bold** formatting when referring to UI elements.
|
||||
|
||||
### Italics
|
||||
|
||||
Use _italics_ for:
|
||||
|
||||
- Parameter names
|
||||
- Mathematical and version variables
|
||||
|
||||
### Code font
|
||||
|
||||
Use _code font_ for:
|
||||
|
||||
- User text input
|
||||
- Command-line utility names
|
||||
- DNS record types
|
||||
- Environment variable names (e.g., `PATH`)
|
||||
- Filenames, filename extensions, and paths
|
||||
- Folders and directories
|
||||
- HTTP verbs, status codes, and content-type values
|
||||
- Placeholder variables
|
||||
|
||||
Use _code blocks_ for code samples and other blocks of code. Be sure to indicate
|
||||
the language your using to apply the proper syntax highlighting.
|
||||
|
||||
```text
|
||||
This is a codeblock.
|
||||
```
|
||||
|
||||
For code that you want users to enter via a command-line interface, use
|
||||
`console`, not `bash`.
|
||||
|
||||
### Punctuation
|
||||
|
||||
Do not use the ampersand (&) as a shorthand for _and_ unless you're referring to
|
||||
a UI element or the name of something that uses _&_.
|
||||
|
||||
You can use the symbol `~` in place of the word _approximately_.
|
||||
|
||||
### UI elements
|
||||
|
||||
When referring to UI elements, including the names for buttons, menus, dialogs,
|
||||
and anything that has a name visible to the user, use bold font.
|
||||
|
||||
**Example:** On the **Environment Overview** page, click **Configure SSH**.
|
||||
|
||||
Don't use code font for UI elements unless it is rendered based on previously
|
||||
entered text. For example, if you tell the user to provide the environment name
|
||||
as `myEnvironment`, then use both bold and cold font when referring to the name.
|
||||
|
||||
**Example**: Click **`myEnvironment`**.
|
||||
|
||||
When writing out instructions that involve UI elements, both of the following
|
||||
options are acceptable:
|
||||
|
||||
- Go to **Manage** > **Users**.
|
||||
- In the **Manage** menu, click **Users**.
|
||||
|
||||
## Product-specific references
|
||||
|
||||
Below summarizes the guidelines regarding how Coder terms should be used.
|
||||
|
||||
### Capitalized terms
|
||||
|
||||
The only Coder-specific terms that should be capitalized are the names of
|
||||
products (e.g., Coder).
|
||||
|
||||
The exception is **code-server**, which is always lowercase. If it appears at
|
||||
the beginning of the sentence, rewrite the sentence to avoid this usage.
|
||||
|
||||
### Uncapitalized terms
|
||||
|
||||
In general, we do not capitalize the names of features (unless the situation
|
||||
calls for it, such as the word appearing at the beginning of a sentence):
|
||||
|
||||
- account dormancy
|
||||
- audit logs
|
||||
- autostart
|
||||
- command-line interface
|
||||
- dev URLs
|
||||
- environment
|
||||
- image
|
||||
- metrics
|
||||
- organizations
|
||||
- progressive web app
|
||||
- registries
|
||||
- single sign-on
|
||||
- telemetry
|
||||
- workspace
|
||||
- workspace providers
|
||||
- workspaces as code
|
||||
|
||||
We also do not capitalize the names of user roles:
|
||||
|
||||
- auditor
|
||||
- member
|
||||
- site admin
|
||||
- site manager
|
||||
|
||||
## Standardized spellings
|
||||
|
||||
- WiFi
|
||||
@@ -0,0 +1,378 @@
|
||||
# Frontend
|
||||
|
||||
Welcome to the guide for contributing to the Coder frontend. Whether you’re part
|
||||
of the community or a Coder team member, this documentation will help you get
|
||||
started.
|
||||
|
||||
If you have any questions, feel free to reach out on our
|
||||
[Discord server](https://discord.com/invite/coder), and we’ll be happy to assist
|
||||
you.
|
||||
|
||||
## Running the UI
|
||||
|
||||
You can run the UI and access the Coder dashboard in two ways:
|
||||
|
||||
1. Build the UI pointing to an external Coder server:
|
||||
`CODER_HOST=https://mycoder.com pnpm dev` inside of the `site` folder. This
|
||||
is helpful when you are building something in the UI and already have the
|
||||
data on your deployed server.
|
||||
2. Build the entire Coder server + UI locally: `./scripts/develop.sh` in the
|
||||
root folder. This is useful for contributing to features that are not
|
||||
deployed yet or that involve both the frontend and backend.
|
||||
|
||||
In both cases, you can access the dashboard on `http://localhost:8080`. If using
|
||||
`./scripts/develop.sh` you can log in with the default credentials.
|
||||
|
||||
> [!NOTE]
|
||||
> **Default Credentials:** `admin@coder.com` and `SomeSecurePassword!`.
|
||||
|
||||
## Tech Stack Overview
|
||||
|
||||
All our dependencies are described in `site/package.json`, but the following are
|
||||
the most important.
|
||||
|
||||
- [React](https://reactjs.org/) for the UI framework
|
||||
- [Typescript](https://www.typescriptlang.org/) to keep our sanity
|
||||
- [Vite](https://vitejs.dev/) to build the project
|
||||
- [Material V5](https://mui.com/material-ui/getting-started/) for UI components
|
||||
- [react-router](https://reactrouter.com/en/main) for routing
|
||||
- [TanStack Query v4](https://tanstack.com/query/v4/docs/react/overview) for
|
||||
fetching data
|
||||
- [axios](https://github.com/axios/axios) as fetching lib
|
||||
- [Playwright](https://playwright.dev/) for end-to-end (E2E) testing
|
||||
- [Jest](https://jestjs.io/) for integration testing
|
||||
- [Storybook](https://storybook.js.org/) and
|
||||
[Chromatic](https://www.chromatic.com/) for visual testing
|
||||
- [PNPM](https://pnpm.io/) as the package manager
|
||||
|
||||
## Structure
|
||||
|
||||
All UI-related code is in the `site` folder. Key directories include:
|
||||
|
||||
- **e2e** - End-to-end (E2E) tests
|
||||
- **src** - Source code
|
||||
- **mocks** - [Manual mocks](https://jestjs.io/docs/manual-mocks) used by Jest
|
||||
- **@types** - Custom types for dependencies that don't have defined types
|
||||
(largely code that has no server-side equivalent)
|
||||
- **api** - API function calls and types
|
||||
- **queries** - react-query queries and mutations
|
||||
- **components** - Reusable UI components without Coder specific business
|
||||
logic
|
||||
- **hooks** - Custom React hooks
|
||||
- **modules** - Coder-specific UI components
|
||||
- **pages** - Page-level components
|
||||
- **testHelpers** - Helper functions for integration testing
|
||||
- **theme** - theme configuration and color definitions
|
||||
- **util** - Helper functions that can be used across the application
|
||||
- **static** - Static assets like images, fonts, icons, etc
|
||||
|
||||
## Routing
|
||||
|
||||
We use [react-router](https://reactrouter.com/en/main) as our routing engine.
|
||||
|
||||
- Authenticated routes - Place routes requiring authentication inside the
|
||||
`<RequireAuth>` route. The `RequireAuth` component handles all the
|
||||
authentication logic for the routes.
|
||||
- Dashboard routes - routes that live in the dashboard should be placed under
|
||||
the `<DashboardLayout>` route. The `DashboardLayout` adds a navbar and passes
|
||||
down common dashboard data.
|
||||
|
||||
## Pages
|
||||
|
||||
Page components are the top-level components of the app and reside in the
|
||||
`src/pages` folder. Each page should have its own folder to group relevant
|
||||
views, tests, and utility functions. The page component fetches necessary data
|
||||
and passes to the view. We explain this decision a bit better in the next
|
||||
section which talks about where to fetch data.
|
||||
|
||||
If code within a page becomes reusable across other parts of the app,
|
||||
consider moving it to `src/utils`, `hooks`, `components`, or `modules`.
|
||||
|
||||
### Handling States
|
||||
|
||||
A page typically has three states: **loading**, **ready**/**success**, and
|
||||
**error**. Ensure you manage these states when developing pages. Use visual
|
||||
tests for these states with `*.stories.ts` files.
|
||||
|
||||
## Data Fetching
|
||||
|
||||
We use [TanStack Query v4](https://tanstack.com/query/v4/docs/react/quick-start)
|
||||
to fetch data from the API. Queries and mutation should be placed in the
|
||||
api/queries folder.
|
||||
|
||||
### Where to fetch data
|
||||
|
||||
In the past, our approach involved creating separate components for page and
|
||||
view, where the page component served as a container responsible for fetching
|
||||
data and passing it down to the view.
|
||||
|
||||
For instance, when developing a page to display users, we would have a
|
||||
`UsersPage` component with a corresponding `UsersPageView`. The `UsersPage`
|
||||
would handle API calls, while the `UsersPageView` managed the presentational
|
||||
logic.
|
||||
|
||||
Over time, however, we encountered challenges with this approach, particularly
|
||||
in terms of excessive props drilling. To address this, we opted to fetch data in
|
||||
proximity to its usage. Taking the example of displaying users, in the past, if
|
||||
we were creating a header component for that page, we would have needed to fetch
|
||||
the data in the page component and pass it down through the hierarchy
|
||||
(`UsersPage -> UsersPageView -> UsersHeader`). Now, with libraries such as
|
||||
`react-query`, data fetching can be performed directly in the `UsersHeader`
|
||||
component, allowing UI elements to declare and consume their data-fetching
|
||||
dependencies directly, while preventing duplicate server requests
|
||||
([more info](https://github.com/TanStack/query/discussions/608#discussioncomment-29735)).
|
||||
|
||||
To simplify visual testing of scenarios where components are responsible for
|
||||
fetching data, you can easily set the queries' value using `parameters.queries`
|
||||
within the component's story.
|
||||
|
||||
```tsx
|
||||
export const WithQuota: Story = {
|
||||
parameters: {
|
||||
queries: [
|
||||
{
|
||||
key: getWorkspaceQuotaQueryKey(MockUserOwner.username),
|
||||
data: {
|
||||
credits_consumed: 2,
|
||||
budget: 40,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
Our project uses [axios](https://github.com/axios/axios) as the HTTP client for
|
||||
making API requests. The API functions are centralized in `site/src/api/api.ts`.
|
||||
Auto-generated TypeScript types derived from our Go server are located in
|
||||
`site/src/api/typesGenerated.ts`.
|
||||
|
||||
Typically, each API endpoint corresponds to its own `Request` and `Response`
|
||||
types. However, some endpoints require additional parameters for successful
|
||||
execution. Here's an illustrative example:"
|
||||
|
||||
```ts
|
||||
export const getAgentListeningPorts = async (
|
||||
agentID: string,
|
||||
): Promise<TypesGen.ListeningPortsResponse> => {
|
||||
const response = await axiosInstance.get(
|
||||
`/api/v2/workspaceagents/${agentID}/listening-ports`,
|
||||
);
|
||||
return response.data;
|
||||
};
|
||||
```
|
||||
|
||||
Sometimes, a frontend operation can have multiple API calls which can be wrapped
|
||||
as a single function.
|
||||
|
||||
```ts
|
||||
export const updateWorkspaceVersion = async (
|
||||
workspace: TypesGen.Workspace,
|
||||
): Promise<TypesGen.WorkspaceBuild> => {
|
||||
const template = await getTemplate(workspace.template_id);
|
||||
return startWorkspace(workspace.id, template.active_version_id);
|
||||
};
|
||||
```
|
||||
|
||||
## Components and Modules
|
||||
|
||||
Components should be atomic, reusable and free of business logic. Modules are
|
||||
similar to components except that they can be more complex and can contain
|
||||
business logic specific to the product.
|
||||
|
||||
### MUI
|
||||
|
||||
The codebase is currently using MUI v5. Please see the
|
||||
[official documentation](https://mui.com/material-ui/getting-started/). In
|
||||
general, favor building a custom component via MUI instead of plain React/HTML,
|
||||
as MUI's suite of components is thoroughly battle-tested and accessible right
|
||||
out of the box.
|
||||
|
||||
### Structure
|
||||
|
||||
Each component and module gets its own folder. Module folders may group multiple
|
||||
files in a hierarchical structure. Storybook stories and component tests using
|
||||
Storybook interactions are required. By keeping these tidy, the codebase will
|
||||
remain easy to navigate, healthy and maintainable for all contributors.
|
||||
|
||||
### Accessibility
|
||||
|
||||
We strive to keep our UI accessible.
|
||||
|
||||
In general, colors should come from the app theme, but if there is a need to add
|
||||
a custom color, please ensure that the foreground and background have a minimum
|
||||
contrast ratio of 4.5:1 to meet WCAG level AA compliance. WebAIM has
|
||||
[a great tool for checking your colors directly](https://webaim.org/resources/contrastchecker/),
|
||||
but tools like
|
||||
[Dequeue's axe DevTools](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd)
|
||||
can also do automated checks in certain situations.
|
||||
|
||||
When using any kind of input element, always make sure that there is a label
|
||||
associated with that element (the label can be made invisible for aesthetic
|
||||
reasons, but it should always be in the HTML markup). Labels are important for
|
||||
screen-readers; a placeholder text value is not enough for all users.
|
||||
|
||||
When possible, make sure that all image/graphic elements have accompanying text
|
||||
that describes the image. `<img />` elements should have an `alt` text value. In
|
||||
other situations, it might make sense to place invisible, descriptive text
|
||||
inside the component itself using MUI's `visuallyHidden` utility function.
|
||||
|
||||
```tsx
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
|
||||
<Button>
|
||||
<GearIcon />
|
||||
<Box component="span" sx={visuallyHidden}>
|
||||
Settings
|
||||
</Box>
|
||||
</Button>;
|
||||
```
|
||||
|
||||
### Should I create a new component or module?
|
||||
|
||||
Components could technically be used in any codebase and still feel at home. A
|
||||
module would only make sense in the Coder codebase.
|
||||
|
||||
- Component
|
||||
- Simple
|
||||
- Atomic, used in multiple places
|
||||
- Generic, would be useful as a component outside of the Coder product
|
||||
- Good Examples: `Badge`, `Form`, `Timeline`
|
||||
- Module
|
||||
- Simple or Complex
|
||||
- Used in multiple places
|
||||
- Good Examples: `Provisioner`, `DashboardLayout`, `DeploymentBanner`
|
||||
|
||||
Our codebase has some legacy components that are being updated to follow these
|
||||
new conventions, but all new components should follow these guidelines.
|
||||
|
||||
## Styling
|
||||
|
||||
We use [Emotion](https://emotion.sh/) to handle CSS styles.
|
||||
|
||||
## Forms
|
||||
|
||||
We use [Formik](https://formik.org/docs) for forms along with
|
||||
[Yup](https://github.com/jquense/yup) for schema definition and validation.
|
||||
|
||||
## Testing
|
||||
|
||||
We use three types of testing in our app: **End-to-end (E2E)**, **Integration**
|
||||
and **Visual Testing**.
|
||||
|
||||
### End-to-End (E2E)
|
||||
|
||||
These are useful for testing complete flows like "Create a user", "Import
|
||||
template", etc. We use [Playwright](https://playwright.dev/). If you only need
|
||||
to test if the page is being rendered correctly, you should consider using the
|
||||
**Visual Testing** approach.
|
||||
|
||||
For scenarios where you need to be authenticated, you can use
|
||||
`test.use({ storageState: getStatePath("authState") })`.
|
||||
|
||||
For ease of debugging, it's possible to run a Playwright test in headful mode
|
||||
running a Playwright server on your local machine, and executing the test inside
|
||||
your workspace.
|
||||
|
||||
You can either run `scripts/remote_playwright.sh` from `coder/coder` on your
|
||||
local machine, or execute the following command if you don't have the repo
|
||||
available:
|
||||
|
||||
```bash
|
||||
bash <(curl -sSL https://raw.githubusercontent.com/coder/coder/main/scripts/remote_playwright.sh) [workspace]
|
||||
```
|
||||
|
||||
The `scripts/remote_playwright.sh` script will start a Playwright server on your
|
||||
local machine and forward the necessary ports to your workspace. At the end of
|
||||
the script, you will land _inside_ your workspace with environment variables set
|
||||
so you can simply execute the test (`pnpm run playwright:test`).
|
||||
|
||||
### Integration
|
||||
|
||||
Test user interactions like "Click in a button shows a dialog", "Submit the form
|
||||
sends the correct data", etc. For this, we use [Jest](https://jestjs.io/) and
|
||||
[react-testing-library](https://testing-library.com/docs/react-testing-library/intro/).
|
||||
If the test involves routing checks like redirects or maybe checking the info on
|
||||
another page, you should probably consider using the **E2E** approach.
|
||||
|
||||
### Visual testing
|
||||
|
||||
We use visual tests to test components without user interaction like testing if
|
||||
a page/component is rendered correctly depending on some parameters, if a button
|
||||
is showing a spinner, if `loading` props are passed correctly, etc. This should
|
||||
always be your first option since it is way easier to maintain. For this, we use
|
||||
[Storybook](https://storybook.js.org/) and
|
||||
[Chromatic](https://www.chromatic.com/).
|
||||
|
||||
To learn more about testing components that fetch API data, refer to the
|
||||
[**Where to fetch data**](#where-to-fetch-data) section.
|
||||
|
||||
### What should I test?
|
||||
|
||||
Choosing what to test is not always easy since there are a lot of flows and a
|
||||
lot of things can happen but these are a few indicators that can help you with
|
||||
that:
|
||||
|
||||
- Things that can block the user
|
||||
- Reported bugs
|
||||
- Regression issues
|
||||
|
||||
### Tests getting too slow
|
||||
|
||||
You may have observed that certain tests in our suite can be notably
|
||||
time-consuming. Sometimes it is because the test itself is complex and sometimes
|
||||
it is because of how the test is querying elements.
|
||||
|
||||
#### Using `ByRole` queries
|
||||
|
||||
One thing we figured out that was slowing down our tests was the use of `ByRole`
|
||||
queries because of how it calculates the role attribute for every element on the
|
||||
`screen`. You can read more about it on the links below:
|
||||
|
||||
- <https://stackoverflow.com/questions/69711888/react-testing-library-getbyrole-is-performing-extremely-slowly>
|
||||
- <https://github.com/testing-library/dom-testing-library/issues/552#issuecomment-625172052>
|
||||
|
||||
Even with `ByRole` having performance issues we still want to use it but for
|
||||
that, we have to scope the "querying" area by using the `within` command. So
|
||||
instead of using `screen.getByRole("button")` directly we could do
|
||||
`within(form).getByRole("button")`.
|
||||
|
||||
❌ Not ideal. If the screen has a hundred or thousand elements it can be VERY
|
||||
slow.
|
||||
|
||||
```tsx
|
||||
user.click(screen.getByRole("button"));
|
||||
```
|
||||
|
||||
✅ Better. We can limit the number of elements we are querying.
|
||||
|
||||
```tsx
|
||||
const form = screen.getByTestId("form");
|
||||
user.click(within(form).getByRole("button"));
|
||||
```
|
||||
|
||||
❌ Does not work
|
||||
|
||||
```ts
|
||||
import { getUpdateCheck } from "api/api"
|
||||
|
||||
createMachine({ ... }, {
|
||||
services: {
|
||||
getUpdateCheck,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
✅ It works
|
||||
|
||||
```ts
|
||||
import { getUpdateCheck } from "api/api"
|
||||
|
||||
createMachine({ ... }, {
|
||||
services: {
|
||||
getUpdateCheck: () => getUpdateCheck(),
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
# Screenshots
|
||||
|
||||
## Log in
|
||||
|
||||

|
||||
|
||||
Install Coder in your cloud or air-gapped on-premises. Developers simply log in
|
||||
via their browser to access their Workspaces.
|
||||
|
||||
## Templates
|
||||
|
||||

|
||||
|
||||
Developers provision their own ephemeral Workspaces in minutes using pre-defined
|
||||
Templates that include approved tooling and infrastructure.
|
||||
|
||||

|
||||
|
||||
Template administrators can either create a new Template from scratch or choose
|
||||
a Starter Template.
|
||||
|
||||

|
||||
|
||||
Template administrators build Templates using Terraform. Templates define the
|
||||
underlying infrastructure that Coder Workspaces run on.
|
||||
|
||||
## Workspaces
|
||||
|
||||

|
||||
|
||||
Developers create and delete their own workspaces. Coder administrators can
|
||||
easily enforce Workspace scheduling and autostop policies to ensure idle
|
||||
Workspaces don’t burn unnecessary cloud budget.
|
||||
|
||||

|
||||
|
||||
Developers launch their favorite web-based or desktop IDE, browse files, or
|
||||
access their Workspace’s Terminal.
|
||||
|
||||
## Administration
|
||||
|
||||

|
||||
|
||||
Coder administrators can access Template usage insights to understand which
|
||||
Templates are most popular and how well they perform for developers.
|
||||
|
||||

|
||||
|
||||
Coder administrators can control *every* aspect of their Coder deployment.
|
||||
|
||||

|
||||
|
||||
Coder administrators and auditor roles can review how users are interacting with
|
||||
their Coder Workspaces and Templates.
|
||||
|
||||

|
||||
|
||||
Coder administrators can monitor the health of their Coder deployment, including
|
||||
database latency, active provisioners, and more.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Why use Coder
|
||||
|
||||
TODO: Make this page!
|
||||
Reference in New Issue
Block a user