Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration of fornax-images from gitlab #28

Merged
merged 44 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c50759e
merge work done towards github hosting
mcdonc Dec 17, 2024
6443b2e
fix build in fresh repo
mcdonc Dec 17, 2024
a627472
only run image generation on push
mcdonc Dec 17, 2024
bee3071
disable heasoft until we have it packaged
mcdonc Dec 17, 2024
adeec91
add symbolic tag
mcdonc Dec 18, 2024
9b004ca
add some docs
mcdonc Dec 18, 2024
0713bda
fix bug found when trying to regen lockfiles
mcdonc Dec 18, 2024
80c0f9c
all scripts require python 3.12
mcdonc Dec 18, 2024
1c32d89
work with python3.11+
mcdonc Dec 18, 2024
20aa784
add more docs
mcdonc Dec 18, 2024
93f3c19
move specific image names out of implementation code
mcdonc Dec 18, 2024
be14c34
remove oldd fornax_forced_photometry folder
zoghbi-a Dec 19, 2024
43bdada
switch to using a single script ./scripts/build.py
zoghbi-a Dec 19, 2024
0bade1c
add --registry option to build.py so it can be passed. Update ci acco…
zoghbi-a Dec 26, 2024
bc464d2
cleanup lables in dockerfiles
zoghbi-a Dec 26, 2024
34a3ff7
remove old readme files in the image folders
zoghbi-a Dec 26, 2024
5ba8363
rename tractor image to astro-default
zoghbi-a Dec 26, 2024
9e0432a
remove unnecessary apt.txt in astro-default
zoghbi-a Dec 26, 2024
9c7fac8
add manual ci for image tests; [skip ci]
zoghbi-a Dec 26, 2024
869415f
add some astro-default tests and a ci matrix to trigger it[skip ci]
zoghbi-a Dec 27, 2024
ae744ab
add more testing ci [skip ci]
zoghbi-a Dec 27, 2024
7a94e76
adding testing workflow with trigger from image-build
zoghbi-a Dec 27, 2024
927e590
trigger builds to test new testing ci
zoghbi-a Dec 28, 2024
5c4233f
test adding manual trigger [skip ci]
zoghbi-a Dec 28, 2024
ba26ea6
merge configure job into main job in run-tests.yml
zoghbi-a Dec 28, 2024
b32f7de
add astro-default tests [skip ci]
zoghbi-a Dec 28, 2024
3397727
remove user/group ids:NB_UID/NB_GID from run-tests
zoghbi-a Dec 29, 2024
6cb28e6
fix astro-default tests [skip ci]
zoghbi-a Dec 29, 2024
34ac538
switch remove_lockfiles to system call so it works with dryrun
zoghbi-a Dec 29, 2024
888d841
further fixes to astro-default tests
zoghbi-a Dec 29, 2024
4ce66ae
add pytest to base_image
zoghbi-a Dec 30, 2024
f36527c
add pytest to astro-default
zoghbi-a Dec 30, 2024
43f71cf
add parameterized notebook tests; with some fixes
zoghbi-a Dec 30, 2024
dfe8c31
move scripts/tests.py -> tests/test_build_code.py
zoghbi-a Dec 30, 2024
b8d3fe6
trigger builds
zoghbi-a Dec 30, 2024
953ced3
trigger builds
zoghbi-a Dec 30, 2024
fb5657b
pass creds to testing ci
zoghbi-a Dec 30, 2024
663e3c9
add login step to testing ci
zoghbi-a Dec 30, 2024
10b1835
base_image/README.md [skip ci]
zoghbi-a Dec 31, 2024
1c08c7d
fix docstrings in scripts/build.py
zoghbi-a Dec 31, 2024
9fc283d
fix path comparison in mac in test_build_code.py
zoghbi-a Dec 31, 2024
ae5f911
make tag use in build.py consistent; update tests accordingly
zoghbi-a Dec 31, 2024
bd37997
break Builder in scripts/build.py into two classes; update tests acco…
zoghbi-a Jan 2, 2025
ecd454b
move changed-images check to a python script and add testing
zoghbi-a Dec 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/check-build-code.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Run tests for the build scripts

on:
push:
branches-ignore: ['releases/**']
paths: ['scripts/**']

jobs:
run-tests:
runs-on: ubuntu-latest
steps:

- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
id: setup_python
with:
python-version: '3.12'

- name: Run builder tests
id: test
run: |
python3 tests/test_build_code.py
81 changes: 81 additions & 0 deletions .github/workflows/image-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Build and push images

on:
push:
branches-ignore: ['releases/**']

