Sign inSign up

flowwrightdev/flowwright

By flowwrightdev

Updated about 2 months ago

Local-first, TypeScript-native pipeline engine — server + worker

Image
Integration & delivery
Developer tools
0

913

flowwrightdev/flowwright repository overview

FlowWright

A local-first, TypeScript-native pipeline engine for building, testing, and shipping.

Swap sprawling, hard-to-test CI YAML for a typed, reusable pipeline.ts that behaves the same on your laptop, in any CI provider, and on this optional team server.

This image contains the control-plane server (API + web UI) and the execution worker. The CLI is distributed separately, on npm as @flowwright/cli.

FlowWright is currently pre-release. The core workflow already works end to end — we're being upfront that APIs may still shift before the first stable release.

Quick start

$ docker run -d -p 4317:4317 -v flowwright-data:/data flowwrightdev/flowwright

Open http://localhost:4317.

Authentication is required by default. On first boot the server creates an administrator and writes a one-time temporary password to <dataDir>/initial-admin-password (mode 0600), also printing it to the log. Set FW_AUTH=disabled only when you explicitly want an open, no-auth development server — it removes the identity boundary entirely and every caller becomes an implicit admin.

Two daemons, one image

The default command runs the server. Override it to run a worker instead:

# server (default)
$ docker run -d -p 4317:4317 -v flowwright-data:/data flowwrightdev/flowwright

# worker — no HTTP server, so the image's healthcheck can't apply to it
$ docker run -d -v flowwright-data:/data --no-healthcheck \
    flowwrightdev/flowwright /app/apps/worker/dist/main.js

Running as non-root

The container runs as uid 1000 (node), not root. A new volume works with no setup — Docker initialises an empty volume from the image, ownership included.

A volume created by an earlier, root-running image needs a one-time chown before you upgrade, or the server exits with unable to open database file:

$ docker compose down                    # or: docker stop <container>
$ docker volume ls                       # compose prefixes it: <project>_data
$ docker run --rm -v flowwright_data:/data alpine chown -R 1000:1000 /data
$ docker compose up -d

For a bind mount, sudo chown -R 1000:1000 ./your-data-dir on the host. If you need to defer the migration, --user 0:0 (or user: "0:0" in compose) restores the old behaviour — set it on the server and every worker, since a root worker plus a non-root server leaves run directories the server can't clean up.

Docker Compose

The published compose.yml runs an enqueue-only server (FW_WORKERS=0) plus a scalable worker pool sharing one data volume:

$ curl -O https://raw.githubusercontent.com/Flow-Wright/FlowWright/main/compose.yml
$ docker compose up -d                    # server + 1 worker
$ docker compose up -d --scale worker=4   # server + 4 workers

Pin a release with FLOWWRIGHT_VERSION=0.1.0 docker compose up -d.

Tags

Built for linux/amd64 and linux/arm64.

TagMovesUse it for
X.Y.Zneverproduction — pin an exact release
X.Ypatch releasesproduction, if you want patches automatically
latestevery releasetrying it out
edgeevery merge to maintesting an unreleased fix
sha-<short>neverreproducing one exact commit

Configuration

VariableDefaultPurpose
PORT / FW_SERVER_PORT4317HTTP listen port
FW_DATA_DIR.flowwrightState, run logs, artifacts, cache, key material
FW_AUTHrequiredrequired or disabled
FW_SECRET_KEYauto-generatedEncrypts stored credentials. Set explicitly, and use the same value on server and workers
FW_WORKERS2In-process concurrency; 0 delegates execution to external workers
FW_CONCURRENCY2Worker concurrency (FW_WORKERS wins if both are set)
FW_WEBHOOK_SECRETHMAC secret for GitHub/GitLab webhook ingestion
FW_DATABASE_URLPostgreSQL URL, for multi-host fleets
FW_ARTIFACTS_S3_BUCKETS3-compatible bucket for shared artifacts
FW_LOG_LEVELinfodebug, info, warn, error
FW_METRICS_TOKENBearer token for scraping /api/metrics
FW_REGISTRATION_MODEclosedopen allows self-service member sign-up
FW_CONFIG_FILE<dataDir>/flowwright.server.yamlConfiguration-as-code path

Full reference: configuration.

Port 4317 · Volume /data — the container's working directory, so the data dir lands at /data/.flowwright.

Treat that volume as sensitive: it holds execution state, logs, artifacts, cache data, and encrypted key material.

Health & monitoring

EndpointAuthPurpose
GET /healthzpublicLiveness / readiness probes
GET /api/healthpublicRicher status (schema version, store check)
GET /api/metricsFW_METRICS_TOKENPrometheus text format

Send SIGTERM for graceful shutdown — traffic, schedulers, GC, and the queue stop before state closes.

Production notes

  • Set FW_SECRET_KEY explicitly from a secret manager, identical across server and workers. If unset, a key is generated onto the data volume, where it sits next to the data it protects.
  • Put the server behind TLS; the app serves plain HTTP on 4317.
  • For more than one host, drop the shared volume: point every server and worker at the same PostgreSQL (FW_DATABASE_URL) and an S3-compatible bucket (FW_ARTIFACTS_S3_BUCKET). No shared filesystem needed.

See the self-hosting guide for fleets, backups, and retention.

License

MIT — see LICENSE.

Tag summary

Content type

Image

Digest

sha256:146fe18ff

Size

134.5 MB

Last updated

about 2 months ago

docker pull flowwrightdev/flowwright