Skip to content

Commit

Permalink
Implement automatic sharding for nf-test (#1810)
Browse files Browse the repository at this point in the history
closes #1811 

<!--
# nf-core/sarek pull request

Many thanks for contributing to nf-core/sarek!

Please fill in the appropriate checklist below (delete whatever is not
relevant).
These are the most common things requested on pull requests (PRs).

Remember that PRs should be made against the dev branch, unless you're
preparing a pipeline release.

Learn more about contributing:
[CONTRIBUTING.md](https://github.com/nf-core/sarek/tree/master/.github/CONTRIBUTING.md)
-->

## PR checklist

- [ ] This comment contains a description of changes (with reason).
- [ ] If you've fixed a bug or added code that should be tested, add
tests!
- [ ] If you've added a new tool - have you followed the pipeline
conventions in the [contribution
docs](https://github.com/nf-core/sarek/tree/master/.github/CONTRIBUTING.md)
- [ ] If necessary, also make a PR on the nf-core/sarek _branch_ on the
[nf-core/test-datasets](https://github.com/nf-core/test-datasets)
repository.
- [ ] Make sure your code lints (`nf-core pipelines lint`).
- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker
--outdir <OUTDIR>`).
- [ ] Check for unexpected warnings in debug mode (`nextflow run .
-profile debug,test,docker --outdir <OUTDIR>`).
- [ ] Usage Documentation in `docs/usage.md` is updated.
- [ ] Output Documentation in `docs/output.md` is updated.
- [ ] `CHANGELOG.md` is updated.
- [ ] `README.md` is updated (including new tool citations and
authors/contributors).
  • Loading branch information
maxulysse authored Feb 26, 2025
1 parent 79f9f82 commit 61e7e9e
Show file tree
Hide file tree
Showing 55 changed files with 841 additions and 705 deletions.
66 changes: 66 additions & 0 deletions .github/actions/get-shards/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: "Get number of shards"
description: "Get the number of nf-test shards for the current CI job"
inputs:
max_shards:
description: "Maximum number of shards allowed"
required: true
paths:
description: "Component paths to test"
required: false
outputs:
shard:
description: "Array of shard numbers"
value: ${{ steps.shards.outputs.shard }}
total_shards:
description: "Total number of shards"
value: ${{ steps.shards.outputs.total_shards }}
runs:
using: "composite"
steps:
- name: Install nf-test
uses: nf-core/setup-nf-test@v1
with:
version: ${{ env.NFT_VER }}
- name: Get number of shards
id: shards
shell: bash
run: |
# Run nf-test with dynamic parameter
nftest_output=$(nf-test test \
--dry-run \
--profile +docker \
--filter function,workflow,pipeline \
--ci \
--changed-since HEAD^) || {
echo "nf-test command failed with exit code $?"
echo "Full output: $nftest_output"
exit 1
}
echo "nf-test dry-run output: $nftest_output"
# Default values for shard and total_shards
shard="[]"
total_shards=0
# Check if there are related tests
if echo "$nftest_output" | grep -q 'No tests to execute'; then
echo "No related tests found."
else
# Extract the number of related tests
number_of_shards=$(echo "$nftest_output" | sed -n 's|.*Executed \([0-9]*\) tests.*|\1|p')
if [[ -n "$number_of_shards" && "$number_of_shards" -gt 0 ]]; then
shards_to_run=$(( $number_of_shards < ${{ inputs.max_shards }} ? $number_of_shards : ${{ inputs.max_shards }} ))
shard=$(seq 1 "$shards_to_run" | jq -R . | jq -c -s .)
total_shards="$shards_to_run"
else
echo "Unexpected output format. Falling back to default values."
fi
fi
# Write to GitHub Actions outputs
echo "shard=$shard" >> $GITHUB_OUTPUT
echo "total_shards=$total_shards" >> $GITHUB_OUTPUT
# Debugging output
echo "Final shard array: $shard"
echo "Total number of shards: $total_shards"
124 changes: 124 additions & 0 deletions .github/actions/nf-test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: "nf-test Action"
description: "Runs nf-test with common setup steps"
inputs:
profile:
description: "Profile to use"
required: true
shard:
description: "Shard number for this CI job"
required: true
total_shards:
description: "Total number of test shards(NOT the total number of matrix jobs)"
required: true
paths:
description: "Test paths"
required: true

runs:
using: "composite"
steps:
- name: Setup Nextflow
uses: nf-core/setup-nextflow@v2
with:
version: "${{ env.NXF_VERSION }}"

- name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5
with:
python-version: "3.11"

- name: Install nf-test
uses: nf-core/setup-nf-test@v1
with:
version: "${{ env.NFT_VER }}"

- name: Setup apptainer
if: contains(inputs.profile, 'singularity')
uses: eWaterCycle/setup-apptainer@main

- name: Set up Singularity
if: contains(inputs.profile, 'singularity')
shell: bash
run: |
mkdir -p $NXF_SINGULARITY_CACHEDIR
mkdir -p $NXF_SINGULARITY_LIBRARYDIR
- name: Conda setup
if: ${{inputs.profile == 'conda'}}
uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3
with:
auto-update-conda: true
conda-solver: libmamba
conda-remove-defaults: true

# Set up secrets
- name: Set up nextflow secrets
if: env.SENTIEON_ENCRYPTION_KEY != '' && env.SENTIEON_LICENSE_MESSAGE != ''
shell: bash
run: |
python -m pip install cryptography
nextflow secrets set SENTIEON_AUTH_DATA $(python3 tests/modules/nf-core/sentieon/license_message.py encrypt --key "$SENTIEON_ENCRYPTION_KEY" --message "$SENTIEON_LICENSE_MESSAGE")
- name: Install pdiff
shell: bash
run: |
python -m pip install pdiff
# TODO Skip failing conda tests and document their failures
# https://github.com/nf-core/modules/issues/7017
- name: Run nf-test
shell: bash
env:
NFT_DIFF: ${{ env.NFT_DIFF }}
NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }}
NFT_WORKDIR: ${{ env.NFT_WORKDIR }}
SENTIEON_AUTH_MECH: "GitHub Actions - token"
SENTIEON_LICSRVR_IP: ${{ env.SENTIEON_LICSRVR_IP }}
run: |
nf-test test \
--profile=+${{ inputs.profile }} \
--tap=test.tap \
--verbose \
--ci \
--shard ${{ inputs.shard }}/${{ inputs.total_shards }} \
--filter function,workflow,pipeline
# Save the absolute path of the test.tap file to the output
echo "tap_file_path=$(realpath test.tap)" >> $GITHUB_OUTPUT
- name: Generate test summary
if: always()
shell: bash
run: |
# Add header if it doesn't exist (using a token file to track this)
if [ ! -f ".summary_header" ]; then
echo "# 🚀 nf-test results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Status | Test Name | Profile | Shard |" >> $GITHUB_STEP_SUMMARY
echo "|:------:|-----------|---------|-------|" >> $GITHUB_STEP_SUMMARY
touch .summary_header
fi
if [ -f test.tap ]; then
while IFS= read -r line; do
if [[ $line =~ ^ok ]]; then
test_name="${line#ok }"
# Remove the test number from the beginning
test_name="${test_name#* }"
echo "| ✅ | ${test_name} | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY
elif [[ $line =~ ^not\ ok ]]; then
test_name="${line#not ok }"
# Remove the test number from the beginning
test_name="${test_name#* }"
echo "| ❌ | ${test_name} | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY
fi
done < test.tap
else
echo "| ⚠️ | No test results found | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY
fi
- name: Clean up
if: always()
shell: bash
run: |
sudo rm -rf /home/ubuntu/tests/
50 changes: 0 additions & 50 deletions .github/nf-test-tags.yml

This file was deleted.

Loading

0 comments on commit 61e7e9e

Please sign in to comment.