env:
REGISTRY: ghcr.io

jobs:

build-and-push-images:

runs-on: ubuntu-latest

# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in
# this job.
permissions:
contents: read
packages: write
attestations: write
id-token: write

outputs:
dir_changes: ${{ steps.changed-images.outputs.changed_dirs }}

steps:
- name: Debug Event Payload
env:
EVENT_PAYLOAD: ${{ toJson(github.event) }}
run: echo "$EVENT_PAYLOAD"

- name: Checkout repository
uses: actions/checkout@v4

- name: Git branch name
id: git-branch-name
run: echo "${{ github.head_ref || github.ref_name }}"


- name: Setup Python
uses: actions/setup-python@v5
id: setup_python
with:
python-version: '3.12'

- name: Changed Images
id: changed-images
run: |
cat <<EOF > tmp_github.json
${{ toJson(github) }}
EOF
changed_dirs=`python scripts/changed_images.py tmp_github.json --debug`
echo "changed_dirs=$changed_dirs" >> $GITHUB_OUTPUT


- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push images
id: push
env:
DIR_CHANGES: ${{ steps.changed-images.outputs.changed_dirs }}
run: |
echo "DIR_CHANGES: $DIR_CHANGES"
python scripts/build.py --debug \
--registry "$REGISTRY" --repository "${{ github.repository }}" \
--tag "${{ github.head_ref || github.ref_name }}" \
--push $DIR_CHANGES

test-images:
needs: build-and-push-images
uses: ./.github/workflows/run-tests.yml
secrets: inherit
with:
# pass the images that changed for testing
images: ${{ needs.build-and-push-images.outputs.dir_changes }}
53 changes: 53 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Tag released images

on:
release:
types: [published]

env:
REGISTRY: ghcr.io

jobs:

build-and-push-images:
runs-on: ubuntu-latest

# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in
# this job.
permissions:

contents: read
packages: write
attestations: write
id-token: write

steps:

- name: Debug Event Payload
env:
EVENT_PAYLOAD: ${{ toJson(github.event) }}
run: echo "$EVENT_PAYLOAD"

- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
id: setup_python
with:
python-version: '3.12'

- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Tag main images with release tags
id: push
run: |
python scripts/build.py --debug --no-build \
--registry "$REGISTRY" --repository "${{ github.repository }}" \
--tag "${{ github.event.release.target_commitish }}" \
--release "${{ github.event.release.tag_name }}" stable
63 changes: 63 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: image-tests
on:
# call from the image build pipeline
workflow_call:
inputs:
images:
required: true
type: string
workflow_dispatch:
inputs:
images:
description: 'Images of the form: ["image-1","image-2"]'
required: true
type: string

env:
REGISTRY: ghcr.io

jobs:
test-images:
runs-on: ubuntu-latest
if: inputs.images != '[]'
strategy:
matrix:
image: ${{ fromJson(inputs.images) }}

steps:
- name: Configure tests
id: configure
run: |
echo "uid=$(id -u)" >> $GITHUB_OUTPUT
echo "gid=$(id -g)" >> $GITHUB_OUTPUT
echo "Images passed for testing: ${{ inputs.images }}"

- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: "Pull Image: ${{ matrix.image }}"
run: |
tag=${{ github.head_ref || github.ref_name }}
image=${{ matrix.image }}
docker pull ghcr.io/${{ github.repository }}/$image:$tag
docker tag ghcr.io/${{ github.repository }}/$image:$tag $image

- name: "Run tests inside the image: ${{ matrix.image }}"
run: |
image=${{ matrix.image }}
docker run -i --rm -v .:/opt/workspace/repo-code \
$image \
bash -c "pytest -s -v /opt/workspace/repo-code/tests/test_${image}.py -o cache_dir=/tmp/"

