CI: Gitea Actions runs the full gate (ci.sh) on push to any branch except main; document runner setup
CI / full-gate (push) Failing after 0s

This commit is contained in:
2026-07-02 14:24:19 +02:00
parent 8afaeccf2c
commit 94654a2adc
3 changed files with 40 additions and 1 deletions
+11
View File
@@ -0,0 +1,11 @@
name: CI
on:
push:
branches-ignore: [main]
jobs:
full-gate:
runs-on: docker-host
steps:
- uses: actions/checkout@v4.2.2
- run: bash ci.sh
+22
View File
@@ -96,6 +96,7 @@ From here, render real pages against the app shell and fetch upstream data — s
- [Testing](#testing)
- [end-to-end](#end-to-end-playwright)
- [the full gate](#the-full-gate-one-command)
- [CI/CD](#cicd)
- [Production & deployment](#production--deployment)
- [Observability](#observability)
- [JWT signing key & rotation](#jwt-signing-key--rotation)
@@ -1161,6 +1162,26 @@ Each E2E suite **owns a clean stack** — never point two suites at one backend
revokes the admin's sessions; full-flow writes users/groups/roles to Keto), which is why the
gate runs them serially, one stack up/down per suite.
## CI/CD
Gitea Actions (`.gitea/workflows/`) runs the pipeline; the test job runs
[`ci.sh`](#the-full-gate-one-command) — the exact gate you run locally:
| Workflow | Trigger | Does |
| --- | --- | --- |
| `ci.yml` | push, any branch except `main` | the full gate (`bash ci.sh`) |
`main` is not re-tested on push — its commits are meant to arrive already green from a
gated branch, so the status check to gate a merge on is `CI / full-gate (push)`.
**One-time server setup** — register an
[act_runner](https://docs.gitea.com/usage/actions/act-runner) in host mode with the label
`docker-host` (config: `labels: ["docker-host:host"]`) on a machine with Docker Engine +
Compose, git, and Node + github.com access (for `actions/checkout`). Runs must **never
overlap** — the e2e stacks use fixed compose project names and the devstack suite uses host
networking — so register exactly **one** `docker-host` runner, keep its capacity at 1, and
keep host ports 3000/4433 free.
## Production & deployment
```bash
@@ -1375,6 +1396,7 @@ plugins/ Drop-in plugin folders (scanned at /app/plugins; bind-mount
examples/ Copy-in reference material, mirroring the mount dirs: plugins/scheduling/ (the reference plugin — list/form over an upstream + permission-gated nav), plugins/admin/ (the system-admin plugin — Users/Groups/Roles/OAuth2-clients over Ory via ctx.system), both copied into plugins/; and config/menu.ts (the menu/branding template copied into config/); shifts-upstream/ is the dev mock backend the scheduling plugin reads/writes (stand-in for your real service)
e2e-tests/ Playwright E2E: visual.spec (design system, Ory-free) + auth-refresh.spec (token timeout/re-mint) + oauth-login.spec (OAuth2 login + consent) + full-flow.spec (browser UI: password/SSO login, menu-by-role, admin CRUD, plugin page, logout) + devstack-login.spec (regression: login works from the banner's localhost URL and 127.0.0.1 is canonicalised, on the plain `docker compose up` topology); proxy.ts (same-origin gateway) + mock-oidc.ts (mock SSO provider) back full-flow. e2e-tests/Dockerfile + e2e-tests/compose.{visual,auth,oauth,full,devstack}.yml run them
ci.sh The full CI gate: typecheck → unit tests → every E2E suite, each on a fresh, always-torn-down stack (`bash ci.sh`)
.gitea/workflows/ Gitea Actions: ci.yml — the full gate (ci.sh) on every branch push except main; see CI/CD
```
## Extending the core
+7 -1
View File
@@ -5,10 +5,16 @@ For each todo item, interview the user extensively to deeply understand the scop
- [x] The plugins/scheduling is an example and shouldn't be committed to the plugins directory since that should be empty to be able to be mounted in via docker or other means for the users/develoeprs using this application/framework. Put it in the examples folder instead.
- [x] The config folder should be empty and the current settings in the menu.ts should be the fallback default. IF a menu.ts where to appear in that folder, it should override the default settings with whatever is in it. The idea is the folder should be empty by default and you mount it in your docker container with your config.
- [x] Make the internal admin pages for users groups etc into a plugin instead in the examples folder and remove them from the internal source. Add a part in the quick start about copying this plugin into the plugins folder to enable GUI user- and group admining.
- [x] CI/CD - Test on push to any branch except main. (`.gitea/workflows/ci.yml` runs `bash ci.sh`; the one-time act_runner setup it needs is documented in README → CI/CD.)
- [ ] CI/CD - Require PR to main and don't allow merge if tests does not pass. Only allow linear history and history that leaves the last commit hash on main the exact same as on the branch we just merged in.
- [ ] CI/CD - Sync up to github after every successful merge to main, URL: git@github.com:larvit/plainpages.git - also note the true home top of the README. Force push to github, it should only ever be a mirror of the gitea.larvit.se repository.
- [ ] CI/CD - Build docker images as part of the requirements to be able to merge to main. Push them with the git commit hash as docker tag. Push to container registry at Gitea.
- [ ] CI/CD - Re-tag docker images from git hash to semver when a semver git tag is pushed.
- [ ] CI/CD - Require human to make docker hub account - sync docker images to docker hub after each deploy build.
- [ ] CI/CD - Setup renovate bot.
- [ ] Add an e2e test for the admin plugin's OAuth2-clients (Hydra) screen. The full-flow e2e suite runs without Hydra (compose.full.yml), so /admin/clients register/detail/delete is only unit-covered (src/http/app.test.ts); wire Hydra into an e2e stack and drive the screen in the browser.
- [ ] Build and publish docker image as CI/CD.
- [ ] Add i18n support.
- [ ] Set up CI/CD. Tests on push to any branch. Require PR to main and don't allow merge if tests does not pass. Publish docker image on valid semver tag. Sync up to github when merging to main.
## Architectural review findings (2026-07-02)