Skip to content

Commit

Permalink
Merge branch 'master' into fix-gfastats
Browse files Browse the repository at this point in the history
  • Loading branch information
fellen31 authored Jan 16, 2025
2 parents 553a546 + 070b1ad commit 72dae4b
Show file tree
Hide file tree
Showing 4,912 changed files with 156,649 additions and 78,225 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
1,117 changes: 14 additions & 1,103 deletions .github/CODEOWNERS

Large diffs are not rendered by default.

124 changes: 124 additions & 0 deletions .github/actions/nf-test-action/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:
- uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4
with:
distribution: "temurin"
java-version: "17"

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

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

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

- 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@d2e6a045a86077fb6cad6f5adf368e9076ddaa8d # 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")
# TODO Skip failing conda tests and document their failures
# https://github.com/nf-core/modules/issues/7017
- name: Run nf-test
shell: bash
env:
SENTIEON_LICSRVR_IP: ${{ env.SENTIEON_LICSRVR_IP }}
SENTIEON_AUTH_MECH: "GitHub Actions - token"
run: |
NFT_WORKDIR=~ \
nf-test test \
--profile=${{ inputs.profile }} \
--tap=test.tap \
--verbose \
--ci \
--shard ${{ inputs.shard }}/${{ inputs.total_shards }} \
--filter process,workflow \
${{ inputs.paths }}
# 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/
1 change: 0 additions & 1 deletion .github/env-template.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
channels:
- conda-forge
- bioconda
- defaults
101 changes: 26 additions & 75 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -1,79 +1,30 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: ["config:best-practices"],
vulnerabilityAlerts: {
labels: ["security"],
schedule: "at any time",
},
prHourlyLimit: 3,
platform: "github",
onboarding: false,
dependencyDashboard: true,
dependencyDashboardTitle: "Renovate Dashboard 🤖",
suppressNotifications: ["prIgnoreNotification"],
rebaseWhen: "conflicted",
reviewers: ["team:modules"],
assigneesFromCodeOwners: true,
gitAuthor: "nf-core-bot <renovate@nf-co.re>",
prHeader: "## WARNING\n - [ ] I have made sure to update the singularity and conda images",
"pre-commit": {
enabled: true,
},
customManagers: [
// TODO waiting on https://github.com/nf-core/modules/pull/4080
// {
// customType: "regex",
// description: "Process Containers dependencies",
// fileMatch: ["(^|/)main\\.nf$"],
// matchStrings: [
// "\\s+'(?<depName>\\S+):(?<currentValue>.*\\-.*)' }\"\n",
// ],
// datasourceTemplate: "docker",
// },
// {
// customType: "regex",
// description: "Upgrade conda dependencies",
// fileMatch: ["(^|/)environment(.*).ya?ml$"],
// matchStrings: [
// '#\\s*renovate\\s+datasource=conda\\s+depName=(?<depName>.*?)\\s+-\\s*[\\w-]+\\s*==?\\s*"?(?<currentValue>.*)"?',
// '# renovate: datasource=conda depName=(?<depName>.*?)\\s+-\\s*[\\w-]+\\s*==?\\s*"?(?<currentValue>.*)"?',
// ],
// datasourceTemplate: "conda",
// },
// {
// customType: "regex",
// description: "Upgrade pypi dependencies inside conda environment files",
// fileMatch: ["(^|/)environment(.*).ya?ml$"],
// matchStrings: [
// "# renovate datasource=pypi\\s+-\\s*(?<depName>[\\w-]+)\\s*(\\[[\\w,\\s]+\\])?\\s*==?\\s*(?<currentValue>.*)",
// "# renovate: datasource=pypi\\s+-\\s*(?<depName>[\\w-]+)\\s*(\\[[\\w,\\s]+\\])?\\s*==?\\s*(?<currentValue>.*)",
// ],
// datasourceTemplate: "pypi",
// },
],
packageRules: [
{
matchDatasources: ["docker"],
registryUrls: ["quay.io"],
},
{
matchManagers: ["github-actions"],
automerge: true,
pinDigest: {
enabled: false,
},
matchPackageNames: ["/^nf-core//", "/^seqera/"],
},
{
matchManagers: ["github-actions"],
groupName: "GitHub Actions",
automerge: true,
schedule: ["before 9am"],
},
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"github>nf-core/ops//.github/renovate/default.json5",
"github>nf-core/ops//.github/renovate/process_updaters.json5"
],
"prHeader": "## WARNING\n - [ ] I have made sure to update the singularity and conda images",
"packageRules": [
{
automerge: true,
schedule: ["before 9am on Monday"],
matchPackageNames: ["/renovate-config-validator/"],
},
"matchDatasources": [
"conda",
"pypi",
"docker"
],
"automerge": false
}
],
"customManagers": [
{
"customType": "regex",
"fileMatch": [
"(^|/)(workflow-templates|\\.(?:github|gitea|forgejo)/(?:workflows|actions))/.+\\.ya?ml$",
"(^|/)action\\.ya?ml$"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-z-.]+?) depName=(?<depName>[^\\s]+?)(?: (?:lookupName|packageName)=(?<packageName>[^\\s]+?))?(?: versioning=(?<versioning>[^\\s]+?))?(?: extractVersion=(?<extractVersion>[^\\s]+?))?\\s+[A-Za-z0-9_]+?_VER(SION)?\\s*:\\s*[\"']?(?<currentValue>.+?)[\"']?\\s"
]
}
]
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 4 additions & 6 deletions .github/scripts/license_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
import re
import secrets
import sys
from datetime import datetime as dt

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from datetime import datetime as dt

