Package directive#7317
Draft
evanroyrees wants to merge 6 commits into
Draft
Conversation
Free `package` as an identifier in the v2 lexer/AST builder and allow it as a process directive, scoped to the process-directive section only (it cannot be declared in the Java DirectiveDsl because it is a keyword). Add the `nextflow.preview.package` feature flag (NextflowMeta preview property, honored from the pipeline script or the config file) and the `packages` config scope (default provider, manifest auto-detection). Parse the directive's runtime argument shape (named-args options map, CharSequence/file values) and auto-detect provider manifest files in the process module directory via PackageProvider.getManifestFileNames() and PackageManager.detectSpec(). The directive requires NXF_SYNTAX_PARSER=v2. Signed-off-by: Evan Rees <evanroyrees@gmail.com>
Each package manager is its own nf-<provider> plugin implementing PackageProvider (environment creation, activation, per-process options), with unit tests, registered in settings.gradle: uv (Python venvs), nix, guix, and R via pak and install2.r. All create local-filesystem environments. Each plugin registers its config scope (ConfigScope) so provider settings are recognized by config validation. Signed-off-by: Evan Rees <evanroyrees@gmail.com>
Move extensions.idx to src/resources so the provider extensions are actually packaged and discovered by pf4j (they sat in a non-packaged directory). Remove the plugin's duplicated copies of CondaCache/CondaConfig and reuse the core classes instead -- the duplicate fully-qualified class names were a classloader hazard; the per-process create-options override moves into the core CondaCache (folded into the environment cache hash). Rework PixiConfig as a ConfigScope so the pixi scope is recognized by config validation. Fix pixi: use the [workspace] table instead of the deprecated [project], generate valid TOML dependency entries, declare the host platform, and treat only a regular .pixi file (not the env directory) as the project marker. Add conda/pixi unit tests. Signed-off-by: Evan Rees <evanroyrees@gmail.com>
Map the conda family and pixi to Wave's CONDA build type and skip Wave for local-only providers (uv, nix, guix, pak, install2r), so their environments are built locally instead of being silently mis-built as conda. No Wave functionality is added. Signed-off-by: Evan Rees <evanroyrees@gmail.com>
tests/nf-test provides a tagged nf-test per provider plus fixtures and a shared config; .github/workflows/package-providers.yml runs one CI job per provider (conda, uv, pixi, nix, pak, install2r), provisioning each tool -- nix via the Determinate installer, which sets up the store and daemon on the runner with flakes enabled. guix remains excluded from CI because it has no comparable turnkey provisioning for ephemeral runners; it is exercised via the demo workflows. Multi-provider demo workflows live under tests/nf-test/examples, kept out of the top-level tests glob so the v1 integration suite does not try to parse the package directive. Signed-off-by: Evan Rees <evanroyrees@gmail.com>
docs/package.md (registered in the docs toctree): the provider/plugin/Wave-compatibility matrix, manifest auto-detection and custom-named manifest rules, per-process options, and the v2 parser requirement. Add the `packages` scope to the config reference, the `nextflow.preview.package` entry to the feature-flags reference, and the `package` directive to the process reference. Record the design decision as an ADR (adr/20260707-package-provider-plugins.md) following the convention on master. Signed-off-by: Evan Rees <evanroyrees@gmail.com>
evanroyrees
force-pushed
the
package-directive
branch
from
July 11, 2026 13:44
ded64b5 to
eaf5049
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Generic
packagedirective with pluggable package providersSummary
This PR continues the
package-directiveproof-of-concept from #6342, building it out into acomplete pluggable package-provider system. It adds a generic
packageprocess directive backedby per-manager
nf-<provider>plugins, so each package manager is an independent plugin ratherthan a dedicated process directive:
Lineage: picks up the conda/pixi PoC from #6342 (thanks @edmundmiller) and follows the
maintainer guidance there: a single generic directive with pluggable providers, aligned with
Wave, instead of per-manager directives (as discussed in #7023). New providers address
long-standing requests: nix and guix (#1526) and the R ecosystem via pak and install2.r
(requested in the #6342 review).
What's included
packagedirective under the v2 (strict) syntax parser, thenextflow.preview.packagefeature flag (script header or config), apackagesconfig scope(
packages.provider,packages.autoDetect), and manifest auto-detection. When a process hasno
packagedirective, the process module directory is scanned for a provider manifest(e.g.
environment.yml,requirements.txt,pixi.toml), analogous to Wave's Dockerfileauto-detection.
nf-uv(Python venvs),nf-nix,nf-guix,nf-pakandnf-install2r(R), each implementing thePackageProviderSPI with its own environmentcache, config scope, and unit tests. All create local-filesystem environments.
extensions.idxso the extensions areactually discovered by pf4j, per-process
options:override (folded into the environmentcache hash), pixi fixes (
[workspace]table, valid TOML dependency entries, host platform,.piximarker handling), and removal of the PoC's duplicatedCondaCache/CondaConfigcopies (see design notes).
nf-tests against a dev build.
docs/package.md(in the toctree) plus entries in the config, feature-flags, andprocess references.
adr/20260707-package-provider-plugins.mdrecords the design decision (genericdirective + provider SPI + plugins), the alternatives considered, and the conda-in-core
rationale, following the ADR convention on
master. It is markedproposedsince you arethe deciders. Happy to remove or rework it if you prefer the design discussion to live in
this PR instead.
Design notes (deviations called out per the review guidelines)
packageis a Groovy/Java keyword, so it cannot bedeclared in the
DirectiveDslinterface. The v2 AST builder stops rejectingpackageas anidentifier (the
PACKAGElexer token was already disabled inScriptLexer.g4), and thedirective resolver allows it only in the process-directive section: it is still rejected
as an input/output qualifier or in
output {}blocks, with tests locking this in. The v1parser is untouched; the feature requires
NXF_SYNTAX_PARSER=v2and is gated behindnextflow.preview.package.conda,mamba,micromamba, andpiximap to Wave'sCONDAbuild type, while local-only providers (uv,nix,guix,pak,install2r) skip Wave and are built locally by their plugin. Mixedpipelines work (conda processes built by Wave alongside uv processes created locally). No
Wave functionality is added.
CondaCache/CondaConfigintoplugins/nf-conda, leaving two classes with the same fully-qualified name on differentclassloaders. This PR removes the copies: the plugin reuses the core classes that the legacy
condadirective already depends on, and the per-process options override lives in the coreCondaCache. Fully extracting conda intonf-condais a natural follow-up once the legacydirective is deprecated.
uv,nix,guix,pak,install2r,pixi) and the newpackagesscope implementConfigScopeand are registeredin
extensions.idx, so the strict config validator recognizes them instead of warning.Why five providers in one PR
The SPI is only proven generic by implementations that differ structurally: uv (venv +
lockfile), nix/guix (store/profile model), pak/install2.r (language-level installers), alongside
conda/pixi (env-file model). Each plugin is small (~6 classes), isolated, and independently
testable; dropping any provider is a directory deletion. Happy to split if preferred.
Testing
parser scoping, feature-flag handling, Wave mapping, manifest auto-detection, per-process
options overrides, and expected-failure cases. Full suite green locally (
make testfor thetouched modules:
nextflow,nf-lang, and all provider plugins)..github/workflows/package-providers.ymlruns an nf-test job per provider (conda, uv, pixi,pak, install2r), provisioning each tool on the runner. nix and guix are excluded from CI
because their store/daemon model does not provision cleanly on ephemeral runners; they are
exercised via the demo workflows under
tests/nf-test/examples/.Limitations / follow-ups
conda from core are natural follow-ups.
All commits are DCO signed-off.