- name: "Run jupyter-lab: ${{ matrix.image }}"
run: |
image=${{ matrix.image }}
cmd="docker run -i --rm $image"
timeout 10 $cmd || [[ $? -eq 124 ]] && { echo "Timed out as expeced."; } || exit $?
50 changes: 46 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
# fornax-images
Customised Jupyterhub images for the Fornax Platform deployments
This repo contains the Docker images for the Fornax Platform deployments.
It produces reproducible computing environments. Some of the parts are
adapted from the [Pangeo](https://github.com/pangeo-data/pangeo-docker-images) project.

Have separate subdirectories for the different images, and please list them below for documentation purposes.
Reproducibility is achived by keeping track of the software environments using conda yaml files.
The following is a general description of the images:

- Each image is in its own directory (e.g. `base_image` and `astro-defaul`).

- `base_image` is a base image that contains basic JupyterHub and Lab setup, and many astronomy packages.
Other images should use it as a starting point (i.e. using `FROM ...`).

- Jupyterlab is installed in a conda environment called `notebook`, and it is the
default environment when running the images. It is also the environment that contains `dask`.

- The `scripts/build.py` script should be used when building the image locally. It takes as parameter
the name of the folder that contains Dockerfile, which is also the name of the image.
For example: `python scripts/build.py base_image` builds the base image, and
`python scripts/build.py astro-default` builds the default image, etc.

- The Dockerfile of each image (other than `base_image`) should start from the base image.

- Starting from `base_image` will trigger the `ONBUILD` sections defined in the
`base_image/Dockerfile`, which include:
- If `apt.txt` exits, it will be parsed for the list of the system software to be installed with `apt-get`.
- If `build-*` files exist, the scripts are run during the build.
- If `conda-{env}.yml` exists, it defines a conda environment called `{env}`, which typically what gets modified by hand.
- Additionally, if `conda-{env}-lock.yml` exists, it locks
the versions of the installed libraries. To create this `-lock` file, or updated it, pass `--update-lock` to the
build script `scripts/build.py`. This will first create or update the conda environment from the `conda-{env}.yml` file, then generate a new `conda-{env}-lock.yml` from the installed packages.
- If `introduction.md` file exists, it is copied to `/opt/scritps`, then copied to the user's `~/notebooks` (by the pre-notebook script) and serve as a landing page (through `JUPYTERHUB_DEFAULT_URL` defined in the jupyterhub depolyment code).

The recommonded workflow is therefore like this:

- Define the libraries requirement in `conda-{env}.yml`.

- Build the image with `python scripts/build.py {image-name} --update-lock`.

- This will generate `conda-{env}-lock.yml`, which should be kept under
version control. The next time the image is built with `python scripts/build.py {image-name}`, the lock
file will be used inside the Dockerfile to reproduce the exact build.

# The images
- `base_image`: is the base image that all other images should start from. It contains jupyter and the basic tools needed for deployment in the fornax project.

- `astro-default`: Main Astro image that was used for the demo notebooks. It contains tractor and other general useful tools.

- `heasoft`: high energy image containing heasoft.

#### fornax_forced_photometry
- Basic image with tractor installed
22 changes: 22 additions & 0 deletions astro-default/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ONBUILD instructions in base-image/Dockerfile are used to
# perform certain actions based on the presence of specific
# files (such as conda-linux-64.lock, start) in this repo.
# Refer to the base-image/Dockerfile for documentation.
ARG BASE_TAG=latest
ARG REPOSITORY=nasa-fornax/fornax-images
ARG REGISTRY=ghcr.io

FROM ${REGISTRY}/${REPOSITORY}/base_image:${BASE_TAG}


LABEL org.opencontainers.image.source=https://github.com/nasa-fornax/fornax-images
LABEL org.opencontainers.image.description "Fornax Main Astronomy Image"
LABEL maintainer="Fornax Project"

# add notebook updater script to run when jupyter starts
USER root
COPY --chmod=0755 update-notebooks.sh /usr/local/bin/before-notebook.d
USER $NB_USER

# For firefly
ENV FIREFLY_URL=https://irsa.ipac.caltech.edu/irsaviewer
29 changes: 29 additions & 0 deletions astro-default/build-tractor.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
set -e
set -o pipefail

pythonenv=notebook
astrometry_commit=e868ccd
tractor_commit=8059ae0

# Install astrometry.net and tractor
cd /tmp
git clone https://github.com/dstndstn/astrometry.net.git
cd astrometry.net
git config --global --add safe.directory $PWD
git checkout $astrometry_commit
conda run -n $pythonenv make
conda run -n $pythonenv make py
conda run -n $pythonenv make extra
conda run -n $pythonenv make install INSTALL_DIR=${CONDA_DIR}/envs/${pythonenv}
mv ${CONDA_DIR}/envs/$pythonenv/lib/python/astrometry \
${CONDA_DIR}/envs/$pythonenv/lib/python3.??/

cd /tmp
git clone https://github.com/dstndstn/tractor.git
cd tractor
git checkout $tractor_commit
conda run -n $pythonenv python setup.py build_ext --inplace --with-cython
conda run -n $pythonenv pip install --no-cache-dir . --target ${CONDA_DIR}/envs/$pythonenv/lib/python3.??/
cd $HOME
rm -rf /tmp/astrometry.net /tmp/tractor
Loading
Loading