A build definition says when it runs in a trigger block of its own

`onPush`, `atTimes`, `branches`, and `activeWithin` move into a nested
`trigger`. The split is structural on purpose: the inheritance from
`builds.default` now subtracts one key instead of a list of four, so a
selector added to `TriggerConfig` later is non-inheritable by
construction rather than because someone remembered to extend the list.

A definition still writing those keys flat is refused by name, per file
and scoped like the version check — the machine and project config abort
the start, a branch's committed config fails only that branch. Ignoring
them would leave the build with no trigger at all, which is a job that
quietly stops running: the failure this refusal exists to prevent.

Two more things a definition can now say:

- A `!` prefix in `trigger.branches` excludes, and an exclusion wins
  whatever the order. `["*", "!master"]` gives one branch a build of its
  own without the default build running over it as well — until now the
  only way out of that double build was to drop the second definition's
  push trigger.
- `statusContext` overrides the Gitea check this build reports as, empty
  keeping the repository-wide one. Two builds of a commit shared a
  context and overwrote each other's result, so a quick check beside a
  long build was not readable in Gitea. Pinned like `requirePullRequest`:
  a branch that could pick its context could take over the check a branch
  protection rule depends on.

Fixed on the way: a branch whose builds all belong to named definitions
rendered an empty row in the branches view, reading as "never built"
directly beside its real builds. That row was unreachable before the
exclusion patterns made such a branch possible.
This commit is contained in:
mhoennig
2026-08-29 12:05:10 +02:00
parent 0fbb25b47f
commit f0f996a53c
22 changed files with 486 additions and 178 deletions
@@ -7,6 +7,29 @@
<div th:replace="~{fragments :: nav(${view})}"></div>
<div class="panel release-notes">
<h2>v0.9.20 <span class="muted">— 2026-08-29</span></h2>
<ul>
<li>A build definition is now split in two: a <code>trigger</code> block says when the
build runs and for which branches (<code>onPush</code>, <code>atTimes</code>,
<code>branches</code>, <code>activeWithin</code>), everything beside it says what
the build does. Only the second half is inherited from <code>builds.default</code>,
and making that structural means a selector added later cannot become inheritable
by accident. A definition still writing those keys flat is refused by name — a
trigger nobody reads any more is a build that silently stops running.</li>
<li>A branch pattern prefixed with <code>!</code> excludes instead of selecting, and an
exclusion wins whatever the order: <code>branches: ["*", "!master"]</code> is every
branch but master. That lets one branch have a build of its own without being built
by the default one as well — previously the only way to avoid the double build was
to give up the second definition's push trigger.</li>
<li>A build may report under its own Gitea check with <code>statusContext</code>; empty
keeps the repository-wide <code>gitea.statusContext</code>. Two builds of one commit
used to overwrite each other's result there, so a second build over the same branch
— a quick check next to a long one — was not readable in Gitea.</li>
<li><strong>Fixed:</strong> a branch whose builds all belong to named definitions showed
an empty row in the branches view, reading as "never built" right next to its actual
builds.</li>
</ul>
<h2>v0.9.19 <span class="muted">— 2026-08-29</span></h2>
<ul>
<li>A build definition now describes its build completely: <code>requirePullRequest</code>