Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
758e685
Initial Docker commit
thomscode Dec 30, 2025
30b3a3a
Setup initial dependencies
thomscode Dec 30, 2025
afa4f28
Install OpenMPI
thomscode Dec 30, 2025
91aad96
Compile and install Boost
thomscode Dec 30, 2025
fa15ff7
Compile and install GA
thomscode Dec 30, 2025
9aaa640
Compile and install PETSc
thomscode Dec 31, 2025
483659d
Finish dependency installation by adding additional variables and set…
thomscode Dec 31, 2025
a912486
Update env vars and their usage
thomscode Jan 2, 2026
44b6532
Set `python` to be same as `python3`
thomscode Jan 2, 2026
7a53fc7
Initial steps toward gridpack installation
thomscode Jan 2, 2026
01ac145
Update PyBind11 to fix issues in Dockerfile
thomscode Jan 6, 2026
20f8658
Finish compiling and installing GridPACK
thomscode Jan 6, 2026
8ea4afd
Fix tests by disabling GLIBC assertions
thomscode Jan 8, 2026
7b00844
Add the `install/bin` and `install/local/bin` folders to the $PATH
thomscode Jan 8, 2026
8f4f63f
Merge branch 'develop' into docker
thomscode Jan 27, 2026
a1b8ff3
Merge branch 'develop' into docker
thomscode Jan 27, 2026
aba9d5b
Don't run `make check` for PETSc as this has limitations that cause p…
thomscode Jan 28, 2026
627b403
Change the default work dir to `/app/workspace`
thomscode Feb 2, 2026
d54ce4c
Update documentation to include Docker
thomscode Feb 3, 2026
ea88ac4
Update pipeline to build on native and deploy to pnnl/gridpack
thomscode Feb 3, 2026
c991a57
Merge branch 'develop' into docker
thomscode Feb 3, 2026
1d03c85
Merge branch 'develop' into docker
thomscode Feb 3, 2026
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
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.idea
external_dependencies
/python/build
/python/dist
/python/gridpack_hadrec.egg-info
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
[submodule "python/pybind11"]
path = python/pybind11
url = https://github.com/pybind/pybind11.git
branch = master
126 changes: 126 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
FROM ubuntu:questing

# Configure dependency versions
ARG boost_version=1.81.0
ARG ga_version=5.9.1
ARG petsc_version=3.24.2

# Setup environment variables used throughout installation
ENV DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC GNUMAKEFLAGS=--no-print-directory
ENV OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1

ENV GRIDPACK_ROOT_DIR=/app GP_EXT_DEPS=/deps
ENV GRIDPACK_INSTALL_DIR=${GRIDPACK_ROOT_DIR}/src/install GRIDPACK_BUILD_DIR=${GRIDPACK_ROOT_DIR}/src/build
ENV GRIDPACK_DIR=${GRIDPACK_INSTALL_DIR}

ENV boost_dir=${GP_EXT_DEPS}/boost-${boost_version} \
ga_dir=${GP_EXT_DEPS}/ga-${ga_version} \
petsc_dir=${GP_EXT_DEPS}/petsc

ENV boost_gp_dir=${boost_dir}/install_for_gridpack \
ga_gp_dir=${ga_dir}/install_for_gridpack \
petsc_gp_dir=${petsc_dir}/install_for_gridpack

ENV PETSC_DIR=${petsc_dir} PETSC_ARCH=build-dir

ENV LD_LIBRARY_PATH=${boost_gp_dir}/lib:${ga_gp_dir}/lib:${petsc_gp_dir}/lib
ENV DYLD_LIBRARY_PATH=${LD_LIBRARY_PATH}

# Install required system packages
RUN apt-get update && \
apt-get install -y --no-install-recommends cmake make wget tzdata git gfortran build-essential pkg-config \
python3 python3-pip python3-venv python3-dev python-is-python3 \
openmpi-bin openmpi-common openmpi-doc libopenmpi-dev && \
apt-get clean

