Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
85 changes: 50 additions & 35 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,53 +28,68 @@ jobs:
run: black --check .


# Run python tests
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python 3.13.1
uses: actions/setup-python@v5
with:
python-version: "3.13.1"
- name: Install dependencies
run: |
cd app
python -m pip install --upgrade pip
pip install pytest coverage
pip install -r requirements.txt
- name: Run pytest
run: cd app && coverage run -m pytest .
- name: Create code coverage report
run: cd app && coverage html
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage
path: app/htmlcov
retention-days: 30


# Build Docker images to verify they can be built
# Build Docker image and save as artifact
docker:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker images
- name: Build and load Docker image
uses: docker/build-push-action@v5.3.0
with:
# Build's context is the set of files located in the specified PATH or URL
context: app
# List of target platforms for build
platforms: linux/amd64,linux/arm64
# Don't push, just build to verify
# Build for single platform to enable loading
platforms: linux/amd64
# Load the image into Docker daemon
load: true
push: false
tags: hv-coordinator:buildtest
- name: Save Docker image
run: docker save hv-coordinator:buildtest -o /tmp/docker-image.tar
- name: Upload Docker image artifact
uses: actions/upload-artifact@v4
with:
name: docker-image
path: /tmp/docker-image.tar
retention-days: 1


# Test inside Docker container
docker-test:
runs-on: ubuntu-latest
needs: docker

steps:
- name: Download Docker image artifact
uses: actions/download-artifact@v4
with:
name: docker-image
path: /tmp
- name: Load Docker image
run: docker load -i /tmp/docker-image.tar
- name: Run tests in container
run: |
docker run --name test-container \
--entrypoint sh \
-e COVERAGE_FILE=/tmp/.coverage \
hv-coordinator:buildtest \
-c "
mamba run -n coordinator pip install -r requirements-dev.txt
mamba run -n coordinator python -m coverage run -m pytest .
mamba run -n coordinator python -m coverage html -d /tmp/htmlcov
"
- name: Copy coverage report from container
run: docker cp test-container:/tmp/htmlcov ./coverage-output
- name: Remove container
run: docker rm test-container
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: docker-coverage
path: coverage-output
retention-days: 30

38 changes: 29 additions & 9 deletions app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,48 @@
# Builder stage - has all build tools
FROM condaforge/mambaforge AS builder

WORKDIR /build
COPY requirements.txt .

# This is where pip will be after the conda environment is created
ENV PIP=/opt/conda/envs/coordinator/bin/pip

# Create conda environment and install dependencies
RUN mamba create -n coordinator -y python=3.13.5 gcc \
&& cd /tmp \
&& git clone https://github.com/sunpy/sunpy.git \
&& cd sunpy \
&& git fetch origin pull/8500/head:pr-8500 \
&& git checkout pr-8500 \
&& mamba run -n coordinator pip install --no-cache-dir . \
&& cd /build \
&& mamba run -n coordinator pip install --no-cache-dir -r requirements.txt \
&& rm -rf /tmp/sunpy

# Final stage - minimal runtime image
FROM condaforge/mambaforge

RUN apt update && apt install -y curl

# Create and switch to non-root user
RUN useradd -m -s /bin/bash nonroot
WORKDIR /home/nonroot/app
USER nonroot

# Copy conda environment from builder (keep same path)
COPY --from=builder /opt/conda/envs/coordinator /opt/conda/envs/coordinator

# copy application files to the container
COPY --chown=nonroot:nonroot . .

USER nonroot

# This is where pip will be after the conda environment is created
# can't conda activate in dockerfile
ENV PIP=/home/nonroot/.conda/envs/coordinator/bin/pip

# Install dependencies in conda environment
RUN <<EOF
mamba create -n coordinator -y python=3.13.1
$PIP install --no-cache-dir -r requirements.txt
EOF
ENV PIP=/opt/conda/envs/coordinator/bin/pip

HEALTHCHECK --interval=2s --timeout=10s \
CMD curl --silent --fail "http://127.0.0.1/health-check"

ENTRYPOINT ["/home/nonroot/.conda/envs/coordinator/bin/python"]
ENTRYPOINT ["/opt/conda/envs/coordinator/bin/python"]

CMD ["-m", "fastapi", "run", "--workers", "4", "--port", "80", "main.py"]
4 changes: 2 additions & 2 deletions app/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
black==26.1.0
pytest==9.0.2
httpx==0.28.1
black==25.12.0
coverage==7.13.3
6 changes: 2 additions & 4 deletions app/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
astropy==7.2.0
sunpy==7.1.0
matplotlib==3.10.8
reproject==0.19.0
mpl_animators==1.2.4
fastapi[standard]==0.128.0
matplotlib==3.10.8
mpl_animators==1.2.4