Skip to content

Migrate from GitLab to GitHub with Docker packaging - #1

Merged
csparker247 merged 5 commits into
mainfrom
github-migration
Jul 25, 2026
Merged

Migrate from GitLab to GitHub with Docker packaging#1
csparker247 merged 5 commits into
mainfrom
github-migration

Conversation

@csparker247

@csparker247 csparker247 commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

Migrates spectral-analysis from GitLab to GitHub: ports CI to GitHub Actions, adds a multi-arch Docker image published to GHCR (with PR-time build validation), retires the Singularity definition in favor of that image, and raises the package to Python 3.12+ to match what the dependency stack now permits.

Changes

Workflows and CI

  • Add .github/workflows/ci.yml: matrix across Python 3.12 and 3.13; installs ExifTool via apt (libimage-exiftool-perl, not the bare exiftool package, which only exists on Debian), runs pip install ., smoke-tests all three console scripts, then runs the unittest suite. Triggers on main pushes, v* tags, PRs, and manual dispatch.
  • Add .github/workflows/build_docker.yml: builds the root Dockerfile and pushes to ghcr.io/educelab/spectral-analysis. Builds linux/amd64,linux/arm64 (arm64 under QEMU emulation) everywhere. On main/tags it publishes; on pull requests it builds the same platforms but does not push, as a Dockerfile-breakage check — so a PR validates exactly what a publish will build. Registry login is skipped on PRs. Tags: latest (release tags only), edge (main tip), and semver tags (e.g. 3.0.0).
  • Concurrency grouped per-ref, with cancel-in-progress only for pull requests, so PR validation builds neither serialize behind each other nor behind a release publish.
  • All actions pinned to current majors, off the deprecated Node 20 runtime: checkout v7, setup-python v7, metadata-action v6, login-action v4, setup-qemu-action v4, setup-buildx-action v4, build-push-action v7.
  • Remove .gitlab-ci.yml, replaced entirely by the above.

Docker image

  • Add Dockerfile: python:3.13-slim base, chosen because every compiled dependency (numpy, scipy, imagecodecs, scikit-image, scikit-learn, pillow) has manylinux wheels for both amd64 and arm64 there, so the image needs no build toolchain. Installs ExifTool from source with SourceForge as the primary mirror and a gzip -t validation guard; installs the package non-editable; sets WORKDIR /data; CMD defaults to spec-enhance -h.
  • Add .dockerignore: excludes .git, __pycache__, legacy/, local venvs, test data, and built containers.

Python support

  • Raise python_requires to >=3.12, and update the CI matrix and README requirements to match.

Documentation and configuration

  • README.md: fix pyhon3 typo, update clone URL, add Docker pull/run examples and an Apptainer section covering apptainer pull docker://ghcr.io/....
  • CLAUDE.md: replace the GitLab CI section with GitHub Actions docs, record the Python floor and image base rationale, and replace the singularity/ description.
  • setup.cfg: project URL to github.com; version 2.1.0 -> 3.0.0.

Retired

  • Remove singularity/spectral-analysis.def and singularity/submit_job.sh. On the cluster, pull with apptainer pull docker://ghcr.io/educelab/spectral-analysis:latest. This drops the writable-overlay, edit-source-in-container workflow; submit_job.sh's SBATCH header and rclone bind settings remain recoverable from git history.

