Skip to content

Latest commit

 

History

History
107 lines (93 loc) · 4.92 KB

policy.org

File metadata and controls

107 lines (93 loc) · 4.92 KB

Policy JSON schema

A policy is the input that turns a universe of parsed easyconfig candidates into one selection. It is a JSON object matching the Policy struct in src/domain.rs.

1 Full shape

{
  "toolchain": {"name": "foss", "version": "2025b"},
  "roots": ["GROMACS"],
  "root_priority": ["GROMACS"],
  "pins": [
    {"name": "OpenBLAS", "version_req": "==0.3.24"}
  ],
  "forbid": ["OpenMPI-4.1.5-foss-2025b.eb"],
  "objective": "prefer_newer",
  "require_upgrade": {"name": "GROMACS", "relative_to_baseline": true}
}

Only toolchain and roots are required; every other field defaults as noted below.

2 Fields

toolchain
{"name": string, "version": string}. Required. Selects which candidates from the parsed tree participate: the policy toolchain, every member of its hierarchy, and SYSTEM. A recipe at GCC takes CMake from GCCcore and a licence file from SYSTEM, so an exact match on the policy toolchain alone cannot satisfy its own dependencies.
roots
Array of package names. Required, non-empty. Every dependency (runtime and build-time) a root needs co-selects automatically; the solve fails if any named root has no candidate at all.
root_priority
Optional array of package names. Declares which root wins the newest-version tie-break when two or more roots share a dependency with conflicting requirements. Defaults to roots list order when omitted or empty. Any root missing from an explicit root_priority is appended in roots order, so every root always participates. Reordering roots does not change the effective priority once root_priority is set explicitly. See the how-to and why this exists.
pins
Optional array of {"name": string, "version_req": string}. Restricts a package to candidates whose version matches the requirement string (grammar below). A pin on a package with no matching candidate fails the solve at policy-construction time, before any Boolean satisfiability (SAT) solving happens.
forbid
Optional array of strings. Each entry matches either a full easyconfig_path or a bare package name; matching candidates are excluded from the universe entirely before solving.
prefer_installed
Optional bool, default false. When true, a package present in the baseline stays at that version unless a pin, a forbid, or require_upgrade says otherwise. The derived criteria are then ["-changed", "-notuptodate"]: staying put outranks moving to newest.
objective
Optional string, default "prefer_newer". The only objective the solver implements: among jointly feasible assignments, prefer the newest version of each root (in priority order), then the newest version of every other co-selected package.
criteria
Optional array of Common Upgradeability Description Format (CUDF) criterion names, in precedence order. Empty means derive them: ["-notuptodate"] by default, or ["-changed", "-notuptodate"] when prefer_installed is true. An explicit list wins. Known names are -changed (minimise packages moved off the baseline version) and -notuptodate (minimise packages held below the newest candidate). Any other name fails the solve. The applied list is recorded on the lock as solver.criteria.
require_upgrade
Optional {"name": string, "relative_to_baseline": bool}, or an array of those objects. When relative_to_baseline is true, the named package’s solved version must be strictly newer than its version in the baseline lock (--baseline-easyconfigs or --baseline-easystack). No baseline, or no baseline entry for that package, fails the solve with an explicit error instead of skipping the requirement without a warning.

3 version_req grammar

Used by both pins[].version_req and parsed easyconfig dependency requirements (==X, >=X, <=X, >X, <X, or a bare X for an exact match). Version comparison is EasyBuild-shaped, not semver: digit runs compare numerically, letter runs compare lexicographically, and a trailing letter run with nothing on the other side sorts as a pre-release (2025a < 2025b, 1.0rc1 < 1.0).

4 Effective root priority

def effective_root_priority(policy):
    order = policy.root_priority or policy.roots
    order = [r for r in order if r in policy.roots]     # only real roots
    for r in policy.roots:
        if r not in order:
            order.append(r)                             # never drop a root
    return order

This is a description of Policy::effective_root_priority in src/domain.rs, not a separate implementation; it is shown here because the outcome of a multi-root solve depends entirely on this order.

5 Where policies are consumed

  • eb-stack stack solve --stack-policy POLICY.json

See how to solve a consistent stack lock.