From f618e7c97d583e24a07202c3f40169e6b4babe0b Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 13:11:30 +0100 Subject: [PATCH 1/9] Docker image for out-of-box qe calculation running --- docker/Dockerfile | 27 +++++++++++++ docker/_static/Si.cif | 28 ++++++++++++++ docker/docker-bake.hcl | 38 +++++++++++++++++++ .../s6-assets/init/run-before-daemon-start.sh | 31 +++++++++++++++ .../dependencies.d/aiida-prepare | 0 .../dependencies.d/base | 0 .../run-before-daemon-start/timeout-up | 1 + .../s6-rc.d/run-before-daemon-start/type | 1 + .../s6-rc.d/run-before-daemon-start/up | 6 +++ .../user/contents.d/run-before-daemon-start | 0 10 files changed, 132 insertions(+) create mode 100644 docker/Dockerfile create mode 100644 docker/_static/Si.cif create mode 100644 docker/docker-bake.hcl create mode 100755 docker/s6-assets/init/run-before-daemon-start.sh create mode 100644 docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare create mode 100644 docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base create mode 100644 docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up create mode 100644 docker/s6-assets/s6-rc.d/run-before-daemon-start/type create mode 100644 docker/s6-assets/s6-rc.d/run-before-daemon-start/up create mode 100644 docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 000000000..f4f1f8d56 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,27 @@ +#FROM aiidateam/aiida-core-with-services:edge +FROM aiidateam/aiida-core-with-services:newly-baked + +USER root + +ARG QE_VERSION +ENV QE_VERSION ${QE_VERSION} + +# Install aiida-quantumespresso from source code +COPY --from=src . /tmp/aiida-quantumespresso +RUN pip install /tmp/aiida-quantumespresso --no-cache-dir && \ + rm -rf /tmp/aiida-quantumespresso + +# Install quantum espresso from conda (the latest version) +RUN mamba install -y -c conda-forge qe=${QE_VERSION} && \ + mamba clean --all -f -y && \ + fix-permissions "${CONDA_DIR}" && \ + fix-permissions "/home/${SYSTEM_USER}" + +COPY s6-assets/s6-rc.d /etc/s6-overlay/s6-rc.d +COPY s6-assets/init /etc/init + +# Static example files +RUN mkdir -p /opt/examples +COPY _static/ /opt/examples + +USER ${SYSTEM_UID} \ No newline at end of file diff --git a/docker/_static/Si.cif b/docker/_static/Si.cif new file mode 100644 index 000000000..deb07daa9 --- /dev/null +++ b/docker/_static/Si.cif @@ -0,0 +1,28 @@ +# generated using pymatgen +data_Si +_symmetry_space_group_name_H-M 'P 1' +_cell_length_a 3.86697465 +_cell_length_b 3.86697465 +_cell_length_c 3.86697465 +_cell_angle_alpha 60.00000000 +_cell_angle_beta 60.00000000 +_cell_angle_gamma 60.00000000 +_symmetry_Int_Tables_number 1 +_chemical_formula_structural Si +_chemical_formula_sum Si2 +_cell_volume 40.88829285 +_cell_formula_units_Z 2 +loop_ + _symmetry_equiv_pos_site_id + _symmetry_equiv_pos_as_xyz + 1 'x, y, z' +loop_ + _atom_site_type_symbol + _atom_site_label + _atom_site_symmetry_multiplicity + _atom_site_fract_x + _atom_site_fract_y + _atom_site_fract_z + _atom_site_occupancy + Si Si0 1 0.75000000 0.75000000 0.75000000 1 + Si Si1 1 0.50000000 0.50000000 0.50000000 1 diff --git a/docker/docker-bake.hcl b/docker/docker-bake.hcl new file mode 100644 index 000000000..5a992dd6a --- /dev/null +++ b/docker/docker-bake.hcl @@ -0,0 +1,38 @@ +# docker-bake.hcl +variable "ORGANIZATION" { + default = "aiidateam" +} + +variable "REGISTRY" { + default = "docker.io/" +} + +variable "PLATFORMS" { + default = ["linux/amd64"] +} + +variable "QE_VERSION" { + default = "7.2" +} + +function "tags" { + params = [image] + result = [ + "${REGISTRY}${ORGANIZATION}/${image}:newly-baked" + ] +} + +group "default" { + targets = ["aiida-quantumespresso"] +} + +target "aiida-quantumespresso" { + tags = tags("aiida-quantumespresso") + contexts = { + src = ".." + } + platforms = "${PLATFORMS}" + args = { + "QE_VERSION" = "${QE_VERSION}" + } +} \ No newline at end of file diff --git a/docker/s6-assets/init/run-before-daemon-start.sh b/docker/s6-assets/init/run-before-daemon-start.sh new file mode 100755 index 000000000..dbef58500 --- /dev/null +++ b/docker/s6-assets/init/run-before-daemon-start.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# If lock file exists, then we have already run this script +if [ -f ${HOME}/.run-before-daemon-start-done ]; then + exit 0 +else + touch ${HOME}/.run-before-daemon-start-done +fi + +# Install pseudopotential libraries +aiida-pseudo install sssp --functional PBE -p efficiency +aiida-pseudo install sssp --functional PBE -p precision +aiida-pseudo install sssp --functional PBEsol -p efficiency +aiida-pseudo install sssp --functional PBEsol -p precision + +# Loop over executables to set up +for code_name in pw ph; do + # Set up caching + verdi config set -a caching.enabled_for aiida.calculations:quantumespresso.${code_name} + # Set up code + verdi code create core.code.installed \ + --non-interactive \ + --label ${code_name}-${QE_VERSION} \ + --description "${code_name}.x code on localhost" \ + --default-calc-job-plugin quantumespresso.${code_name} \ + --computer localhost --prepend-text 'eval "$(conda shell.posix hook)"\nconda activate base\nexport OMP_NUM_THREADS=1' \ + --filepath-executable ${code_name}.x +done + +# Import example structures +verdi data core.structure import ase /opt/examples/Si.cif \ No newline at end of file diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare b/docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare new file mode 100644 index 000000000..e69de29bb diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base b/docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base new file mode 100644 index 000000000..e69de29bb diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up b/docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up @@ -0,0 +1 @@ +0 diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/type b/docker/s6-assets/s6-rc.d/run-before-daemon-start/type new file mode 100644 index 000000000..bdd22a185 --- /dev/null +++ b/docker/s6-assets/s6-rc.d/run-before-daemon-start/type @@ -0,0 +1 @@ +oneshot diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/up b/docker/s6-assets/s6-rc.d/run-before-daemon-start/up new file mode 100644 index 000000000..37d82070a --- /dev/null +++ b/docker/s6-assets/s6-rc.d/run-before-daemon-start/up @@ -0,0 +1,6 @@ +#!/command/execlineb -S0 + +with-contenv + +foreground { s6-echo "Calling /etc/init/run-before-daemon-start" } +/etc/init/run-before-daemon-start.sh diff --git a/docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start b/docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start new file mode 100644 index 000000000..e69de29bb From f4ec7e6d98308cf51dddbd9e3824a4c0e3faa92b Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 15:44:51 +0100 Subject: [PATCH 2/9] Add github action to build and push --- .github/workflows/docker.yml | 90 ++++++++++++++++++++++++++++++++++++ docker/Dockerfile | 4 +- docker/requirements.txt | 8 ++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/docker.yml create mode 100644 docker/requirements.txt diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..76a0a9cc0 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,90 @@ +--- +name: Build, test and push Docker Images + +on: + pull_request: + paths-ignore: + - "docs/**" + - "tests/**" + push: + branches: + - main + tags: + - "v*" + paths-ignore: + - "docs/**" + - "tests/**" + workflow_dispatch: + +# https://docs.github.com/en/actions/using-jobs/using-concurrency +concurrency: + # only cancel in-progress jobs or runs for the current workflow - matches against branch & tags + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + amd64-build: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: .docker + + steps: + - name: Checkout Repo ⚡️ + uses: actions/checkout@v3 + - name: Set Up Python 🐍 + uses: actions/setup-python@v4 + with: + python-version: 3.x + + - name: Install Dev Dependencies 📦 + run: | + pip install --upgrade pip + pip install --upgrade -r .docker/requirements.txt + + - name: Build image + run: docker buildx bake -f docker-bake.hcl -f --set *.platform=linux/amd64 --load + env: + # Full logs for CI build + BUILDKIT_PROGRESS: plain + + #- name: Run tests ✅ + # run: TAG=newly-baked python -m pytest -s tests + + + #- name: Docker meta 📝 + # id: meta + # uses: docker/metadata-action@v4 + # env: ${{ fromJson(steps.build_vars.outputs.vars) }} + # with: + # images: | + # name=${{ inputs.registry }}/${{ env.OWNER }}/${{ matrix.image }} + # tags: | + # type=edge,enable={{is_default_branch}} + # type=sha,enable=${{ github.ref_type != 'tag' }} + # type=ref,event=pr + # type=match,pattern=v(\d+\.\d+.\d+),group=1 + # type=raw,value={{tag}},enable=${{ startsWith(github.ref, 'refs/tags/v') }} + # type=raw,value=python-${{ env.PYTHON_VERSION }},enable=${{ startsWith(github.ref, 'refs/tags/v') }} + # type=raw,value=postgresql-${{ env.PGSQL_VERSION }},enable=${{ startsWith(github.ref, 'refs/tags/v') }} + + #- name: Login to Container Registry 🔑 + # uses: docker/login-action@v2 + # with: + # registry: ${{ inputs.registry }} + # username: ${{ secrets.REGISTRY_USERNAME }} + # password: ${{ secrets.REGISTRY_TOKEN }} + + #- name: Set tags for image and push 🏷️📤💾 + # run: | + # declare -a arr=(${{ steps.meta.outputs.tags }}) + # for tag in "${arr[@]}"; do + # arch_tag=$(echo ${tag} | sed "s/:/:${{ inputs.architecture }}-/") + # docker tag ${{ env.OWNER }}/${{ matrix.image }}:newly-baked ${arch_tag} + # docker push ${arch_tag} + + # # write tag to file + # mkdir -p /tmp/aiida-core + # echo ${arch_tag} >> /tmp/aiida-core/${{ matrix.image }}-${{ inputs.architecture }}-tags.txt + # done diff --git a/docker/Dockerfile b/docker/Dockerfile index f4f1f8d56..e6370ea3d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ -#FROM aiidateam/aiida-core-with-services:edge -FROM aiidateam/aiida-core-with-services:newly-baked +FROM aiidateam/aiida-core-with-services:edge +#FROM aiidateam/aiida-core-with-services:newly-baked USER root diff --git a/docker/requirements.txt b/docker/requirements.txt new file mode 100644 index 000000000..3ba15482b --- /dev/null +++ b/docker/requirements.txt @@ -0,0 +1,8 @@ +docker +pre-commit +pytest +requests +tabulate +pytest-docker +docker-compose +pyyaml<=5.3.1 From 852853ce42a988b1b47785129a218a5d617502a2 Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 15:47:55 +0100 Subject: [PATCH 3/9] f-m --- {docker => .docker}/Dockerfile | 0 {docker => .docker}/_static/Si.cif | 0 {docker => .docker}/docker-bake.hcl | 0 {docker => .docker}/requirements.txt | 0 .../s6-assets/init/run-before-daemon-start.sh | 0 .../dependencies.d/aiida-prepare | 0 .../run-before-daemon-start/dependencies.d/base | 0 .../s6-rc.d/run-before-daemon-start/timeout-up | 0 .../s6-assets/s6-rc.d/run-before-daemon-start/type | 0 .../s6-assets/s6-rc.d/run-before-daemon-start/up | 0 .../s6-rc.d/user/contents.d/run-before-daemon-start | 0 .github/workflows/docker.yml | 12 ++++++------ 12 files changed, 6 insertions(+), 6 deletions(-) rename {docker => .docker}/Dockerfile (100%) rename {docker => .docker}/_static/Si.cif (100%) rename {docker => .docker}/docker-bake.hcl (100%) rename {docker => .docker}/requirements.txt (100%) rename {docker => .docker}/s6-assets/init/run-before-daemon-start.sh (100%) rename {docker => .docker}/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare (100%) rename {docker => .docker}/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base (100%) rename {docker => .docker}/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up (100%) rename {docker => .docker}/s6-assets/s6-rc.d/run-before-daemon-start/type (100%) rename {docker => .docker}/s6-assets/s6-rc.d/run-before-daemon-start/up (100%) rename {docker => .docker}/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start (100%) diff --git a/docker/Dockerfile b/.docker/Dockerfile similarity index 100% rename from docker/Dockerfile rename to .docker/Dockerfile diff --git a/docker/_static/Si.cif b/.docker/_static/Si.cif similarity index 100% rename from docker/_static/Si.cif rename to .docker/_static/Si.cif diff --git a/docker/docker-bake.hcl b/.docker/docker-bake.hcl similarity index 100% rename from docker/docker-bake.hcl rename to .docker/docker-bake.hcl diff --git a/docker/requirements.txt b/.docker/requirements.txt similarity index 100% rename from docker/requirements.txt rename to .docker/requirements.txt diff --git a/docker/s6-assets/init/run-before-daemon-start.sh b/.docker/s6-assets/init/run-before-daemon-start.sh similarity index 100% rename from docker/s6-assets/init/run-before-daemon-start.sh rename to .docker/s6-assets/init/run-before-daemon-start.sh diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare similarity index 100% rename from docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare rename to .docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base similarity index 100% rename from docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base rename to .docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up similarity index 100% rename from docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up rename to .docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/type b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/type similarity index 100% rename from docker/s6-assets/s6-rc.d/run-before-daemon-start/type rename to .docker/s6-assets/s6-rc.d/run-before-daemon-start/type diff --git a/docker/s6-assets/s6-rc.d/run-before-daemon-start/up b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/up similarity index 100% rename from docker/s6-assets/s6-rc.d/run-before-daemon-start/up rename to .docker/s6-assets/s6-rc.d/run-before-daemon-start/up diff --git a/docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start b/.docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start similarity index 100% rename from docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start rename to .docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 76a0a9cc0..9cf639a56 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -7,10 +7,10 @@ on: - "docs/**" - "tests/**" push: - branches: - - main - tags: - - "v*" + #branches: + # - main + #tags: + # - "v*" paths-ignore: - "docs/**" - "tests/**" @@ -41,10 +41,10 @@ jobs: - name: Install Dev Dependencies 📦 run: | pip install --upgrade pip - pip install --upgrade -r .docker/requirements.txt + pip install --upgrade -r requirements.txt - name: Build image - run: docker buildx bake -f docker-bake.hcl -f --set *.platform=linux/amd64 --load + run: docker buildx bake -f docker-bake.hcl --set *.platform=linux/amd64 --load env: # Full logs for CI build BUILDKIT_PROGRESS: plain From 8b41937349ef68def5b3956aaadf2c4e67c15769 Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 16:05:49 +0100 Subject: [PATCH 4/9] Implement unit test for the built image --- .../docker-compose.aiida-quantumespresso.yml | 15 +++++ .docker/tests/conftest.py | 61 +++++++++++++++++++ .docker/tests/test_aiida.py | 39 ++++++++++++ .github/workflows/docker.yml | 5 +- 4 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 .docker/docker-compose.aiida-quantumespresso.yml create mode 100644 .docker/tests/conftest.py create mode 100644 .docker/tests/test_aiida.py diff --git a/.docker/docker-compose.aiida-quantumespresso.yml b/.docker/docker-compose.aiida-quantumespresso.yml new file mode 100644 index 000000000..ab8725175 --- /dev/null +++ b/.docker/docker-compose.aiida-quantumespresso.yml @@ -0,0 +1,15 @@ +--- +version: '3.4' + +services: + + aiida: + image: ${REGISTRY:-}${BASE_IMAGE:-aiidateam/aiida-quantumespresso}:${TAG:-latest} + environment: + TZ: Europe/Zurich + SETUP_DEFAULT_AIIDA_PROFILE: 'true' + #volumes: + # - aiida-home-folder:/home/aiida + +volumes: + aiida-home-folder: diff --git a/.docker/tests/conftest.py b/.docker/tests/conftest.py new file mode 100644 index 000000000..f347c8df8 --- /dev/null +++ b/.docker/tests/conftest.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# pylint: disable=missing-docstring, redefined-outer-name +import json +import re +from pathlib import Path + +import pytest + + +@pytest.fixture(scope='session', params=['aiida-quantumespresso']) +def variant(request): + return request.param + + +@pytest.fixture(scope='session') +def docker_compose_file(pytestconfig, variant): # pylint: disable=unused-argument + return f'docker-compose.{variant}.yml' + + +@pytest.fixture(scope='session') +def docker_compose(docker_services): + # pylint: disable=protected-access + return docker_services._docker_compose + + +@pytest.fixture +def timeout(): + """Container and service startup timeout""" + return 60 + + +@pytest.fixture +def container_user(): + return 'aiida' + + +@pytest.fixture +def aiida_exec(docker_compose): + + def execute(command, user=None, **kwargs): + if user: + command = f'exec -T --user={user} aiida {command}' + else: + command = f'exec -T aiida {command}' + return docker_compose.execute(command, **kwargs) + + return execute + +@pytest.fixture +def qe_version(aiida_exec): + info = json.loads( + aiida_exec( + "mamba list -n base --json --full-name qe" + ).decode() + )[0] + return info['version'] + +@pytest.fixture +def sssp_version(aiida_exec, container_user): + output = aiida_exec("aiida-pseudo list", user=container_user).decode().strip() + return re.search(r"SSSP/(\d+\.\d+)/PBE/efficiency", output).group(1) diff --git a/.docker/tests/test_aiida.py b/.docker/tests/test_aiida.py new file mode 100644 index 000000000..61f2ce798 --- /dev/null +++ b/.docker/tests/test_aiida.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# pylint: disable=missing-docstring +import json +import time + +from packaging.version import parse +import pytest + + +def test_verdi_status(aiida_exec, container_user, timeout): + time.sleep(timeout) + output = aiida_exec('verdi status', user=container_user).decode().strip() + assert 'Connected to RabbitMQ' in output + assert 'Daemon is running' in output + + # check that we have suppressed the warnings + assert 'Warning' not in output + + +def test_computer_setup_success(aiida_exec, container_user, timeout): + time.sleep(timeout) + output = aiida_exec('verdi computer test localhost', user=container_user).decode().strip() + + assert "Success" in output + assert "Failed" not in output + +def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version, timeout): + import re + + time.sleep(timeout) + output = aiida_exec("verdi data core.structure import ase /opt/examples/Si.cif", user=container_user).decode().strip() + + # Find pk + pk = re.search(r"PK = (\d+)", output).group(1) + + cmd = f"aiida-quantumespresso calculation launch pw -X pw-{qe_version}@localhost -F SSSP/{sssp_version}/PBE/efficiency -S {pk} -k 1 1 1" + output = aiida_exec(cmd, user=container_user).decode().strip() + + assert "terminated with state: finished [0]" in output \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9cf639a56..606189add 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -49,9 +49,8 @@ jobs: # Full logs for CI build BUILDKIT_PROGRESS: plain - #- name: Run tests ✅ - # run: TAG=newly-baked python -m pytest -s tests - + - name: Run tests ✅ + run: TAG=newly-baked python -m pytest -s tests #- name: Docker meta 📝 # id: meta From ea658a5226248d4471ea68b9c341b812d679019a Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 18:41:48 +0100 Subject: [PATCH 5/9] timeout for session count when test start --- .docker/tests/conftest.py | 2 +- .docker/tests/test_aiida.py | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.docker/tests/conftest.py b/.docker/tests/conftest.py index f347c8df8..31a920d57 100644 --- a/.docker/tests/conftest.py +++ b/.docker/tests/conftest.py @@ -23,7 +23,7 @@ def docker_compose(docker_services): return docker_services._docker_compose -@pytest.fixture +@pytest.fixture(scope='session') def timeout(): """Container and service startup timeout""" return 60 diff --git a/.docker/tests/test_aiida.py b/.docker/tests/test_aiida.py index 61f2ce798..9f6fbf2a3 100644 --- a/.docker/tests/test_aiida.py +++ b/.docker/tests/test_aiida.py @@ -1,14 +1,7 @@ # -*- coding: utf-8 -*- # pylint: disable=missing-docstring -import json -import time -from packaging.version import parse -import pytest - - -def test_verdi_status(aiida_exec, container_user, timeout): - time.sleep(timeout) +def test_verdi_status(aiida_exec, container_user): output = aiida_exec('verdi status', user=container_user).decode().strip() assert 'Connected to RabbitMQ' in output assert 'Daemon is running' in output @@ -17,17 +10,15 @@ def test_verdi_status(aiida_exec, container_user, timeout): assert 'Warning' not in output -def test_computer_setup_success(aiida_exec, container_user, timeout): - time.sleep(timeout) +def test_computer_setup_success(aiida_exec, container_user): output = aiida_exec('verdi computer test localhost', user=container_user).decode().strip() assert "Success" in output assert "Failed" not in output -def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version, timeout): +def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version): import re - time.sleep(timeout) output = aiida_exec("verdi data core.structure import ase /opt/examples/Si.cif", user=container_user).decode().strip() # Find pk From e1641446c61356ef0a43265cc1a34489b9351b48 Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 18:42:27 +0100 Subject: [PATCH 6/9] test --- .docker/Dockerfile | 4 ++-- .docker/tests/conftest.py | 6 +++--- .docker/tests/test_aiida.py | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index e6370ea3d..f4f1f8d56 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -1,5 +1,5 @@ -FROM aiidateam/aiida-core-with-services:edge -#FROM aiidateam/aiida-core-with-services:newly-baked +#FROM aiidateam/aiida-core-with-services:edge +FROM aiidateam/aiida-core-with-services:newly-baked USER root diff --git a/.docker/tests/conftest.py b/.docker/tests/conftest.py index 31a920d57..e9139e67f 100644 --- a/.docker/tests/conftest.py +++ b/.docker/tests/conftest.py @@ -23,7 +23,7 @@ def docker_compose(docker_services): return docker_services._docker_compose -@pytest.fixture(scope='session') +@pytest.fixture def timeout(): """Container and service startup timeout""" return 60 @@ -56,6 +56,6 @@ def qe_version(aiida_exec): return info['version'] @pytest.fixture -def sssp_version(aiida_exec, container_user): - output = aiida_exec("aiida-pseudo list", user=container_user).decode().strip() +def sssp_version(aiida_exec): + output = aiida_exec("aiida-pseudo list").decode().strip() return re.search(r"SSSP/(\d+\.\d+)/PBE/efficiency", output).group(1) diff --git a/.docker/tests/test_aiida.py b/.docker/tests/test_aiida.py index 9f6fbf2a3..5f54e1f16 100644 --- a/.docker/tests/test_aiida.py +++ b/.docker/tests/test_aiida.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=missing-docstring +import time -def test_verdi_status(aiida_exec, container_user): +def test_verdi_status(aiida_exec, container_user, timeout): + time.sleep(timeout) output = aiida_exec('verdi status', user=container_user).decode().strip() assert 'Connected to RabbitMQ' in output assert 'Daemon is running' in output @@ -10,20 +12,20 @@ def test_verdi_status(aiida_exec, container_user): assert 'Warning' not in output -def test_computer_setup_success(aiida_exec, container_user): +def test_computer_setup_success(aiida_exec, container_user, timeout): output = aiida_exec('verdi computer test localhost', user=container_user).decode().strip() assert "Success" in output assert "Failed" not in output -def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version): +def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version, timeout): import re output = aiida_exec("verdi data core.structure import ase /opt/examples/Si.cif", user=container_user).decode().strip() # Find pk pk = re.search(r"PK = (\d+)", output).group(1) - + cmd = f"aiida-quantumespresso calculation launch pw -X pw-{qe_version}@localhost -F SSSP/{sssp_version}/PBE/efficiency -S {pk} -k 1 1 1" output = aiida_exec(cmd, user=container_user).decode().strip() From db854fdb29fb3b27b85593c74d24ee5139245384 Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 20:14:12 +0100 Subject: [PATCH 7/9] More proper service wait fixture --- .docker/tests/conftest.py | 33 +++++++++++++++++++-------------- .docker/tests/test_aiida.py | 7 +++---- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.docker/tests/conftest.py b/.docker/tests/conftest.py index e9139e67f..314dd220c 100644 --- a/.docker/tests/conftest.py +++ b/.docker/tests/conftest.py @@ -2,19 +2,13 @@ # pylint: disable=missing-docstring, redefined-outer-name import json import re -from pathlib import Path import pytest -@pytest.fixture(scope='session', params=['aiida-quantumespresso']) -def variant(request): - return request.param - - @pytest.fixture(scope='session') -def docker_compose_file(pytestconfig, variant): # pylint: disable=unused-argument - return f'docker-compose.{variant}.yml' +def docker_compose_file(pytestconfig): # pylint: disable=unused-argument + return f'docker-compose.aiida-quantumespresso.yml' @pytest.fixture(scope='session') @@ -22,12 +16,23 @@ def docker_compose(docker_services): # pylint: disable=protected-access return docker_services._docker_compose - -@pytest.fixture -def timeout(): - """Container and service startup timeout""" - return 60 - +def is_container_ready(dodkec_compose): + output = dodkec_compose.execute('exec -T aiida verdi status').decode().strip() + return 'Connected to RabbitMQ' in output and 'Daemon is running' in output + +@pytest.fixture(scope='session', autouse=True) +def _docker_service_wait(docker_services): + """Container startup wait.""" + # XXX: Temporary fail the real run test because daemon start is should depened on + # run-before-daemon-start but it does not. + + #docker_compose = docker_services._docker_compose + + #docker_services.wait_until_responsive( + # timeout=120.0, pause=0.1, check=lambda: is_container_ready(docker_compose) + #) + import time + time.sleep(60) @pytest.fixture def container_user(): diff --git a/.docker/tests/test_aiida.py b/.docker/tests/test_aiida.py index 5f54e1f16..1f62c5deb 100644 --- a/.docker/tests/test_aiida.py +++ b/.docker/tests/test_aiida.py @@ -2,8 +2,7 @@ # pylint: disable=missing-docstring import time -def test_verdi_status(aiida_exec, container_user, timeout): - time.sleep(timeout) +def test_verdi_status(aiida_exec, container_user): output = aiida_exec('verdi status', user=container_user).decode().strip() assert 'Connected to RabbitMQ' in output assert 'Daemon is running' in output @@ -12,13 +11,13 @@ def test_verdi_status(aiida_exec, container_user, timeout): assert 'Warning' not in output -def test_computer_setup_success(aiida_exec, container_user, timeout): +def test_computer_setup_success(aiida_exec, container_user): output = aiida_exec('verdi computer test localhost', user=container_user).decode().strip() assert "Success" in output assert "Failed" not in output -def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version, timeout): +def test_run_real_pw_computation(aiida_exec, container_user, qe_version, sssp_version): import re output = aiida_exec("verdi data core.structure import ase /opt/examples/Si.cif", user=container_user).decode().strip() From 58e074a05bbe86168b88a26d8fb48132c834a598 Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 23:15:54 +0100 Subject: [PATCH 8/9] Use run-before-daemon to simplify implementation --- .docker/Dockerfile | 3 +-- .../dependencies.d/aiida-prepare | 0 .../run-before-daemon-start/dependencies.d/base | 0 .../s6-rc.d/run-before-daemon-start/timeout-up | 1 - .../s6-assets/s6-rc.d/run-before-daemon-start/type | 1 - .../s6-assets/s6-rc.d/run-before-daemon-start/up | 6 ------ .../s6-rc.d/user/contents.d/run-before-daemon-start | 0 .../60-pseudo-code-setup.sh} | 4 ++-- .docker/tests/conftest.py | 13 ++++--------- .docker/tests/test_aiida.py | 1 - 10 files changed, 7 insertions(+), 22 deletions(-) delete mode 100644 .docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare delete mode 100644 .docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base delete mode 100644 .docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up delete mode 100644 .docker/s6-assets/s6-rc.d/run-before-daemon-start/type delete mode 100644 .docker/s6-assets/s6-rc.d/run-before-daemon-start/up delete mode 100644 .docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start rename .docker/{s6-assets/init/run-before-daemon-start.sh => scripts/60-pseudo-code-setup.sh} (91%) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index f4f1f8d56..0262c8ee4 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -17,8 +17,7 @@ RUN mamba install -y -c conda-forge qe=${QE_VERSION} && \ fix-permissions "${CONDA_DIR}" && \ fix-permissions "/home/${SYSTEM_USER}" -COPY s6-assets/s6-rc.d /etc/s6-overlay/s6-rc.d -COPY s6-assets/init /etc/init +COPY scripts/60-pseudo-code-setup.sh /etc/init/run-before-daemon-start/ # Static example files RUN mkdir -p /opt/examples diff --git a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/aiida-prepare deleted file mode 100644 index e69de29bb..000000000 diff --git a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/dependencies.d/base deleted file mode 100644 index e69de29bb..000000000 diff --git a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up deleted file mode 100644 index 573541ac9..000000000 --- a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/timeout-up +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/type b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/type deleted file mode 100644 index bdd22a185..000000000 --- a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/type +++ /dev/null @@ -1 +0,0 @@ -oneshot diff --git a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/up b/.docker/s6-assets/s6-rc.d/run-before-daemon-start/up deleted file mode 100644 index 37d82070a..000000000 --- a/.docker/s6-assets/s6-rc.d/run-before-daemon-start/up +++ /dev/null @@ -1,6 +0,0 @@ -#!/command/execlineb -S0 - -with-contenv - -foreground { s6-echo "Calling /etc/init/run-before-daemon-start" } -/etc/init/run-before-daemon-start.sh diff --git a/.docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start b/.docker/s6-assets/s6-rc.d/user/contents.d/run-before-daemon-start deleted file mode 100644 index e69de29bb..000000000 diff --git a/.docker/s6-assets/init/run-before-daemon-start.sh b/.docker/scripts/60-pseudo-code-setup.sh similarity index 91% rename from .docker/s6-assets/init/run-before-daemon-start.sh rename to .docker/scripts/60-pseudo-code-setup.sh index dbef58500..1e48acd70 100755 --- a/.docker/s6-assets/init/run-before-daemon-start.sh +++ b/.docker/scripts/60-pseudo-code-setup.sh @@ -1,10 +1,10 @@ #!/bin/bash # If lock file exists, then we have already run this script -if [ -f ${HOME}/.run-before-daemon-start-done ]; then +if [ -f ${HOME}/.lock_pseudo_code_setup ]; then exit 0 else - touch ${HOME}/.run-before-daemon-start-done + touch ${HOME}/.lock_pseudo_code_setup fi # Install pseudopotential libraries diff --git a/.docker/tests/conftest.py b/.docker/tests/conftest.py index 314dd220c..266d2be96 100644 --- a/.docker/tests/conftest.py +++ b/.docker/tests/conftest.py @@ -23,16 +23,11 @@ def is_container_ready(dodkec_compose): @pytest.fixture(scope='session', autouse=True) def _docker_service_wait(docker_services): """Container startup wait.""" - # XXX: Temporary fail the real run test because daemon start is should depened on - # run-before-daemon-start but it does not. - - #docker_compose = docker_services._docker_compose + docker_compose = docker_services._docker_compose - #docker_services.wait_until_responsive( - # timeout=120.0, pause=0.1, check=lambda: is_container_ready(docker_compose) - #) - import time - time.sleep(60) + docker_services.wait_until_responsive( + timeout=120.0, pause=0.1, check=lambda: is_container_ready(docker_compose) + ) @pytest.fixture def container_user(): diff --git a/.docker/tests/test_aiida.py b/.docker/tests/test_aiida.py index 1f62c5deb..c4cbc6acd 100644 --- a/.docker/tests/test_aiida.py +++ b/.docker/tests/test_aiida.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # pylint: disable=missing-docstring -import time def test_verdi_status(aiida_exec, container_user): output = aiida_exec('verdi status', user=container_user).decode().strip() From 080637739204731c17d240a2cf4ac9a9a20bbcdf Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Sat, 4 Nov 2023 23:25:08 +0100 Subject: [PATCH 9/9] finalize the docker tag and push --- .docker/Dockerfile | 4 +-- .github/workflows/docker.yml | 58 ++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 0262c8ee4..6555ec3fa 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -1,5 +1,5 @@ -#FROM aiidateam/aiida-core-with-services:edge -FROM aiidateam/aiida-core-with-services:newly-baked +#FROM ghcr.io/aiidateam/aiida-core-with-services:edge +FROM ghcr.io/aiidateam/aiida-core-with-services:pr-6170 USER root diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 606189add..379fb7fa3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -52,38 +52,30 @@ jobs: - name: Run tests ✅ run: TAG=newly-baked python -m pytest -s tests - #- name: Docker meta 📝 - # id: meta - # uses: docker/metadata-action@v4 - # env: ${{ fromJson(steps.build_vars.outputs.vars) }} - # with: - # images: | - # name=${{ inputs.registry }}/${{ env.OWNER }}/${{ matrix.image }} - # tags: | - # type=edge,enable={{is_default_branch}} - # type=sha,enable=${{ github.ref_type != 'tag' }} - # type=ref,event=pr - # type=match,pattern=v(\d+\.\d+.\d+),group=1 - # type=raw,value={{tag}},enable=${{ startsWith(github.ref, 'refs/tags/v') }} - # type=raw,value=python-${{ env.PYTHON_VERSION }},enable=${{ startsWith(github.ref, 'refs/tags/v') }} - # type=raw,value=postgresql-${{ env.PGSQL_VERSION }},enable=${{ startsWith(github.ref, 'refs/tags/v') }} - - #- name: Login to Container Registry 🔑 - # uses: docker/login-action@v2 - # with: - # registry: ${{ inputs.registry }} - # username: ${{ secrets.REGISTRY_USERNAME }} - # password: ${{ secrets.REGISTRY_TOKEN }} + - name: Docker meta 📝 + id: meta + uses: docker/metadata-action@v4 + with: + images: | + name=ghcr.io/aiidateam/aiida-quantumespresso + tags: | + type=edge,enable={{is_default_branch}} + type=sha,enable=${{ github.ref_type != 'tag' }} + type=ref,event=pr + type=match,pattern=v(\d+\.\d+.\d+),group=1 + type=raw,value={{tag}},enable=${{ startsWith(github.ref, 'refs/tags/v') }} - #- name: Set tags for image and push 🏷️📤💾 - # run: | - # declare -a arr=(${{ steps.meta.outputs.tags }}) - # for tag in "${arr[@]}"; do - # arch_tag=$(echo ${tag} | sed "s/:/:${{ inputs.architecture }}-/") - # docker tag ${{ env.OWNER }}/${{ matrix.image }}:newly-baked ${arch_tag} - # docker push ${arch_tag} + - name: Login to Container Registry 🔑 + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - # # write tag to file - # mkdir -p /tmp/aiida-core - # echo ${arch_tag} >> /tmp/aiida-core/${{ matrix.image }}-${{ inputs.architecture }}-tags.txt - # done + - name: Set tags for image and push 🏷️📤💾 + run: | + declare -a arr=(${{ steps.meta.outputs.tags }}) + for tag in "${arr[@]}"; do + docker tag aiidateam/aiida-quantumespresso:newly-baked ${tag} + docker push ${tag} + done