Notes / follow-ups

  • Repository visibility: the repo must be made public before the first v* tag push, or the published GHCR package will be private.
  • Python 3.12+ is a dependency constraint, not a preference: tifffile declares requires_python >=3.12 and numpy 2.5 dropped cp310/cp311 wheels, so older interpreters cannot install current versions of this project's own dependencies. Python 3.10 reaches EOL in October 2026; 3.11 in October 2027.
  • Version number: bumped to 3.0.0. Raising python_requires breaks installation for 3.10/3.11 users, so this is a major bump rather than a minor one. A larger refactor is expected before the release is published, so this may move again. ENHANCE_VERSION in enhance.py is versioned independently and was left alone, since spec-enhance's behavior is unchanged.
  • Docker build does not gate on tests: build_docker.yml runs independently of ci.yml, mirroring the sibling preppy repo. A red test suite can still publish a tagged image, including latest.
  • PR builds cover both arches, so an arch-specific Dockerfile failure is caught before merge rather than after. The cost is wall-clock: amd64-only took 1m41s, both arches take ~13m45s, essentially all of it the emulated arm64 leg (ExifTool's make test runs its perl suite under QEMU, and the pip install is emulated too). If that becomes annoying, the levers are dropping make test from the ExifTool build, or moving to native ubuntu-24.04-arm runners — free for public repos, and no emulation at all.
  • ExifTool is intentionally unpinned: exiftool.org only ever hosts the current tarball, so pinned URLs 404 once a new version ships (the reason 459929d moved the old .def to ver.txt). Distribution is really via SourceForge, so that is the primary source with exiftool.org as fallback, retries, and a gzip -t guard against the SF redirector returning an HTML error page. Mirrors pgs-recon's Dockerfile.
  • Docker image is verified building on both arches: the image had never been built anywhere (no local Docker daemon), so the new pull_request trigger produced its first real builds on this PR. amd64 and arm64 both succeed, login is correctly skipped, and nothing is pushed. The remaining unexercised path is the publish itself, which cannot run until this merges to main.
  • Local verification: pip install ., all three console-script smoke tests, and the unittest suite pass on Python 3.12 and 3.13; Python 3.10 is now correctly rejected by python_requires. A real spec-enhance run was verified end-to-end, including the ExifTool -Software= tag.
  • CI results on this branch: the first push passed all four legs (3.10, 3.11, 3.12, 3.13) before the matrix was narrowed; the current matrix (3.12, 3.13) also passes.
  • Prior GitLab CI bug, for the record: the old test:3.11 job specified image: python:3.10, so 3.11 was never actually tested despite CI reporting green on it. It is no longer tested here either — 3.11 is now below the supported floor.
  • Test coverage: the suite is a single test asserting setup_logging sets the log level, so CI is an install-and-import check rather than a behavioral one. Tracked in Expand the test suite beyond the single smoke test #2 — worth resolving before any large refactor.
  • GitLab issues: the 27 open issues intentionally remain on GitLab and were not migrated. All predate the 2.0 rewrite and reference the legacy/ package.

🤖 Generated with Claude Code

csparker247 and others added 5 commits July 25, 2026 10:03
- Add .github/workflows/ci.yml (test matrix: Python 3.10-3.13) and
  build_docker.yml (multi-arch GHCR publish on main/tag/dispatch)
- Add root Dockerfile (python:3.12-slim, ExifTool from source) and .dockerignore
- Remove .gitlab-ci.yml and singularity/ directory (retire Apptainer definition
  and SLURM submit script in favor of published Docker image)
- Update README.md with Docker/Apptainer pull instructions and fix typo
- Update CLAUDE.md and setup.cfg URLs and CI documentation for the new home

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Docker workflow gains a pull_request trigger (amd64-only, unpushed) to catch
  Dockerfile breakage before merge; login and QEMU steps skipped on PRs, and
  concurrency regrouped per-ref with cancel-in-progress for PRs only
- Bump all GitHub Actions off deprecated Node 20 versions: checkout v7,
  setup-python v7, metadata-action v6, login-action v4, setup-qemu-action v4,
  setup-buildx-action v4, build-push-action v7
- Move Dockerfile base from python:3.12-slim to python:3.13-slim
- Raise the package to Python 3.12+ (python_requires, README, CI matrix), forced
  by the dependency stack: tifffile requires >=3.12 and numpy 2.5 dropped
  cp310/cp311, so older interpreters cannot install current dependencies
- Bump version 2.1.0 -> 2.2.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Raising python_requires to >=3.12 breaks installation for 3.10/3.11 users, so
this is a major bump rather than a minor one. A larger refactor is expected
before the release is published.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PR builds now cover linux/amd64 and linux/arm64, matching what a publish builds,
so an arch-specific Dockerfile failure is caught before merge instead of after.
QEMU setup therefore runs on PRs as well; the arm64 leg is emulated, so expect a
slower job. PR builds still differ from publishing builds only in not pushing,
and the registry login stays skipped on PRs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
spec-enhance carried its own VERSION_MAJOR/MINOR/PATCH constants, versioned
independently of the package, which had drifted to 1.2.0 while the package moved
to 3.0.0. Expose spec_tools.__version__ from importlib.metadata instead and use
it for both the JSON run log's `program` field and the `-Software=` ExifTool tag,
making `version` in setup.cfg the single source of truth.

Note this changes output metadata: newly written images are stamped
`EduceLab spec-enhance v3.0.0` rather than v1.2.0.

When the package is not installed and no build metadata is discoverable,
__version__ falls back to '0.0.0+unknown' rather than asserting a version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@csparker247
csparker247 merged commit 2341669 into main Jul 25, 2026
3 checks passed
@csparker247
csparker247 deleted the github-migration branch July 25, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant