advanced pipeline
ci/woodpecker/push/deploy Pipeline was successful
ci/woodpecker/push/warp_engine Pipeline was successful

This commit is contained in:
2026-08-25 23:50:11 +02:00
parent 259de781bb
commit a58e91520e
42 changed files with 403 additions and 60 deletions
+75 -3
View File
@@ -106,11 +106,14 @@ JSON contract baselines for `/api/software` and `/api/builds` live in
### Backend (RuboCop)
```bash
docker compose run --rm --no-deps api bundle exec rubocop # check
docker compose run --rm --no-deps api bundle exec rubocop -A # autofix
docker compose run --rm --no-deps api bundle exec rubocop # host app
docker compose run --rm --no-deps api bundle exec rubocop -A # host app, autofix
docker exec -w /libs/ruby/warp_engine api \
env BUNDLE_GEMFILE=/app/Gemfile bundle exec rubocop # engine
```
Config: `apps/api/.rubocop.yml` (rubocop-rails-omakase preset)
Config: `apps/api/.rubocop.yml` and `libs/ruby/warp_engine/.rubocop.yml`
(both rubocop-rails-omakase). Both are green, and CI keeps them that way.
### Frontend (ESLint)
@@ -120,3 +123,72 @@ docker compose run --rm --no-deps frontend npm run lint:fix # autofix
```
Config: `apps/frontend/eslint.config.js` (ESLint 9 flat config, Vue + TypeScript)
## Pipelines
Woodpecker reads every file in `.woodpecker/` as its own workflow, each with its
own trigger.
### `.woodpecker/warp_engine.yaml` — the gem
Runs when a push to master touches `libs/ruby/warp_engine/**`, on a manual run,
and on a `warp_engine-v*` tag:
| Step | What it guards |
|---|---|
| `version-bumped` | the engine changed but `WarpEngine::VERSION` did not — fails first, before anything else runs |
| `tag-matches-version` | tag events only: `warp_engine-v0.9.1` must find `VERSION = "0.9.1"` |
| `rubocop` | `libs/ruby/warp_engine` against its own `.rubocop.yml` |
| `test-engine` | the engine suite (dummy app, `warp_engine_test` DB) |
| `split-mirror` | pushes the subtree split to `engines/warp_engine` (master pushes only) |
| `publish-gem` | `gem push` to the Forgejo registry (tags only) |
Nothing is mirrored or published until the version check, RuboCop and the suite
have all passed. The mirror repository deliberately has no CI of its own: the
subtree split overwrites it on every run.
### `.woodpecker/deploy.yaml` — the deploy
Runs on every push to master (and manually): `rubocop``test-host` (host
suite + a production-mode `zeitwerk:check`) → `pull``restart`.
The `pull` and `restart` steps reach the server through the host Docker socket
rather than SSH — the `woodpecker-agent` runs in the same stack as `api` and
`frontend`. Two things this depends on:
- The stack directory is bind-mounted **at the same path** it has on the host
(`/srv/stacks/teletype-games`), so the compose file's relative bind mounts
(`./data`, `./apps`) still resolve where they did.
- Woodpecker only allows step volumes on a **trusted** repository: enable
*Trusted → Volumes* in the repo settings (admin only), or the deploy steps
are rejected.
`pull` fails if the server checkout is not on `master` (a detached HEAD would
make the pull look successful while the running code never moves). `restart`
installs dependencies, runs `db:migrate` and only then restarts — and it
touches only `api` and `frontend`: restarting `woodpecker-server` would cut off
the very pipeline doing the deploy.
`db:migrate` in the host app covers the engine too — WarpEngine appends its own
`db/migrate` to the host's migration paths. A failing migration stops the
deploy before the restart, so the old code keeps running.
Secret used by both workflows: `forge_token` — a Forgejo token with
repository read/write and package:write.
## Version bump hook
The engine's version rule is enforced twice, by the same script:
```bash
git config core.hooksPath .githooks # once per clone
```
`.githooks/pre-commit` runs `script/warp_engine_version_check.rb --staged`: a
commit that touches `libs/ruby/warp_engine/**` must also raise
`WarpEngine::VERSION` above the one in `HEAD`. The pipeline runs the same script
in `--range` mode over the pushed commits, so nothing slips through a
`--no-verify`.
Escape hatch when a bump genuinely does not belong:
`SKIP_WARP_ENGINE_VERSION_CHECK=1 git commit ...`