Skip to content

Commit 5c86e0f

Browse files
committed
Add north_tools.
1 parent 0556ea3 commit 5c86e0f

File tree

10 files changed

+479
-2
lines changed

10 files changed

+479
-2
lines changed

.cruft.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,22 @@
1111
"reader_class": "SPMReader",
1212
"author_name": "The NOMAD authors",
1313
"author_email": "fairmat@physik.hu-berlin.de",
14+
"github_username": "RubelMozumder",
1415
"license": "Apache Software License 2.0",
1516
"zenodo_record": "17390485",
1617
"vscode_settings": false,
1718
"include_nomad_app": true,
1819
"include_nomad_example_upload": true,
20+
"include_north_tools": true,
21+
"north_tool_name": "spm",
1922
"__package_name": "pynxtools-spm",
2023
"__module_name": "pynxtools_spm",
2124
"__nomad_example": "spm_example_upload_entry_point",
22-
"__nomad_app": "",
23-
"_copy_without_render": ["*.html"],
25+
"__nomad_app": "spm_app_entry_point",
26+
"__north_tool_EP_name": "north_tool",
27+
"_copy_without_render": [
28+
"*.html"
29+
],
2430
"_template": "/home/rubel/NOMAD-FAIRmat/GH/pynxtools-spm/pynxtools-plugin-template",
2531
"_commit": "85cb547ddd7150e3fd71b8572c140bb4ac8ded31"
2632
}

