Skip to content

Commit 410759b

Browse files
committed
Enhance Docker workflow and entry script for improved testing and compatibility
- Updated GitHub Actions workflow to use newer versions of Docker actions and added smoke test steps. - Modified Dockerfile to include additional environment variables and install pytest. - Created new smoke tests for ARC and RMG-Py functionalities. - Refined entrywrapper.sh for better command handling and user experience.
1 parent 5fa10f7 commit 410759b

4 files changed

Lines changed: 150 additions & 46 deletions

File tree

.github/workflows/docker_build.yml

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,68 @@ jobs:
3232
large-packages: true
3333
docker-images: false
3434
swap-storage: true
35+
3536
- name: Checkout
36-
uses: actions/checkout@v2
37+
uses: actions/checkout@v5.0.0
3738

39+
- name: Set up Buildx
40+
uses: docker/setup-buildx-action@v3.11.1
41+
42+
# ----- PR and non-main branch steps -----
43+
# For PRs: Build image but do not push and run smoke tests
3844
- name: Build Docker Image (No Push)
3945
if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref != 'refs/heads/main')
40-
uses: docker/build-push-action@v5.1.0
46+
uses: docker/build-push-action@v6.18.0
4147
with:
4248
context: .
4349
file: ./Dockerfile
4450
push: false
51+
load: true
52+
tags: arc:test
53+
cache-from: type=gha
54+
cache-to: type=gha,mode=max
55+
56+
- name: Run Smoke Tests
57+
if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref != 'refs/heads/main')
58+
run: |
59+
docker run --rm bash arc:test -lc \
60+
"cd /home/mambauser/Code/ARC && micromamba run -n arc_env pytest dockerfiles/docker_tests/test_docker_smoke.py -m smoke -q"
61+
62+
# ----- Main branch only steps -----
63+
# For pushes to main: Build, run smoke tests, and push to Docker Hub
64+
- name: Build test stage (main)
65+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
66+
uses: docker/build-push-action@v6.18.0
67+
with:
68+
context: .
69+
file: ./Dockerfile
70+
load: true
71+
tags: arc:final-${{ github.sha }}
72+
cache-from: type=gha
73+
cache-to: type=gha,mode=max
74+
75+
- name: Run smoke (main, test stage)
76+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
77+
run: |
78+
docker run --rm arc:final-${{ github.sha }} bash -lc \
79+
"cd /home/mambauser/Code/ARC && micromamba run -n arc_env pytest dockerfiles/docker_tests/test_docker_smoke.py -m smoke -q"
4580
4681
- name: Login to Docker Hub
4782
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
48-
uses: docker/login-action@v3.0.0
83+
uses: docker/login-action@v3.5.0
4984
with:
5085
username: ${{ secrets.DOCKERHUB_USERNAME }}
5186
password: ${{ secrets.DOCKERHUB_TOKEN }}
5287

53-
- name: Set up Docker Buildx
54-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
55-
uses: docker/setup-buildx-action@v3.0.0
56-
57-
- name: Build and Push Docker Image
88+
- name: Build final and push (main)
5889
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
59-
uses: docker/build-push-action@v5.1.0
90+
uses: docker/build-push-action@v6.18.0
6091
with:
6192
context: .
6293
file: ./Dockerfile
6394
push: true
64-
tags: ${{ secrets.DOCKERHUB_USERNAME }}/arc:latest
95+
tags: |
96+
${{ secrets.DOCKERHUB_USERNAME }}/arc:latest
97+
${{ secrets.DOCKERHUB_USERNAME }}/arc:${{ github.sha }}
98+
cache-from: type=gha
99+
cache-to: type=gha,mode=max

Dockerfile

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Stage 1: RMG setup
2-
# RMG Dockerfile
1+
# Stage 1: RMG setup & ARC setup
32
# The parent image is the base image that the Dockerfile builds upon.
43
# The RMG installation instructions suggest Anaconda for installation by source, however, we use micromamba for the Docker image due to its smaller size and less overhead.
4+
# Installation of ARC will also be done in this stage.
55
FROM --platform=linux/amd64 mambaorg/micromamba:2.2-ubuntu24.04 AS builder
66

77
# Set ARGS
@@ -51,19 +51,24 @@ RUN micromamba create -y -n rmg_env -f /home/mambauser/Code/RMG-Py/environment.y
5151

