Skip to content

Commit 22a0028

Browse files
fix docker hack (#404)
1 parent 457a12c commit 22a0028

3 files changed

Lines changed: 41 additions & 49 deletions

File tree

.github/workflows/run_tests.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,19 @@ jobs:
5353
python -c "import openproblems"
5454
5555
- name: Build Docker images
56+
if: "!startsWith(github.ref, 'refs/heads/main')"
5657
run: |
5758
cd workflow
58-
snakemake -j $(grep -c processor /proc/cpuinfo) docker_build
59+
snakemake -j $(nproc) docker_build
5960
cd ..
6061
61-
- name: Push Docker images
62-
if: startsWith(github.ref, 'refs/heads/main')
62+
- name: Build and push Docker images
63+
if: "startsWith(github.ref, 'refs/heads/main')"
6364
env:
6465
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
6566
run: |
6667
cd workflow
67-
snakemake -j $(grep -c processor /proc/cpuinfo) docker_push
68+
snakemake -j $(nproc) docker_build docker_push
6869
cd ..
6970
echo "CHANGED=`git diff --exit-code > /dev/null && echo false || echo true`" >> $GITHUB_ENV
7071
@@ -342,7 +343,7 @@ jobs:
342343
AWS_DEFAULT_REGION: us-west-2
343344
NXF_DEFAULT_DSL: 1
344345
run: |
345-
RUN_NAME="$(echo "$BRANCH" | sed "s/[^a-z]//g")_$(git rev-parse --short HEAD)_${GITHUB_RUN_ATTEMPT}"
346+
RUN_NAME="$(echo "$BRANCH" | sed "s/[^a-zA-Z0-9]//g")_$(git rev-parse --short HEAD)_${GITHUB_RUN_ATTEMPT}"
346347
cd /mnt/openproblems-nextflow/cwd/${BRANCH}
347348
nextflow run \
348349
-revision v1.2 \

workflow/Snakefile

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,12 @@ rule docker_pull:
2626
rule docker_refresh:
2727
input: tools.refresh_images
2828

29-
# this is a dirty hack
30-
if "docker_build" in sys.argv:
31-
ruleorder: build_docker_image > refresh_docker_image
32-
else:
33-
ruleorder: refresh_docker_image > build_docker_image
34-
3529
rule refresh_docker_image:
3630
input:
3731
dockerfile = "{}/{{image}}/refresh.Dockerfile".format(tools.IMAGES_DIR),
32+
requirements = tools.docker_refresh_requirements,
3833
output:
39-
temp(touch("{}/{{image}}/.docker_refresh".format(tools.IMAGES_DIR))),
40-
temp(touch("{}/{{image}}/.docker_update".format(tools.IMAGES_DIR)))
34+
temp(touch("{}/{{image}}/.docker_refresh".format(tools.IMAGES_DIR)))
4135
params:
4236
sourcedir = os.path.dirname(tools.SCRIPTS_DIR),
4337
user = "singlecellopenproblems",
@@ -69,13 +63,18 @@ RUN cd /usr/src/singlecellopenproblems && sudo git clean -fxdq
6963
RUN sudo pip install --no-cache-dir --editable /usr/src/singlecellopenproblems
7064
' > {output}"""
7165

66+
rule update_docker_image:
67+
input:
68+
tools.docker_update_requirements
69+
output:
70+
temp(touch("{}/{{image}}/.docker_update".format(tools.IMAGES_DIR)))
71+
7272
rule build_docker_image:
7373
input:
7474
dockerfile = "{}/{{image}}/Dockerfile".format(tools.IMAGES_DIR),
75-
requirements = tools.docker_requirements,
75+
requirements = tools.docker_build_requirements,
7676
output:
77-
temp(touch("{}/{{image}}/.docker_build".format(tools.IMAGES_DIR))),
78-
temp(touch("{}/{{image}}/.docker_update".format(tools.IMAGES_DIR)))
77+
temp(touch("{}/{{image}}/.docker_build".format(tools.IMAGES_DIR)))
7978
params:
8079
sourcedir = os.path.dirname(tools.SCRIPTS_DIR),
8180
user = "singlecellopenproblems",
@@ -100,7 +99,7 @@ rule login_docker:
10099

101100
rule push_docker_image:
102101
input:
103-
build = tools.docker_push_requirements,
102+
build = "{}/{{image}}/.docker_update".format(tools.IMAGES_DIR),
104103
login = ".docker_login",
105104
output:
106105
temp(touch("{}/{{image}}/.docker_push".format(tools.IMAGES_DIR)))

workflow/snakemake_tools.py

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,6 @@ def build_type(wildcards):
4848
return "github_actions" if "GITHUB_ACTIONS" in os.environ else "local"
4949

5050

51-
def image_markers(wildcards):
52-
"""Get the appropriate marker for each image."""
53-
return [
54-
docker_image_marker(image)
55-
for image in os.listdir(IMAGES_DIR)
56-
if os.path.isdir(os.path.join(IMAGES_DIR, image))
57-
]
58-
59-
6051
def push_images(wildcards):
6152
"""Get Docker push timestamp for all images."""
6253
images = _images(".docker_push")
@@ -321,21 +312,24 @@ def docker_image_marker(image, refresh=True):
321312
"""Get the file to be created to ensure Docker image exists from the image name."""
322313
docker_path = os.path.join(IMAGES_DIR, image)
323314
# possible outputs
324-
docker_refresh = os.path.join(docker_path, ".docker_update")
315+
docker_refresh = os.path.join(docker_path, ".docker_refresh")
325316
dockerfile = os.path.join(docker_path, "Dockerfile")
326317
no_change = docker_refresh if refresh else dockerfile
327318
no_change_text = "refreshing source code only" if refresh else "no change"
328319
docker_build = os.path.join(docker_path, ".docker_build")
329320

330-
# inputs to conditional logic
331-
local_imagespec_changed = docker_imagespec_changed(image, dockerfile)
332-
local_codespec_changed = not version_not_changed()
333-
if local_codespec_changed:
321+
if "docker_build" in sys.argv:
322+
# building everything from scratch
323+
requirement_file = docker_build
324+
elif not version_not_changed():
334325
print(
335326
"Code version changed: {}".format(openproblems.__version__), file=sys.stderr
336327
)
337-
if local_imagespec_changed or local_codespec_changed:
338-
# spec has changed, let's rebuild
328+
# codebase has changed, let's rebuild
329+
print("{}: rebuilding".format(image), file=sys.stderr)
330+
requirement_file = docker_build
331+
elif docker_imagespec_changed(image, dockerfile):
332+
# image has changed, let's rebuild
339333
print("{}: rebuilding".format(image), file=sys.stderr)
340334
requirement_file = docker_build
341335
elif docker_image_exists(image, local=True) or docker_image_exists(
@@ -352,48 +346,46 @@ def docker_image_marker(image, refresh=True):
352346
return requirement_file
353347

354348

355-
def _docker_requirements(image, include_self=False, refresh=True):
349+
def _docker_requirements(image, refresh=True):
356350
"""Get all files to ensure a Docker image is up to date from the image name."""
357351
docker_dir = os.path.join(IMAGES_DIR, image)
358-
dockerfile = os.path.join(docker_dir, "Dockerfile")
359-
requirements = [dockerfile]
352+
requirements = []
353+
if not refresh:
354+
dockerfile = os.path.join(docker_dir, "Dockerfile")
355+
requirements.append(dockerfile)
360356
requirements.extend(
361357
[
362358
os.path.join(docker_dir, f)
363359
for f in os.listdir(docker_dir)
364360
if f.endswith("requirements.txt")
365361
]
366362
)
367-
if include_self:
368-
requirements.append(docker_image_marker(image, refresh=refresh))
369363
base_image = _docker_base(image)
370364
if base_image is not None:
371-
requirements.extend(
372-
_docker_requirements(base_image, include_self=True, refresh=refresh)
373-
)
365+
requirements.append(os.path.join(IMAGES_DIR, base_image, ".docker_update"))
374366
return requirements
375367

376368

377-
def docker_requirements(wildcards):
369+
def docker_build_requirements(wildcards):
378370
"""Get all files to ensure a Docker image is up to date from wildcards."""
379-
return _docker_requirements(wildcards.image)
371+
return _docker_requirements(wildcards.image, refresh=False)
380372

381373

382374
def docker_update_requirements(wildcards):
375+
"""Check if we need to refresh or build a docker image."""
376+
return docker_image_marker(wildcards.image, refresh=True)
377+
378+
379+
def docker_refresh_requirements(wildcards):
383380
"""Get all files to ensure a Docker image is built and up to date from wildcards."""
384-
return _docker_requirements(wildcards.image, include_self=True, refresh=True)
381+
return _docker_requirements(wildcards.image, refresh=True)
385382

386383

387384
def docker_push_requirements(wildcards):
388385
"""Get all files to ensure a Docker image is ready to push from wildcards."""
389386
return _docker_requirements(wildcards.image, include_self=True, refresh=False)
390387

391388

392-
def docker_push(wildcards):
393-
"""Get the file to be created to ensure Docker image exists from wildcards."""
394-
return docker_image_marker(docker_image_name(wildcards))
395-
396-
397389
def docker_command(wildcards, output):
398390
"""Get the Docker command to be run given a set of wildcards."""
399391
image = docker_image_name(wildcards)

0 commit comments

Comments
 (0)