.dockerignore

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Git
2+
.gitignore
3+
.gitattributes
4+
5+
# Python
6+
__pycache__
7+
*.py[cod]
8+
*$py.class
9+
*.so
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
.pytest_cache/
30+
31+
# Virtual Environments
32+
.venv
33+
venv/
34+
ENV/
35+
env/
36+
.venv/
37+
38+
# IDE
39+
.vscode/
40+
.idea/
41+
*.swp
42+
*.swo
43+
*~
44+
.DS_Store
45+
.project
46+
.pydevproject
47+
.settings/
48+
*.sublime-project
49+
*.sublime-workspace
50+
51+
# CI/CD
52+
.github/
53+
.gitlab-ci.yml
54+
.travis.yml
55+
.circleci/
56+
57+
# Testing
58+
.coverage
59+
.coverage.*
60+
htmlcov/
61+
.tox/
62+
.hypothesis/
63+
pytest.ini
64+
.pytest_cache/
65+
66+
# Documentation
67+
docs/_build/
68+
site/
69+
.mkdocs.yml
70+
mkdocs.yml
71+
72+
# Docker
73+
Dockerfile*
74+
.dockerignore
75+
docker/
76+
77+
# Node (if used)
78+
node_modules/
79+
npm-debug.log
80+
package-lock.json
81+
82+
# Misc
83+
*.md
84+
LICENSE
85+
MANIFEST.in
86+
*.tar.gz
87+
*.zip
88+
.tmp/
89+
.cache/
90+
91+
# IDE configuration files
92+
.editorconfig
93+
.env
94+
.env.local
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: Build and publish docker images
2+
on:
3+
push:
4+
branches:
5+
- main
6+
tags:
7+
- "v*.*.*"
8+
pull_request:
9+
branches:
10+
- main
11+
12+
env:
13+
REGISTRY: ghcr.io
14+
UV_VERSION: 0.9
15+
PYTHON_VERSION: 3.12
16+
JUPYTER_VERSION: 2025-12-31
17+
NORTH_TOOL_DIR: src/pynxtools_spm/nomad/north_tools/spm
18+
TEST_DATA_DIR: tests/data/north_tools/spm
19+
TEST_NOTEBOOKS: CommandLine.ipynb
20+
21+
permissions:
22+
packages: write
23+
contents: read
24+
attestations: write
25+
id-token: write
26+
27+
jobs:
28+
build:
29+
name: Build Jupyter Image
30+
runs-on: ubuntu-latest
31+
outputs:
32+
tags: ${{ steps.meta.outputs.tags }} # list
33+
labels: ${{ steps.meta.outputs.labels }} # list
34+
steps:
35+
- uses: actions/checkout@v4
36+
with:
37+
ref: ${{ github.head_ref || github.ref_name }}
38+
fetch-depth: 0
39+
show-progress: true
40+
submodules: true
41+
42+
# Replace driver `Docker' by `Docker-container` to support cache export/import
43+
- name: Set up Docker Buildx
44+
uses: docker/setup-buildx-action@v3
45+
46+
# https://github.com/docker/metadata-action
47+
- name: Extract Docker metadata
48+
id: meta
49+
uses: docker/metadata-action@v5
50+
with:
51+
images: ${{ env.REGISTRY }}/${{ github.repository }}
52+
# set latest tag for main branch and tags
53+
# https://github.com/docker/metadata-action?tab=readme-ov-file#image-name-and-tag-sanitization
54+
tags: |
55+
type=ref,event=tag
56+
type=ref,event=pr,prefix={{branch}}-
57+
type=raw,value=main,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
58+
flavor: |
59+
latest=auto
60+
61+
# https://docs.docker.com/build/ci/github-actions/share-image-jobs/
62+
# https://github.com/docker/build-push-action
63+
- name: Build and export to Jupyter image
64+
uses: docker/build-push-action@v6
65+
with:
66+
context: .
67+
file: ${{ env.NORTH_TOOL_DIR }}/Dockerfile
68+
build-args: |
69+
UV_VERSION=${{ env.UV_VERSION }}
70+
JUPYTER_TAG=${{ env.JUPYTER_VERSION }}
71+
cache-from: type=gha
72+
cache-to: type=gha,mode=max
73+
push: false
74+
tags: ${{ steps.meta.outputs.tags }}
75+
labels: ${{ steps.meta.outputs.labels }}
76+
outputs: type=docker,dest=${{ runner.temp }}/jupyter.tar
77+
- name: Upload artifact
78+
uses: actions/upload-artifact@v4
79+
with:
80+
name: jupyter-image
81+
path: ${{ runner.temp }}/jupyter.tar.gz
82+
test_and_push_image:
83+
name: Test Jupyter Image
84+
needs: build
85+
runs-on: ubuntu-latest
86+
# https://docs.docker.com/build/ci/github-actions/share-image-jobs/
87+
steps:
88+
- name: Setup Repository
89+
uses: actions/checkout@v4
90+
- name: Download artifact
91+
uses: actions/download-artifact@v4
92+
with:
93+
name: jupyter-image
94+
path: ${{ runner.temp }}
95+
pattern: "!*.dockerbuild" # warning at https://github.com/docker/build-push-action?tab=readme-ov-file
96+
97+
- name: Load and test in Jupyter container
98+
run: |
99+
docker load -i ${{ runner.temp }}/jupyter.tar.gz
100+
101+
RAW_TAGS="${{ needs.build.outputs.tags }}"
102+
echo "Raw tags: $RAW_TAGS"
103+
FIRST_TAG=$(echo "$RAW_TAGS" | tr -s '[:space:]' '\n' | grep -v '^$' | head -n 1)
104+
echo "Using tag: $FIRST_TAG"
105+
106+
for nb in ${{ env.TEST_NOTEBOOKS }}; do
107+
echo "Running notebook: $nb"
108+
docker run \
109+
--mount type=bind,src=./${{ env.TEST_DATA_DIR }},dst="/home/jovyan/north_test" \
110+
--rm "$FIRST_TAG" \
111+
/bin/bash -c "jupyter execute \$HOME/north_test/$nb"
112+
done
113+
114+
- uses: docker/login-action@v3
115+
with:
116+
registry: ${{ env.REGISTRY }}
117+
username: ${{ github.actor }}
118+
password: ${{ secrets.GITHUB_TOKEN }}
119+
- name: Push Jupyter Image
120+
run: |
121+
RAW_TAGS="${{ needs.build.outputs.tags }}"
122+
for TAG in $RAW_TAGS; do
123+
echo "Pushing tag: $TAG"
124+
docker push "$TAG"
125+
done

pyproject.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,18 @@ docs = [
5252
"mkdocs-simple-hooks",
5353
]
5454

55+
north = [
56+
"jupyterlab-h5web",
57+
"jupyterlab",
58+
"ipywidgets",
59+
]
60+
nomad = ["nomad-lab[infrastructure]>=1.4.1rc2"]
61+
5562
[project.entry-points."pynxtools.reader"]
5663
spm = "pynxtools_spm.reader:SPMReader"
5764

5865
[project.entry-points."nomad.plugin"]
66+
spm = "pynxtools_spm.nomad.north_tools.spm:north_tool"
5967
sts_example = "pynxtools_spm.nomad.entrypoints:sts_example"
6068
stm_example = "pynxtools_spm.nomad.entrypoints:stm_example"
6169
afm_example = "pynxtools_spm.nomad.entrypoints:afm_example"

src/pynxtools_spm/nomad/north_tools/__init__.py

