automerge tailscale + component patch updates behind a PR build
Add .woodpecker/pr-build.yaml: builds all three arches (dry-run, no push) on PRs and pushes to main, reporting status to Gitea. This is the gate for automerge. renovate.json automerge rules (platformAutomerge, merged only after the PR build passes): - tailscale stable patch AND minor - Go/Alpine/busybox PATCH only - base-image digest refreshes Minor/major of build deps and tooling stay manual. Move pinDigests into a dockerfile packageRule (top-level dockerfile.* is deprecated). Document the automerge policy and its caveat (PR build proves build-only, not runtime) in DESIGN.md.
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
# Build validation for pull requests (and pushes to main).
|
||||||
|
#
|
||||||
|
# Builds the full multi-arch image but does NOT push it anywhere — it only
|
||||||
|
# proves the Dockerfile still builds for every supported architecture. This is
|
||||||
|
# the gate Renovate automerge waits on: a dependency bump that breaks the build
|
||||||
|
# fails this check and will NOT be automerged (and therefore never reaches
|
||||||
|
# :stable or the routers).
|
||||||
|
#
|
||||||
|
# Reports pass/fail status back to Gitea, so it shows up as a required check on
|
||||||
|
# the PR.
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: pull_request
|
||||||
|
- event: push
|
||||||
|
branch: main
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Build all arches (no push)
|
||||||
|
image: woodpeckerci/plugin-docker-buildx:5.2.2
|
||||||
|
privileged: true
|
||||||
|
settings:
|
||||||
|
repo: mikrotik-tailscale
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
dry-run: true
|
||||||
|
build_args:
|
||||||
|
- OCI_VERSION=ci-${CI_COMMIT_SHA}
|
||||||
+24
-3
@@ -324,14 +324,35 @@ run **self-hosted** from a Woodpecker cron pipeline (Woodpecker has no native
|
|||||||
Renovate support):
|
Renovate support):
|
||||||
|
|
||||||
- `renovate.json` — repository rules. All dependencies follow the latest
|
- `renovate.json` — repository rules. All dependencies follow the latest
|
||||||
upstream releases (including major versions); each bump arrives as its own PR
|
upstream releases; each bump arrives as its own PR. Base image tags also get
|
||||||
that the multi-arch build validates before you merge. Base image tags also
|
their `@sha256` digests refreshed via `pinDigests`. Notable rules:
|
||||||
get their `@sha256` digests refreshed via `pinDigests`. The one special rule:
|
|
||||||
- `tailscale` only follows **stable** releases — Tailscale uses even minor
|
- `tailscale` only follows **stable** releases — Tailscale uses even minor
|
||||||
versions for stable (`v1.98.x`) and odd for unstable (`v1.99.x`), so the
|
versions for stable (`v1.98.x`) and odd for unstable (`v1.99.x`), so the
|
||||||
rule filters to even minors.
|
rule filters to even minors.
|
||||||
- `.woodpecker/renovate.yaml` — the scheduled job that runs `renovate/renovate`
|
- `.woodpecker/renovate.yaml` — the scheduled job that runs `renovate/renovate`
|
||||||
against this repo.
|
against this repo.
|
||||||
|
- `.woodpecker/pr-build.yaml` — builds all three arches (no push) on every PR
|
||||||
|
and reports status to Gitea. This is the gate for automerge.
|
||||||
|
|
||||||
|
### Automerge policy
|
||||||
|
|
||||||
|
These updates **automerge** once the PR build passes — they reach `:stable`
|
||||||
|
(and the routers) without manual review:
|
||||||
|
|
||||||
|
| Update | Automerge? | Why |
|
||||||
|
|---|---|---|
|
||||||
|
| Tailscale stable (patch **and** minor) | ✅ | the point of the project; the PR build catches breakage |
|
||||||
|
| Go / Alpine / busybox **patch** | ✅ | bugfix-only, build-internal |
|
||||||
|
| Base-image **digest** refresh (same tag) | ✅ | content refresh, no version change |
|
||||||
|
| Go / Alpine / busybox **minor/major** | ❌ manual | larger toolchain/base changes warrant review |
|
||||||
|
| Renovate runner, syntax frontend | ❌ manual | tooling — review deliberately |
|
||||||
|
|
||||||
|
**Important:** automerge depends on the PR build being a **required status
|
||||||
|
check** in Gitea branch protection. The PR build only proves the image *builds*
|
||||||
|
for all arches — it does not run the daemon, so a runtime regression in a new
|
||||||
|
Tailscale release could still be automerged. That is an accepted trade-off for
|
||||||
|
the convenience of unattended Tailscale updates; if a release misbehaves, roll
|
||||||
|
back by re-tagging the previous `v…-mt.N` (the immutable tags are kept).
|
||||||
|
|
||||||
Validate the configs locally:
|
Validate the configs locally:
|
||||||
|
|
||||||
|
|||||||
+27
-3
@@ -7,10 +7,12 @@
|
|||||||
],
|
],
|
||||||
"labels": ["dependencies"],
|
"labels": ["dependencies"],
|
||||||
"rebaseWhen": "behind-base-branch",
|
"rebaseWhen": "behind-base-branch",
|
||||||
"dockerfile": {
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchManagers": ["dockerfile"],
|
||||||
|
"description": "Keep base-image tags pinned to a digest.",
|
||||||
"pinDigests": true
|
"pinDigests": true
|
||||||
},
|
},
|
||||||
"packageRules": [
|
|
||||||
{
|
{
|
||||||
"matchDatasources": ["github-releases"],
|
"matchDatasources": ["github-releases"],
|
||||||
"matchPackageNames": ["tailscale/tailscale"],
|
"matchPackageNames": ["tailscale/tailscale"],
|
||||||
@@ -18,6 +20,28 @@
|
|||||||
"extractVersion": "^v(?<version>\\d+\\.\\d+\\.\\d+)$",
|
"extractVersion": "^v(?<version>\\d+\\.\\d+\\.\\d+)$",
|
||||||
"allowedVersions": "/^\\d+\\.\\d*[02468]\\.\\d+$/",
|
"allowedVersions": "/^\\d+\\.\\d*[02468]\\.\\d+$/",
|
||||||
"ignoreUnstable": true
|
"ignoreUnstable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchDatasources": ["github-releases"],
|
||||||
|
"matchPackageNames": ["tailscale/tailscale"],
|
||||||
|
"description": "Automerge all stable Tailscale releases (patch AND minor) once the PR build passes.",
|
||||||
|
"matchUpdateTypes": ["minor", "patch"],
|
||||||
|
"automerge": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": ["dockerfile"],
|
||||||
|
"matchPackageNames": ["golang", "alpine", "busybox"],
|
||||||
|
"description": "Automerge PATCH-only bumps of build components (Go/Alpine/busybox) once the PR build passes; review minor/major manually.",
|
||||||
|
"matchUpdateTypes": ["patch"],
|
||||||
|
"automerge": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": ["dockerfile"],
|
||||||
|
"matchUpdateTypes": ["digest", "pinDigest"],
|
||||||
|
"description": "Automerge base-image digest refreshes (same tag, new sha256) once the PR build passes.",
|
||||||
|
"automerge": true
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"automergeType": "pr",
|
||||||
|
"platformAutomerge": true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user