An easystack is the list the bot will build

Questions

  • What is an easystack file, if it is not a second recipe format?

  • Which YAML key is stable in EasyBuild 5, and which top-level key is not implemented yet?

  • How does EESSI decide which EasyBuild version to load for a given file?

What you will be able to do

  1. Read an easystack YAML file and say which eb commands it is equivalent to, including per-item options.

  2. Name the EESSI path and filename a new package belongs in, and say why the EasyBuild version is in the name.

  3. Tell a from-commit entry from a rebuild, and say what each one causes the bot to pass to eb.

Before this chapter

An easyconfig defines a single package. A site and EESSI require a list of packages for one toolchain generation, one EasyBuild version, and one repository version. That list is an easystack file: YAML that EasyBuild reads with --easystack. EasyBuild 5 marked the format stable. It no longer needs --experimental.

The file does not invent a second recipe language. Each item is a filename the robot already knows how to resolve. Extra keys under options: become extra eb flags for that one item.

A list of filenames, plus flags without dashes

This is the official shape as presented on EasyBuild’s page.

easyconfigs:
  - PyTorch-1.12.0-foss-2022a-CUDA-11.7.0.eb:
      options:
        from-pr: 15924
        debug: True
  - Hypre-2.25.0-foss-2022a.eb
  - GROMACS-2025.4-foss-2025b.eb:
      options:
        installpath: /my/custom/installpath
        parallel: "1"

That is equivalent to three eb invocations:

eb PyTorch-1.12.0-foss-2022a-CUDA-11.7.0.eb --from-pr 15924 --debug
eb Hypre-2.25.0-foss-2022a.eb
eb GROMACS-2025.4-foss-2025b.eb --installpath /my/custom/installpath --parallel 1

Three rules are easy to miss and costly to discover after a bot job fails. A list marker must be present. YAML lacking the leading - = does not constitute an easystack. Dashes that form a command‑line flag are *omitted* in the file. =from-pr: 15924 corresponds to --from-pr 15924. Short options such as D: True are permitted but discouraged. Certain values must be quoted. YAML converts an unquoted 1 to the boolean True. parallel expects an integer, so the file should contain parallel: "1". debug: True illustrates the opposite case: the automatic conversion matches the option’s requirement.

Command-line options come first, and last wins

