Skip to content

Commit 9edbf49

Browse files
jst-cyrclaude
andcommitted
Step D: add the Puppet 9 profile and wire the major through the pipeline
profiles/puppet_profiles.json gains 9-latest-maintained: Puppet 9.0.0 (the deliberate starting point per the 2026-08-21 product decision, not "newest 9.x"), facter 4.21.0, Ruby 3.4, bundler 2.5.22, private gem source. No 9-previous-maintained — 9.0.0 is the first 9.x, so there is nothing previous to pin until 9.1 ships. Plumbing so the two majors stay independent (design §3, §5): - classify_module_result.py resolves and stamps puppet_major from the run's profile. update_ledger.py has keyed on that field since Step B but nothing ever set it, so every row silently landed in puppet_majors["8"]. - detect_changes.py takes the major from PUPPET_MAJOR instead of a hardcoded DEFAULT_MAJOR, so each caller's leanness is computed against its own ledger slice. - prepare-test-matrix exposes it as a puppet-major input; both callers set it explicitly ('8' / '9') rather than leaning on the default. - compatibility-runner-puppet9.yml gets its nightly cron (03:00 UTC, an hour after the Puppet 8 caller — runner contention only; the shared compat-ledger-* group already serializes the one racing step). build_matrix.rb needed no change despite the design listing it: a caller selects its major via the profile it passes to run-module-test, and per-major leanness arrives pre-resolved in INCLUDE_IDS, so matrix rows are major-agnostic. Added a comment saying so. Facter is pinned by assumption, not lookup: 4.21.0 is the newest build known to exist on the private source and satisfies Puppet 9.0.0's declared facter >= 4.3.0, < 5. Without an API key here it couldn't be confirmed that the private source pairs a different facter with 9.0.0. bootstrap.rb pins facter exactly, so a wrong pin fails loudly at bundle install in the gate dispatch. Verified locally against the real ledger, no CI needed: - PUPPET_MAJOR=9 includes all 75 modules (never-tested); PUPPET_MAJOR=8 includes 0 (all green and fresh). - After merging a synthetic Puppet 9 run (one clean, one failing) into a ledger copy: 74 included on 9 (73 never-tested + 1 unit-failing), still 0 on 8, with puppet-telegraf sitting at unit+acceptance on 8 and unit-failing on 9 in the same row. That is §5's independence requirement end to end. - render_status_dashboard.py rendered both majors' column pairs off that ledger with no changes needed; build_matrix.rb built 74 unit rows from the major-9 include list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent efd23c7 commit 9edbf49

14 files changed

Lines changed: 131 additions & 45 deletions

.github/actions/prepare-test-matrix/action.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ inputs:
2424
description: 'Path to the calling thin trigger workflow file, scoped out of the sibling major material-path matching'
2525
required: false
2626
default: ''
27+
puppet-major:
28+
description: "Puppet major this caller tests ('8' | '9'); scopes every ledger read to that major's slice"
29+
required: false
30+
default: '8'
2731
window-hours:
2832
description: 'Upstream/harness change window in hours'
2933
required: false
@@ -80,6 +84,7 @@ runs:
8084
LEAN: ${{ inputs.lean }}
8185
GITHUB_TOKEN: ${{ github.token }}
8286
CALLER_WORKFLOW_FILE: ${{ inputs.caller-workflow-file }}
87+
PUPPET_MAJOR: ${{ inputs.puppet-major }}
8388

8489
- name: Build module matrix
8590
id: matrix

.github/workflows/compatibility-runner-puppet8.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ name: Puppet Core 8 Compatibility
2323
# strategy, dynamic name, runs-on, timeout, needs/if gates, env passthrough)
2424
# that GitHub has no sharing primitive for below a full reusable workflow -
2525
# a small, mostly-static block that should look nearly identical to
26-
# compatibility-runner-puppet9.yml (once Step D adds it) except for the
27-
# profile name and concurrency-group suffix.
26+
# compatibility-runner-puppet9.yml except for the profile name, the
27+
# concurrency-group suffix, the puppet-major input, and the cron hour.
2828
#
29-
# This is now the sole owner of the nightly cron: the old
29+
# This is now the sole owner of the Puppet 8 nightly cron: the old
3030
# compatibility-runner.yml (retired in this same commit, per its gate
3131
# passing — see docs/puppet-core-9-dual-major-support.md §12) previously
3232
# owned it. Both never ran on the same cron at once — that would have
@@ -101,6 +101,7 @@ jobs:
101101
event-name: ${{ github.event_name }}
102102
lean: ${{ github.event.inputs.lean || 'true' }}
103103
caller-workflow-file: .github/workflows/compatibility-runner-puppet8.yml
104+
puppet-major: '8'
104105
window-hours: ${{ vars.PUPPET_CHANGE_WINDOW_HOURS || '48' }}
105106
stale-days: ${{ vars.PUPPET_STALE_DAYS || '30' }}
106107

