Skip to content

Commit 1e69b77

Browse files
authored
ci: restore Renovate updates and vulnerability-alert access (#2200)
* ci: restore Renovate updates and vulnerability-alert access The first Renovate run under the config from #2196 surfaced two regressions. `minimumReleaseAge: "7 days"` runs under the default `minimumReleaseAgeBehaviour: timestamp-required`, and the docker datasource derives a release timestamp for Docker Hub images only. Every ghcr.io update is therefore held pending regardless of age: run 31591982463 marked uv 0.12.0 through 0.12.3 and the HA container 2026.8.1 pending with `check: minimumReleaseAge` and no timestamp, and uv 0.12.0 was two weeks old. `timestamp-optional` keeps the age gate wherever a timestamp exists and stops blocking where none does. The same PR narrowed the installation token to four `permission-*` inputs, and a token that names any permission drops the ones it does not name. The run now warns `Cannot access vulnerability alerts` and the dashboard carries a Repository Problems section for it, so the `vulnerabilityAlerts` carve-out added in the same PR cannot fire. Granting `permission-vulnerability-alerts: read` is the first step; if the warning survives, the App installation itself lacks the permission. Both invariants are pinned by structural tests in the supply-chain shape suite. * test: pin the release-age gate itself, not only its behaviour The conditional form passed vacuously if minimumReleaseAge were dropped.
1 parent 7abe094 commit 1e69b77

3 files changed

Lines changed: 34 additions & 0 deletions

File tree

.github/workflows/renovate.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ jobs:
4444
permission-contents: write
4545
permission-issues: write
4646
permission-pull-requests: write
47+
# Without this the vulnerabilityAlerts carve-out in renovate.json is
48+
# dead: an installation token that lists any permission-* input drops
49+
# every permission it does not name, including vulnerability_alerts.
50+
permission-vulnerability-alerts: read
4751
permission-workflows: write
4852

4953
- name: Self-hosted Renovate

renovate.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"after 3pm on tuesday"
99
],
1010
"minimumReleaseAge": "7 days",
11+
"minimumReleaseAgeBehaviour": "timestamp-optional",
1112
"vulnerabilityAlerts": {
1213
"minimumReleaseAge": null
1314
},

tests/src/unit/test_supply_chain_workflow_shape.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Guard supply-chain hardening that cannot be exercised by PR workflows."""
22

3+
import json
34
from pathlib import Path
45
from typing import Any
56

@@ -99,6 +100,34 @@ def test_pr_checkout_guard_follows_reusable_workflows(tmp_path: Path) -> None:
99100
_assert_checkout_credentials_are_not_persisted(caller, tmp_path)
100101

101102

103+
def test_renovate_token_can_read_vulnerability_alerts() -> None:
104+
steps = _workflow(_WORKFLOW_DIR / "renovate.yml")["jobs"]["renovate"]["steps"]
105+
token_step = next(
106+
step
107+
for step in steps
108+
if "actions/create-github-app-token" in str(step.get("uses", ""))
109+
)
110+
111+
assert (token_step["with"]).get("permission-vulnerability-alerts") == "read", (
112+
"the Renovate token lists permission-* inputs and so drops every "
113+
"permission it does not name; without vulnerability_alerts read the "
114+
"vulnerabilityAlerts carve-out in renovate.json cannot fire"
115+
)
116+
117+
118+
def test_renovate_age_gate_tolerates_datasources_without_timestamps() -> None:
119+
config = json.loads((_REPO_ROOT / "renovate.json").read_text(encoding="utf-8"))
120+
121+
assert config.get("minimumReleaseAge") is not None, (
122+
"the release-age gate from #2196 is part of the supply-chain contract"
123+
)
124+
assert config.get("minimumReleaseAgeBehaviour") == "timestamp-optional", (
125+
"ghcr.io tags carry no releaseTimestamp - the docker datasource reads it "
126+
"from Docker Hub only - so minimumReleaseAge under the default "
127+
"timestamp-required behaviour holds every ghcr update pending forever"
128+
)
129+
130+
102131
def test_dev_release_tag_cleanup_uses_authenticated_github_api() -> None:
103132
jobs = _workflow(_WORKFLOW_DIR / "publish-dev.yml")["jobs"]
104133
create_run = next(

0 commit comments

Comments
 (0)