Commit Sage code, GitHub Actions builds a self-contained Apptainer image, and the cluster pulls and runs it as a Slurm job.
.github/workflows/build-sage-container.yml CI workflow
container/sage.def Apptainer definition
code/main.sage Your Sage entry point (edit me)
slurm/run_sage.sbatch Submission script for the cluster
- A push to
mainthat touchescode/orcontainer/triggers the workflow. - The runner installs Apptainer, builds
sage-job.siffromcontainer/sage.def(which bakescode/into the image at/opt/sage-code), and runsapptainer testas a smoke test. - The SIF is pushed to GitHub Container Registry as an ORAS artifact, tagged
latestand with the commit SHA. It's also attached as a workflow artifact as a fallback. - On the cluster,
sbatch slurm/run_sage.sbatchpulls the image and runs it. The container's runscript executessage /opt/sage-code/main.sage, forwarding any arguments you pass tosbatch ... script args.
-
Edit
REPOinslurm/run_sage.sbatchto yourghcr.io/<user>/<repo>/sage-jobpath. -
After the first push, go to the package on GitHub (Profile → Packages → sage-job) and either make it public (simplest for the cluster) or, if it must stay private, authenticate on the cluster once with a classic PAT that has
read:packages:apptainer registry login --username <gh-user> oras://ghcr.io -
Make sure your cluster's login/compute nodes can reach
ghcr.io. If they can't, download the workflow artifact instead andscpthe SIF over.
sbatch slurm/run_sage.sbatch # runs main.sage
sbatch slurm/run_sage.sbatch --n 1000 # args are forwarded to main.sage
SAGE_IMAGE_TAG=<commit-sha> sbatch slurm/run_sage.sbatch # pin a specific build
Outputs written to /output inside the container land in results-<jobid>/ next to where you submitted.
- Image size: the image installs core Sage from conda-forge on a micromamba base — typically ~2 GB instead of the ~6+ GB official Docker image. Need extra Python packages? Add them to the
micromamba installline incontainer/sage.def(e.g.numpy scipy pandas). - Reproducibility: pin the Sage version in
sage.def(pinned tosage=10.4in the conda install) and submit jobs with the commit-SHA tag rather thanlatest. - Different entry point: change the
%runscriptinsage.def, or override at runtime withapptainer exec sage-job.sif sage /opt/sage-code/whatever.sage. - MPI / GPU: add
--nvto theapptainer runline for CUDA, or restructure withsrun apptainer exec ...for multi-task MPI jobs.