MESSAGE_TIMEOUT = 60 * 60 * 24 # Messages are valid for 1 day
NONCE_BYTES = 12


class DecryptionTimeout(Exception):
class DecryptionTimeoutError(Exception):
# Decrypting a message that is too old
pass

Expand Down Expand Up @@ -60,7 +60,7 @@ def decrypt_message(key, ciphertext, timeout=MESSAGE_TIMEOUT):
msg_timestamp = int.from_bytes(msg_timestamp, byteorder="big")
timestamp = calendar.timegm(dt.now().utctimetuple())
if (timestamp - msg_timestamp) > timeout:
raise DecryptionTimeout("The message has an expired timeout")
raise DecryptionTimeoutError("The message has an expired timeout")
return message.decode("utf-8")


Expand All @@ -82,9 +82,7 @@ def parse_args(argv=None):

subparsers = parser.add_subparsers(help="Available sub-commands")

gen_parser = subparsers.add_parser(
"generate_key", help="Generate a random key string"
)
gen_parser = subparsers.add_parser("generate_key", help="Generate a random key string")
gen_parser.set_defaults(func=handle_generate_key)

encrypt_parser = subparsers.add_parser("encrypt", help="Encrypt a message")
Expand Down
File renamed without changes.
88 changes: 88 additions & 0 deletions .github/scripts/wave_singularity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "requests",
# "rich",
# "rich_click"
# ]
# ///

import logging

import requests
import rich_click as click
from rich.logging import RichHandler

# Replace the basic logger setup with rich logging
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
handlers=[
RichHandler(
rich_tracebacks=True,
show_time=False,
markup=True,
)
],
)
logger = logging.getLogger(__name__)
click.rich_click.SHOW_ARGUMENTS = True


@click.command()
@click.option(
"--platform-pat",
envvar="SEQERA_ACCESS_TOKEN",
show_envvar=True,
help="Platform authentication token",
)
@click.argument("image_name")
def main(image_name, platform_pat):
"""Script to return a HTTPS Singularity image URL from Seqera Containers."""

if image_name.startswith("oras://"):
image_name = image_name.replace("oras://", "")

wave_api_url_base = "https://wave.seqera.io"
wave_api_url = f"{wave_api_url_base}/v1alpha1/inspect"
container_url_base = "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256"

request_data = {"containerImage": image_name}
if platform_pat:
request_data["toweraccesstoken"] = platform_pat
else:
logger.debug("'--platform-pat' / '$TOWER_ACCESS_TOKEN' not set, no auth to wave back end")

try:
logger.debug(f"Calling image inspect at {wave_api_url} for image url '{image_name}'")
response = requests.post(
url=wave_api_url,
json=request_data,
headers={"content-type": "application/json"},
)

data = response.json()
logger.debug(data)
layers = data.get("container", {}).get("manifest", {}).get("layers", [])
is_singularity = len(layers) == 1 and layers[0].get("mediaType", "").endswith(".sif")
logger.debug(layers)
if not is_singularity:
raise ValueError("Not a singularity image")
if "digest" not in layers[0]:
raise ValueError("no 'digest' in first layer found")

digest = layers[0]["digest"].replace("sha256:", "")
container_url = f"{container_url_base}/{digest[:2]}/{digest}/data"
print(container_url)

except requests.RequestException as exc:
raise ValueError(f"An error occurred while requesting {wave_api_url}\n {exc}")


if __name__ == "__main__":
try:
main()
except ValueError as exc:
logger.error(f"[red]{exc}[/red]")
exit(1)
Loading

0 comments on commit 72dae4b

Please sign in to comment.