Whitespace-only changes.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
ARG JUPYTER_TAG=2025-12-31
2+
ARG BASE_JUPYTER=quay.io/jupyter/base-notebook
3+
ARG UV_VERSION=0.9
4+
ARG PLUGIN_NAME=pynxtools-spm
5+
6+
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv_stage
7+
8+
FROM ${BASE_JUPYTER}:${JUPYTER_TAG} AS base_notebook
9+
# https://github.com/hadolint/hadolint/wiki/DL4006
10+
# https://github.com/koalaman/shellcheck/wiki/SC3014
11+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
12+
13+
COPY --from=uv_stage /uv /uvx /bin/
14+
15+
USER root
16+
17+
# Define environment variables
18+
# With pre-existing NB_USER="jovyan" and NB_UID=100, NB_GID=1000
19+
ENV HOME=/home/${NB_USER}
20+
ENV CONDA_DIR=/opt/conda
21+
22+
ARG PLUGIN_NAME
23+
24+
RUN apt-get update \
25+
&& apt-get install --yes --quiet --no-install-recommends \
26+
libmagic1 \
27+
file \
28+
build-essential \
29+
curl \
30+
zip \
31+
unzip \
32+
git
33+
34+
# By default base-notebook:2025-10-20 has node 18
35+
# But, node > 20 is required for jupyterlab >= 4.4.10
36+
# Add NodeSource APT repo for Debian-base distributions repository
37+
RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash -
38+
39+
# Install Node.js from the Debian-based distributions repository
40+
RUN apt-get install nodejs -y \
41+
&& npm install -g configurable-http-proxy@^4.2.0 \
42+
# clean cache and logs
43+
&& rm -rf /var/lib/apt/lists/* /var/log/* /var/tmp/* ~/.npm
44+
45+
USER ${NB_USER}
46+
47+
# uv env
48+
ENV UV_PROJECT_ENVIRONMENT=${CONDA_DIR} \
49+
UV_LINK_MODE=copy \
50+
UV_NO_CACHE=1 \
51+
# Use python from conda which is default for base-notebook
52+
# so that uv pip and pip refer to the same python
53+
# If needed one can create another venv with 'uv venv'
54+
UV_SYSTEM_PYTHON=1
55+
56+
COPY --chown=${NB_USER}:${NB_GID} . ${HOME}/${PLUGIN_NAME}
57+
58+
WORKDIR ${HOME}/${PLUGIN_NAME}
59+
60+
# https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers
61+
# Install dependencies
62+
RUN --mount=type=cache,target=/root/.cache/uv \
63+
uv pip install ".[north]"
64+
# uv pip install . --group north --constraint requirements.txt
65+
66+
WORKDIR ${HOME}
67+
RUN rm -rf ${HOME}/${PLUGIN_NAME}
68+
69+
RUN jupyter lab build --dev-build=False --minimize=False && \
70+
fix-permissions "/home/${NB_USER}" \
71+
&& fix-permissions "${CONDA_DIR}"
72+
73+
WORKDIR ${HOME}
74+
75+
EXPOSE 8888
76+
77+
RUN touch ${HOME}/.hushlogin
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# pynxtools-spm - NORTH Jupyter tool
2+
3+
This directory contains the NORTH tool configuration and Docker file for programmatic creation of a Jupyter-based NOMAD NORTH tool.
4+
5+
## Quick start
6+
7+
The spm NORTH tool provides a containerized JupyterLab environment for interactive analysis with the pynxtools-spm plugin.
8+
9+
## Building and testing
10+
11+
Build the Docker image locally from package root:
12+
13+
```bash
14+
docker build -f src/pynxtools_spm/north_tools/spm/Dockerfile \
15+
-t ghcr.io/RubelMozumder/pynxtools-spm:latest .
16+
```
17+
18+
Test the image:
19+
20+
```bash
21+
docker run -p 8888:8888 ghcr.io/RubelMozumder/pynxtools-spm:latest
22+
```
23+
24+
Access JupyterLab at `http://localhost:8888`.
25+
26+
## Documentation
27+
28+
For comprehensive guidance, see the main docs and the single source of truth for NORTHTool and NorthToolEntryPoint. These resources cover entry point configuration, image structure, and dependency management.
29+
30+
- [NOMAD NORTH tools](https://fairmat-nfdi.github.io/nomad-docs/howto/plugins/types/north_tools.html)
31+
- [Reference for NorthToolEntryPoint](https://fairmat-nfdi.github.io/nomad-docs/reference/plugins.html#northtoolentrypoint)
32+
- [Reference for NORTHTool](https://fairmat-nfdi.github.io/nomad-docs/howto/plugins/types/north_tools.html#north-tool-entry-point)

0 commit comments

Comments
 (0)