eb --easystack my.yaml --dry-run applies --dry-run to every item. EasyBuild puts the command-line flags before the per-item options from the file, and “always respect[s] the argument that was put last”. So a file that sets debug: True on one item still enables debug for that item even if the command line said --disable-debug. The opposite is not true. A flag that exists only on the command line applies to every item. A top-level options: block that would apply to the whole file is documented as “to be developed” (EasyBuild issues #4105, #4106, #4104, #3512): global options, an intended EasyBuild version, dropping --easystack in favour of auto-detection, and labels such as gpu. None of those are in 5.4.0. A file that puts robot: True at the top level is not doing what the comment above it hopes. EESSI does not wait for that work. The bot adds --robot (or --rebuild) on the command line, once, around the whole file. That is the next section.

EESSI puts the EasyBuild version in the filename

The EESSI/software-layer repository was split on 2025-06-11. The build scripts reside in EESSI/software-layer-scripts. Remaining content in software-layer consists mainly of easystack files and a 33-line bot/build.sh that pins the scripts commit. Installations for a specific EESSI version are no longer tracked by a git branch. Tracking now uses the directory:

easystacks/software.eessi.io/<eessi_version>/eessi-<eessi_version>-eb-<eb_version>-<toolchain>.yml

A new entry for GROMACS on the 2025.06 tree, compiled with EasyBuild 5.3.0 and the 2025b generation, belongs in.

easystacks/software.eessi.io/2025.06/eessi-2025.06-eb-5.3.0-2025b.yml

The filename determines which EasyBuild module EESSI-install-software.sh loads.

eb_version=$(echo ${easystack_file} | sed 's/.*eb-\([0-9.]*\).*.yml/\1/g')
source ${TOPDIR}/load_easybuild_module.sh ${eb_version}

A line added to the 5.3.0 file is built with EasyBuild 5.3.0, even when 5.4.0 is already present on the tree. Therefore, a new package is placed in the file for the current EasyBuild release on that EESSI version, rather than in an older file that lists similar software. The 001-system files run first. The 2023.06 README in software-layer states: “Software installed with system toolchain should be installed first, this includes EasyBuild itself.” CUDA easystacks are processed before any components that depend on CUDA. Filename order determines the processing order. The pull request targets main. The previous version branches (2023.06-software.eessi.io and others) have been removed.

from-commit is how an unmerged easyconfig gets built

The 4 May 2026 webinar by Lara Peeters and Kenneth Hoste walks the two cases that actually occur. If the easyconfig is already present in the EasyBuild release that the easystack filename names, the entry is a bare filename. Their scikit-bio 0.7.1 example:

- scikit-bio-0.7.1.post1-foss-2025a.eb

If the easyconfig exists only in an EasyBuild pull request, the entry includes from-commit (or the older from-pr). The live 2025.06 / EasyBuild 5.3.0 / 2025b file on software-layer shows this for GROMACS 2025.4:

- GROMACS-2025.4-foss-2025b.eb:
    options:
        # see https://github.com/easybuilders/easybuild-easyconfigs/pull/24956
        from-commit: a3bb54895c3de5600fdfd2893a818378daebc7ee

GROMACS 2026.2 on the same file also pulls an easyblock from a commit.

- GROMACS-2026.2-foss-2025b.eb:
    options:
      # see https://github.com/easybuilders/easybuild-easyconfigs/pull/25879
      from-commit: 9320dfe8ae6f45d37edd0ef52be37e7d3668d298
      # see https://github.com/easybuilders/easybuild-easyblocks/pull/3531
      include-easyblocks-from-commit: cfb6f93bfae8bef5d8996ae6696defcafbf0d4ad

The webinar states the merge order explicitly. The software-layer pull request can be opened while the easyconfig pull request remains open. Deployment to the CernVM-FS repository occurs only after the EasyBuild pull request has been merged. A from-commit pin is a temporary bridge rather than a permanent source of truth.

The 2026.06 tree maintains the same shape while representing a newer generation. The live eessi-2026.06-eb-5.4.0-2026.1.yml opens with OpenMPI and foss-2026.1.eb, which declares the first toolchain generation of a new EESSI version.

EB-Easystack-1 — Which file, and which options

A colleague has a working local install of Octave-11.1.0-foss-2025b.eb on EESSI 2025.06, built with EasyBuild 5.3.0. The easyconfig is already in that EasyBuild release. A second package, scikit-bio-0.7.2-foss-2025b.eb, exists only as EasyBuild easyconfigs pull request 25908, commit d04690454404aee9d12fc57858c79382adf64d8b.

  1. Which easystack file receives each line?

  2. Write the two YAML items.

  3. The software-layer pull request is opened today. When can the installations be deployed into software.eessi.io?

Solution
  1. Both lines go in easystacks/software.eessi.io/2025.06/eessi-2025.06-eb-5.3.0-2025b.yml. The EasyBuild version in the filename is the one the bot will load. Octave is already on that tree as a bare name; scikit-bio is the from-commit case from the same file.

  2. The live file already contains both, and they look like this:

    - Octave-11.1.0-foss-2025b.eb
    - scikit-bio-0.7.2-foss-2025b.eb:
    options:
    # see https://github.com/easybuilders/easybuild-easyconfigs/pull/25908
    from-commit: d04690454404aee9d12fc57858c79382adf64d8b
    
  3. Octave can be deployed as soon as the bot has green artefacts on every supported CPU target. scikit-bio waits on pull request 25908 being merged, even if the bot has already built it from that commit. That is the webinar’s rule, not a courtesy.

Rebuilds are a different directory, and a different flag

EESSI does not rebuild by default. A rebuild changes the bytes behind a module name that users are already loading. When a rebuild is unavoidable, the entry does not go in the ordinary easystack. It goes in rebuilds/, with a date in the name:

easystacks/software.eessi.io/<ver>/rebuilds/YYYYMMDD-eb-<eb_version>-<name>-<short-reason>.yml

A live example from 2025.06, 21 June 2026, rebuilding Rust to pick up an RPATH fix that landed in EasyBuild 5.3.1:

# rebuild Rust/1.91.1-GCCcore-14.3.0, to fix RPATH linking
# see https://github.com/easybuilders/easybuild-easyconfigs/issues/26232
# fixed in EasyBuild v5.3.1, see https://github.com/easybuilders/easybuild-easyblocks/pull/4156
easyconfigs:
  - Rust-1.91.1-GCCcore-14.3.0.eb

The EESSI-install-software.sh script splits the changed YAML files of the pull request into two lists and rebuilds the first list.

if [[ ${easystack_file} == *"/rebuilds/"* ]]; then
    ${EB} --easystack ${easystack_file} --rebuild
else
    ${EB} --easystack ${easystack_file} --robot
fi

The directory is the flag. Placing a rebuild in the ordinary easystack file does not cause --rebuild to be passed, and EasyBuild will not overwrite an existing installation. Placing a new package in rebuilds/ causes --rebuild to be passed and bypasses the robot, which is the incorrect command for a package that has not yet been added. The comments at the top of a rebuild file constitute the bill of materials: what was rebuilt, why, and which issue or pull request required it. The CUDA 12.1.1 rebuild from May 2024 is the documented template, including accept-eula-for: CUDA under options:.

How the bot finds the file at all

The bot ignores tickets and commit messages when determining what to build. EESSI-install-software.sh scans the pull request .diff for new or modified YAML files in easystacks/, excludes the CUDA helper easystacks in scripts/gpu_support/, and retains only files whose paths match the repository and the EESSI version this job builds for:

changed_easystacks=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' \
  | sed 's@^[a-z]/@@g' | grep 'easystacks/.*yml$' \
  | egrep -v 'known-issues|missing' \
  | (grep -v "scripts/gpu_support/" || true))

A pull request that edits a README and makes no changes under easystacks/ prints “No missing installations, party time!” and exits green. That is why the contribution is the YAML line, not a comment on the pull request.

EB-Easystack-2 — What the bot will type

A pull request against EESSI/software-layer main adds one file:

easystacks/software.eessi.io/2025.06/rebuilds/20260911-eb-5.3.1-OpenMPI-ofi-fix.yml

The file contains a single item, OpenMPI-5.0.8-GCC-14.3.0.eb, with no options:. The job is building EESSI 2025.06 for x86_64/amd/zen4.

  1. Which EasyBuild version is loaded, and from where is that decided?

  2. What is the eb command the install script will run?

  3. The same pull request also adds a line to eessi-2025.06-eb-5.3.1-2025b.yml. In which order are the two files processed, and why does the order matter?

Solution
  1. EasyBuild 5.3.1. The sed in EESSI-install-software.sh pulls the version out of eb-5.3.1 in the filename. The EESSI version in the path only decides whether this job considers the file.

  2. eb --easystack <that rebuilds file> --rebuild. The /rebuilds/ component is what selects --rebuild over --robot.

  3. Rebuilds first, then new-install files. A rebuild that is meant to replace an OpenMPI the new-install file then depends on has to land before the dependent is planned. The script says so: “first process rebuilds, if any, then easystack files for new installations”.

What to remember

  • An easystack is a YAML list of easyconfig filenames. Per-item options: become eb flags with the dashes stripped, and last-wins means those flags beat the command line.

  • EESSI’s path is easystacks/software.eessi.io/<ver>/eessi-<ver>-eb-<ebver>-<tc>.yml. The EasyBuild version in the name is the module the bot loads.

  • from-commit (or from-pr) is how an unmerged easyconfig is built. Deployment into the repository waits on the EasyBuild merge.

  • A rebuild lives under rebuilds/ and is the only case that passes --rebuild instead of --robot.