mirror of
https://github.com/gmeligio/flutter-docker-image.git
synced 2026-05-24 12:30:34 +00:00
feat(renovate): manage GitHub Actions through gx.toml (#441)
- Reconfigures Mend Renovate to manage GitHub Action versions exclusively through `.github/gx.toml` instead of editing workflow files directly - Disables Renovate's built-in `github-actions` manager; adds a custom regex manager reading specifiers from `gx.toml` with `github-tags` datasource and `npm` versioning (so `^6` and `~0.3.0` are honored) - Moves the monthly schedule (`* 0-3 1 * *`) to a rule scoped to `.github/gx.toml`; the existing `gx.yml` tidy job propagates Renovate's manifest edits to `gx.lock` and workflow files on the PR branch - Syncs the updated `actions-version-tracking` spec into `openspec/specs/` --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+19
-9
@@ -9,22 +9,32 @@
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Schedule Github Actions updates on the first day of the month",
|
||||
"description": "Disable Renovate's built-in github-actions manager — gx owns workflow and composite-action files",
|
||||
"matchManagers": ["github-actions"],
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"description": "Schedule gx.toml-driven action major upgrades on the first day of the month",
|
||||
"matchFileNames": [".github/gx.toml"],
|
||||
"groupName": "github-actions",
|
||||
"matchDatasources": [
|
||||
"github-tags"
|
||||
],
|
||||
"schedule": [
|
||||
"* 0-3 1 * *"
|
||||
]
|
||||
"schedule": ["* 0-3 1 * *"]
|
||||
}
|
||||
],
|
||||
"customManagers": [
|
||||
{
|
||||
"customType": "regex",
|
||||
"fileMatch": [
|
||||
"^Dockerfile$"
|
||||
"description": "Read GitHub Action specifiers from gx.toml",
|
||||
"managerFilePatterns": ["/^\\.github/gx\\.toml$/"],
|
||||
"matchStrings": [
|
||||
"\"(?<depName>(?<packageName>[^/\"]+/[^/\"]+)(?:/[^\"]+)?)\"\\s*=\\s*\"(?<currentValue>[^\"]+)\""
|
||||
],
|
||||
"datasourceTemplate": "github-tags",
|
||||
"versioningTemplate": "npm",
|
||||
"extractVersionTemplate": "^v?(?<version>.+)$"
|
||||
},
|
||||
{
|
||||
"customType": "regex",
|
||||
"managerFilePatterns": ["/^Dockerfile$/"],
|
||||
"matchStrings": [
|
||||
"#\\s*renovate:\\s*suite=(?<suite>.*?) depName=(?<depName>.*?)\\sARG .*?_VERSION=\"(?<currentValue>.*)\"\\s"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-09
|
||||
@@ -0,0 +1 @@
|
||||
passed
|
||||
@@ -0,0 +1,133 @@
|
||||
## Context
|
||||
|
||||
After `adopt-gx-for-actions` (#439), the repository has three coordinated artifacts: `.github/gx.toml` (manifest), `.github/gx.lock` (resolved versions and SHAs), and `.github/workflows/gx.yml` (CI lint + tidy on PR). However, the existing `.github/renovate.json` still drives version bumps using Renovate's built-in `github-actions` manager, which edits the workflow YAML directly. The current `gx.yml` `tidy` job then runs and pushes a follow-up commit to sync `.github/gx.lock`. This works, but:
|
||||
|
||||
1. Manifest specifiers like `"^6"` and `"~0.3.0"` are not honored by Renovate — it walks past majors freely.
|
||||
2. Two systems edit overlapping files; cross-PR races and noisy chase-commits are routine.
|
||||
3. The "what versions are allowed" question has no canonical answer — `gx.toml` describes one constraint, Renovate operates on a different one, the lock records the resolution.
|
||||
|
||||
The repository is hosted on the **Mend Renovate App**, which forbids `postUpgradeTasks` (those require self-hosted Renovate with `allowedPostUpgradeCommands`). The single-commit-PR option from self-hosted Renovate is therefore unavailable. This design takes the next-best path: scope Renovate to a single file (`gx.toml`), and let CI propagate.
|
||||
|
||||
Verified beforehand:
|
||||
|
||||
- `gx tidy` resolves manifest specifier changes and rewrites both `gx.lock` and workflow `uses:` SHAs in a single run (`~/Code/gx/src/tidy/command.rs:97-148`). Phase 1 (`sync_manifest_actions`) only adds/removes manifest entries and does not overwrite a specifier already present, so a Renovate edit (`^6` → `^6.0.2`) survives Phase 1 untouched and is consumed by Phase 3 (`lock_sync`) and Phase 4 (`compute_workflow_patches`).
|
||||
- Renovate's built-in `github-actions` manager covers both `.github/workflows/**` and `.github/actions/**` (https://docs.renovatebot.com/modules/manager/github-actions/), so disabling it must be done by manager name, not file pattern.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Make `.github/gx.toml` the only Renovate-editable file for GitHub Actions versions.
|
||||
- Honor manifest specifiers (`^6`, `~0.3.0`) in Renovate's upgrade proposals so cross-major bumps require a human commit.
|
||||
- Keep the existing `gx.yml` `tidy` job as the sole agent that rewrites `gx.lock` and workflow `uses:` references.
|
||||
- Preserve the current monthly schedule (`* 0-3 1 * *`) for action upgrades.
|
||||
- Preserve all existing non-actions Renovate rules (Dockerfile suite tracking, npm grouping, weekly cadence, etc.).
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Switching off the Mend Renovate App or migrating to self-hosted Renovate.
|
||||
- Introducing `postUpgradeTasks` (incompatible with Mend App).
|
||||
- Changing `gx`, `gx.yml`, or any workflow file behavior.
|
||||
- Changing the schedule cadence or grouping for non-actions dependencies.
|
||||
- Adding a new scheduled `gx upgrade` cron workflow (option A from the prior research; rejected here in favor of letting Renovate continue to be the upgrade trigger).
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Use a Renovate `customManagers` regex over `gx.toml`, not Renovate's TOML manager
|
||||
|
||||
Renovate has no first-class manager for `gx.toml`. Two options:
|
||||
|
||||
- **Custom regex manager (chosen)**: One `customManagers` entry with a regex over `gx.toml`. Direct, debuggable, well-supported.
|
||||
- **Upstream a `gx` manager into Renovate**: A months-long external dependency. Out of scope.
|
||||
|
||||
The regex must extract:
|
||||
|
||||
- `depName` — full string from the manifest line (e.g., `github/codeql-action/upload-sarif`). Used in PR titles, dashboards, changelogs.
|
||||
- `packageName` — first two slash-separated segments only (`github/codeql-action`). Used by the `github-tags` datasource to query the right repo. The non-capturing group `(?:/[^"]+)?` swallows the optional subpath.
|
||||
- `currentValue` — the specifier (`^6`, `~0.3.0`).
|
||||
|
||||
Final pattern:
|
||||
|
||||
```
|
||||
"(?<depName>(?<packageName>[^/"]+/[^/"]+)(?:/[^"]+)?"\s*=\s*"(?<currentValue>[^"]+)"
|
||||
```
|
||||
|
||||
Datasource: `github-tags`. Versioning: `npm` (handles `^` and `~`). Extract template: `^v?(?<version>.+)$` (strip `v` prefix from tags so npm versioning compares cleanly).
|
||||
|
||||
Renovate docs (https://docs.renovatebot.com/configuration-options/#custommanagers) recommend "use only one method" per field but do not forbid two named captures from the same regex. We intentionally capture both `depName` and `packageName` because they differ for subpath actions; if Renovate rejects this combination at validation time, fall back to a `packageNameTemplate` Handlebars expression.
|
||||
|
||||
### Decision 2: Disable Renovate's built-in `github-actions` manager via `matchManagers`
|
||||
|
||||
Two options for stopping Renovate from editing workflow files:
|
||||
|
||||
- **`matchManagers: ["github-actions"]` + `enabled: false` (chosen)** — disables the manager by name. Clean, explicit, future-proof if Renovate adds new file patterns to the manager.
|
||||
- **`ignorePaths` covering `.github/workflows/**` and `.github/actions/**`** — file-pattern-based. Brittle if Renovate's coverage changes; also affects unrelated managers if any.
|
||||
|
||||
Manager-based disabling is the documented idiomatic path.
|
||||
|
||||
### Decision 3: Reuse the existing `gx.yml` `tidy` job; do not introduce a new workflow
|
||||
|
||||
The `tidy` job in `.github/workflows/gx.yml` already runs `gx tidy` on every PR (when not from a fork) and pushes the result via the `VERIFIED_COMMIT_*` GitHub App. After Path 2, that job's role expands from "sync the lock to match Renovate's workflow edits" to "resolve Renovate's manifest edit into lock + workflow rewrites". Both are well within `gx tidy`'s capability and the existing workflow's permission scope. No workflow changes are needed.
|
||||
|
||||
### Decision 4: Keep the schedule on the rule that targets `gx.toml`
|
||||
|
||||
The current `renovate.json` puts `schedule: ["* 0-3 1 * *"]` on the `github-actions` package rule. After this change, that rule is gone. The schedule moves to a new rule keyed on `matchFileNames: [".github/gx.toml"]`, preserving the monthly-first-day cadence. Grouping name `github-actions` is preserved so existing PR-routing rules (if any in branch-protection or auto-merge configs) continue to apply.
|
||||
|
||||
### Decision 5: Accept the two-commit PR shape
|
||||
|
||||
Each Renovate upgrade PR will contain:
|
||||
|
||||
1. Renovate's commit: 1-line edit in `gx.toml`.
|
||||
2. gx-bot's commit (via `grafana/github-api-commit-action`, App-token-signed): updated `gx.lock` + workflow files + composite actions.
|
||||
|
||||
A one-commit alternative requires `postUpgradeTasks`, which is unavailable on the Mend App. Two commits is acceptable: it matches the current observed PR shape (Renovate + chase-commit), and the "verified" App-token commit on top makes intent obvious in `git log`.
|
||||
|
||||
### Decision 6: Do not change `.github/gx.toml` or `gx.lock` as part of this proposal
|
||||
|
||||
This is a pure config refactor on the Renovate side. Manifest specifiers stay as currently committed. Future tightening of specifiers (e.g., switching `^6` to `~6.0.0` to forbid minor bumps) is a separate decision and a separate change.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Risk**: The two-named-capture regex (`depName` + `packageName` in the same `matchStrings`) may fail Renovate's config validation or runtime extraction. → Mitigation: dry-run validation step in tasks (`renovate-config-validator`); fallback design uses a Handlebars `packageNameTemplate` instead.
|
||||
- **Risk**: `npm` versioning may misinterpret action tags that don't follow strict semver (e.g., `v6.0` instead of `v6.0.0`). → Mitigation: `extractVersionTemplate` strips the `v` prefix; if loose tags persist, Renovate will skip those bumps rather than corrupting them. `gx lint` would surface any resulting inconsistency.
|
||||
- **Risk**: Lint (in `gx.yml`) runs in parallel with `tidy` and may fail on the first commit (manifest ahead of workflows). The PR shows a transient red check that flips green after `tidy` pushes its commit. → Mitigation: behavior is identical to the current chase-commit pattern; documented in tasks; out-of-scope to restructure `gx.yml`.
|
||||
- **Risk**: An action used in workflows but missing from `gx.toml` would not be picked up by Renovate (since the only manager is now manifest-scoped). → Mitigation: `gx tidy` adds missing actions to the manifest on PR; `gx lint` flags unsynced manifest entries. A one-shot `gx tidy` locally before merging this proposal verifies completeness.
|
||||
- **Trade-off**: Loses Renovate's ability to identify exact patch-level upgrades for actions whose tags don't follow semver. The lock will still be regenerated against the manifest specifier whenever upstream publishes a tag in range — just not driven by a Renovate PR for non-semver-compliant tags. Acceptable for the action set in this repo.
|
||||
- **Trade-off**: Renovate's PR body will reference `depName` (full string with subpath); the github-tags lookup uses `packageName` (org/repo). The PR will list a `package: github/codeql-action`, dep: `github/codeql-action/upload-sarif`. Slight cosmetic asymmetry; not a correctness issue.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Local pre-flight: run `gx tidy` against the current tree; confirm zero diff. This validates that workflows, manifest, and lock are mutually consistent before changing Renovate.
|
||||
2. Locally validate the new `renovate.json` with the Renovate config validator and a `--dry-run=full` against the local checkout. Confirm Renovate finds `gx.toml`, parses each line, and resolves expected `currentVersion` for at least three sample actions (one with subpath, one with caret, one with tilde).
|
||||
3. Open a PR with the new `renovate.json`. The change is isolated to one file.
|
||||
4. Watch the next Mend Renovate cycle. Confirm:
|
||||
- No PRs editing `.github/workflows/**` or `.github/actions/**` are produced.
|
||||
- Any new PR edits only `.github/gx.toml`.
|
||||
- `gx.yml`'s `tidy` job adds the lock + workflow commit and `gx lint` passes on the head commit.
|
||||
|
||||
**Rollback**: revert the `renovate.json` change. Behavior returns to the prior (workflow-editing) Renovate model. No data migration is required because no other artifacts are touched.
|
||||
|
||||
## Automated Test Strategy
|
||||
|
||||
This change has no application code; verification is configuration-level and observational.
|
||||
|
||||
- **Critical path**: Renovate scans `gx.toml`, opens a PR with one `gx.toml` edit, `gx.yml` propagates lock + workflow updates, `gx lint` passes.
|
||||
- **Pre-merge verification**:
|
||||
- `npx --package renovate -- renovate-config-validator .github/renovate.json` — must pass.
|
||||
- Local Renovate dry-run (`renovate --platform=local --dry-run=full`) — must list expected upgrades for `gx.toml` entries and zero upgrades from the now-disabled `github-actions` manager.
|
||||
- Local `gx tidy` against the tree before opening the PR — must produce no diff (proves baseline consistency).
|
||||
- **Post-merge verification (first Renovate cycle, time-bounded)**: confirm one Renovate PR opens, edits only `gx.toml`, `gx.yml` `tidy` succeeds, and `gx lint` passes on the merged head.
|
||||
- **No new test infrastructure**. The existing `gx lint` job in `.github/workflows/gx.yml` is the on-going invariant check.
|
||||
|
||||
## Observability
|
||||
|
||||
- **Renovate-side failure surface**: Mend Renovate dashboard shows manager-extraction errors per repo. If the regex fails to match any line in `gx.toml`, Renovate's logs surface a warning and produce zero PRs for actions — visible as "no upgrades opened this cycle" on the dashboard. This is *silent* on the GitHub side; first observation is the absence of expected PRs after the cycle.
|
||||
- **gx-side failure surface**: `gx tidy` failures in the `gx.yml` `tidy` job appear as failed CI checks on the PR. `gx lint` failures appear as failed CI checks on every commit.
|
||||
- **Drift surface**: if a Renovate PR ever lands without the `tidy` follow-up commit (e.g., `tidy` job timed out, App token expired), `gx lint` fails on the PR head and merge is blocked. This is the load-bearing safety net.
|
||||
- **What is logged**: nothing new. `gx.yml` already prints tidy/lint progress; Renovate's logs are visible via the Mend dashboard.
|
||||
- **Can a failure be silent?**: yes — if Renovate's custom manager extracts zero matches, there is no GitHub-side signal until someone notices that monthly action upgrade PRs stopped arriving. Mitigation: the migration plan's local dry-run is the front-loaded check; running it before merge converts the silent failure into a loud, pre-merge one.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Does Renovate's config validator accept the two-named-capture regex (`depName` + `packageName` in the same `matchStrings`)? Tasks include the verification step; if validation fails, fall back to `packageNameTemplate` with a Handlebars conditional.
|
||||
- Should the `github-actions` group label be preserved on the new rule (`groupName: "github-actions"`) for any downstream branch-protection or auto-merge config? Default: yes, unless evidence emerges that no rule depends on it.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
Today Renovate edits workflow files directly and `gx tidy` chases each PR with a fixup commit to sync `.github/gx.lock`. The two tools race on the same files, manifest specifiers (`^6`, `~0.3.0`) declared in `.github/gx.toml` are ignored, and Renovate can therefore propose a cross-major upgrade that the manifest was meant to forbid. Pointing Renovate at the manifest instead of the workflows turns `gx.toml` into the single source of truth for which action versions are allowed, and lets gx own propagation to the lock and workflow files.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Disable Renovate's built-in `github-actions` manager so it stops editing files under `.github/workflows/` and `.github/actions/`.
|
||||
- Add a Renovate `customManagers` regex entry that reads action specifiers from `.github/gx.toml` using the `github-tags` datasource and `npm` versioning (so `^6` and `~0.3.0` are honored).
|
||||
- Move the existing monthly schedule from the `github-actions` package rule to a new rule that targets `.github/gx.toml`.
|
||||
- Document that Renovate-driven action upgrades arrive as a `gx.toml`-only edit and are completed in-PR by the existing `gx.yml` `tidy` job.
|
||||
- **BREAKING** for the spec only: the requirement that Renovate PRs already carry the lock update on open is replaced by a requirement that `gx.yml`'s `tidy` job pushes the lock and workflow updates onto the Renovate PR branch before merge.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
_None._
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `actions-version-tracking`: the "Renovate-driven upgrades keep the lock in sync" requirement is replaced with one that scopes Renovate to `.github/gx.toml` and assigns lock + workflow propagation to `gx tidy` running in CI on the PR branch.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected files: `.github/renovate.json` (rewrite), `openspec/specs/actions-version-tracking/spec.md` (delta applied during archive).
|
||||
- No code changes; no changes to `.github/workflows/gx.yml`, `.github/gx.toml`, or `.github/gx.lock`.
|
||||
- Operational impact: monthly Renovate PRs will edit one TOML line; the existing `gx.yml` `tidy` job adds a follow-up commit on the same PR with the lock and workflow updates. Net commit count per upgrade PR is unchanged or lower than today.
|
||||
- Safety property gained: Renovate cannot propose a major-version upgrade unattended. Crossing a major now requires a human to edit `gx.toml` (`^6` → `^7`), which becomes the review surface.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Renovate-driven upgrades keep the lock in sync
|
||||
|
||||
Renovate SHALL be configured to manage GitHub Action versions exclusively through `.github/gx.toml`, not by editing workflow files. The repository's CI SHALL propagate every Renovate-driven `gx.toml` edit through to `.github/gx.lock` and the workflow files on the same pull request branch before merge, so that when the PR is merged the manifest, lock, and workflow `uses:` SHAs are mutually consistent.
|
||||
|
||||
#### Scenario: Renovate edits the manifest only
|
||||
|
||||
- **WHEN** Renovate opens an upgrade PR for a GitHub Action
|
||||
- **THEN** the only file modified by Renovate's commit is `.github/gx.toml`
|
||||
- **AND** the modification is a change to the action's specifier (e.g., `"^6.0.1"` → `"^6.0.2"`, or `"^6"` → `"^6"` with no change if already the broadest in-major specifier)
|
||||
|
||||
#### Scenario: gx.yml propagates the manifest edit on the PR branch
|
||||
|
||||
- **WHEN** a PR contains a `.github/gx.toml` edit and the workflow `uses:` SHAs do not yet match the new specifier
|
||||
- **THEN** the `gx.yml` workflow's `tidy` job runs `gx tidy`, regenerates `.github/gx.lock`, rewrites every affected `uses: <owner>/<repo>@<sha> # vX.Y.Z` reference in `.github/workflows/**` and `.github/actions/**`, and pushes the resulting changes onto the PR branch as a single commit
|
||||
- **AND** `gx lint` passes on the resulting head commit
|
||||
|
||||
#### Scenario: Manifest specifier bounds the upgrade
|
||||
|
||||
- **WHEN** a new major version of an action is published upstream and the manifest specifier is `^N` for the prior major
|
||||
- **THEN** Renovate does not propose an upgrade that crosses the major boundary
|
||||
- **AND** crossing the major requires a human commit that changes `.github/gx.toml` from `^N` to `^N+1`, after which `gx tidy` resolves the new major and rewrites lock and workflow files on the same PR
|
||||
|
||||
#### Scenario: Renovate's built-in github-actions manager is disabled
|
||||
|
||||
- **WHEN** Renovate evaluates this repository
|
||||
- **THEN** the built-in `github-actions` manager is disabled by configuration
|
||||
- **AND** no Renovate run produces a commit that edits any file under `.github/workflows/` or `.github/actions/`
|
||||
|
||||
#### Scenario: Lock drift is detected before merge
|
||||
|
||||
- **WHEN** for any reason a Renovate PR's head commit lacks the lock and workflow updates that match its `gx.toml` edit
|
||||
- **THEN** the `gx lint` CI job fails the PR
|
||||
- **AND** merge is blocked until `gx tidy` is run and committed
|
||||
@@ -0,0 +1,38 @@
|
||||
## 1. Pre-flight
|
||||
|
||||
- [x] 1.1 Run `gx tidy` against the current tree and confirm zero diff (proves the manifest, lock, and workflows are mutually consistent before changing Renovate)
|
||||
- [x] 1.2 Confirm Mend Renovate App is the bot in use by checking the author of the most recent Renovate PR
|
||||
|
||||
## 2. Rewrite `.github/renovate.json`
|
||||
|
||||
- [x] 2.1 Add a `packageRules` entry that disables Renovate's built-in `github-actions` manager (`matchManagers: ["github-actions"]` + `enabled: false`)
|
||||
- [x] 2.2 Remove the existing `github-actions` package rule (the one with `matchDatasources: ["github-tags"]` and the monthly schedule)
|
||||
- [x] 2.3 Add a `customManagers` regex entry targeting `^\\.github/gx\\.toml$` with named captures `depName`, `packageName`, `currentValue`, datasource `github-tags`, versioning `npm`, and `extractVersionTemplate: "^v?(?<version>.+)$"`
|
||||
- [x] 2.4 Add a new `packageRules` entry keyed on `matchFileNames: [".github/gx.toml"]` with `groupName: "github-actions"` and the existing monthly schedule `["* 0-3 1 * *"]`
|
||||
- [x] 2.5 Preserve the existing Dockerfile `customManagers` entry untouched
|
||||
- [x] 2.6 Preserve the existing `extends` array untouched
|
||||
- [x] 2.7 Apply Renovate's `fileMatch` → `managerFilePatterns` migration (regex wrapped in `/.../`) on both `customManagers` entries to silence the validator's deprecation notice on first run
|
||||
|
||||
## 3. Local validation
|
||||
|
||||
- [x] 3.1 Run `npx --package renovate -- renovate-config-validator .github/renovate.json` and confirm exit 0
|
||||
- [x] 3.2 Run `renovate --platform=local --dry-run=full` (with `LOG_LEVEL=debug`) and confirm: (a) zero upgrades from the `github-actions` manager, (b) `actions/checkout` is extracted with `packageName=actions/checkout` and a current version, (c) `github/codeql-action/upload-sarif` is extracted with `packageName=github/codeql-action`, (d) `plexsystems/container-structure-test-action` is extracted with the `~0.3.0` specifier
|
||||
- [x] 3.3 If validation fails on the two-named-capture regex, fall back to a `packageNameTemplate` Handlebars conditional that returns the first two slash-separated segments of `depName`, and re-run 3.1 and 3.2
|
||||
|
||||
## 4. Open the PR
|
||||
|
||||
- [ ] 4.1 Commit the `renovate.json` change on a topic branch and open a PR
|
||||
- [ ] 4.2 Confirm `gx.yml` `lint` and `tidy` jobs pass on the PR (no functional change yet, so they should be green)
|
||||
- [ ] 4.3 Merge after review
|
||||
|
||||
## 5. Post-merge observation (next Renovate cycle)
|
||||
|
||||
- [ ] 5.1 On the next monthly Renovate cycle, confirm any opened upgrade PR edits only `.github/gx.toml`
|
||||
- [ ] 5.2 Confirm `gx.yml`'s `tidy` job pushes a follow-up commit on the PR branch with `gx.lock` and workflow updates
|
||||
- [ ] 5.3 Confirm `gx lint` passes on the head commit of the Renovate PR
|
||||
- [ ] 5.4 If no Renovate PR appears within the expected window, check the Mend dashboard for manager-extraction errors against `gx.toml` and resolve before archiving
|
||||
|
||||
## 6. Archive
|
||||
|
||||
- [ ] 6.1 Run `/opsx:verify` to validate that the shipped behavior matches the specs
|
||||
- [ ] 6.2 Run `/opsx:archive` to fold the spec delta into `openspec/specs/actions-version-tracking/spec.md`
|
||||
@@ -68,17 +68,35 @@ The repository's CI SHALL run `gx lint` on every pull request and SHALL fail whe
|
||||
|
||||
### Requirement: Renovate-driven upgrades keep the lock in sync
|
||||
|
||||
Renovate-generated upgrade pull requests for GitHub Actions SHALL leave `.github/gx.lock` consistent with the workflow SHAs they introduce, either by running `gx tidy` as a `postUpgradeTask` in `renovate.json` or via an equivalent CI workflow that pushes a fixup commit to the PR before merge.
|
||||
Renovate SHALL be configured to manage GitHub Action versions exclusively through `.github/gx.toml`, not by editing workflow files. The repository's CI SHALL propagate every Renovate-driven `gx.toml` edit through to `.github/gx.lock` and the workflow files on the same pull request branch before merge, so that when the PR is merged the manifest, lock, and workflow `uses:` SHAs are mutually consistent.
|
||||
|
||||
#### Scenario: Renovate bumps a SHA and the lock is updated
|
||||
#### Scenario: Renovate edits the manifest only
|
||||
|
||||
- **WHEN** Renovate opens a PR that bumps `actions/checkout` from one SHA to another
|
||||
- **THEN** the same PR contains a corresponding update to `.github/gx.lock`
|
||||
- **AND** `gx lint` passes on the PR
|
||||
- **WHEN** Renovate opens an upgrade PR for a GitHub Action
|
||||
- **THEN** the only file modified by Renovate's commit is `.github/gx.toml`
|
||||
- **AND** the modification is a change to the action's specifier (e.g., `"^6.0.1"` → `"^6.0.2"`, or `"^6"` → `"^6"` with no change if already the broadest in-major specifier)
|
||||
|
||||
#### Scenario: gx.yml propagates the manifest edit on the PR branch
|
||||
|
||||
- **WHEN** a PR contains a `.github/gx.toml` edit and the workflow `uses:` SHAs do not yet match the new specifier
|
||||
- **THEN** the `gx.yml` workflow's `tidy` job runs `gx tidy`, regenerates `.github/gx.lock`, rewrites every affected `uses: <owner>/<repo>@<sha> # vX.Y.Z` reference in `.github/workflows/**` and `.github/actions/**`, and pushes the resulting changes onto the PR branch as a single commit
|
||||
- **AND** `gx lint` passes on the resulting head commit
|
||||
|
||||
#### Scenario: Manifest specifier bounds the upgrade
|
||||
|
||||
- **WHEN** a new major version of an action is published upstream and the manifest specifier is `^N` for the prior major
|
||||
- **THEN** Renovate does not propose an upgrade that crosses the major boundary
|
||||
- **AND** crossing the major requires a human commit that changes `.github/gx.toml` from `^N` to `^N+1`, after which `gx tidy` resolves the new major and rewrites lock and workflow files on the same PR
|
||||
|
||||
#### Scenario: Renovate's built-in github-actions manager is disabled
|
||||
|
||||
- **WHEN** Renovate evaluates this repository
|
||||
- **THEN** the built-in `github-actions` manager is disabled by configuration
|
||||
- **AND** no Renovate run produces a commit that edits any file under `.github/workflows/` or `.github/actions/`
|
||||
|
||||
#### Scenario: Lock drift is detected before merge
|
||||
|
||||
- **WHEN** for any reason a Renovate PR lands without the lock update
|
||||
- **WHEN** for any reason a Renovate PR's head commit lacks the lock and workflow updates that match its `gx.toml` edit
|
||||
- **THEN** the `gx lint` CI job fails the PR
|
||||
- **AND** merge is blocked until `gx tidy` is run and committed
|
||||
|
||||
|
||||
Reference in New Issue
Block a user