Skip to content

Commit 9b85e90

Browse files
committed
migrate infra components and tidy up
1 parent 920595e commit 9b85e90

File tree

79 files changed

+244
-444056
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+244
-444056
lines changed

.github/dependabot.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "github-actions"
9+
directory: "/"
10+
schedule:
11+
# Check for updates to GitHub Actions every day
12+
interval: "daily"
13+
time: "09:00"
14+
timezone: "UTC"
15+
assignees:
16+
- "jimboid"

.github/workflows/build.yaml

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
name: ci/cd
2+
on:
3+
pull_request:
4+
repository_dispatch:
5+
types: [build]
6+
workflow_dispatch:
7+
8+
jobs:
9+
build:
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
platform:
14+
- linux/amd64
15+
- linux/arm64
16+
runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-24.04' || matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' }}
17+
name: build ${{ matrix.platform }}
18+
outputs:
19+
tag: ${{ steps.envvars.outputs.tag }}
20+
steps:
21+
- name: checkout
22+
uses: actions/checkout@v5.0.0
23+
24+
- name: Prepare env
25+
id: envvars
26+
run: |
27+
platform=${{ matrix.platform }}
28+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
29+
if [ ${{ github.event.client_payload.tag }} != 'null' ]; then
30+
echo "tag=${{ github.event.client_payload.tag }}" >> $GITHUB_OUTPUT
31+
else
32+
echo "tag=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
33+
fi
34+
35+
- name: Metadata
36+
id: meta
37+
uses: docker/metadata-action@v5.8.0
38+
with:
39+
images: ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}
40+
41+
- name: Authenticate with GHCR
42+
id: auth
43+
uses: docker/login-action@v3.5.0
44+
with:
45+
registry: ghcr.io
46+
username: ${{github.actor}}
47+
password: ${{secrets.BUILD_TOKEN}}
48+
49+
- name: Set up Docker Buildx
50+
id: buildx
51+
uses: docker/setup-buildx-action@v3.11.1
52+
53+
- name: Build and push by digest
54+
id: build
55+
uses: docker/build-push-action@v6.18.0
56+
with:
57+
file: ./docker/Dockerfile
58+
platforms: ${{ matrix.platform }}
59+
labels: ${{ steps.meta.outputs.labels }}
60+
tags: ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}
61+
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
62+
63+
- name: Export digest
64+
run: |
65+
mkdir -p ${{ runner.temp }}/digests
66+
digest="${{ steps.build.outputs.digest }}"
67+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
68+
69+
- name: Upload digest
70+
uses: actions/upload-artifact@v4.6.2
71+
with:
72+
name: digests-${{ env.PLATFORM_PAIR }}
73+
path: ${{ runner.temp }}/digests/*
74+
if-no-files-found: error
75+
retention-days: 1
76+
77+
merge:
78+
runs-on: ubuntu-24.04
79+
name: merge into multiarch manifest
80+
needs:
81+
- build
82+
steps:
83+
- name: Download digests
84+
uses: actions/download-artifact@v5.0.0
85+
with:
86+
path: ${{ runner.temp }}/digests
87+
pattern: digests-*
88+
merge-multiple: true
89+
90+
- name: Authenticate with GHCR
91+
id: auth
92+
uses: docker/login-action@v3.5.0
93+
with:
94+
registry: ghcr.io
95+
username: ${{github.actor}}
96+
password: ${{secrets.BUILD_TOKEN}}
97+
98+
- name: Set up Docker Buildx
99+
id: buildx
100+
uses: docker/setup-buildx-action@v3.11.1
101+
102+
- name: Metadata
103+
id: meta
104+
uses: docker/metadata-action@v5.8.0
105+
with:
106+
images: ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}
107+
tags: dev
108+
109+
- name: Create manifest list and push
110+
id: annotate
111+
continue-on-error: true
112+
working-directory: ${{ runner.temp }}/digests
113+
run: |
114+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
115+
--annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
116+
--annotation='index:org.opencontainers.image.licenses=MIT' \
117+
--annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
118+
--annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
119+
--annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
120+
$(printf 'ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}@sha256:%s ' *)
121+
122+
- name: Create manifest list and push without annotations
123+
if: steps.annotate.outcome == 'failure'
124+
working-directory: ${{ runner.temp }}/digests
125+
run: |
126+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
127+
$(printf 'ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}@sha256:%s ' *)
128+
129+
- name: Inspect image
130+
run: |
131+
docker buildx imagetools inspect ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}:dev
132+
133+
tests:
134+
strategy:
135+
fail-fast: false
136+
matrix:
137+
platform:
138+
- linux/amd64
139+
- linux/arm64
140+
runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-latest' || matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' }}
141+
name: testing on ${{ matrix.platform }}
142+
timeout-minutes: 360
143+
needs:
144+
- build
145+
- merge
146+
steps:
147+
148+
- name: Test notebooks
149+
shell: bash
150+
run: |
151+
docker run -t ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}:dev bash -c "\
152+
pip install pytest nbmake; \
153+
find . -name '*.ipynb' | pytest --nbmake --nbmake-timeout=3600 --ignore=answers; "
154+
155+
tags:
156+
runs-on: ubuntu-24.04
157+
if: github.event_name != 'pull_request'
158+
name: add tags
159+
needs:
160+
- build
161+
- tests
162+
steps:
163+
- name: Authenticate with GHCR
164+
id: auth
165+
uses: docker/login-action@v3.5.0
166+
with:
167+
registry: "ghcr.io"
168+
username: ${{github.actor}}
169+
password: ${{secrets.BUILD_TOKEN}}
170+
171+
- name: tag release versions
172+
shell: bash
173+
run: |
174+
docker buildx imagetools create \
175+
--tag ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}:latest \
176+
--tag ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}:${{ needs.build.outputs.tag }} \
177+
ghcr.io/${{ vars.ORG_REPO }}/${{ github.event.repository.name }}:dev
178+
179+
- name: Post version update to dash
180+
uses: peter-evans/repository-dispatch@v3.0.0
181+
with:
182+
token: ${{ secrets.BUILD_TOKEN }}
183+
repository: jimboid/biosim-workshops-dash
184+
event-type: build
185+
client-payload: '{"repo": "${{ github.event.repository.name }}", "tag": "${{ needs.build.outputs.tag }}"}'

README.md

Lines changed: 11 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,17 @@
1-
## Aimed at:
2-
Anyone interested in using Python for Biomodelling. The material in
3-
this workshop will help you get the most out of the other workshops
4-
run during the week.
1+
# CCPBioSim Basic Python Workshop
52

6-
## Requirements:
7-
Basic knowledge of Python e.g. as in [https://chryswoods.com/beginning_python](https://chryswoods.com/beginning_python)
3+
[![build](https://github.com/ccpbiosim/python-workshop/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/ccpbiosim/python-workshop/actions/workflows/build.yaml)
84

9-
## Abstract:
10-
This workshop will introduce more intermediate features of Python that
11-
are useful for biomolecular modellers. This will include the use of
12-
Jupyter notebooks, how to write Python functions and classes, and
13-
how to properly structure, document and test code. The second
14-
part will introduce you to data analysis tools such as Pandas,
15-
NumPy and MatplotLib.
5+
## Docker
166

17-
## Training Material
7+
This container is derived from the CCPBioSim JupyterHub image. This container
8+
adds the necessary software packages and notebook content to form a deployable
9+
course container. The source content for this course can be found at
10+
https://github.com/CCPBioSim/python-and-data-workshop
1811

19-
The workshop consists of a series of Jupyter notebooks. These are available
20-
below, and can be run using the
21-
<a href="https://notebook.biosimspace.org" target="_blank">workshop Jupyter server</a>.
12+
## How to Use
2213

23-
Once you have started the server, navigate to the `python_and_data` directory
24-
and you will find all workshop material there.
14+
In our containers we are using the JupyterHub default port 8888, so you should
15+
forward this port when deploying locally::
2516

26-
The workshops are numbered sequentially from `01_jupyter_howto.ipynb` to
27-
`17_regular_expressions.ipynb`. They cover a variety of useful Python topics,
28-
and are *mostly* independent. Feel free to go through them in the order you
29-
prefer, and to skip topics that you feel you are already comfortable with.
30-
31-
There are exercises in many of the topics. You can find answers in the
32-
equivalent notebook in the `answers` directory.
33-
34-
Below is a summary of each topic, together with links to view html versions
35-
of the notebooks the their answers, and to download the notebooks.
36-
37-
## Contents
38-
39-
### [01_jupyter_howto.ipynb](html/01_jupyter_howto.html) ([answers](html/answers/01_jupyter_howto.html))
40-
41-
Introduction to Jupyter notebooks, including how to use the interface,
42-
how to view molecules, draw graphs, download files, and start a bash
43-
terminal.
44-
45-
[download](01_jupyter_howto.ipynb) | [download answers](answers/01_jupyter_howto.ipynb)
46-
47-
### [02_lists.ipynb](html/02_lists.html) ([answers](html/answers/02_lists.html))
48-
49-
Learn how to use Python Lists
50-
51-
[download](02_lists.ipynb) | [download answers](answers/02_lists.ipynb)
52-
53-
### [03_dictionaries.ipynb](html/03_dictionaries.html) ([answers](html/answers/03_dictionaries.html))
54-
55-
Learn how to use Python dictionaries
56-
57-
[download](03_dictionaries.ipynb) | [download answers](answers/03_dictionaries.ipynb)
58-
59-
### [04_functions.ipynb](html/04_functions.html) ([answers](html/answers/04_functions.html))
60-
61-
Learn how to write a function in Python
62-
63-
[download](04_functions.ipynb) | [download answers](answers/04_functions.ipynb)
64-
65-
### [05_objects.ipynb](html/05_objects.html) ([answers](html/answers/05_objects.html))
66-
67-
Learn about objects and object orientated programming
68-
69-
[download](05_objects.ipynb) | [download answers](answers/05_objects.ipynb)
70-
71-
### [06_classes.ipynb](html/06_classes.html) ([answers](html/answers/06_classes.html))
72-
73-
Learn how to write your own Python classes
74-
75-
[download](06_classes.ipynb) | [download answers](answers/06_classes.ipynb)
76-
77-
### [07_documentation.ipynb](html/07_documentation.html) ([answers](html/answers/07_documentation.html))
78-
79-
Learn how to add documentation to your code
80-
81-
[download](07_documentation.ipynb) | [download answers](answers/07_documentation.ipynb)
82-
83-
### [08_class_documentation.ipynb](html/08_class_documentation.html) ([answers](html/answers/08_class_documentation.html))
84-
85-
Learn how to document Python classes, and protect hidden (private) functions
86-
and data from view.
87-
88-
[download](08_class_documentation.ipynb) | [download answers](answers/08_class_documentation.ipynb)
89-
90-
### [09_exceptions.ipynb](html/09_exceptions.html) ([answers](html/answers/09_exceptions.html))
91-
92-
Learn about exceptions, and how they can be used to signify errors.
93-
94-
[download](09_exceptions.ipynb) | [download answers](answers/09_exceptions.ipynb)
95-
96-
### [10_error_handling.ipynb](html/10_error_handling.html) ([answers](html/answers/10_error_handling.html))
97-
98-
Learn how to handle errors by catching exceptions
99-
100-
[download](10_error_handling.ipynb) | [download answers](answers/10_error_handling.ipynb)
101-
102-
### [11_modules.ipynb](html/11_modules.html) ([answers](html/answers/11_modules.html))
103-
104-
Learn how to package and share your code as a module
105-
106-
[download](11_modules.ipynb) | [download answers](answers/11_modules.ipynb)
107-
108-
### [12_pandas.ipynb](html/12_pandas.html) ([answers](html/answers/12_pandas.html))
109-
110-
Learn how to use the pandas library for data analysis
111-
112-
[download](12_pandas.ipynb) | [download answers](answers/12_pandas.ipynb)
113-
114-
### [13_basic_numpy.ipynb](html/13_basic_numpy.html) ([answers](html/answers/13_basic_numpy.html))
115-
116-
Learn how to use the NumPy library for numeric calculation
117-
118-
[download](13_basic_numpy.ipynb) | [download answers](answers/13_basic_numpy.ipynb)
119-
120-
### [14_more_numpy.ipynb](html/14_more_numpy.html) ([answers](html/answers/14_more_numpy.html))
121-
122-
Learn more about how to use NumPy, including understanding copies and views
123-
124-
[download](14_more_numpy.ipynb) | [download answers](answers/14_more_numpy.ipynb)
125-
126-
### [15_matplotlib.ipynb](html/15_matplotlib.html) ([answers](html/answers/15_matplotlib.html))
127-
128-
Learn how to use the pandas with the MatPlotLib library to draw graphs
129-
130-
[download](15_matplotlib.ipynb) | [download answers](answers/15_matplotlib.ipynb)
131-
132-
### [16_viewing_molecules.ipynb](html/16_viewing_molecules.html) ([answers](html/answers/16_viewing_molecules.html))
133-
134-
Learn how to use the nglview and BioSimSpace libraries to create 3D
135-
views of molecules.
136-
137-
[download](16_viewing_molecules.ipynb) | [download answers](answers/16_viewing_molecules.ipynb)
138-
139-
### [17_regular_expressions.ipynb](html/17_regular_expressions.html) ([answers](html/answers/17_regular_expressions.html))
140-
141-
Learn how to understand and write regular expressions for text/pattern matching.
142-
143-
[download](17_regular_expressions.ipynb) | [download answers](answers/17_regular_expressions.ipynb)
17+
docker run -p 8888:8888 ghcr.io/jimboid/biosim-python-workshop:latest

_config.yml

Lines changed: 0 additions & 3 deletions
This file was deleted.

docker/Dockerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Start with BioSim base image.
2+
ARG BASE_IMAGE=latest
3+
FROM ghcr.io/ccpbiosim/jupyterhub-base:$BASE_IMAGE
4+
5+
LABEL maintainer="James Gebbie-Rayet <james.gebbie@stfc.ac.uk>"
6+
LABEL org.opencontainers.image.source=https://github.com/jimboid/biosim-python-workshop
7+
LABEL org.opencontainers.image.description="A container environment for the ccpbiosim workshop on Python."
8+
LABEL org.opencontainers.image.licenses=MIT
9+
10+
# Switch to jovyan user.
11+
USER $NB_USER
12+
WORKDIR $HOME
13+
14+
# Install workshop deps
15+
RUN conda install matplotlib numpy pandas nglview ipywidgets -y
16+
RUN pip install mdtraj
17+
18+
# Get workshop files and move them to jovyan directory.
19+
COPY --chown=1000:100 . .
20+
RUN rm -r _config.yml AUTHORS README.md docker .git .github
21+
22+
# Copy lab workspace
23+
COPY --chown=1000:100 docker/default-37a8.jupyterlab-workspace /home/jovyan/.jupyter/lab/workspaces/default-37a8.jupyterlab-workspace
24+
25+
# UNCOMMENT THIS LINE FOR REMOTE DEPLOYMENT
26+
COPY docker/jupyter_notebook_config.py /etc/jupyter/
27+
28+
# Always finish with non-root user as a precaution.
29+
USER $NB_USER
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"data":{"layout-restorer:data":{"main":{"dock":{"type":"tab-area","currentIndex":0,"widgets":["notebook:01_jupyter_howto.ipynb"]},"current":"notebook:01_jupyter_howto.ipynb"},"left":{"collapsed":false,"current":"filebrowser","widgets":["filebrowser","running-sessions","@jupyterlab/toc:plugin","extensionmanager.main-view"]},"right":{"collapsed":true,"widgets":["jp-property-inspector"]}},"notebook:01_jupyter_howto.ipynb":{"data":{"path":"01_jupyter_howto.ipynb","factory":"Notebook"}}},"metadata":{"id":"default"}}

docker/jupyter_notebook_config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
c.JupyterHub.authenticator_class = 'tmpauthenticator.TmpAuthenticator'

0 commit comments

Comments
 (0)