Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
197 commits
Select commit Hold shift + click to select a range
bb9bd55
Added script to build GridPACK in one-go, including installing all de…
abhyshr Dec 31, 2022
eb24be9
Updated installation script tested on EIOC-Ubuntu8
abhyshr Mar 16, 2023
f29a18f
Minor modifications to install script
abhyshr Mar 17, 2023
42d4807
Small modification to check python
abhyshr Mar 18, 2023
0e6b2ce
Updated gridpack install script to only install GridPACK and python w…
abhyshr Apr 7, 2023
2d9d2f1
More work on installation script
abhyshr Apr 7, 2023
1778817
Create external-dependencies directory, if not present.
abhyshr Apr 7, 2023
37c8dd7
Apply shellcheck suggestions and run formatter
jacksavage Sep 6, 2023
24cdd96
Move blocks into functions and extract versions
jacksavage Sep 6, 2023
af2952c
Correct how variables are checked
jacksavage Sep 6, 2023
1e93924
Bump versions out of script with env vars
jacksavage Sep 6, 2023
1d509f0
Remove GA-based dense matrix; adjust matrix transpose
wperkins Aug 23, 2023
e85428a
Remove all PETSC_VERSION usage.
wperkins Aug 24, 2023
b9f6171
Update PETSc settings for tlaloc
wperkins Aug 28, 2023
4efdd6b
Add smoke test for 240-bus dynamic simulation
wperkins Aug 28, 2023
a0a0869
Add a CMake macro to do the LU solver check and use it
wperkins Aug 28, 2023
b713505
Add smoke test for 2-area dynamic simulation
wperkins Aug 28, 2023
f99aeac
Add smoke test for two area case w/ renewables
wperkins Aug 30, 2023
e4c2171
Remove math::transpose(Matrix<>, Matrix<>) because of PETSc transpose…
wperkins Aug 30, 2023
6580fda
Add smoke tests for dsf2.x (same as for dsf.x).
wperkins Aug 30, 2023
e7ab92b
Add smoke test for Wind DSA 9-bus case
wperkins Aug 31, 2023
5b38344
Fix typos in Wind DSA TAMU 2000 case
wperkins Aug 31, 2023
7514dcc
Add a smoke test for Wind DSA TAMU 2000 case
wperkins Aug 31, 2023
f84ae13
Remove ancient test from `applications/development/dynamic_simulation…
wperkins Sep 6, 2023
7ed20ef
Fix env var
jacksavage Sep 6, 2023
d3aecd9
Set number of make threads dynamically
jacksavage Sep 6, 2023
795505d
Add ci script and container image definition
jacksavage Sep 6, 2023
66fbc23
Fix incorrect Matrix type Jacobian supplied to DAESolver constructor
wperkins Sep 13, 2023
2c0744e
Update my build script
wperkins Sep 13, 2023
7ac8094
Test pipeline trigger
jacksavage Sep 14, 2023
7744e71
Build container, make dep from test optional
jacksavage Sep 14, 2023
9cc9d04
Update dockerfile path
jacksavage Sep 14, 2023
09dd060
Increase k8s memory limit
jacksavage Sep 27, 2023
1a5b94a
Increase mem request/limit and job timeout
jacksavage Sep 27, 2023
60572f0
Add cpu and increase timeout further
jacksavage Sep 27, 2023
50adb0d
Troubleshooting env
jacksavage Oct 2, 2023
8d052b2
Use correct predefined CI variable
jacksavage Oct 2, 2023
e0cecaa
Add conditions for building container
jacksavage Oct 2, 2023
4d60837
Adjust k8s parameters and gitlab job timeout
jacksavage Oct 3, 2023
503dabd
Update CPU limit
jacksavage Oct 3, 2023
a07da9a
Adjust CPU req/limits
jacksavage Oct 3, 2023
3f0fca8
Adjust CPU limit
jacksavage Oct 3, 2023
263135f
Adjust cpu request
jacksavage Oct 3, 2023
7d97be1
Set GRIDPACK_DIR
jacksavage Oct 3, 2023
8ba3542
Uncomment gp_include and gp_libs
jacksavage Oct 3, 2023
9b533f0
Add Boost_NO_BOOST_CMAKE
jacksavage Oct 4, 2023
48d1adc
Set max number of make jobs
jacksavage Oct 4, 2023
e88724d
Only append python path if exists
jacksavage Oct 4, 2023
a442f45
Add comment
jacksavage Oct 11, 2023
1107658
Add test job
jacksavage Oct 11, 2023
725cf47
Use default timeout for build
jacksavage Oct 11, 2023
920d93e
Remove 2000-bus Wind-DSA smoke tests - they take too long
wperkins Oct 11, 2023
f5e91bc
Switch to a direct linear solver because this was diverging
wperkins Oct 11, 2023
d7d8907
Whitespace change
jacksavage Oct 16, 2023
d8b0a9c
Merge remote-tracking branch 'origin/fix/testing' into gitlab-ci
jacksavage Oct 16, 2023
1231f64
Troubleshooting
jacksavage Oct 16, 2023
d4c0929
Revert block comment
jacksavage Oct 17, 2023
9f77461
Fix test command and save results
jacksavage Oct 17, 2023
1fd0ea7
Always save artifacts for the test job
jacksavage Oct 17, 2023
ea037d8
Remove version numbers from LD_LIBRARY_PATH
jacksavage Oct 17, 2023
098a846
Run tests as non-root user
jacksavage Oct 17, 2023
22b88f5
Fix rules for build-container job
jacksavage Oct 17, 2023
ddf9948
Don't override env vars
jacksavage Oct 23, 2023
fc96b36
Remove manual container build rule
jacksavage Oct 23, 2023
45b0463
Add build status badge
jacksavage Oct 23, 2023
d71c50c
Only use two processors
jacksavage Oct 24, 2023
0fe20f0
Show output for failed tests
jacksavage Nov 8, 2023
b7003fc
Test with multiple distributions
jacksavage Dec 28, 2023
18ca8b0
Merge branch 'develop' into gitlab-ci
jacksavage Dec 29, 2023
0f5883d
Back out changes to src
jacksavage Dec 29, 2023
41bc8cc
Remove attempted variable substitution
jacksavage Dec 29, 2023
c985f45
Set conditions for when container is built
jacksavage Jan 2, 2024
be884de
Fix quoting
jacksavage Jan 2, 2024
46969d6
Make script available to setup env
jacksavage Jan 2, 2024
b83499e
Make scripts executable for docker image build
jacksavage Jan 2, 2024
d7bf557
Save logs from install_gridpack_deps
jacksavage Jan 2, 2024
71099a3
Fix artifact path for logs
jacksavage Jan 2, 2024
401494a
Test - remove parallel config
jacksavage Jan 2, 2024
6bd8336
Link logs to project folder
jacksavage Jan 3, 2024
f9a76ec
Send logs to back console 😫
jacksavage Jan 3, 2024
7d842a3
Redirect output to files
jacksavage Jan 3, 2024
2910f3b
Build PETSc with MUMPS instead of SuperLU_dist
jacksavage Jan 3, 2024
186b938
Redirect both streams from kaniko exe to file
jacksavage Jan 3, 2024
65965a5
Move the container registry check to its own job
jacksavage Jan 5, 2024
6ca911f
Use block scalar to avoid issues with special chars
jacksavage Jan 5, 2024
25ddd79
Always save untracked files
jacksavage Jan 5, 2024
fe63603
Fix block scalar
jacksavage Jan 5, 2024
9e26370
Swap out mpms for superlu for now
jacksavage Jan 5, 2024
70deb07
Pull back on untracked artifacts where it makes sense
jacksavage Jan 5, 2024
8c91600
Revert "Swap out mpms for superlu for now"
jacksavage Jan 5, 2024
9253abf
Add scalapack per error message
jacksavage Jan 5, 2024
37ad180
Remove the artifact path spec for build container
jacksavage Jan 5, 2024
574be1c
Pull container repo id into var
jacksavage Jan 5, 2024
cc7ecae
Try to see log files I need when build fails
jacksavage Jan 5, 2024
1ae11b1
Set the proxy var for kaniko
jacksavage Jan 10, 2024
317ddc4
Pass proxy to all jobs
jacksavage Jan 10, 2024
bb44759
Try lowercase
jacksavage Jan 10, 2024
cae4119
Mark as variables
jacksavage Jan 10, 2024
6a576ee
Remove petsc config option
jacksavage Jan 19, 2024
d0113b4
Remove unused log folder
jacksavage Jan 20, 2024
e21f58f
Try to parallelize the pipeline again
jacksavage Jan 20, 2024
2f9ae93
Revert troubleshooting command
jacksavage Jan 20, 2024
8f1ccb4
Separate scripts to improve caching
jacksavage Jan 20, 2024
9af3251
Install mpi4py dependency
jacksavage Jan 20, 2024
da31230
Set proxy build args in container build env
jacksavage Jan 22, 2024
109ee89
Get mpi4py from system repos instead of through pip
jacksavage Jan 22, 2024
65cd863
Use common check for distro between scripts
jacksavage Jan 22, 2024
31d1fb2
Manually define job parallelization and adjust whitespace
jacksavage Jan 22, 2024
3fc6c43
Try adding docker config and cert to kaniko container
jacksavage Jan 23, 2024
6eede55
Make the build container job an optional dep
jacksavage Jan 23, 2024
8464d31
Add verbose flag
jacksavage Jan 23, 2024
c54637c
Remove manual trigger from container build job
jacksavage Jan 23, 2024
d3222bb
Use a heredoc to populate docker config
jacksavage Jan 23, 2024
98877ae
Dump environment variables
jacksavage Jan 23, 2024
78f5ace
Disable rules for build container job for now
jacksavage Jan 23, 2024
7780979
Organize job into stages
jacksavage Jan 23, 2024
240306a
Add epel repo and enable crb repo
jacksavage Jan 23, 2024
11df6b1
Remove troubleshooting commands
jacksavage Jan 23, 2024
20051dd
Normalize ENV declarations
jacksavage Jan 23, 2024
c580ba2
Formatting changes
jacksavage Jan 24, 2024
08e019a
Add mpicc to path after openmpi-devel install
jacksavage Jan 24, 2024
a377342
Reenable ubuntu build
jacksavage Jan 24, 2024
b66c87a
Add mpicc to path if on RHEL
jacksavage Jan 24, 2024
c2089f1
Remove path mod for mpicc
jacksavage Jan 24, 2024
bdebd00
Load mpi module for RHEL
jacksavage Jan 24, 2024
96214c0
Load mpi module instead of altering PATH
jacksavage Jan 24, 2024
d85e3f1
Add boost-openmpi package to rocky linux
jacksavage Jan 24, 2024
073a9b2
Remove rocky linux jobs for now
jacksavage Jan 24, 2024
c566c0d
Bump up timeout
jacksavage Jan 24, 2024
2e13f34
Bump the test timeout again
jacksavage Jan 24, 2024
90d222d
Remove cmake download flag
jacksavage Jan 25, 2024
73ec77a
Remove boost-openmpi package
jacksavage Jan 30, 2024
f8f9dd4
Remove mpi module load from this script
jacksavage Jan 31, 2024
60929fa
More specifically remove scripts
jacksavage Jan 31, 2024
37354aa
Formatting
jacksavage Jan 31, 2024
1eac86f
Force remove tar file
jacksavage Jan 31, 2024
8dd6945
Use MAKE_JOBS for global array install too
jacksavage Jan 31, 2024
10535ab
Remove mpi module load from install_gridpack_deps
jacksavage Jan 31, 2024
7e408d3
Add script to load mpi module on RHEL
jacksavage Jan 31, 2024
a4414e3
Load the mpi module via script before bootstrapping boost
jacksavage Jan 31, 2024
3afbf68
Group scripts and dockerfile under build dir
jacksavage Jan 31, 2024
894235c
Move MAKE_JOBS var to global scope
jacksavage Jan 31, 2024
f0b7ca4
Move some variables to the devops.pnnl.gov GitLab CI/CD vars
jacksavage Jan 31, 2024
548fdf4
Point kaniko args to new build dir
jacksavage Jan 31, 2024
5b36074
Add open MPI vars to silence warnings
jacksavage Jan 31, 2024
dd58702
Script renames
jacksavage Jan 31, 2024
af832bc
Load mpi module via script before generating make files
jacksavage Jan 31, 2024
ecd4c7c
Update paths for kaniko args
jacksavage Jan 31, 2024
4728088
Test
jacksavage Jan 31, 2024
061f121
Rework module load
jacksavage Jan 31, 2024
f5e1ce8
Avoid extra chmod step
jacksavage Jan 31, 2024
b25748a
Dot source since using sh not bash
jacksavage Jan 31, 2024
64df129
Put open MPI env vars in right spot to suppress warnings
jacksavage Jan 31, 2024
4a645f7
Add back script to check if container tag exists
jacksavage Feb 6, 2024
b1b87c7
Add comment on bash options
jacksavage Feb 6, 2024
84a4a5f
Reorder things
jacksavage Feb 6, 2024
60b8558
Simplify arg checks
jacksavage Feb 7, 2024
e258077
Roll functions into lib.sh
jacksavage Feb 7, 2024
a247e33
Check commands are installed
jacksavage Feb 7, 2024
fe8402e
Split apart check_build_container into two jobs
jacksavage Feb 7, 2024
971c972
Remove doc comments
jacksavage Feb 7, 2024
88217a2
Use bash in dockerfile
jacksavage Feb 7, 2024
2096c5c
Reorg scripts
jacksavage Feb 16, 2024
41be3a4
Use lib function to load mpi module and test distro
jacksavage Feb 18, 2024
8c59fcd
Load mpi module before running tests
jacksavage Feb 18, 2024
66c080e
Load mpi module from the boost script directly
jacksavage Feb 18, 2024
5b209f9
Add container check jobs to a stage
jacksavage Feb 18, 2024
cab5119
Use image with bash to run container image checks
jacksavage Feb 19, 2024
8b3c60a
Install jq for container image checks
jacksavage Feb 19, 2024
65ff2e9
Need curl too
jacksavage Feb 19, 2024
aacf182
Troubleshoot url issue
jacksavage Feb 19, 2024
1875102
Merge form data with url so theres not a false arg
jacksavage Feb 19, 2024
ac71d39
Try different header name
jacksavage Feb 19, 2024
4483102
Use PRIVATE_TOKEN until gitlab updated to allow JOB_TOKEN by default
jacksavage Feb 19, 2024
fc607c6
Fix newline
jacksavage Feb 19, 2024
d328502
Use intermediate variable between curl and jq
jacksavage Feb 19, 2024
f275d8c
Try echoing to jq
jacksavage Feb 19, 2024
cd133fb
Remove the troubleshooting from earlier...
jacksavage Feb 19, 2024
55bfa71
Use proper tag when checking registry
jacksavage Feb 19, 2024
1b88fba
Only depend on container-needs-built file in .build-container
jacksavage Feb 19, 2024
c9aa739
Try project path, not project path slug
jacksavage Feb 19, 2024
f3421d6
Inline build_container function
jacksavage Feb 19, 2024
dc82d3e
Uppercase variable
jacksavage Feb 19, 2024
6e9646f
Break script into multiple array items
jacksavage Feb 19, 2024
b5ea6ae
Try a different yaml string format for kaniko command
jacksavage Feb 19, 2024
7edf6db
Add a brief readme
jacksavage Feb 19, 2024
3aa1ca3
Add rules for when GridPACK build/test jobs should run
jacksavage Feb 19, 2024
063d954
Separate GP_EXT_DEPS for ref by LD_LIBRARY_PATH
jacksavage Feb 20, 2024
c2fa807
Add rocky linux jobs back
jacksavage Feb 20, 2024
9cebab7
Load mpi for GA and PETSC, fix docker RUN error handling
jacksavage Feb 20, 2024
7bbb045
Tee to build log with pipefail reporting nonzero exit from kaniko
jacksavage Feb 20, 2024
1a7f3ab
Provide option to run jobs from web UI
jacksavage Feb 21, 2024
99007f2
Remove nounset for kaniko job
jacksavage Feb 21, 2024
ec163b1
Add more specific file rules for check-container-definition-changed
jacksavage Feb 22, 2024
ad3edd0
Rename build to build-system, update readme contents
jacksavage Feb 22, 2024
3a91064
Disable rockylinux jobs from automatically running for now
jacksavage Feb 22, 2024
0e4f663
Update readme
jacksavage Feb 22, 2024
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
141 changes: 141 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
default:
tags: [basic, gridpack, ikp, k8s]
artifacts:
when: always
untracked: true
image: ubuntu:22.04

stages:
- check-container
- build-container
- build-gridpack
- test-gridpack

variables:
MAKE_JOBS: "2"
UBUNTU_BASE_IMAGE: "ubuntu:22.04"
UBUNTU_ENV_IMAGE: "ubuntu-gridpack-env"
ROCKY_BASE_IMAGE: "rockylinux:9"
ROCKY_ENV_IMAGE: "rocky-gridpack-env"

check-container-definition-changed:
stage: check-container
script:
- touch container-definition-changed
rules:
- if: $CI_PIPELINE_SOURCE == "push"
changes:
- "build-system/dockerfile"
- "build-system/install_package_deps_lib.sh"
- "build-system/install_boost.sh"
- "build-system/install_ga.sh"
- "build-system/install_petsc.sh"

.check-container-needs-built:
stage: check-container
needs:
- job: check-container-definition-changed
optional: true
script:
- set -o xtrace -o errexit -o nounset -o pipefail
- apt-get update && apt-get install -y curl jq
- source ./build-system/container_lib.sh
- check_container_needs_built "${ENV_IMAGE}"

check-container-needs-built:ubuntu:
extends: .check-container-needs-built
variables:
ENV_IMAGE: ${UBUNTU_ENV_IMAGE}

check-container-needs-built:rocky:
extends: .check-container-needs-built
variables:
ENV_IMAGE: ${ROCKY_ENV_IMAGE}
when: manual # todo remove when ready to test with rockylinux

# https://docs.gitlab.com/ee/ci/docker/using_kaniko.html#building-an-image-with-kaniko-behind-a-proxy
.build-container:
stage: build-container
timeout: 5 hours
image:
name: gcr.io/kaniko-project/executor:v1.9.0-debug
entrypoint: [""]
script:
- set -o errexit -o pipefail
- test -f container-needs-built || test "$FORCE_CONTAINER_BUILD" = "true" || exit 0
- >-
/kaniko/executor
--context build-system
--build-arg "BASE_IMAGE=${BASE_IMAGE}"
--build-arg "http_proxy=${HTTP_PROXY}"
--build-arg "https_proxy=${HTTPS_PROXY}"
--dockerfile build-system/dockerfile
--destination "${CI_REGISTRY_IMAGE}:${ENV_IMAGE}" 2>&1 | tee build.log

build-container:ubuntu:
extends: .build-container
needs: [check-container-needs-built:ubuntu]
variables:
BASE_IMAGE: ${UBUNTU_BASE_IMAGE}
ENV_IMAGE: ${UBUNTU_ENV_IMAGE}

build-container:rocky:
extends: .build-container
needs: [check-container-needs-built:rocky]
variables:
BASE_IMAGE: ${ROCKY_BASE_IMAGE}
ENV_IMAGE: ${ROCKY_ENV_IMAGE}
when: manual # todo remove when ready to test with rockylinux

.build-gridpack:
stage: build-gridpack
script:
- /bin/bash ./build-system/install_gridpack.sh
rules:
- if: $CI_PIPELINE_SOURCE == "push"
changes:
- "build-system/**/*"
- "src/**/*"
- "python/**/*"
- if: $CI_PIPELINE_SOURCE == "web"

build-gridpack:ubuntu:
extends: .build-gridpack
image: ${CI_REGISTRY_IMAGE}:${UBUNTU_ENV_IMAGE}
needs: [build-container:ubuntu]

build-gridpack:rocky:
extends: .build-gridpack
image: ${CI_REGISTRY_IMAGE}:${ROCKY_ENV_IMAGE}
needs: [build-container:rocky]
when: manual # todo remove when ready to test with rockylinux

.test-gridpack:
stage: test-gridpack
script:
# load mpi module if on RHEL
- source ./build-system/install_package_deps_lib.sh
- load_mpi_module

# run tests
- ctest --test-dir src/build --output-on-failure
artifacts:
paths: [src/build/Testing/Temporary]
rules:
- if: $CI_PIPELINE_SOURCE == "push"
changes:
- "build-system/**/*"
- "src/**/*"
- "python/**/*"
- if: $CI_PIPELINE_SOURCE == "web"

test-gridpack:ubuntu:
extends: .test-gridpack
image: ${CI_REGISTRY_IMAGE}:${UBUNTU_ENV_IMAGE}
needs: [build-gridpack:ubuntu]

test-gridpack:rocky:
extends: .test-gridpack
image: ${CI_REGISTRY_IMAGE}:${ROCKY_ENV_IMAGE}
needs: [build-gridpack:rocky]
when: manual # todo remove when ready to test with rockylinux
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# GridPACK<sup>TM</sup>-->
# GridPACK: High-Performance Electric Grid Simulation

![PNNL Build Status](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.github.com%2Frepos%2FGridOPTICS%2FGridPACK%2Fcommits%2Fdevelop%2Fstatus&query=%24.state&logo=gitlab&label=build%20status&color=white
)

GridPACK is an open-source high-performance (HPC) package for simulation of large-scale electrical grids. Powered by distributed (parallel) computing and high-performance numerical solvers, GridPACK offers several applications forfast simulation of electrical transmission systems. GridPACK includes a number of prebuilt applications that can be directly used. The most commonly used and well-developed are:
- AC Power Flow
- Dynamics Simulation
Expand All @@ -18,7 +21,7 @@ In addition, GridPACK is also a framework to simplify the development of new app
See the [instructions](docs/markdown/BASIC_INSTALL.md) for installing GridPACK, prerequisite software, and installation notes for different platforms.

## Usage
See [User manual](docs/user_manual/GridPACK.pdf) for a deep dive on GridPACK internals and/or refer to the [tutorials](docs/markdown/TUTORIALS.md) for more info.
See [User manual](docs/user_manual/GridPACK.pdf) for a deep dive on GridPACK internals and/or refer to the [tutorials](docs/markdown/TUTORIALS.md) for more info.

- Quick Guide (To do)

Expand All @@ -36,16 +39,16 @@ The best (and fastest) way to reach us for any technical questions is by posting

## Citing GridPACK
```
@article{doi:10.1177/1094342015607609,
author = {Bruce Palmer and William Perkins and Yousu Chen and Shuangshuang Jin and David C allahan and Kevin Glass and Ruisheng Diao and Mark Rice and Stephen Elbert and Mallikarjun a Vallem and Zhenyu Huang},
title ={GridPACKTM: A framework for developing power grid simulations on high-performance computing platforms},
journal = {The International Journal of High Performance Computing Applications},
volume = {30},
number = {2},
pages = {223-240},
year = {2016},
doi = {10.1177/1094342015607609},
URL = {https://doi.org/10.1177/1094342015607609},
@article{doi:10.1177/1094342015607609,
author = {Bruce Palmer and William Perkins and Yousu Chen and Shuangshuang Jin and David C allahan and Kevin Glass and Ruisheng Diao and Mark Rice and Stephen Elbert and Mallikarjun a Vallem and Zhenyu Huang},
title ={GridPACKTM: A framework for developing power grid simulations on high-performance computing platforms},
journal = {The International Journal of High Performance Computing Applications},
volume = {30},
number = {2},
pages = {223-240},
year = {2016},
doi = {10.1177/1094342015607609},
URL = {https://doi.org/10.1177/1094342015607609},
eprint = {https://doi.org/10.1177/1094342015607609}
```

Expand All @@ -69,7 +72,7 @@ GridPACK has been developed through funding from various sources over the years.
## Copyright
Copyright &copy; 2013, Battelle Memorial Institute.

GridPACK<sup>TM</sup> is a free software distributed under a BSD 2-clause license. You may reuse, modify, and redistribute the software.
GridPACK<sup>TM</sup> is a free software distributed under a BSD 2-clause license. You may reuse, modify, and redistribute the software.

See the [license](src/LICENSE.md) file for details.

Expand Down
25 changes: 25 additions & 0 deletions build-system/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
The shell scripts in this directory are used to automate the installation of GridPACK on Debian/RHEL based systems.

# GitLab Build Automation

## Repository Mirror

A [PNNL GitLab instance](https://devops.pnnl.gov/gridpack-code/GridPACK) hosting a [pull-mirror](https://docs.gitlab.com/ee/user/project/repository/mirror/pull.html) of this [GitHub repo](https://github.com/GridOPTICS/GridPACK) uses these scripts to execute tests whenever commits are pushed to GitHub. GitLab polls the GitHub repo to check for new commits every 30 minutes or every 5 minutes when triggered by the GitLab UI/API. An [integration](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html) is configured to report a pass/fail status back to GitHub for any commit associated with a build ["pipeline"](https://docs.gitlab.com/ee/ci/pipelines/).

## Build Jobs

The build/test automation is defined by the following set of ["jobs"](https://docs.gitlab.com/ee/ci/jobs/) in `/.gitlab-ci.yml`, which are conditionally added to a pipeline by GitLab when a build is triggered:

1. `check-container-definition-changed`: Creates a file called `container-definition-changed` if the scripts or `./dockerfile` used to build the container image have been modified. The file is passed to subsequent jobs as an ["artifact"](https://docs.gitlab.com/ee/ci/jobs/job_artifacts.html).
2. `.check-container-needs-built`: A template (note the leading `.`) to define jobs for multiple distributions via [extension](https://docs.gitlab.com/ee/ci/yaml/#extends). Runs `check_container_needs_built`, a function in `./container_lib.sh` which creates another file called `container-needs-built` if `container-definition-changed` exists or the container image tag does not exist in the GitLab project [container registry](https://docs.gitlab.com/ee/user/packages/container_registry/). Additionally, if the container image does need to be rebuilt, this function [deletes](https://docs.gitlab.com/ee/api/container_registry.html#delete-a-registry-repository-tag) the image tag from the registry to avoid unintentional use by subsequent pipelines in the event that the container image build fails and does not replace the old image.
3. `.build-container`: A template job for multiple distributions. Uses [kaniko](https://github.com/GoogleContainerTools/kaniko) to build a container image based on a given distribution if the file `container-needs-built` exists or an environment variable called `FORCE_CONTAINER_BUILD` is set to `true`. The environment variable is intended to be used when [manually triggering a pipeline from the GitLab UI](https://docs.gitlab.com/ee/ci/pipelines/#run-a-pipeline-manually).
4. `.build-gridpack`: A template job for multiple distributions. Builds GridPACK in a container using an image from the GitLab project container registry based on a given distribution whenever files in `/src`, `/python`, or `/build` are modified using `./install_gridpack.sh`. All files created by the build are saved as artifacts.
5. `.test-gridpack`: A template job for multiple distributions. Tests GridPACK in a new container using the artifacts from the associated `.build-container` job and with the same container image that was used in that job. These tests could have been performed at the end of the `.build-container` job but were separated to provide a distinct status for each of these concerns and to maintain organized logs/artifacts.

`check-container-definition-changed` and `.check-container-needs-built` are very slim, taking about a minute each to run. Considering the source code and GitLab runner resources as of writing, `.build_container` takes about 35 minutes, `.build-gridpack` about 25 minutes, and `.test-gridpack` about 15 minutes for the `ubuntu:22.04` base image. Note again that the `.build_container` job only needs to run if the container image definition has changed. This mainly means changes to package dependencies, from-source dependencies, or environment variables.

## Variables

From the [project settings](https://devops.pnnl.gov/gridpack-code/GridPACK/-/settings/ci_cd) in GitLab a few variables are defined that are injected into each build pipeline. The difference between this type of variable and those in `/.gitlab-ci.yml` is that they can contain secrets and do not require source code modification to change. `API_TOKEN` is a [project access token](https://devops.pnnl.gov/gridpack-code/GridPACK/-/settings/access_tokens) which allows jobs to interact with the container registry API. When PNNL's GitLab instance is upgraded to `v16.8`, this variable should no longer be necessary. At that point it can be removed and curl can use the `JOB-TOKEN: ${CI_JOB_TOKEN}` header instead. That is desirable because the token will not need to be rotated.

Another set of variables are used to manage resources available to the [GitLab runner](https://docs.gitlab.com/runner/executors/kubernetes/) executing each job in Kubernetes: `KUBERNETES_CPU_LIMIT`, `KUBERNETES_CPU_REQUEST`, `KUBERNETES_MEMORY_LIMIT`, and `KUBERNETES_MEMORY_REQUEST`. These mainly need to be considered if tests are performed for multiple distributions because that makes jobs available for concurrent processing. In this situation active jobs must share the resources from the namespace quota. Currently the runner is configured to allow two concurrent jobs, but the performance of this hasn't been compared to a serial approach with full resources.
146 changes: 146 additions & 0 deletions build-system/container_lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#! /bin/bash

# library of functions related to building the container image

# print a set of args as a comma-space seperated list
# usage:
# print_array item1 item2 item3
# usage:
# array=('item1' 'item2' 'item3')
# print_array "${array[@]}"
# https://www.gnu.org/software/bash/manual/html_node/Arrays.html
print_array() {
local list
list=$(printf "'%s', " "${@}")
echo "${list%, }"
}

# check that a command is available
# usage:
# check_installed jq curl
check_installed() {
# gather a list of missing commands
missing_commands=()
for cmd in "${@}"; do
if ! command -v "$cmd" &>/dev/null; then
missing_commands+=("$cmd")
fi
done

# if any commands are missing, print an error and exit
if [[ ${#missing_commands[@]} -gt 0 ]]; then
local list
list=$(print_array "${missing_commands[@]}")
echo "Please install $list" >&2
exit 1
fi
}

# make a gitlab api call
# usage:
# glab_api GET /projects/123/registry/repositories
# glab_api POST /projects/123/registry/repositories "name=foo" "path=bar"
# needs: curl, $CI_API_V4_URL, $API_TOKEN
function glab_api {
local method=${1:?}
local endpoint=${2:?}
local form_items=("${@:3}")

local api_url=${CI_API_V4_URL:?}
local api_token=${API_TOKEN:?}

check_installed curl

# construct the form data
local form_data=""
for item in "${form_items[@]}"; do
form_data+="--form ${item} "
done

# curl options:
# - no-progress-meter: don't show progress bar but show errors
# - location: follow redirects
# - fail: return 22 on server errors
# - header: send private token for authentication
# - request: specify the HTTP method
# https://docs.gitlab.com/ee/api/container_registry.html
curl \
--no-progress-meter \
--fail \
--location \
--header "PRIVATE-TOKEN: ${api_token}" \
--request "${method}" \
"${form_data}${api_url}${endpoint}"
}

# get the id of a container registry repo for a project by path
# usage:
# get_container_registry_repo_id
# needs: jq, curl, $CI_API_V4_URL, $API_TOKEN, $CI_PROJECT_ID, $CI_PROJECT_PATH
function get_container_registry_repo_id {
local project_id=${CI_PROJECT_ID:?}
: "${CI_PROJECT_PATH:?}"
local project_path=${CI_PROJECT_PATH,,}

check_installed jq

# jq query:
# - raw-output: output raw strings instead of json
# - exit-status: return 1 if no results
# - for each elements of the array
# - where the registry repo path is the one we care about
# - select the id prop
# https://jqlang.github.io/jq/manual/
glab_api GET "/projects/${project_id}/registry/repositories" \
| jq --raw-output --exit-status ".[] | select(.path == \"${project_path}\") | .id"
}

# check if a tag exists in a project's container registry
# usage:
# container_tag_exists 123 "my-tag"
# needs: curl, $CI_API_V4_URL, $API_TOKEN, $CI_PROJECT_ID
function container_tag_exists {
local reg_repo_id=${1:?}
local image_tag=${2:?}

local project_id=${CI_PROJECT_ID:?}

glab_api GET "/projects/${project_id}/registry/repositories/${reg_repo_id}/tags/${image_tag}" >/dev/null
}

# delete tag from a project's container registry
# usage:
# delete_container_tag 123 "my-tag"
# needs: curl, $CI_API_V4_URL, $API_TOKEN, $CI_PROJECT_ID
function delete_container_tag {
local reg_repo_id=${1:?}
local image_tag=${2:?}

local project_id=${CI_PROJECT_ID:?}

glab_api DELETE "/projects/${project_id}/registry/repositories/${reg_repo_id}/tags/${image_tag}" >/dev/null
}

# build container image if not available in registry or force_rebuild = 'true'
# usage:
# check_container_needs_built "ubuntu:22.04"
# needs: jq, curl, $CI_API_V4_URL, $API_TOKEN, $CI_PROJECT_ID, $CI_PROJECT_PATH_SLUG
function check_container_needs_built {
local tag=${1:?}

local repo_id
repo_id=$(get_container_registry_repo_id)

# if we see a file in the current directory called "container-definition-changed"
# or the tag does not exist in the registry, then the container needs rebuilt
if test -f ./container-definition-changed || ! container_tag_exists "$repo_id" "$tag"; then
# in case the build fails, delete the image associated with this tag from the registry
# this will signal to potential subsequent pipelines that the container image still needs
# rebuilt even if relevant files have not changed
# this provents unknowingly using an outdated image in subsequent pipelines
delete_container_tag "$repo_id" "$tag"

# signal to the next job via an empty file artifact that the container needs built
touch ./container-needs-built
fi
}
Loading