Ctrl K
ComunidadGuías…

CONTRIBUTING.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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).