diff --git a/.gitignore b/.gitignore index 0eb3ce9..60ad61e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ testing* null/ .idea/ test_data + +# Ignore Nextflow test output files, which may contain sensitive information and are not relevant to the repository. +.nf-test* diff --git a/modules/local/ena_webin_cli/main.nf b/modules/local/ena_webin_cli/main.nf index 25b12f4..b82a08a 100644 --- a/modules/local/ena_webin_cli/main.nf +++ b/modules/local/ena_webin_cli/main.nf @@ -5,8 +5,11 @@ process ENA_WEBIN_CLI { container "quay.io/biocontainers/ena-webin-cli:9.0.1--hdfd78af_1" stageInMode 'copy' - secret 'WEBIN_ACCOUNT' - secret 'WEBIN_PASSWORD' + // Require authentication secrets for real runs, but not for mock testing. + if (!params.webincli_mock) { + secret 'WEBIN_ACCOUNT' + secret 'WEBIN_PASSWORD' + } input: tuple val(meta), path(submission_item), path(manifest) @@ -29,12 +32,12 @@ process ENA_WEBIN_CLI { export ITEM_FULL_PATH=\$(readlink -f ${submission_item}) sed 's|^FASTA\t.*|FASTA\t'"\${ITEM_FULL_PATH}"'|g' ${manifest} > ${prefix}_updated_manifest.manifest - ena-webin-cli \\ - -context=genome \\ - -manifest=${prefix}_updated_manifest.manifest \\ - -userName="\${WEBIN_ACCOUNT}" \\ - -password="\${WEBIN_PASSWORD}" \\ - ${submit_or_validate} \\ + ena-webin-cli \ + -context=genome \ + -manifest=${prefix}_updated_manifest.manifest \ + -userName="\${WEBIN_ACCOUNT}" \ + -password="\${WEBIN_PASSWORD}" \ + ${submit_or_validate} \ ${mode} mv webin-cli.report "${prefix}_webin-cli.report" @@ -53,6 +56,10 @@ process ENA_WEBIN_CLI { # there was attempt to re-submit already submitted genome export STATUS="success" true + elif grep -q "Submission(s) validated successfully" "${prefix}_webin-cli.report"; then + # we ran with -validate flag + export STATUS="success" + true else export STATUS="failed" false diff --git a/modules/local/ena_webin_cli/main.nf.test b/modules/local/ena_webin_cli/main.nf.test new file mode 100644 index 0000000..0569425 --- /dev/null +++ b/modules/local/ena_webin_cli/main.nf.test @@ -0,0 +1,119 @@ +nextflow_process { + name "Test Process ENA_WEBIN_CLI" + script "modules/local/ena_webin_cli/main.nf" + process "ENA_WEBIN_CLI" + + // Set WEBINCLI_TEST_MOCK=true to run against a mocked ena-webin-cli. + def useMocking = (System.getenv('WEBINCLI_TEST_MOCK') ?: 'false').toBoolean() + def launchDir = System.getProperty('user.dir') + def mockConfigPath = "${launchDir}/modules/local/ena_webin_cli/test-mocking/nextflow.config" + + test("Run validate with no failures") { + + if (useMocking) { + options "-c ${mockConfigPath}" + } + + when { + params { + webincli_submit = false + webincli_mock = useMocking + } + process { + """ + input[0] = Channel.of( + tuple( + [id: 'lachnospira_eligens'], + file("https://github.com/nf-core/test-datasets/raw/refs/heads/seqsubmit/test_data/bins/bin_lachnospira_eligens.fa.gz", checkIfExists: true), + file("https://github.com/nf-core/test-datasets/raw/refs/heads/seqsubmit/test_data/lachnospira_eligens.manifest", checkIfExists: true) + ) + ) + """ + } + } + + then { + assertAll { + assert process.success + assert process.out.upload_status[0][1] == 'success' + def report_lines = path(process.out.webin_report[0][1]).readLines() + // When mocking it validates the parameters are passed correctly, but doesn't actually run the submission, + // so we check for the presence of the parameters in the report. + if (useMocking) { + assert report_lines.any { it.contains("MOCK WEBIN RUN") } + assert report_lines.any { it.contains("-context=genome") } + assert report_lines.any { it.contains("-manifest=lachnospira_eligens_updated_manifest.manifest") } + assert report_lines.any { it.contains("-validate") } + } + assert report_lines.any { it.contains("Submission(s) validated successfully") } + assert snapshot(process.out.versions).match() + } + } + + } + + test("Run push with no failures") { + if (useMocking) { + options "-c ${mockConfigPath}" + } + + setup { + run("GENERATE_TEST_DATA") { + script "./setup_test.nf" + process { + """ + input[0] = Channel.of( + file("https://github.com/nf-core/test-datasets/raw/refs/heads/seqsubmit/test_data/lachnospira_eligens.manifest", checkIfExists: true) + ) + """ + } + } + + } + + when { + params { + webincli_submit = true + test_upload = true + webincli_mock = useMocking + } + process { + """ + def fasta = file("https://github.com/nf-core/test-datasets/raw/refs/heads/seqsubmit/test_data/bins/bin_lachnospira_eligens.fa.gz", checkIfExists: true) + + input[0] = GENERATE_TEST_DATA.out.test_manifest.map { manifest -> + tuple( + [id: 'lachnospira_eligens'], + fasta, + file(manifest) + ) + } + """ + } + } + + then { + assertAll { + assert process.success + assert process.out.upload_status[0][1] == 'success' + def report_lines = path(process.out.webin_report[0][1]).readLines() + // When mocking it validates the parameters are passed correctly, but doesn't actually run the submission, + // so we check for the presence of the parameters in the report. + if (useMocking) { + assert report_lines.any { it.contains("MOCK WEBIN RUN") } + assert report_lines.any { it.contains("-context=genome") } + assert report_lines.any { it.contains("-manifest=lachnospira_eligens_updated_manifest.manifest") } + assert report_lines.any { it.contains("-submit") } + assert report_lines.any { it.contains("-test") } + } + assert report_lines.any { it.contains("Submission(s) validated successfully") } + assert report_lines.any { it.contains("The submission has been completed successfully") } + assert report_lines.any { it.contains("This was a TEST submission(s)") } + assert snapshot(process.out.versions).match() + + } + } + + } + +} diff --git a/modules/local/ena_webin_cli/main.nf.test.snap b/modules/local/ena_webin_cli/main.nf.test.snap new file mode 100644 index 0000000..ef27c95 --- /dev/null +++ b/modules/local/ena_webin_cli/main.nf.test.snap @@ -0,0 +1,26 @@ +{ + "Run validate with no failures": { + "content": [ + [ + "versions.yml:md5,a38fb03bead632d71062a101d7889ded" + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-29T14:09:00.202532371" + }, + "Run push with no failures": { + "content": [ + [ + "versions.yml:md5,a38fb03bead632d71062a101d7889ded" + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-29T14:01:42.491885321" + } +} \ No newline at end of file diff --git a/modules/local/ena_webin_cli/setup_test.nf b/modules/local/ena_webin_cli/setup_test.nf new file mode 100644 index 0000000..9b71031 --- /dev/null +++ b/modules/local/ena_webin_cli/setup_test.nf @@ -0,0 +1,17 @@ +process GENERATE_TEST_DATA { + label 'process_low' + container "quay.io/biocontainers/ena-webin-cli:9.0.1--hdfd78af_1" + + input: + path(manifest_template) + + output: + path("*.manifest"), emit: test_manifest + + script: + """ + timestamp="\$(date +%s)" + + sed -E "s/^(ASSEMBLYNAME\t[^\t]+)/\\1_\${timestamp}/" "${manifest_template}" > "lachnospira_eligens_dynamic_fixture.manifest" + """ +} diff --git a/modules/local/ena_webin_cli/test-mocking/ena-webin-cli b/modules/local/ena_webin_cli/test-mocking/ena-webin-cli new file mode 100755 index 0000000..fa67290 --- /dev/null +++ b/modules/local/ena_webin_cli/test-mocking/ena-webin-cli @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Mock ena-webin-cli script for testing without credentials. +set -euo pipefail + +# Verify that a real ena-webin-cli exists somewhere in PATH beyond this mock. +real_bin="$(which -a ena-webin-cli 2>/dev/null | grep -v "$(realpath "$0")" | head -1 || true)" +if [[ -z "$real_bin" ]]; then + echo "FATAL: No real ena-webin-cli found in PATH besides this mock." >&2 + exit 666 +fi + +# Outputs the version of the real ena-webin-cli when called with -version, to allow testing of version parsing logic. +if [[ "${1:-}" == "-version" ]]; then + echo $(${real_bin} -version 2>&1) + exit 0 +fi + +manifest="" +action="" +mode="" + +for arg in "$@"; do + case "$arg" in + -manifest=*) + manifest="${arg#-manifest=}" + ;; + -submit|-validate) + action="$arg" + ;; + -test) + mode="$arg" + ;; + esac +done + +if [[ -z "$manifest" || -z "$action" ]]; then + echo "Mock ena-webin-cli: missing required arguments" >&2 + exit 1 +fi + +prefix="$(basename "$manifest")" +prefix="${prefix%_updated_manifest.manifest}" + +template_dir="${WEBINCLI_MOCK_TEMPLATE_DIR:-.}" +if [[ "$action" == "-submit" ]]; then + template="$template_dir/mock_submit.report" +else + template="$template_dir/mock_validate.report" +fi + +if [[ ! -f "$template" ]]; then + echo "Mock template file not found: $template" >&2 + exit 1 +fi + +sed \ + -e "s||$prefix|g" \ + -e "s||$action|g" \ + -e "s||$mode|g" \ + "$template" > webin-cli.report diff --git a/modules/local/ena_webin_cli/test-mocking/mock_submit.report b/modules/local/ena_webin_cli/test-mocking/mock_submit.report new file mode 100644 index 0000000..692b300 --- /dev/null +++ b/modules/local/ena_webin_cli/test-mocking/mock_submit.report @@ -0,0 +1,5 @@ +INFO : MOCK WEBIN RUN +INFO : command=ena-webin-cli -context=genome -manifest=_updated_manifest.manifest +INFO : Submission(s) validated successfully +INFO : The submission has been completed successfully +INFO : This was a TEST submission(s) diff --git a/modules/local/ena_webin_cli/test-mocking/mock_validate.report b/modules/local/ena_webin_cli/test-mocking/mock_validate.report new file mode 100644 index 0000000..b3f9e7a --- /dev/null +++ b/modules/local/ena_webin_cli/test-mocking/mock_validate.report @@ -0,0 +1,3 @@ +INFO : MOCK WEBIN RUN +INFO : command=ena-webin-cli -context=genome -manifest=_updated_manifest.manifest +INFO : Submission(s) validated successfully diff --git a/modules/local/ena_webin_cli/test-mocking/nextflow.config b/modules/local/ena_webin_cli/test-mocking/nextflow.config new file mode 100644 index 0000000..07ada48 --- /dev/null +++ b/modules/local/ena_webin_cli/test-mocking/nextflow.config @@ -0,0 +1,12 @@ +params.testMockingDir = "${projectDir}/modules/local/ena_webin_cli/test-mocking" +env { + WEBIN_ACCOUNT = "mock_account" + WEBIN_PASSWORD = "mock_password" + PATH = "${params.testMockingDir}:\$PATH" + WEBINCLI_MOCK_TEMPLATE_DIR = "${params.testMockingDir}" +} +process { + withName: 'ENA_WEBIN_CLI' { + containerOptions = "-v ${params.testMockingDir}:${params.testMockingDir}" + } +}