5252
WORKDIR /home/mambauser/Code/ARC
5353
RUN micromamba create -y -n arc_env -f environment.yml --channel-priority flexible && \
54+
micromamba install -y -n arc_env -c conda-forge pytest && \
5455
micromamba clean --all -f -y && \
5556
micromamba run -n arc_env bash -euxo pipefail -c \
5657
"make compile && bash ./devtools/install_pyrdl.sh" && \
5758
micromamba clean --all --yes
5859

59-
60-
RUN rm -rf ~/.cache ~/.npm ~/.yarn /tmp/* && \
61-
find /opt/conda -name '*.a' -delete && \
62-
find /opt/conda -name '*.pyc' -delete && \
63-
find /opt/conda -name '__pycache__' -type d -exec rm -rf {} +
64-
60+
# Stage 2: Final image
61+
# The final image is based on the same micromamba image, but we copy over the installed RMG and ARC from the builder stage.
62+
# This keeps the final image size smaller and avoids unnecessary layers.
6563
FROM --platform=linux/amd64 mambaorg/micromamba:2.2-ubuntu24.04
6664

65+
ENV MAMBA_ROOT_PREFIX=/opt/conda
66+
ENV PATH=$MAMBA_ROOT_PREFIX/bin:/home/mambauser/.juliaup/bin:/home/mambauser/Code/RMG-Py:/home/mambauser/Code/ARC:$PATH
67+
ENV PYTHONPATH="/home/mambauser/Code/RMG-Py:/home/mambauser/Code/ARC"
68+
ENV RMG_PY_DIR="/home/mambauser/Code/RMG-Py"
69+
ENV ARC_DIR="/home/mambauser/Code/ARC"
70+
ENV MAMBA_DOCKERFILE_ACTIVATE=1
71+
6772
USER root
6873
RUN apt-get update && \
6974
apt-get install -y --no-install-recommends \
@@ -79,18 +84,9 @@ COPY --from=builder --chown=mambauser:mambauser /opt/conda /opt/conda
7984
COPY --from=builder --chown=mambauser:mambauser /home/mambauser/.juliaup /home/mambauser/.juliaup
8085
COPY --from=builder --chown=mambauser:mambauser /home/mambauser/Code /home/mambauser/Code
8186

82-
83-
ENV MAMBA_ROOT_PREFIX=/opt/conda
84-
ENV PATH=$MAMBA_ROOT_PREFIX/bin:/home/mambauser/.juliaup/bin:/home/mambauser/Code/RMG-Py:$PATH
85-
ENV PYTHONPATH="/home/mambauser/Code/RMG-Py:/home/mambauser/Code/ARC"
86-
ENV RMG_PY_DIR="/home/mambauser/Code/RMG-Py"
87-
ENV ARC_DIR="/home/mambauser/Code/ARC"
88-
ENV MAMBA_DOCKERFILE_ACTIVATE=1
89-
9087
# --- Entry wrapper ----------------------------------------------------------
9188
COPY --chmod=755 dockerfiles/entrywrapper.sh /usr/local/bin/entrywrapper.sh
9289
COPY --chmod=644 dockerfiles/aliases.sh /etc/profile.d/aliases.sh
9390
COPY --chmod=755 dockerfiles/aliases_print.sh /usr/local/bin/aliases
9491

9592
ENTRYPOINT ["/usr/local/bin/entrywrapper.sh"]
96-
# -----------------------------------------------------------------------------
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import pytest
2+
import subprocess
3+
import tempfile
4+
import pathlib
5+
import textwrap
6+
7+
8+
@pytest.mark.smoke
9+
def test_import_arc():
10+
"""Test that ARC can be imported in the docker image."""
11+
try:
12+
import arc
13+
assert hasattr(arc, '__version__')
14+
except ImportError as e:
15+
pytest.fail(f"ImportError: {e}")
16+
17+
18+
@pytest.mark.smoke
19+
def test_arc_cli_help_runs():
20+
"""Test that ARC CLI help runs in the docker image."""
21+
cmd = ["bash","-lc","micromamba run -n arc_env python -m ARC --help || true"]
22+
p = subprocess.run(cmd, capture_output=True, text=True)
23+
# Just ensure it executes and prints usage/help
24+
assert "help" in (p.stdout + p.stderr).lower()
25+
26+
27+
@pytest.mark.smoke
28+
def test_arkane_cli_help_runs():
29+
"""Test that Arkane CLI help runs in the docker image."""
30+
cmd = ["bash","-lc","micromamba run -n rmg_env python -m arkane --help || true"]
31+
p = subprocess.run(cmd, capture_output=True, text=True)
32+
# Just ensure it executes and prints usage/help
33+
assert "arkane" in (p.stdout + p.stderr).lower()
34+
35+
36+
@pytest.mark.smoke
37+
def test_arc_can_execute_arkane_minimal():
38+
"""Test that ARC can execute Arkane with a minimal input in the docker image."""
39+
arkane_input = textwrap.dedent("""\
40+
#!/usr/bin/env python
41+
modelChemistry = 'wb97m-v/def2-tzvpd' # irrelevant here, just parseable
42+
useHinderedRotors = False
43+
thermo('H2', 'H298')
44+
""")
45+
with tempfile.TemporaryDirectory() as td:
46+
inp = pathlib.Path(td, "input.py")
47+
inp.write_text(arkane_input)
48+
# Call arkane via rmg_env the same way ARC would (subprocess)
49+
cmd = ["bash", "-lc", f"micromamba run -n rmg_env python -m arkane {inp} || true"]
50+
p = subprocess.run(cmd, capture_output=True, text=True)
51+
# We only assert it runs and produces any Arkane header/output (no heavy calc)
52+
assert "arkane" in (p.stdout + p.stderr).lower()
53+
54+
55+
@pytest.mark.smoke
56+
def test_rmgpy_imports():
57+
"""Test that RMG-Py can be imported in the docker image."""
58+
code = r"""
59+
import importlib, sys
60+
m = importlib.import_module('rmgpy')
61+
print('rmgpy OK', getattr(m, '__version__', 'unknown'))
62+
"""
63+
cmd = ["bash","-lc", f"micromamba run -n rmg_env python - <<'PY'\n{code}\nPY"]
64+
p = subprocess.run(cmd, capture_output=True, text=True)
65+
assert p.returncode == 0, p.stderr
66+
assert "rmgpy OK" in p.stdout
67+
68+
69+
@pytest.mark.smoke
70+
def test_rmg_cli_help_runs():
71+
"""Test that RMG CLI help runs in the docker image."""
72+
cmd = ["bash", "-lc", "micromamba run -n rmg_env rmg --help || true"]
73+
p = subprocess.run(cmd, capture_output=True, text=True)
74+
# Just ensure it executes and prints usage/help
75+
assert "rmg" in (p.stdout + p.stderr).lower()

dockerfiles/entrywrapper.sh

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4-
# 1) Micromamba setup (for both interactive & non-interactive)
5-
eval "$(micromamba shell hook --shell bash)"
6-
7-
# 1.1) Ensure the Code directory is owned by mambauser
8-
if [ ! -O /home/mambauser/Code ]; then
9-
chown -R mambauser:mambauser /home/mambauser/Code
4+
# 0) Only try chown if we're root (bind-mounts may be root-owned)
5+
if [[ "$(id -u)" -eq 0 ]] && [[ ! -O /home/mambauser/Code ]]; then
6+
chown -R mambauser:mambauser /home/mambauser/Code || true
107
fi
118

12-
# 2) Interactive mode: login shells or docker exec … bash
13-
if [ -t 0 ] && [ -t 1 ]; then
14-
# # Show the aliases cheat-sheet
15-
# /home/rmguser/.aliases_print.sh
16-
# Drop into an interactive Bash
9+
# 1) If no args → interactive shell (when run with -it)
10+
if [[ $# -eq 0 ]]; then
1711
exec /bin/bash -l
1812
fi
1913

20-
# 3) Non-interactive command mode: rmg or arc
21-
case "${1:-}" in
14+
# 2) Subcommands: rmg / arc
15+
cmd="$1"; shift || true
16+
case "$cmd" in
2217
rmg)
23-
micromamba activate rmg_env
24-
exec python /home/mambauser/Code/RMG-Py/rmg.py "${2:-input.py}"
18+
exec micromamba run -n rmg_env python /home/mambauser/Code/RMG-Py/rmg.py "${@:-input.py}"
2519
;;
2620
arc)
27-
micromamba activate arc_env
28-
exec python /home/mambauser/Code/ARC/ARC.py "${2:-input.yml}"
21+
exec micromamba run -n arc_env python /home/mambauser/Code/ARC/ARC.py "${@:-input.yml}"
2922
;;
3023
*)
31-
echo "Usage: <rmg|arc> [input-file]" >&2
32-
exit 1
24+
# 3) Pass-through: run arbitrary commands (keeps CI 'bash -lc "...") working
25+
exec "$cmd" "$@"
3326
;;
3427
esac
28+
29+
if [[ $# -eq 0 ]] && [[ ! -t 1 ]]; then
30+
echo "Usage: <rmg|arc> [input-file] or pass a shell command (e.g., bash -lc '…')" >&2
31+
exit 1
32+
fi

0 commit comments

Comments
 (0)