Skip to content
Open
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
110 changes: 110 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
on: [pull_request, push, merge_group]
name: ci
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:

generate-matrix:
# https://stackoverflow.com/questions/59977364
name: Generate build matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- id: set-matrix
run: echo "matrix=$(src/test/generate_matrix.py)" >> $GITHUB_OUTPUT
- run: src/test/generate_matrix.py | jq -S .
- run: echo "GITHUB_BRANCH=${GITHUB_REF#refs/heads}" >> $GITHUB_OUTPUT
- run: echo "GITHUB_TAG=${GITHUB_REF#refs/tags}" >> $GITHUB_OUTPUT
- run: echo "EVENT_NAME=${{ github.event_name }}" >> $GITHUB_OUTPUT

ci-checks:
needs: [generate-matrix]
runs-on: ${{matrix.runner}}
env:
TAP_DRIVER_QUIET: 1
FLUX_TEST_TIMEOUT: 300
DOCKER_REPO: libscr/scr
DOCKER_USERNAME: travisflux
DOCKER_PASSWORD: ${{ secrets.DOCKER_HUB_TRAVISFLUX_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy:
matrix: ${{fromJson(needs.generate-matrix.outputs.matrix)}}
fail-fast: false
name: ${{matrix.name}}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0

- name: fetch annotated tag
if: >
(matrix.create_release || matrix.docker_tag) &&
github.ref != 'refs/heads/master'
run: |
# Ensure git-describe works on a tag.
# (checkout@v4 action may have left current tag as
# lightweight instead of annotated. See
# https://github.com/actions/checkout/issues/290)
#
echo github.ref == ${{ github.ref }} ;
git fetch -f origin ${{ github.ref }}:${{ github.ref }} ;
echo git describe now reports $(git describe --always)

- name: docker buildx
uses: docker/setup-buildx-action@v3
if: matrix.needs_buildx

- name: docker-run-checks
timeout-minutes: ${{matrix.timeout_minutes}}
env: ${{matrix.env}}
run: ${{matrix.command}}

- name: docker deploy
if: success() && matrix.docker_tag
env: ${{matrix.env}}
run: src/test/docker-deploy.sh

- name: create release
id: create_release
if: |
success()
&& matrix.create_release
&& github.repository == 'LLNL/scr'
env: ${{matrix.env}}
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ matrix.tag }}
name: scr ${{ matrix.tag }}
prerelease: true
files: scr*.tar.gz
body: |
View [Release Notes](https://github.com/${{ github.repository }}/blob/${{ matrix.tag }}/NEWS.md) for scr ${{ matrix.tag }}

generate-manifest:
name: Generate docker manifest
runs-on: ubuntu-latest
needs: [ci-checks]
env:
DOCKER_REPO: libscr/scr
DOCKER_USERNAME: travisflux
DOCKER_PASSWORD: ${{ secrets.DOCKER_HUB_TRAVISFLUX_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: make and push manifest as libscr/scr
if: >
(startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master')
run: |
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker manifest push libscr/scr:bookworm
for d in el9 noble alpine fedora40 bookworm ; do
docker manifest create libscr/scr:$d libscr/scr:$d-amd64 libscr/scr:$d-arm64
docker manifest push libscr/scr:$d
done

48 changes: 48 additions & 0 deletions src/test/checks-lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# Helper functions for GitHub actions, See:
#
# https://docs.github.com/actions/reference/workflow-commands-for-github-actions
#
#
# Only emit group/endgroup when running under CI, see:
#
# https://docs.github.com/en/actions/reference/environment-variables
#
#
if test "$CI" = "true"; then
checks_group_start() {
printf "::group::%s\n" "$1"
}
checks_group_end() {
printf "::endgroup::\n"
}
else
checks_group_start() { echo "$@"; }
checks_group_end() { echo "$@"; }
fi

#
# Usage: checks_group DESC COMMANDS...
#
checks_group() {
local DESC="$1"
shift 1
checks_group_start "$DESC"
eval "$@"
rc=$?
checks_group_end
return $rc
}

#
# Usage: checks_die MESSAGE COMMANDS...
#
checks_die() {
local MSG="$1"
shift 1
printf "::error::$MSG\n"
if [ $# -gt 0 ]; then
eval "$@"
fi
exit 1
}
82 changes: 82 additions & 0 deletions src/test/checks_run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/bash
#
# Test runner script meant to be executed inside of a docker container
#
# Usage: checks_run.sh [OPTIONS...]
#
# Where OPTIONS are passed directly to `cmake``
#
# The script is otherwise influenced by the following environment variables:
#
# JOBS=N Argument for make's -j option, default=2
# PROJECT Project name
# CPPCHECK Run cppcheck if set to "t"
# RECHECK Run `make recheck` if `make check` fails the first time
# UNIT_TEST_ONLY Only run `make check` under ./src
# QUICK_CHECK Run only `make TESTS=` and a simple test
#
# And, obviously, some crucial variables that configure itself cares about:
#
# CC, CXX, LDFLAGS, CFLAGS, etc.
#

# source check_group and check_time functions:
. src/test/checks-lib.sh

ARGS="$@"
JOBS=${JOBS:-2}
MAKECMDS="make -j ${JOBS} install"
CHECKCMDS="ctest --output-on-failure"


# Force git to update the shallow clone and include tags so git-describe works
checks_group "git fetch tags" "git fetch --unshallow --tags" \
git fetch --unshallow --tags || true

checks_group_start "build setup"
ulimit -c unlimited

source /etc/profile.d/modules.sh
module load mpi


POSTCHECKCMDS=":"
# Enable coverage for $CC-coverage build
# We can't use distcheck here, it doesn't play well with coverage testing:

if test -n "$UNIT_TEST_ONLY"; then
CHECKCMDS="(cd src && $CHECKCMDS)"
fi

checks_group_end # Setup

WORKDIR=$(pwd)
if test -n "$BUILD_DIR" ; then
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
rm -f CMakeCache.txt
fi

checks_group "cmake ${ARGS}" cmake ${ARGS} \
|| checks_die "cmake failed" cat config.log
checks_group "make clean..." make clean

checks_group "${MAKECMDS}" "${MAKECMDS}" \
|| checks_die "${MAKECMDS} failed"

checks_group "${CHECKCMDS}" "${CHECKCMDS}" && \
checks_group "${POSTCHECKCMDS}" "${POSTCHECKCMDS}"
RC=$?

if test "$RECHECK" = "t" -a $RC -ne 0; then
#
# `make recheck` is not recursive, only perform it if at least some tests
# under ./t were run (and presumably failed)
#
printf "::warning::make check failed, trying recheck\n"
${CHECKCMDS} --rerun-failed && \
checks_group "${POSTCHECKCMDS}" "${POSTCHECKCMDS}"
RC=$?
fi

exit $RC
21 changes: 21 additions & 0 deletions src/test/docker-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
#
# Tag docker images

log() { echo "docker-deploy: $@" >&2; }
die() { log "$@"; exit 1; }

if test "$GITHUB_REPOSITORY" != "LLNL/scr"; then
log "not in LLNL/scr repo, exiting..."
exit 0
fi

test -n "$DOCKER_REPO" || die "DOCKER_REPO not set"
test -n "$DOCKER_PASSWORD" || die "DOCKER_PASSWORD not set"
test -n "$DOCKER_USERNAME" || die "DOCKER_USERNAME not set"
test -n "$DOCKER_TAG" || die "DOCKER_TAG not set"

echo $DOCKER_PASSWORD | docker login -u "$DOCKER_USERNAME" --password-stdin

log "docker push ${DOCKER_TAG}"
docker push ${DOCKER_TAG}
51 changes: 51 additions & 0 deletions src/test/docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
### Docker Images for SCR

The Dockerfiles, resulting docker images, and `docker-run-checks.sh`
script contained herein are used as part of the strategy for CI testing
of SCR.

Docker is used under CI to speed up deployment of an
environment with correct build dependencies and to keep a docker
image deployed at `libscr/scr` DockerHub with latest master build
(`libscr/scr:latest`) and tagged builds (`scr/SCR:v<tag>`),
which can be used by other projects to build against the latest
or a tagged version of SCR.

#### libscr/scr Docker Images

The Dockerfiles `noble/Dockerfile`, `fedora40/Dockerfile`,
`el9/Dockerfile`, and `alpine/Dockerfile` describe the images built
under the `libscr/scr:noble`, `libscr/scr:fedora40`,
`libscr/scr:el9`, and `libscr/scr:alpine` respectively, and
include the base dependencies required to build SCR. The Dockerfiles
should be kept up to date for a single point of management.

#### Multiarch Images

Building the images for linux/amd64 and linux/arm64 requires the
Docker buildx extensions, see

https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/

and run
```
$ docker buildx build --push --platform=linux/arm64,linux/amd64 --tag libscr/scr:noble -f src/test/docker/noble/Dockerfile .
```

to build and push images to docker hub.

#### Local Testing

Developers can test the docker images themselves. If new dependencies are needed,
they can update the `$image` Dockerfiles manually.
To create a local Docker image, run the command:

```
docker build -t libscr/scr:$image src/test/docker/$image
```

To test the locally created image, run:

```
src/test/docker/docker-run-checks.sh -i $image [options] -- [arguments]
```
14 changes: 14 additions & 0 deletions src/test/docker/add_docker_user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
if test "$USER" != "scr"; then
sudo groupadd -g $UID $USER
sudo useradd -g $USER -u $UID -d /home/$USER -m $USER
sudo sh -c "printf \"$USER ALL= NOPASSWD: ALL\\n\" >> /etc/sudoers"
case "$ID" in
ubuntu|debian)
sudo adduser $USER sudo
;;
fedora|rocky|alma|rhel|centos|alpine)
sudo usermod -G wheel $USER
;;
esac
fi
39 changes: 39 additions & 0 deletions src/test/docker/alpine/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
FROM alpine:3.18

LABEL maintainer="James Corbett <corbett8@llnl.gov>"

ARG USER=scr
ARG UID=1000
ARG GID=1000

# Update pkg caches, install latest pkg utils and basics:
RUN apk add \
coreutils \
bash \
sudo \
shadow \
gcc \
g++ \
gfortran \
libtool \
make \
cmake \
python3 \
git \
jq \
valgrind \
openmpi \
openmpi-dev \
openssh \
pdsh \
zlib

ENV LANG=C.UTF-8

# copy scripts into image
COPY src/test/docker/add_docker_user.sh /etc/add_docker_user.sh
# Add configured user to image with sudo access:
RUN /etc/add_docker_user.sh

USER $USER
WORKDIR /home/$USER
Loading