.github/workflows/compatibility-runner-puppet9.yml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ name: Puppet Core 9 Compatibility
1010
# - .github/actions/run-module-test (the actual per-module test)
1111
# - .github/actions/publish-compatibility-results (ledger/dashboard write)
1212
# A diff against the Puppet 8 caller should show only the profile name, the
13-
# concurrency-group suffix, the caller-workflow-file path, and this comment —
14-
# anything more is drift to catch in review.
13+
# concurrency-group suffix, the caller-workflow-file path, the puppet-major
14+
# input, the cron hour, and this comment — anything more is drift to catch in
15+
# review.
1516
#
16-
# STATUS: skeleton only, landed on main ahead of the rest of Step D so that
17-
# workflow_dispatch is discoverable (GitHub only exposes dispatch for workflow
18-
# files that exist on the default branch). The `9-latest-maintained` profile
19-
# does not exist in profiles/puppet_profiles.json yet, and the `major`
20-
# parameter is not yet wired through detect_changes.py / build_matrix.rb — so
21-
# dispatching this today will fail at profile resolution. Intentionally has NO
22-
# `schedule:` trigger for that reason; the nightly cron gets added when the
23-
# profile lands and Step D's gate dispatch passes.
17+
# The file itself landed on main ahead of the rest of Step D, because GitHub
18+
# only exposes workflow_dispatch for workflow files present on the default
19+
# branch (the constraint hit in Step C).
20+
#
21+
# The cron is offset an hour after the Puppet 8 caller's so the two nightly
22+
# runs don't contend for runners; correctness doesn't depend on the offset —
23+
# the shared compat-ledger-* concurrency group on `publish` already serializes
24+
# the one step that would otherwise race (§4.2).
2425

2526
on:
27+
schedule:
28+
- cron: "0 3 * * *" # Nightly at 03:00 UTC (an hour after the Puppet 8 caller)
2629
workflow_dispatch:
2730
inputs:
2831
profile:
@@ -88,6 +91,7 @@ jobs:
8891
event-name: ${{ github.event_name }}
8992
lean: ${{ github.event.inputs.lean || 'true' }}
9093
caller-workflow-file: .github/workflows/compatibility-runner-puppet9.yml
94+
puppet-major: '9'
9195
window-hours: ${{ vars.PUPPET_CHANGE_WINDOW_HOURS || '48' }}
9296
stale-days: ${{ vars.PUPPET_STALE_DAYS || '30' }}
9397

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ must **not** be pre-emptively marked incompatible.
3838
- `config/modules.schema.json`: schema for module config validation.
3939
- `config/beaker/setfiles/`: Beaker host definition files (one per acceptance target, e.g. `el9.yml`).
4040
- `scripts/validate_modules_config.py`: local schema validation helper.
41-
- `.github/workflows/compatibility-runner-puppet8.yml`: CI pipeline and matrix execution for Puppet 8 (a `compatibility-runner-puppet9.yml` sibling is added in Step D of `docs/puppet-core-9-dual-major-support.md`). Shared prepare/publish logic lives in `.github/actions/prepare-test-matrix` and `.github/actions/publish-compatibility-results` — see that doc's §12 for why these are composite actions, not a reusable workflow.
41+
- `.github/workflows/compatibility-runner-puppet8.yml` / `compatibility-runner-puppet9.yml`: CI pipeline and matrix execution, one self-contained caller per Puppet major (see `docs/puppet-core-9-dual-major-support.md` §4). They are deliberate near-copies — a diff between them should show only the profile name, concurrency-group suffix, `puppet-major` input, and cron hour; anything else is drift. Shared prepare/publish logic lives in `.github/actions/prepare-test-matrix` and `.github/actions/publish-compatibility-results` — see that doc's §12 for why these are composite actions, not a reusable workflow.
4242
- `profiles/puppet_profiles.json`: profile constraints used by the runner.
4343
- `docs/architecture-flow.md`: end-to-end architecture diagram and stage reference. Must be kept in sync with runner logic, classification rules, and CI workflow changes.
4444

