Skip the test gate on docs-only branches #34
+22
-1
@@ -8,7 +8,28 @@ jobs:
|
||||
runs-on: docker-host
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- run: bash ci.sh
|
||||
with:
|
||||
fetch-depth: 0 # the merge-base below needs history; checkout defaults to depth 1
|
||||
- name: Detect a docs-only branch
|
||||
id: scope
|
||||
|
lilleman marked this conversation as resolved
Outdated
|
||||
run: |
|
||||
|
lilleman marked this conversation as resolved
Outdated
lilleman
commented
There is a bunch of scripts here in "run". Could this be written in the ci.sh script instead, to make this all testable locally? There is a bunch of scripts here in "run". Could this be written in the ci.sh script instead, to make this all testable locally?
|
||||
git fetch --no-tags --quiet origin +refs/heads/main:refs/remotes/origin/main
|
||||
base=$(git merge-base refs/remotes/origin/main HEAD) \
|
||||
|| { echo 'No merge-base with main - running the gate'; echo 'docs_only=false' >> "$GITHUB_OUTPUT"; exit 0; }
|
||||
changed=$(git diff --name-only "$base" HEAD)
|
||||
printf '%s\n' "$changed"
|
||||
# Skip only when there IS a diff and every path is *.md. An empty diff, an unreadable
|
||||
# range, anything else - fall through to the gate.
|
||||
if [ -n "$changed" ] && ! printf '%s\n' "$changed" | grep -qvE '\.md$'; then
|
||||
echo 'docs_only=true' >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo 'docs_only=false' >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Full gate
|
||||
if: steps.scope.outputs.docs_only != 'true'
|
||||
run: bash ci.sh
|
||||
# Never gated on docs_only: release.yml re-tags this exact image, and ff-only merges make
|
||||
# every branch head a main commit - a main commit without an image is an unreleasable one.
|
||||
- name: Push app image tagged with the commit hash
|
||||
env:
|
||||
IMAGE: gitea.larvit.se/${{ github.repository }}:${{ github.sha }}
|
||||
|
||||
@@ -1173,7 +1173,7 @@ Gitea Actions (`.gitea/workflows/`) runs the pipeline; the test job runs
|
||||
|
||||
| Workflow | Trigger | Does |
|
||||
| --- | --- | --- |
|
||||
| `ci.yml` | push, any branch except `main` | the full gate (`bash ci.sh`), then build + push the app image |
|
||||
| `ci.yml` | push, any branch except `main` | the full gate (`bash ci.sh`) — skipped on a docs-only branch — then build + push the app image |
|
||||
| `release.yml` | push of a `vX.Y.Z` tag | re-tag that commit's image as `X.Y.Z`, `X.Y`, `X`, `latest`; sync those tags to Docker Hub |
|
||||
| `mirror.yml` | push to `main` or any tag, or manual | force-push `main` + tags to the [GitHub mirror](https://github.com/larvit/plainpages) |
|
||||
| `registry-cleanup.yml` | nightly cron, or manual | delete registry images that are neither release-tagged nor a branch head |
|
||||
@@ -1188,6 +1188,12 @@ no repo files involved): direct pushes are blocked, changes land via PR only, th
|
||||
**fast-forward-only** — history stays linear and `main`'s head is the exact commit hash of
|
||||
the merged branch, which is why the branch's push-triggered status carries over.
|
||||
|
||||
**Docs-only branches skip the gate** — when every path a branch changes against its merge-base
|
||||
with `main` ends in `.md`, `ci.yml` skips `bash ci.sh`. The job itself still runs and still
|
||||
builds + pushes the commit-hash image, so `CI / full-gate (push)` reports green and neither the
|
||||
merge gate nor `release.yml` notices the difference. Everything else in a diff — code, compose,
|
||||
Ory config, the workflows themselves — runs the full gate, as does an empty or unreadable diff.
|
||||
|
||||
**Container images** — after a green gate, `ci.yml` builds the app image and pushes it to the
|
||||
|
lilleman marked this conversation as resolved
Outdated
lilleman
commented
More of the same as the previous comment. Look through the README to see if there are more stuff like this we can remove that is not relevant for the day to day developer and can be easily found out if you dig into the code. More of the same as the previous comment. Look through the README to see if there are more stuff like this we can remove that is not relevant for the day to day developer and can be easily found out if you dig into the code.
|
||||
Gitea container registry as `gitea.larvit.se/larvit/plainpages:<full commit hash>`. Because
|
||||
merges are fast-forward-only, the image for any `main` commit already exists — it was built
|
||||
@@ -1494,7 +1500,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;
|
||||
.gitea/workflows/ Gitea Actions: ci.yml — the full gate (ci.sh) on every branch push except main, skipped for docs-only branches;
|
||||
mirror.yml — force-sync main + tags to the GitHub mirror; see CI/CD
|
||||
README-dockerhub.md The Docker Hub repository description (docker.io/larvit/plainpages) — pasted into the Docker Hub overview by hand when it changes; see CI/CD
|
||||
```
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Guards the docs-only fast path in .gitea/workflows/ci.yml: a branch that only touches *.md
|
||||
// skips `ci.sh`, but must still publish its commit-hash image — release.yml re-tags that exact
|
||||
// image, and fast-forward-only merges make every branch head a main commit.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
const ci = readFileSync(new URL("../.gitea/workflows/ci.yml", import.meta.url), "utf8");
|
||||
const steps = ci.split("\n - ").slice(1);
|
||||
const step = (needle: string) => {
|
||||
const found = steps.filter((s) => s.includes(needle));
|
||||
assert.equal(found.length, 1, `exactly one step contains ${needle}`);
|
||||
return found[0]!;
|
||||
};
|
||||
|
||||
test("checkout is unshallow — the merge-base with main needs the branch's history", () => {
|
||||
assert.match(step("actions/checkout"), /fetch-depth: 0/);
|
||||
});
|
||||
|
||||
test("a docs-only branch skips the test gate", () => {
|
||||
assert.match(step("bash ci.sh"), /if: steps\.scope\.outputs\.docs_only != 'true'/);
|
||||
});
|
||||
|
||||
test("a docs-only branch still pushes its commit-hash image", () => {
|
||||
assert.doesNotMatch(step("docker push"), /^\s*if:/m);
|
||||
});
|
||||
|
||||
test("only *.md counts as docs, and anything unexpected runs the gate", () => {
|
||||
const detect = step("docs_only=");
|
||||
assert.ok(detect.includes("\\.md$"), "the non-docs match is a *.md suffix test");
|
||||
assert.ok(detect.includes("docs_only=false"), "the fallback is the full gate, never a skip");
|
||||
});
|
||||
Reference in New Issue
Block a user
Remove this comment, it is the inner workings of ci.sh and should be obvious if you read the shell scripts code. It is also not very important to know when you are day to day developing.