# Compile/Install Boost
WORKDIR ${GP_EXT_DEPS}
RUN wget "https://github.com/boostorg/boost/releases/download/boost-${boost_version}/boost-${boost_version}.tar.gz"
RUN tar -xf "boost-${boost_version}.tar.gz"
WORKDIR ${boost_dir}
RUN ./bootstrap.sh --prefix=install_for_gridpack --with-libraries=mpi,serialization,random,filesystem,system
RUN echo 'using mpi : mpicxx ; ' >> project-config.jam
RUN ./b2 -a -d+2 link="shared" stage
RUN ./b2 -a -d+2 link="shared" install

# Compile/Install GA (Global Arrays)
WORKDIR ${GP_EXT_DEPS}
RUN wget "https://github.com/GlobalArrays/ga/releases/download/v${ga_version}/ga-${ga_version}.tar.gz"
RUN tar -xf "ga-${ga_version}.tar.gz"
WORKDIR ${ga_dir}
RUN ./configure --with-mpi-ts --disable-f77 \
--without-blas --without-lapack --without-scalapack \
--enable-cxx --enable-i4 \
--prefix=${ga_gp_dir} \
CFLAGS="-Wno-implicit-function-declaration -Wno-incompatible-pointer-types -Wno-old-style-definition" \
CXXFLAGS="-Wno-incompatible-pointer-types" \
--enable-shared=yes --enable-static=no
RUN make -j 10 install
WORKDIR ${GP_EXT_DEPS}

# Compile/Install PETSc
RUN git clone https://gitlab.com/petsc/petsc.git
WORKDIR ${petsc_dir}
RUN git checkout "tags/v${petsc_version}" -b "v${petsc_version}"
RUN ./configure \
--prefix=${PWD}/install_for_gridpack \
--scalar-type=real \
--with-fortran-bindings=0 \
--download-superlu_dist \
--download-metis \
--download-parmetis \
--download-suitesparse \
--download-f2cblaslapack \
--download-scalapack \
--download-mumps \
--download-cmake=0 \
--with-sowing=0 \
--with-debugging=0 \
--with-shared-libraries=1
RUN make all
RUN make install
#RUN make PETSC_DIR=${petsc_gp_dir} PETSC_ARCH="" check

# Copy in GridPACK source code from repository
COPY README.md .gitignore .gitmodules ${GRIDPACK_ROOT_DIR}/
COPY .git ${GRIDPACK_ROOT_DIR}/.git
COPY docs ${GRIDPACK_ROOT_DIR}/docs
COPY python ${GRIDPACK_ROOT_DIR}/python
COPY src ${GRIDPACK_ROOT_DIR}/src

# Build GridPACK
WORKDIR ${GRIDPACK_BUILD_DIR}
RUN cmake -Wdev -D GA_DIR:STRING=${ga_gp_dir} \
-D Boost_ROOT:STRING=${boost_gp_dir} \
-D Boost_DIR:string=${boost_gp_dir}/lib/cmake/Boost-${boost_version} \
-D PETSC_DIR:PATH=${petsc_gp_dir} \
-D MPI_CXX_COMPILER:STRING='mpicxx' \
-D MPI_C_COMPILER:STRING='mpicc' \
-D MPIEXEC:STRING='mpiexec' \
-D MPIEXEC_MAX_NUMPROCS:STRING=2 \
-D GRIDPACK_TEST_TIMEOUT:STRING=120 \
-D ENABLE_ENVIRONMENT_FROM_COMM:BOOL=YES \
-D CMAKE_INSTALL_PREFIX:PATH=${GRIDPACK_INSTALL_DIR} \
-D CMAKE_BUILD_TYPE:STRING=Debug \
-D BUILD_SHARED_LIBS=true \
-D CMAKE_CXX_FLAGS_DEBUG:STRING="-D_GLIBCXX_NO_ASSERTIONS" \
..
RUN make install

# Install Python bindings
WORKDIR ${GRIDPACK_ROOT_DIR}
RUN git submodule update --init
RUN pip config --global set global.break-system-packages true
WORKDIR ${GRIDPACK_ROOT_DIR}/python
RUN pip install --upgrade --prefix=${GRIDPACK_INSTALL_DIR} .