@@ -198,7 +198,7 @@ When you need a narrow CI run, use workflow input `modules_json` with only new o
198198
| Downgrade override rules (`lib/module_tester/adapters.rb`) | Downgrade overrides table — add, remove, or update trigger conditions and reclassification outcome |
199199
| Guardrails checks (`lib/module_tester/guardrails.rb`) | Guardrails row in stage table |
200200
| Acceptance adapter or Docker isolation model (`lib/module_tester/adapters.rb`, `lib/module_tester/docker.rb`) | Two-Stage Docker Isolation Model section; Docker Container Modes table; S1/S2S/S2D node labels in diagram; FOSS fallback description |
201-
| CI workflow (`.github/workflows/compatibility-runner-puppet8.yml`, `.github/actions/prepare-test-matrix/action.yml`, `.github/actions/publish-compatibility-results/action.yml`) | CI: Prepare section; diagram CI subgraph |
201+
| CI workflow (`.github/workflows/compatibility-runner-puppet8.yml`, `compatibility-runner-puppet9.yml`, `.github/actions/prepare-test-matrix/action.yml`, `.github/actions/publish-compatibility-results/action.yml`) | CI: Prepare section; diagram CI subgraph |
202202
| Reporting outputs (`lib/module_tester/reporting.rb`) | Reporting section |
203203

204204
### Rules for diagram edits

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ STATUS.md # Generated fleet dashboard (do not hand-edit)
6363
KNOWN_COMPATIBLE.md # Generated list of fully-validated modules (do not hand-edit)
6464
.github/
6565
workflows/compatibility-runner-puppet8.yml # Puppet 8 CI trigger + full pipeline
66+
workflows/compatibility-runner-puppet9.yml # Puppet 9 CI trigger + full pipeline (same shape)
6667
actions/run-module-test/action.yml # Composite action: run one module's test
6768
actions/prepare-test-matrix/action.yml # Composite action: change detection + matrix build
6869
actions/publish-compatibility-results/action.yml # Composite action: ledger update + dashboard render

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ If invalid, the script prints path-based errors and exits non-zero.
5959

6060
The GitHub Actions workflow validates [config/modules.json](config/modules.json) before building the module matrix.
6161

62-
Workflow: [.github/workflows/compatibility-runner-puppet8.yml](.github/workflows/compatibility-runner-puppet8.yml)
62+
Workflows: [.github/workflows/compatibility-runner-puppet8.yml](.github/workflows/compatibility-runner-puppet8.yml) and [.github/workflows/compatibility-runner-puppet9.yml](.github/workflows/compatibility-runner-puppet9.yml) (one per Puppet major; both validate identically)
6363

6464
If schema validation fails, the `prepare` job fails and module test jobs are blocked.
6565

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Some modules are no longer maintained or are incompatible with Puppet Core:
3131
- Markdown summary: `results/.../compatibility-summary.md`
3232
- Stage logs per module: `results/.../artifacts/<module>/.stage-*.log`
3333
- Per-module dependency status/message (`dependency_status`, `dependency_message`) in JSON report
34-
- GitHub Actions workflow with module matrix: `.github/workflows/compatibility-runner-puppet8.yml`
34+
- GitHub Actions workflow with module matrix, one per Puppet major: `.github/workflows/compatibility-runner-puppet8.yml`, `.github/workflows/compatibility-runner-puppet9.yml`
3535

3636
## Quick start (local)
3737

@@ -101,11 +101,14 @@ Split-source behavior (default):
101101

102102
## GitHub Actions usage
103103

104-
Workflow file: `.github/workflows/compatibility-runner-puppet8.yml`
104+
Workflow files, one self-contained caller per Puppet major:
105+
`.github/workflows/compatibility-runner-puppet8.yml` and
106+
`.github/workflows/compatibility-runner-puppet9.yml`. They take the same inputs
107+
and run the same pipeline; only the default profile differs.
105108

106-
- Trigger: **Actions → Puppet Core 8 Compatibility → Run workflow**
109+
- Trigger: **Actions → Puppet Core 8 Compatibility** (or **Puppet Core 9 Compatibility**) **→ Run workflow**
107110
- Inputs:
108-
- `profile` (default `8-latest-maintained`)
111+
- `profile` (default `8-latest-maintained` / `9-latest-maintained`)
109112
- `metadata_mode` (`warn` or `fail`, default `warn`)
110113
- `modules_json` (optional JSON array override)
111114

0 commit comments

Comments
 (0)