CONTRIBUTING.md
Rama main · réplica de lectura del repositorio original.
# Contributing to Flagraft
Thanks for taking the time. Flagraft is a small, deliberately boring codebase, and
the aim is to keep it that way.
## Getting set up
You need Node 20+, pnpm 10, and Docker (for Postgres).
```sh
pnpm install
docker compose up -d # Postgres on :5432, plus the test database
cp .env.example .env # then set DATABASE_URL and JWT_SECRET
pnpm db:migrate
pnpm dev # API on :3000
pnpm ui:dev # admin UI on :5173
```
`pnpm dev:all` runs both at once.
`JWT_SECRET` must be at least 32 characters or the server refuses to start:
```sh
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
## Running the checks
CI runs these, so run them before opening a pull request:
```sh
pnpm lint # typecheck across all packages, then eslint
pnpm format:check # prettier
pnpm test # server tests, then every package's tests
pnpm build # tsup bundle
```
The integration tests need a second database. `docker compose up` creates it via
`docker/initdb/01-test-db.sql`; point `TEST_DATABASE_URL` at it and run
`pnpm db:migrate` against it once. Tests that need a database skip themselves
when `TEST_DATABASE_URL` is unset, so a bare `pnpm test` passes without ever
telling you it silently skipped half the suite -- check the skip count.
End-to-end tests are Playwright. One command builds the server and the UI,
starts them, runs the suite and shuts the server down again:
```sh
pnpm test:e2e
```
It runs against what ships -- one server on one origin serving both the UI and
the API -- not the Vite dev proxy.
It uses port 3999 rather than 3000, because the e2e server is a throwaway and
3000 is the port most likely to already have something on it. Override with
`E2E_PORT` if 3999 is taken too.
That command rebuilds every time, which is right for a one-off but wasteful when
iterating. Start the server once and leave it up; runs then reuse it and skip the
build entirely (~24s instead of ~45s):
```sh
pnpm e2e:server & # build once, keep it running
npx playwright test # reuses it, no rebuild
```
Rebuild by restarting that server after changing the app.
To run against a server you started yourself, which skips the build:
```sh
E2E_BASE_URL=http://localhost:5173 pnpm test:e2e
```
Useful while iterating: `npx playwright test --headed` to watch it,
`--debug` to step through, `-g "sign out"` for one test, and
`npx playwright show-report` after a failure. Pass `E2E_PORT` the same way.
## Changing the database
Schema lives in `src/db/schema.ts`. After editing it:
```sh
pnpm db:generate # writes a migration into src/db/migrations
pnpm db:migrate # applies it
```
Commit the generated SQL. Never edit a migration that has already been applied --
Drizzle records a hash of each one and will refuse to run against a changed file.
## House style
- **Tests are required.** Every fix and feature lands with one. Non-trivial logic
leaves behind the smallest test that fails if the logic breaks.
- **Comments are the exception.** Default to none. When one is genuinely needed,
it is one line and explains what the code cannot: a library's surprising
behavior, a deliberate trade-off, a branch that looks wrong but isn't. Use
JSDoc `/** ... */`, never `//` for multiple lines.
- **Document what a user can see.** A new environment variable, config value or
behavior change belongs in the README config table and `.env.example`, not one
of the two.
- Prettier and ESLint decide formatting arguments. Run `pnpm format`.
## Pull requests
Keep them focused -- one concern per PR. Describe what changes for someone
running Flagraft, not just what you edited. If you changed behavior, say so in
`CHANGELOG.md` under `[Unreleased]`.
Flagraft is pre-1.0 and the roadmap ([docs/ROADMAP.md](docs/ROADMAP.md)) says what
is planned and what is deliberately not. Worth a look before building something
large -- it may already be a decided "no", and that is nothing personal.
## Releasing
Releases are cut by hand; there is no publish workflow. The SDK is the only
published artifact.
```sh
pnpm --filter @flagraft/sdk typecheck
pnpm --filter @flagraft/sdk test
pnpm --filter @flagraft/sdk build
cd packages/sdk-js
npm publish --dry-run --tag alpha --access public # read the file list first
npm publish --tag alpha --access public
```
Two rules the tooling will not enforce for you:
- **A prerelease never goes out as `latest`.** While the version carries a
`-alpha.N` suffix it publishes under `--tag alpha`, so `npm i @flagraft/sdk`
resolves to nothing and only `@flagraft/sdk@alpha` installs. Drop the suffix
and switch to `--tag latest` in the same change, never separately.
- **`--access public` every time.** `@flagraft/sdk` is scoped, and scoped
packages default to restricted. `publishConfig` in `package.json` sets it too;
the flag is belt and braces.
Publishing cannot be undone after 72 hours, so the dry run is worth the extra
minute. `--provenance` is deliberately absent: it needs a CI environment with
OIDC and fails from a laptop.
Then tag the repo and write the release notes from `CHANGELOG.md`:
```sh
git tag v0.1.0-alpha.0 && git push origin v0.1.0-alpha.0
```
## Reporting bugs and asking for features
Use the issue templates. For anything security related, do **not** open an issue
-- see [SECURITY.md](SECURITY.md).