# Configure Python module search path using .pth file (no environment variables needed)
# Python automatically reads .pth files from its site-packages directories
RUN pyvnum=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && \
system_site_packages=$(python3 -c 'import site; print(site.getsitepackages()[0])') && \
echo "${GRIDPACK_INSTALL_DIR}/lib/python${pyvnum}/site-packages" > ${system_site_packages}/gridpack.pth && \
echo "${GRIDPACK_INSTALL_DIR}/local/lib/python${pyvnum}/dist-packages" >> ${system_site_packages}/gridpack.pth && \
echo "Configured Python ${pyvnum} module search path via ${system_site_packages}/gridpack.pth"

WORKDIR ${GRIDPACK_ROOT_DIR}/workspace
ENV PATH=${GRIDPACK_INSTALL_DIR}/bin:${GRIDPACK_INSTALL_DIR}/local/bin:${PATH}
10 changes: 0 additions & 10 deletions Dockerfile.test

This file was deleted.

20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,32 @@ In addition, GridPACK is also a framework to simplify the development of new app
## Installation
See the [instructions](docs/markdown/BASIC_INSTALL.md) for installing GridPACK, prerequisite software, and installation notes for different platforms. Formal releases are available [here](https://github.com/GridOPTICS/GridPACK/releases).

### Using Docker (Recommended)

GridPACK is available as a multi-architecture Docker image with all dependencies pre-installed:

```bash
# Pull the image
docker pull pnnl/gridpack:latest

# Run with your files (container starts in /app/workspace)
docker run -it --rm -v $(pwd):/app/workspace pnnl/gridpack:latest bash
```

The Docker image supports both AMD64 and ARM64 architectures. See the [Docker usage guide](https://gridpack.readthedocs.io/en/latest/Section2-Docker.html) for more examples.

### Building from Source

See the [installation instructions](docs/markdown/BASIC_INSTALL.md) for building GridPACK from source, prerequisite software, and platform-specific installation notes. Formal releases are available [here](https://github.com/GridOPTICS/GridPACK/releases).

## Usage
See the [user manual](https://gridpack.readthedocs.io/en/latest/index.html) for a deep dive on GridPACK internals and/or refer to the [tutorials](docs/markdown/TUTORIALS.md) for more info.

- Quick Guide (To do)

## Documentation
- [Docker Usage Guide](https://gridpack.readthedocs.io/en/latest/Section2-Docker.html)
- [CI/CD Pipeline](docs/markdown/CI-CD.md)
- [User manual](https://gridpack.readthedocs.io/en/latest/index.html)
- [Tutorials](docs/markdown/TUTORIALS.md)
- [FAQS](docs/markdown/FAQS.md)
Expand Down
203 changes: 203 additions & 0 deletions docs/markdown/CI-CD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# CI/CD Pipeline Documentation

## Overview

GridPACK uses GitHub Actions to build multi-architecture Docker images that are automatically published to Docker Hub at `pnnl/gridpack`.

## Pipeline Architecture

The pipeline uses native ARM64 and AMD64 runners for optimal build performance:

```
prepare-metadata → build-native (amd64 + arm64) → merge-manifest → test-native (amd64 + arm64)
↓ parallel ↓ ↓ ↓ parallel ↓
```

### Jobs

1. **prepare-metadata**: Generates Docker tags and labels
2. **build-native**: Builds images natively on AMD64 and ARM64 runners in parallel
3. **merge-manifest**: Stitches architecture-specific images into a multi-arch manifest
4. **test-native**: Runs ctest smoke tests on both architectures in parallel

### Performance

- **Native ARM64 builds**: 3-10x faster than QEMU emulation
- **Parallel execution**: Both architectures build simultaneously
- **Total build time**: ~20-35 minutes (vs 45-90 minutes with QEMU)

## Triggers

### Automatic: Release Published

When a GitHub release is created, the pipeline automatically builds and publishes:

```bash
gh release create v3.3.0 --title "Release 3.3.0" --notes "Release notes"
```

Generated tags:
- `pnnl/gridpack:3.3.0`
- `pnnl/gridpack:3.3`
- `pnnl/gridpack:latest`

### Manual: Workflow Dispatch

Trigger builds manually from the GitHub Actions UI or CLI:

**Via GitHub UI:**
1. Go to: Actions → Docker Multi-Architecture Build and Publish
2. Click "Run workflow"
3. Configure options:
- **tag**: Custom Docker tag (default: `dev`)
- **skip_tests**: Skip ctest smoke tests (default: `false`)
- **dockerfile**: Dockerfile path (default: `./Dockerfile`)
4. Click "Run workflow"

**Via GitHub CLI:**

```bash
# Basic run with defaults
gh workflow run docker-build.yml

# With custom tag
gh workflow run docker-build.yml -f tag=test-build

# Skip tests for faster iteration
gh workflow run docker-build.yml -f skip_tests=true

# Use custom Dockerfile
gh workflow run docker-build.yml -f dockerfile=./Dockerfile.custom
```

## Docker Image

### Repository
- **Location**: `pnnl/gridpack`
- **Registry**: Docker Hub

### Supported Architectures
- `linux/amd64` (Intel/AMD)
- `linux/arm64` (ARM64/Apple Silicon/AWS Graviton)

### Usage

See [Docker Usage Guide](./DOCKER.md) for detailed examples.

## Testing

The pipeline runs ctest smoke tests on both architectures after building. Key points:

- **Non-blocking**: Test failures do NOT prevent image publication (`continue-on-error: true`)
- **Expected pass rate**: ~94%
- **Can be skipped**: Use `skip_tests=true` for faster iteration

## Secrets Required

The pipeline requires two GitHub repository secrets:

| Secret | Description |
|--------|-------------|
| `DOCKERHUB_USERNAME` | Docker Hub username for authentication |
| `DOCKERHUB_TOKEN` | Docker Hub access token (not password!) |

### Setting Up Secrets

1. **Generate Docker Hub Access Token:**
- Go to: https://hub.docker.com → Account Settings → Security
- Create token: Name: `gridpack-ci`, Permissions: Read, Write, Delete
- Copy the token (shown only once)

2. **Add to GitHub:**
- Go to: Repository Settings → Secrets and variables → Actions
- Add both secrets with the values above

## Monitoring

### View Workflow Runs

```bash
# List recent runs
gh run list --workflow=docker-build.yml --limit 5

# Watch a specific run
gh run watch <run-id>

# View detailed logs
gh run view <run-id> --log
```

### Inspect Published Image

```bash
# View manifest with both architectures
docker buildx imagetools inspect pnnl/gridpack:latest

# Expected output shows:
# - linux/amd64 manifest
# - linux/arm64 manifest
```

## Caching

The pipeline uses GitHub Actions cache to speed up builds:

- Separate cache per architecture (`build-amd64`, `build-arm64`)
- Automatically managed by GitHub
- Improves rebuild times significantly

## Troubleshooting

### Build Fails on One Architecture

The pipeline uses `fail-fast: false`, so if one architecture fails, the other continues. Check job logs for architecture-specific issues.

### Manifest Merge Fails

This usually indicates both architecture builds failed. Check that:
- Docker Hub credentials are correct
- Both build jobs completed successfully
- Digest artifacts were uploaded

### Authentication Issues

Verify secrets are configured correctly:
```bash
gh secret list
```

Should show:
- `DOCKERHUB_USERNAME`
- `DOCKERHUB_TOKEN`

## Technical Details

### Push-by-Digest Workflow

The pipeline uses a digest-based approach:

1. Each architecture builds and pushes: `pnnl/gridpack@sha256:abc123...`
2. These are content-addressed (by digest), not tagged yet
3. Manifest merge creates tags that reference both digests
4. Docker automatically selects the right image based on client platform

### Why Native Runners?

- **Performance**: 3-10x faster ARM64 builds without QEMU
- **Reliability**: No emulation issues or crashes
- **Testing**: Tests run on actual target platforms
- **Cost**: Same GitHub Actions pricing as AMD64

## Workflow File

Location: `.github/workflows/docker-build.yml`

The workflow definition must be in the default branch to be accessible. Changes to the workflow require merging to the default branch.

## Future Enhancements

Potential improvements:
- Additional architectures (RISC-V when runners available)
- Multi-registry support (GitHub Container Registry)
- Build time metrics/reporting
- Automated security scanning per architecture
Loading
Loading