Skip to content

Commit ae96b1f

Browse files
author
Alan Christie
committed
Experimental support for nextflow
1 parent bbfda4c commit ae96b1f

File tree

2 files changed

+64
-32
lines changed

2 files changed

+64
-32
lines changed

src/jote/compose.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111

1212
INSTANCE_DIRECTORY: str = '.instance-88888888-8888-8888-8888-888888888888'
1313

14+
# A default, 30 minute timeout
15+
DEFAULT_TEST_TIMEOUT_S: int = 30 * 60
16+
17+
# The user id containers will be started as
18+
_USER_ID: int = 8888
19+
1420
_COMPOSE_CONTENT: str = """---
1521
version: '2.4'
1622
services:
@@ -29,12 +35,6 @@
2935
cpus: {cpus}.0
3036
"""
3137

32-
# A default, 30 minute timeout
33-
_DEFAULT_TEST_TIMEOUT: int = 30 * 60
34-
35-
# The user id containers will be started as
36-
_USER_ID: int = 8888
37-
3838

3939
def _get_docker_compose_version() -> str:
4040

@@ -168,15 +168,15 @@ def run(self) -> Tuple[int, str, str]:
168168
cwd = os.getcwd()
169169
os.chdir(self.get_test_path())
170170

171-
timeout: int = _DEFAULT_TEST_TIMEOUT
171+
timeout_s: int = DEFAULT_TEST_TIMEOUT_S
172172
try:
173173
# Run the container
174174
# and then cleanup
175175
test = subprocess.run(['docker-compose', 'up',
176176
'--exit-code-from', 'job',
177177
'--abort-on-container-exit'],
178178
capture_output=True,
179-
timeout=timeout,
179+
timeout=timeout_s,
180180
check=False)
181181
_ = subprocess.run(['docker-compose', 'down'],
182182
capture_output=True,

src/jote/jote.py

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import argparse
66
import os
77
import shutil
8+
import subprocess
89
import sys
910
from typing import Any, Dict, List, Optional, Tuple
1011

@@ -15,7 +16,7 @@
1516

1617
from decoder import decoder
1718

18-
from .compose import get_test_root, INSTANCE_DIRECTORY
19+
from .compose import get_test_root, INSTANCE_DIRECTORY, DEFAULT_TEST_TIMEOUT_S
1920
from .compose import Compose
2021

2122
# Where can we expect to find Job definitions?
@@ -295,6 +296,30 @@ def _check(t_compose: Compose,
295296
return True
296297

297298

299+
def _run_nextflow(command: str, project_path: str)\
300+
-> Tuple[int, str, str]:
301+
"""Runs nextflow in the project directory returning the exit code,
302+
stdout and stderr.
303+
"""
304+
assert command
305+
assert project_path
306+
307+
cwd = os.getcwd()
308+
os.chdir(project_path)
309+
310+
try:
311+
test = subprocess.run(command.split(),
312+
capture_output=True,
313+
timeout=DEFAULT_TEST_TIMEOUT_S,
314+
check=False)
315+
finally:
316+
os.chdir(cwd)
317+
318+
return test.returncode,\
319+
test.stdout.decode("utf-8"),\
320+
test.stderr.decode("utf-8")
321+
322+
298323
def _test(args: argparse.Namespace,
299324
collection: str,
300325
job: str,
@@ -325,10 +350,6 @@ def _test(args: argparse.Namespace,
325350
else:
326351
job_image_type = _DEFAULT_IMAGE_TYPE
327352

328-
# Exclude nextflow image types for now.
329-
if job_image_type in [_IMAGE_TYPE_NEXTFLOW]:
330-
return tests_passed, tests_skipped, tests_ignored, tests_failed
331-
332353
for job_test_name in job_definition.tests:
333354

334355
# If a job test has been named,
@@ -437,6 +458,7 @@ def _test(args: argparse.Namespace,
437458
job_variables[variable] = os.path.basename(value)
438459
input_files.append(value)
439460

461+
decoded_command: str = ''
440462
if test_status:
441463

442464
# Job variables must contain 'built-in' variables: -
@@ -462,11 +484,14 @@ def _test(args: argparse.Namespace,
462484
# Create the test directories, docker-compose file
463485
# and copy inputs...
464486
t_compose: Optional[Compose] = None
487+
job_command: str = ''
488+
project_path: str = ''
465489
if test_status:
466490

467491
# The command must not contain new-lines.
468492
# So split then join the command.
469-
job_command: str = ''.join(decoded_command.splitlines())
493+
assert decoded_command
494+
job_command = ''.join(decoded_command.splitlines())
470495

471496
print(f'> image={job_image}')
472497
print(f'> image-type={job_image_type}')
@@ -483,7 +508,7 @@ def _test(args: argparse.Namespace,
483508
job_working_directory,
484509
job_command,
485510
args.run_as_user)
486-
project_path: str = t_compose.create()
511+
project_path = t_compose.create()
487512

488513
test_path: str = t_compose.get_test_path()
489514
print(f'# path={test_path}')
@@ -496,37 +521,44 @@ def _test(args: argparse.Namespace,
496521
# Run the container
497522
if test_status and not args.dry_run:
498523

524+
exit_code: int = 0
525+
out: str = ''
526+
err: str = ''
499527
if job_image_type in [_IMAGE_TYPE_SIMPLE]:
500528
# Run the image container
501529
assert t_compose
502530
exit_code, out, err = t_compose.run()
503531
elif job_image_type in [_IMAGE_TYPE_NEXTFLOW]:
504532
# Run nextflow directly
505-
pass
506-
507-
# Delete the test directory?
508-
# Not if there's an error
509-
# and not if told not to.
510-
expected_exit_code: int =\
511-
job_definition.tests[job_test_name].checks.exitCode
512-
513-
if exit_code != expected_exit_code:
533+
assert job_command
534+
assert project_path
535+
exit_code, out, err = _run_nextflow(job_command, project_path)
536+
else:
514537
print('! FAILURE')
515-
print(f'! exit_code={exit_code}'
516-
f' expected_exit_code={expected_exit_code}')
517-
print('! Container stdout follows...')
518-
print(out)
519-
print('! Container stderr follows...')
520-
print(err)
538+
print(f'! unsupported image-type ({job_image_type}')
521539
test_status = False
522540

541+
if test_status:
542+
expected_exit_code: int =\
543+
job_definition.tests[job_test_name].checks.exitCode
544+
545+
if exit_code != expected_exit_code:
546+
print('! FAILURE')
547+
print(f'! exit_code={exit_code}'
548+
f' expected_exit_code={expected_exit_code}')
549+
print('! Test stdout follows...')
550+
print(out)
551+
print('! Test stderr follows...')
552+
print(err)
553+
test_status = False
554+
523555
if args.verbose:
524556
print(out)
525557

526558
# Inspect the results
527559
# (only if successful so far)
528-
if test_status \
529-
and not args.dry_run \
560+
if test_status\
561+
and not args.dry_run\
530562
and job_definition.tests[job_test_name].checks.outputs:
531563

532564
assert t_compose

0 commit comments

Comments
 (0)