Skip to content

feat(config): declare version guards with required_runok_version#299

Merged
fohte merged 4 commits intomainfrom
fohte/required-version-config
Apr 11, 2026
Merged

feat(config): declare version guards with required_runok_version#299
fohte merged 4 commits intomainfrom
fohte/required-version-config

Conversation

@fohte
Copy link
Copy Markdown
Owner

@fohte fohte commented Apr 11, 2026

Why

  • A preset that depends on newer runok schema features either silently drifts away from the author's intent (older runok ignores unknown fields) or suddenly starts producing parse errors during normal operations
  • runok update-presets always jumps to the newest tag regardless of whether it is compatible with the current runok binary, leaving users on older runok without a way to notice that their presets have outgrown their runok

What

  • Accept a required_runok_version field in every config and preset file so authors can declare "this file needs runok X or newer" with a semver requirement such as ">=0.3.0" or ">=0.3, <0.5"
    • Every child file reached via extends is validated independently
  • Make runok update-presets walk candidate tags from newest to oldest and adopt the newest one whose entire preset tree satisfies the current runok. Rejected candidates are surfaced in a warning so users know that upgrading runok would unlock newer preset versions
  • Never update the cache working tree to a revision that is incompatible with the current runok, in both the automatic TTL refresh and the manual update path. This prevents concurrent runok processes from observing a half-updated cache
    • Automatic refresh stays silent and keeps using the existing cache so normal operations do not break
  • Treat nightly builds (X.Y.Z-nightly+<sha>) as "latest" so any ">=X.Y.Z" requirement passes automatically
required_runok_version: '>=0.3.0'
definitions:
  flag_groups:
    field-flag: ['-f', '--field']

Open with Devin

fohte and others added 2 commits April 11, 2026 00:37
Any config or preset file can now declare a semver requirement that the
running runok must satisfy to load it. The check runs per file so that
every file in the extends chain, including transitively extended
presets, is validated independently. Loading fails with an error that
names the exact source file and the constraint, rather than silently
ignoring newer schema fields.

`runok update-presets` now honors the field when picking upgrade tags:
candidate tags are inspected from newest to oldest, and the newest
candidate whose preset tree (including transitive `extends`) satisfies
the current runok binary is adopted. This lets preset repositories ship
schema-incompatible changes under newer tags without breaking users on
older runok.

Nightly builds are modeled as strictly greater than every release so
that `">=X.Y.Z"` constraints always pass; upper-bounded ranges still
reject nightly intentionally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply the `required_runok_version` check to both the automatic TTL
refresh path (`handle_stale_cache`) and the manual `update-presets`
path via a shared `git show`-based inspector. The cache working tree
is only advanced to a new revision after the revision (and every
same-repo `extends` child) has been validated, so concurrent runok
processes never observe a preset revision that is too new for the
running binary.

`update-presets` now surfaces a warning listing the candidate tags it
skipped because of `required_runok_version`, so users know when
upgrading runok would unlock newer preset versions. The automatic
refresh path stays silent to keep normal operations quiet.

Also make `PresetCache::write_metadata` atomic (tempfile + rename) so
a concurrent reader never sees a half-written `metadata.json`.
gemini-code-assist[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 11, 2026

Codecov Report

❌ Patch coverage is 78.85246% with 129 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.13%. Comparing base (02de56c) to head (c4c31ed).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
src/update_presets/mod.rs 77.10% 49 Missing ⚠️
src/config/git_client.rs 51.94% 37 Missing ⚠️
src/config/preset_remote.rs 85.26% 28 Missing ⚠️
src/config/preset.rs 45.00% 11 Missing ⚠️
src/config/cache.rs 81.25% 3 Missing ⚠️
src/config/loader.rs 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #299      +/-   ##
==========================================
- Coverage   89.55%   89.13%   -0.43%     
==========================================
  Files          52       53       +1     
  Lines       11015    11538     +523     
==========================================
+ Hits         9865    10284     +419     
- Misses       1150     1254     +104     
Flag Coverage Δ
Linux 88.94% <78.85%> (-0.42%) ⬇️
macOS 90.37% <78.85%> (-0.52%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

intent(update-presets): satisfy the "no embedded \n in test string
  literals" rule in CLAUDE.md that asks for `indoc!`/`formatdoc!`
  instead of raw `format!` with escaped newlines
intent(extends): give preset authors a single place that explains
  when to set `required_runok_version`, how `update-presets` selects
  compatible tags, and why automatic refresh stays silent on
  incompatible revisions. The schema page previously held all of
  this, but preset authors reading the `extends` guide had no
  pointer to the behavior they care about
decision(extends): keep `schema.md` as the terse field reference and
  move the authoring guidance + `update-presets` / auto-refresh
  interaction into `extends.md`, cross-linked from both directions
@fohte fohte merged commit 2990a0e into main Apr 11, 2026
11 checks passed
@fohte fohte deleted the fohte/required-version-config branch April 11, 2026 09:21
@fohte-bot fohte-bot Bot mentioned this pull request Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant