From 5e2120efd64da43d210435b7287fa8141b33e066 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 18 Jan 2022 21:39:27 -0600 Subject: [PATCH 1/3] feat: Add Debian based Dockerfile Build struture assumes running docker build from the top level of the repository. e.g. docker build --file docker/Dockerfile --tag madanalysis5/madanalysis5:debug-local . Add .dockerignore --- .dockerignore | 1 + docker/Dockerfile | 64 +++++++++++++++++++++++++++++++++++++++++ docker/requirements.txt | 4 +++ 3 files changed, 69 insertions(+) create mode 100644 .dockerignore create mode 100644 docker/Dockerfile create mode 100644 docker/requirements.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..26f5c15f --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.github diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..27a0281a --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,64 @@ +ARG BUILDER_IMAGE=python:3.9-slim-bullseye +FROM ${BUILDER_IMAGE} as builder + +USER root +WORKDIR / + +SHELL [ "/bin/bash", "-c" ] + +COPY . /root/madanalysis5 + +# Set PATH to pickup virtualenv by default +ENV PATH=/usr/local/venv/bin:"${PATH}" +RUN apt-get -qq -y update && \ + apt-get -qq -y install --no-install-recommends \ + gcc \ + g++ \ + make \ + zlib1g \ + bash-completion \ + python3-dev \ + less \ + tree \ + wget \ + curl \ + gnuplot \ + git && \ + apt-get -y clean && \ + apt-get -y autoremove && \ + rm -rf /var/lib/apt/lists/* && \ + python -m venv /usr/local/venv && \ + . /usr/local/venv/bin/activate && \ + python -m pip --no-cache-dir install --upgrade pip setuptools wheel && \ + python -m pip --no-cache-dir install pip-tools && \ + python -m pip list && \ + python -m piptools compile \ + --generate-hashes \ + --output-file /root/madanalysis5/requirements.lock \ + /root/madanalysis5/docker/requirements.txt && \ + python -m pip --no-cache-dir install --upgrade --requirement /root/madanalysis5/requirements.lock && \ + python -m pip list && \ + export PATH="$(find / -type d -iname madanalysis5)/bin:${PATH}" && \ + python -c 'import multiprocessing; print(multiprocessing.cpu_count())' | ma5 && \ + printf '\nexport PATH=/usr/local/venv/bin:"${PATH}"\n' >> /root/.bashrc && \ + printf '\nexport PATH='"$(find / -type d -iname madanalysis5)/bin"':"${PATH}"\n' >> /root/.bashrc + +# Enable tab completion by uncommenting it from /etc/bash.bashrc +# The relevant lines are those below the phrase "enable bash completion in interactive shells" +RUN export SED_RANGE="$(($(sed -n '\|enable bash completion in interactive shells|=' /etc/bash.bashrc)+1)),$(($(sed -n '\|enable bash completion in interactive shells|=' /etc/bash.bashrc)+7))" && \ + sed -i -e "${SED_RANGE}"' s/^#//' /etc/bash.bashrc && \ + unset SED_RANGE + +# Use C.UTF-8 locale to avoid issues with ASCII encoding +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +# Default user is root to avoid uid write permission problems with volumes +ENV HOME /root +WORKDIR ${HOME}/data + +ENV PATH="${HOME}/.local/bin:${PATH}" +ENV PATH="/root/madanalysis5/bin:${PATH}" + +ENTRYPOINT ["/bin/bash", "-l", "-c"] +CMD ["/bin/bash"] diff --git a/docker/requirements.txt b/docker/requirements.txt new file mode 100644 index 00000000..57d2a58e --- /dev/null +++ b/docker/requirements.txt @@ -0,0 +1,4 @@ +six>=1.16.0 # required by ma5 +scipy>=1.7.0 # optional for reinterpretation +pyhf>=0.6.3 # optional for reinterpretation +matplotlib>=3.5.0 # optional for histogramming From 6086449a4ded79b97ee4265b7db35f3fd771029c Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 18 Jan 2022 22:01:03 -0600 Subject: [PATCH 2/3] feat: Add differential cross-section plot example Taken from http://madanalysis.irmp.ucl.ac.be/wiki/FAQNormalMode --- examples/differential_xsec_plot.ma5 | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 examples/differential_xsec_plot.ma5 diff --git a/examples/differential_xsec_plot.ma5 b/examples/differential_xsec_plot.ma5 new file mode 100644 index 00000000..0b1777cb --- /dev/null +++ b/examples/differential_xsec_plot.ma5 @@ -0,0 +1,25 @@ +# differential cross-section plot +# c.f. http://madanalysis.irmp.ucl.ac.be/wiki/FAQNormalMode + +# install samples +install samples + +# load sample and set cross-section +import /root/madanalysis5/samples/zz.lhe.gz as my_sample +set my_sample.xsection = 123 + +# plot transverse momentum for leading positron +plot PT(e+[1]) + +# Note that automatically this will create a selection +display selection[1] + +# change the luminosity value to get the cross-section +set main.lumi = 1e-3 * 10 + +# Format the plot +set selection[1].titleY = "$\\frac{d\\sigma}{dp_{T}}\ {\\rm [pb/GeV]}$" # matplotlib formatting +# set selection[1].titleY = "#frac{d#sigma}{dp_{T}} [pb/GeV]" # ROOT formatting + +# Run an analysis to make the plot +submit differential_xsec_example From 5ff8b5a09c335cd095aa6ec2ea8b26ad9c390055 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 18 Jan 2022 21:45:04 -0600 Subject: [PATCH 3/3] ci: Add GitHub Actions workflow to build and publish Docker image Run tests builds on: * push events to main or tags * pull request events targetting main * on CRON schedule weekly at 01:23 UTC on Sundays * on releases * on demand with workflow dispatch Publish to the GitHub Container Registry by default, and publish with latest tag on pushed to main and publish with version tags on GitHub releases. --- .github/workflows/docker-debian.yml | 139 ++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 .github/workflows/docker-debian.yml diff --git a/.github/workflows/docker-debian.yml b/.github/workflows/docker-debian.yml new file mode 100644 index 00000000..c490b12c --- /dev/null +++ b/.github/workflows/docker-debian.yml @@ -0,0 +1,139 @@ +name: Docker Images Debian + +on: + push: + branches: + - main + tags: + - v* + pull_request: + branches: + - main + schedule: + - cron: '23 1 * * 0' + release: + types: [published] + workflow_dispatch: + +jobs: + docker: + name: Build and publish Debian images + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Prepare + id: prep + run: | + DOCKER_IMAGE=madanalysis5/madanalysis5 + VERSION=latest + MADANALYSIS_VERISON=v1.10.0 + REPO_NAME=${{github.repository}} + REPO_NAME_LOWERCASE="${REPO_NAME,,}" + if [[ $GITHUB_REF == refs/tags/* ]]; then + VERSION=${GITHUB_REF#refs/tags/} + elif [[ $GITHUB_REF == refs/pull/* ]]; then + VERSION=pr-${{ github.event.number }} + fi + TAGS="${DOCKER_IMAGE}:${VERSION}" + TAGS="$TAGS,${DOCKER_IMAGE}:latest,${DOCKER_IMAGE}:${MADANALYSIS_VERISON},${DOCKER_IMAGE}:sha-${GITHUB_SHA::8}" + # Releases also have GITHUB_REFs that are tags, so reuse VERSION + if [ "${{ github.event_name }}" = "release" ]; then + TAGS="ghcr.io/${REPO_NAME_LOWERCASE}:latest,ghcr.io/${REPO_NAME_LOWERCASE}:latest-stable,ghcr.io/${REPO_NAME_LOWERCASE}:${MADANALYSIS_VERISON},ghcr.io/${REPO_NAME_LOWERCASE}:sha-${GITHUB_SHA::8}" + fi + echo ::set-output name=version::${VERSION} + echo ::set-output name=tags::${TAGS} + echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ') + echo ::set-output name=repo_name_lowercase::"${REPO_NAME_LOWERCASE}" + echo ::set-output name=MADANALYSIS_VERISON::"${MADANALYSIS_VERISON}" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + # - name: Login to DockerHub + # if: github.event_name != 'pull_request' + # uses: docker/login-action@v1 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Test build + id: docker_build_test + uses: docker/build-push-action@v2 + with: + context: . + file: docker/Dockerfile + tags: ${{ steps.prep.outputs.tags }} + labels: | + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.created=${{ steps.prep.outputs.created }} + org.opencontainers.image.revision=${{ github.sha }} + load: true + push: false + + - name: Image digest + run: echo ${{ steps.docker_build_test.outputs.digest }} + + - name: List built images + run: docker images + + - name: List ma5 users settings + run: >- + docker run --rm + madanalysis5/madanalysis5:sha-${GITHUB_SHA::8} + 'cat $(find / -name "installation_options.dat")' + + - name: Run test program + run: >- + docker run --rm + -v $PWD:$PWD + madanalysis5/madanalysis5:sha-${GITHUB_SHA::8} + 'cat $(find /root/ -iname "differential_xsec_plot.ma5") | ma5 && tree differential_xsec_example' + + - name: Build and publish to registry + # every PR will trigger a push event on main, so check the push event is actually coming from main + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'MadAnalysis/madanalysis5' + id: docker_build_latest + uses: docker/build-push-action@v2 + with: + context: . + file: docker/Dockerfile + tags: | + ghcr.io/${{ steps.prep.outputs.repo_name_lowercase }}:latest + labels: | + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.created=${{ steps.prep.outputs.created }} + org.opencontainers.image.revision=${{ github.sha }} + push: true + + - name: Build and publish to registry with release tag + if: github.event_name == 'release' && github.event.action == 'published' && github.repository == 'MadAnalysis/madanalysis5' + id: docker_build_release + uses: docker/build-push-action@v2 + with: + context: . + file: docker/Dockerfile + tags: | + ghcr.io/${{ steps.prep.outputs.repo_name_lowercase }}:latest + ghcr.io/${{ steps.prep.outputs.repo_name_lowercase }}:latest-stable + ghcr.io/${{ steps.prep.outputs.repo_name_lowercase }}:${{ steps.prep.outputs.MADANALYSIS_VERISON }} + ghcr.io/${{ steps.prep.outputs.repo_name_lowercase }}:sha-${GITHUB_SHA::8} + labels: | + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.created=${{ steps.prep.outputs.created }} + org.opencontainers.image.revision=${{ github.sha }} + push: true