Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eb2f709
`dev` -> `main` for 4.1.0 (#4429)
mashehu Jul 29, 2026
9b35ede
Add basic support to Apple container
mribeirodantas Aug 16, 2026
01219ae
Add support to Apple container downloading images
mribeirodantas Aug 16, 2026
a14bd27
Finishing touches to the Apple container support
mribeirodantas Aug 16, 2026
2c8137a
[automated] Fix code linting
nf-core-bot Aug 16, 2026
6fac7ca
Add snapshot file for RunTestWorkflow (apple_container)
mribeirodantas Aug 16, 2026
6a0f043
'nf-core modules test module --profile' now supports apple container
mribeirodantas Aug 20, 2026
34cc95e
Update Textual snapshots for Apple Container feature
mribeirodantas Aug 20, 2026
92173be
Merge branch 'dev' into support2appleContainer
mribeirodantas Aug 20, 2026
57ab00f
feat(appleContainer): enable Wave arm64 provisioning and document limits
mribeirodantas Aug 21, 2026
617d9c7
Add mock build registry so CI stops complaining about nextflow inspect
mribeirodantas Aug 21, 2026
3e8e906
fix(test): don't route mock container fixture through Wave in appleCo…
mribeirodantas Aug 21, 2026
9ef2889
fix(ci): pin Nextflow version in CodSpeed workflow
Copilot Aug 21, 2026
f4171b6
fix(appleContainer): emulate amd64 by default instead of Wave/arm64-only
mribeirodantas Aug 24, 2026
e372c38
Fix linting error in GitHub Action
mribeirodantas Aug 24, 2026
867220d
feat(appleContainer): make appleContainerWave a self-contained, selec…
mribeirodantas Aug 24, 2026
21abd60
Apply suggestion from reviewer
mribeirodantas Aug 25, 2026
81dea56
Apply batched suggestions from code review
mribeirodantas Aug 31, 2026
55e2308
Revert this change
mribeirodantas Aug 31, 2026
c0b6844
add appleContainerWave to usage docs
mribeirodantas Aug 31, 2026
e8e1071
Update apple container profile names to snake case capitalization
mribeirodantas Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions .github/snapshots/apple_container.nf.test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"-profile test": {
"content": [
{
"FASTQC": {
"fastqc": "0.12.1"
},
"Workflow": {
"my-prefix/testpipeline": "v1.0.0dev"
}
},
[
"fastqc",
"fastqc/SAMPLE1_PE_1_fastqc.html",
"fastqc/SAMPLE1_PE_1_fastqc.zip",
"fastqc/SAMPLE1_PE_2_fastqc.html",
"fastqc/SAMPLE1_PE_2_fastqc.zip",
"fastqc/SAMPLE2_PE_1_fastqc.html",
"fastqc/SAMPLE2_PE_1_fastqc.zip",
"fastqc/SAMPLE2_PE_2_fastqc.html",
"fastqc/SAMPLE2_PE_2_fastqc.zip",
"fastqc/SAMPLE3_SE_1_fastqc.html",
"fastqc/SAMPLE3_SE_1_fastqc.zip",
"fastqc/SAMPLE3_SE_2_fastqc.html",
"fastqc/SAMPLE3_SE_2_fastqc.zip",
"multiqc",
"multiqc/multiqc_data",
"multiqc/multiqc_data/fastqc-status-check-heatmap.txt",
"multiqc/multiqc_data/fastqc_overrepresented_sequences_plot.txt",
"multiqc/multiqc_data/fastqc_per_base_n_content_plot.txt",
"multiqc/multiqc_data/fastqc_per_base_sequence_quality_plot.txt",
"multiqc/multiqc_data/fastqc_per_sequence_gc_content_plot_Counts.txt",
"multiqc/multiqc_data/fastqc_per_sequence_gc_content_plot_Percentages.txt",
"multiqc/multiqc_data/fastqc_per_sequence_quality_scores_plot.txt",
"multiqc/multiqc_data/fastqc_sequence_counts_plot.txt",
"multiqc/multiqc_data/fastqc_sequence_duplication_levels_plot.txt",
"multiqc/multiqc_data/fastqc_sequence_length_distribution_plot.txt",
"multiqc/multiqc_data/fastqc_top_overrepresented_sequences_table.txt",
"multiqc/multiqc_data/llms-full.txt",
"multiqc/multiqc_data/multiqc.log",
"multiqc/multiqc_data/multiqc.parquet",
"multiqc/multiqc_data/multiqc_citations.txt",
"multiqc/multiqc_data/multiqc_data.json",
"multiqc/multiqc_data/multiqc_fastqc.txt",
"multiqc/multiqc_data/multiqc_general_stats.txt",
"multiqc/multiqc_data/multiqc_software_versions.txt",
"multiqc/multiqc_data/multiqc_sources.txt",
"multiqc/multiqc_plots",
"multiqc/multiqc_plots/pdf",
"multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf",
"multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf",
"multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf",
"multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf",
"multiqc/multiqc_plots/pdf/fastqc_per_sequence_gc_content_plot_Counts.pdf",
"multiqc/multiqc_plots/pdf/fastqc_per_sequence_gc_content_plot_Percentages.pdf",
"multiqc/multiqc_plots/pdf/fastqc_per_sequence_quality_scores_plot.pdf",
"multiqc/multiqc_plots/pdf/fastqc_sequence_counts_plot-cnt.pdf",
"multiqc/multiqc_plots/pdf/fastqc_sequence_counts_plot-pct.pdf",
"multiqc/multiqc_plots/pdf/fastqc_sequence_duplication_levels_plot.pdf",
"multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf",
"multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf",
"multiqc/multiqc_plots/png",
"multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png",
"multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png",
"multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png",
"multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png",
"multiqc/multiqc_plots/png/fastqc_per_sequence_gc_content_plot_Counts.png",
"multiqc/multiqc_plots/png/fastqc_per_sequence_gc_content_plot_Percentages.png",
"multiqc/multiqc_plots/png/fastqc_per_sequence_quality_scores_plot.png",
"multiqc/multiqc_plots/png/fastqc_sequence_counts_plot-cnt.png",
"multiqc/multiqc_plots/png/fastqc_sequence_counts_plot-pct.png",
"multiqc/multiqc_plots/png/fastqc_sequence_duplication_levels_plot.png",
"multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png",
"multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png",
"multiqc/multiqc_plots/svg",
"multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg",
"multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg",
"multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg",
"multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg",
"multiqc/multiqc_plots/svg/fastqc_per_sequence_gc_content_plot_Counts.svg",
"multiqc/multiqc_plots/svg/fastqc_per_sequence_gc_content_plot_Percentages.svg",
"multiqc/multiqc_plots/svg/fastqc_per_sequence_quality_scores_plot.svg",
"multiqc/multiqc_plots/svg/fastqc_sequence_counts_plot-cnt.svg",
"multiqc/multiqc_plots/svg/fastqc_sequence_counts_plot-pct.svg",
"multiqc/multiqc_plots/svg/fastqc_sequence_duplication_levels_plot.svg",
"multiqc/multiqc_plots/svg/fastqc_sequence_length_distribution_plot.svg",
"multiqc/multiqc_plots/svg/fastqc_top_overrepresented_sequences_table.svg",
"multiqc/multiqc_report.html",
"pipeline_info",
"pipeline_info/testpipeline_software_mqc_versions.yml"
],
[
"fastqc-status-check-heatmap.txt:md5,0f1975c565a16bf09be08a05c204ded7",
"fastqc_overrepresented_sequences_plot.txt:md5,4b23cea39c4e23deef6b97810bc1ee46",
"fastqc_per_base_n_content_plot.txt:md5,037692101c0130c72493d3bbfa3afac1",
"fastqc_per_base_sequence_quality_plot.txt:md5,bfe735f3e31befe13bdf6761bb297d6e",
"fastqc_per_sequence_gc_content_plot_Counts.txt:md5,7108d19c46ef7883e864ba274c457d2e",
"fastqc_per_sequence_gc_content_plot_Percentages.txt:md5,23f527c80a148e4f34e5a43f6e520a90",
"fastqc_per_sequence_quality_scores_plot.txt:md5,a0cc0e6df7bfb05257da1cfc88b13c50",
"fastqc_sequence_counts_plot.txt:md5,c6e4e1588e6765fe8df27812a1322fbd",
"fastqc_sequence_duplication_levels_plot.txt:md5,3cde2db4033f6c64648976d1174db925",
"fastqc_sequence_length_distribution_plot.txt:md5,e82b9b14a7e24c0c5f27af97cebb6870",
"multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f",
"multiqc_fastqc.txt:md5,1a41c2158adc9947bff9232962f70110",
"multiqc_general_stats.txt:md5,0b54e4e764665bd57fe0f95216744a78"
]
],
"meta": {
"nf-test": "0.9.3",
"nextflow": "25.10.4"
},
"timestamp": "2025-06-16T14:29:10.076573"
}
}
2 changes: 1 addition & 1 deletion .github/workflows/codspeed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- name: Install Nextflow
uses: nf-core/setup-nextflow@893c28b667aedeba26e37f296d260ccc5bc4d914 # v3
with:
version: ${{ github.event.inputs.nextflow-version || matrix.nextflow-version }}
version: "25.10.4"
Comment thread
mribeirodantas marked this conversation as resolved.
Outdated

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
Expand Down
6 changes: 3 additions & 3 deletions nf_core/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def command_pipelines_lint(
@click.option(
"-s",
"--container-system",
type=click.Choice(["none", "singularity", "docker", "apptainer"]),
type=click.Choice(["none", "singularity", "docker", "apptainer", "appleContainer"]),
help="Download container images of required software.",
)
@click.option(
Expand Down Expand Up @@ -1303,7 +1303,7 @@ def command_modules_create(
)
@click.option(
"--profile",
type=click.Choice(["docker", "singularity", "conda"]),
type=click.Choice(["docker", "singularity", "conda", "appleContainer", "appleContainerWave"]),
default=None,
help="Run tests with a specific profile",
)
Expand Down Expand Up @@ -1665,7 +1665,7 @@ def command_subworkflows_create(ctx, subworkflow, directory, author, force):
)
@click.option(
"--profile",
type=click.Choice(["docker", "singularity", "conda"]),
type=click.Choice(["docker", "singularity", "conda", "appleContainer", "appleContainerWave"]),
default=None,
help="Run tests with a specific profile",
)
Expand Down
10 changes: 8 additions & 2 deletions nf_core/components/components_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,16 @@ def check_inputs(self) -> None:
"type": "list",
"name": "profile",
"message": "Choose container software to run the test with",
"choices": ["Docker", "Singularity", "Conda"],
"choices": ["Docker", "Singularity", "Conda", "Apple Container", "Apple Container (Wave/arm64)"],
}
answer = questionary.unsafe_prompt([question], style=nf_core.utils.nfcore_question_style)
profile = answer["profile"].lower()
profile = answer["profile"]
# Map display names to Nextflow profile names
profile_map = {
"Apple Container": "appleContainer",
"Apple Container (Wave/arm64)": "appleContainerWave",
}
profile = profile_map.get(profile, profile.lower())
os.environ["PROFILE"] = profile

