Thanks for your interest in contributing! Whether it's a bug fix, new feature, documentation improvement, or something else — all contributions are welcome.
Questions or ideas? Start a GitHub Discussion or open an issue.
-
Fork the repository and clone your fork.
-
Use Node.js 24+ (required for local development and tests):
nvm use || nvm install -
Install dependencies — each workspace manages its own:
cd app && npm install cd ui && npm install cd e2e && npm install
-
Create a branch from the appropriate base:
- Bug fixes for the current release: branch from
main - New features targeting the next release: branch from the active feature branch (check open branches for the current one)
- Bug fixes for the current release: branch from
npm run build # TypeScript compilation (tsc)
npm test # Vitest with coverage (100% thresholds enforced)
npx vitest run path/to/file.test.ts # Run a single test filenpm run build # Vite production build
npm run test:unit # Vitest with coverage (100% thresholds enforced)
npm run serve # Dev server on port 8080 (proxies API to backend)docker build -t drydock:dev .
docker compose -f test/qa-compose.yml up -d # Starts on port 3333- Language: TypeScript (ESM,
NodeNextmodule resolution) - Linter/formatter: Biome — direct devDependency in the root workspace. Qlty runs all other linters (actionlint, shellcheck, trivy, etc.)
- Line width: 100
- Quotes: single quotes
- No transpiler: the project compiles with
tscdirectly
Run from any workspace:
npm run lint # biome check .
npm run lint:fix # biome check --fix .
npm run format # biome format --write .Or check everything from the repo root:
qlty check --all --no-progressWe use Gitmoji + Conventional Commits:
<emoji> <type>(<scope>): <description>
| Emoji | Type | Use |
|---|---|---|
| ✨ | feat |
New feature |
| 🐛 | fix |
Bug fix |
| 📝 | docs |
Documentation |
| 💄 | style |
UI/cosmetic changes |
| ♻️ | refactor |
Code refactor (no feature/fix) |
| ⚡ | perf |
Performance improvement |
| ✅ | test |
Adding/updating tests |
| 🔧 | chore |
Build, config, tooling |
| 🔒 | security |
Security fix |
| ⬆️ | deps |
Dependency upgrade |
| 🗑️ | revert |
Revert a previous commit |
Scope is optional. Subject line should be imperative, lowercase, no trailing period.
✨ feat(docker): add health check endpoint
🐛 fix: resolve socket EACCES (#38)
♻️ refactor(store): simplify collection init
-
Framework: Vitest with globals enabled — no need to import
describe,test,expect, orvi -
Coverage: 100% thresholds enforced for both
app/andui/— new features and bug fixes must include tests -
Shared helpers:
app/test/helpers.tsandapp/test/mock-constructor.ts -
Logger mock pattern (used in most backend tests):
vi.mock('../../log/index.js', () => ({ default: { child: () => ({ info: vi.fn(), warn: vi.fn(), debug: vi.fn(), error: vi.fn() }) }, }));
-
Mock hoisting constraint:
vi.mock()factory callbacks are hoisted above all imports. You cannot reference imported helpers inside them — only values fromvi.hoisted()in the same file. Shared helpers can be used in test bodies andbeforeEach, but not inside mock factories.
Lefthook runs a piped (sequential, fail-fast) pipeline on every git push:
| Step | What it does |
|---|---|
ts-nocheck |
Rejects any @ts-nocheck directives |
biome |
Biome lint and format check |
qlty |
Full qlty lint pass (qlty check --all) |
build-and-test |
Parallel build + test for both app/ and ui/ |
e2e |
Cucumber E2E tests against a fresh Drydock instance |
zizmor |
GitHub Actions workflow linting (advisory, skipped if not installed) |
snyk-deps |
Dependency vulnerability scan (skipped if Snyk not installed) |
snyk-code |
Static analysis security scan (skipped if Snyk not installed) |
If lefthook passes locally, CI will pass. Fix any issues before pushing.
Documentation lives in content/docs/ (MDX format, versioned by release) and is published to drydock.codeswhat.com. When your code change affects user-facing behavior, include the corresponding documentation update in the same PR.
CHANGELOG and README updates should accompany each logical change — don't batch them separately.
- Target branch:
mainfor bug fixes on the current release; the active feature branch for new features - Keep commits focused and atomic — one concern per commit
- Ensure all pre-push checks pass before opening a PR
- Include tests for new functionality and bug fixes
- Update documentation when changing user-facing behavior
Open a GitHub Issue with steps to reproduce.
Do not open a public issue. See SECURITY.md for responsible disclosure instructions.
By contributing, you agree that your contributions will be licensed under the GNU Affero General Public License v3.0.