def display_nftest_output(self, nftest_out: bytes, nftest_err: bytes) -> None:
Expand Down
1 change: 1 addition & 0 deletions nf_core/pipeline-template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)
[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)
[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)
[![run with apple container](https://img.shields.io/badge/run%20with-apple%20container-000000.svg?labelColor=000000&logo=apple)](https://github.com/apple/container)
[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/{{ name }})

{% endif -%}
Expand Down
4 changes: 3 additions & 1 deletion nf_core/pipeline-template/docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,12 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof
- A generic configuration profile to be used with [Charliecloud](https://charliecloud.io/)
- `apptainer`
- A generic configuration profile to be used with [Apptainer](https://apptainer.org/)
- `appleContainer`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document appleContainerWave as well?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this camelCase? Should it not be snake_case?
could we just call apple?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confusing to just call it apple imo

@mribeirodantas mribeirodantas Aug 31, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nextflow uses appleContainer, so I kept it on our side, but I agree we should go with snake_case as for the other profiles. It's just that the user will see both capitalizations, such as appleContainer.enabled = true, but the profile is named apple_container. I will update the mentions in the profile to snake case.

As for the actual name, I agree with @mashehu that apple is not clear enough.

- A generic configuration profile to be used with [Apple container](https://github.com/apple/container) on macOS (Apple silicon)
- `wave`
- A generic configuration profile to enable [Wave](https://seqera.io/wave/) containers. Use together with one of the above (requires Nextflow `24.03.0-edge` or later).
- `conda`
- A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer.
- A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, or Apple container.

### `-resume`

Expand Down
76 changes: 68 additions & 8 deletions nf_core/pipeline-template/nextflow.config
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ params {
{%- if test_config %}
pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/'{% endif %}
trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss')
{%- if apple_container %}

// Apple Container options
// When true, the appleContainer profile emulates amd64 images with Rosetta
// (faster) instead of the default plain amd64 emulation. Requires Rosetta
// installed in the host OS.
apple_rosetta = false
{%- endif %}
{%- if nf_core_configs %}

// Config options
Expand Down Expand Up @@ -107,8 +115,9 @@ profiles {
podman.enabled = false
shifter.enabled = false
charliecloud.enabled = false
conda.channels = ['conda-forge', 'bioconda']
apptainer.enabled = false
appleContainer.enabled = false
conda.channels = ['conda-forge', 'bioconda']
}
mamba {
conda.enabled = true
Expand All @@ -119,6 +128,7 @@ profiles {
shifter.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
appleContainer.enabled = false
}
docker {
docker.enabled = true
Expand All @@ -128,6 +138,7 @@ profiles {
shifter.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
appleContainer.enabled = false
docker.runOptions = '-u $(id -u):$(id -g)'
}
arm64 {
Expand All @@ -153,6 +164,7 @@ profiles {
shifter.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
appleContainer.enabled = false
}
podman {
podman.enabled = true
Expand All @@ -162,6 +174,7 @@ profiles {
shifter.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
appleContainer.enabled = false
}
shifter {
shifter.enabled = true
Expand All @@ -171,6 +184,7 @@ profiles {
podman.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
appleContainer.enabled = false
}
charliecloud {
charliecloud.enabled = true
Expand All @@ -180,6 +194,7 @@ profiles {
podman.enabled = false
shifter.enabled = false
apptainer.enabled = false
appleContainer.enabled = false
}
apptainer {
apptainer.enabled = true
Expand All @@ -190,6 +205,50 @@ profiles {
podman.enabled = false
shifter.enabled = false
charliecloud.enabled = false
appleContainer.enabled = false
}
appleContainer {
appleContainer.enabled = true
conda.enabled = false
docker.enabled = false
singularity.enabled = false
podman.enabled = false
shifter.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
// Apple Container runs natively on Apple Silicon (arm64), but like
// Docker it can also run amd64 images via emulation. Since most nf-core
// modules ship amd64 container images, emulate amd64 by default so
// standard pipelines run without any Wave dependency. Set
// `--apple_rosetta` to use faster Rosetta emulation (requires Rosetta
// installed in the Apple Container VM).
process.arch = 'linux/amd64'
appleContainer.runOptions = params.apple_rosetta ? '--platform linux/amd64 --rosetta' : '--platform linux/amd64'
}
appleContainerWave {
// Self-contained Apple Container + Wave profile: provision native arm64
// images from conda via Wave instead of emulating amd64. Usable on its
// own (`-profile appleContainerWave`, e.g. with
// `nf-core modules test --profile appleContainer`-style single-profile
// callers) or composed after appleContainer
// (`-profile appleContainer,appleContainerWave`). Faster per task when
// an arm64 build exists, but only works for tools with an arm64 (conda
// linux-aarch64 / multi-arch) build available, and pushes frozen images
// to a registry (set TOWER_ACCESS_TOKEN for durable, reproducible
// builds).
appleContainer.enabled = true
conda.enabled = false
docker.enabled = false
singularity.enabled = false
podman.enabled = false
shifter.enabled = false
charliecloud.enabled = false
apptainer.enabled = false
process.arch = 'arm64'
appleContainer.runOptions = ''
wave.enabled = true
wave.freeze = true
wave.strategy = 'conda,container'
}
wave {
apptainer.ociAutoPull = true
Expand Down Expand Up @@ -236,14 +295,15 @@ includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !pa
// includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/pipeline/{{ short_name }}.config" : "/dev/null"
{%- endif %}

// Set default registry for Apptainer, Docker, Podman, Charliecloud and Singularity independent of -profile
// Will not be used unless Apptainer / Docker / Podman / Charliecloud / Singularity are enabled
// Set default registry for Apptainer, Docker, Podman, Charliecloud, Singularity and Apple container independent of -profile
// Will not be used unless Apptainer / Docker / Podman / Charliecloud / Singularity / Apple container are enabled
// Set to your registry if you have a mirror of containers
apptainer.registry = 'quay.io'
docker.registry = 'quay.io'
podman.registry = 'quay.io'
singularity.registry = 'quay.io'
charliecloud.registry = 'quay.io'
apptainer.registry = 'quay.io'
appleContainer.registry = 'quay.io'
docker.registry = 'quay.io'
podman.registry = 'quay.io'
singularity.registry = 'quay.io'
charliecloud.registry = 'quay.io'

{% if igenomes -%}
// Load igenomes.config if required
Expand Down
9 changes: 8 additions & 1 deletion nf_core/pipeline-template/nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,14 @@
"fa_icon": "far calendar",
"description": "Suffix to add to the trace report filename. Default is the date and time in the format yyyy-MM-dd_HH-mm-ss.",
"hidden": true
}{% if nf_schema %},
}{% if apple_container %},
"apple_rosetta": {
"type": "boolean",
"fa_icon": "fab fa-apple",
"description": "Use faster Rosetta amd64 emulation in the appleContainer profile instead of plain amd64 emulation.",
"help_text": "Only applies to the `appleContainer` profile. When `true`, amd64 container images are emulated with Rosetta (faster) instead of the default plain amd64 emulation. Requires Rosetta to be installed in the Apple Container VM.",
Comment thread
mribeirodantas marked this conversation as resolved.
Outdated
"hidden": true
}{% endif %}{% if nf_schema %},
"help": {
"type": ["boolean", "string"],
"description": "Display the help message."
Expand Down
2 changes: 2 additions & 0 deletions nf_core/pipelines/containers_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"singularity_oras_arm64": ["singularity", "linux/arm64", "name"],
"singularity_https_amd64": ["singularity", "linux/amd64", "https"],
"singularity_https_arm64": ["singularity", "linux/arm64", "https"],
"appleContainer_amd64": ["docker", "linux/amd64", "name"],
"appleContainer_arm64": ["docker", "linux/arm64", "name"],
"conda_lock_files_amd64": ["conda", "linux/amd64", "lock_file"],
"conda_lock_files_arm64": ["conda", "linux/arm64", "lock_file"],
}
Expand Down
Loading
Loading