Conversation
9f2439a to
499b648
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a GitHub Actions workflow that mirrors branches to an LRZ GitLab instance and triggers an LRZ GitLab CI pipeline intended to run tests on LRZ GPU hardware, alongside the corresponding GitLab CI configuration and helper scripts.
Changes:
- Add LRZ GitLab CI configuration (
.gitlab-ci.yml) with NVIDIA/AMD/Intel GPU job templates and build/test jobs. - Add GitHub Actions workflow to push to LRZ GitLab, trigger a pipeline, wait for completion, and attempt to cancel prior pipelines.
- Add helper bash scripts for LRZ GitLab build/test, pipeline triggering/waiting/canceling; plus small REUSE and test-matrix updates.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| include/OGL/MatrixWrapper/HostMatrix.hpp | Fix typo in a comment. |
| ci/lrz-gitlab/build-and-test.sh | New vendor-specific build/test script for LRZ GitLab runners. |
| ci/github/wait_pipeline.sh | New script to poll LRZ GitLab pipeline status from GitHub Actions. |
| ci/github/trigger_pipeline.sh | New script to trigger LRZ GitLab pipelines with variables from GitHub Actions. |
| ci/github/cancel_triggered_pipelines.sh | New script intended to cancel running/pending LRZ GitLab pipelines before triggering new ones. |
| .reuse/dep5 | Add REUSE metadata entry for the new GitHub workflow. |
| .gitlab-ci.yml | New LRZ GitLab CI pipeline definition for GPU builds/tests. |
| .github/workflows/trigger-lrz-gitlab-ci.yaml | New GitHub workflow to mirror to LRZ GitLab and orchestrate LRZ pipelines. |
| .github/workflows/test_matrix.json | Update OpenFOAM matrix version/path used by existing GitHub workflows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export CXX_COMPILER_PATH="$(which g++)" | ||
| export CXX_SOURCE="${CXX_COMPILER_PATH%/*/*}" | ||
| export CXX_LIBDIR="${CXX_SOURCE}/lib64" | ||
| export LD_LIBRARY_PATH=${CXX_LIBDIR}:${LD_LIBRARY_PATH} |
There was a problem hiding this comment.
With set -u, this export will fail if LD_LIBRARY_PATH is unset in the job environment. Use a default (e.g., ${LD_LIBRARY_PATH:-}) and avoid producing a leading/trailing colon when empty.
| export LD_LIBRARY_PATH=${CXX_LIBDIR}:${LD_LIBRARY_PATH} | |
| export LD_LIBRARY_PATH="${CXX_LIBDIR}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" |
| if [ $# -lt 1 ]; then | ||
| echo "Usage: $0 <branch>" | ||
| exit 1 | ||
| fi | ||
|
|
||
| GROUP=greole | ||
| HOST="gitlab-ce.lrz.de" | ||
| PROJECT=$1 | ||
| BRANCH=$2 | ||
| CHECK_TOKEN=$3 | ||
| TRIGGER_TOKEN=$4 | ||
| shift 4 | ||
| VARIABLES="$@" # Optional extra variables in the form: "variables[KEY]=VALUE" | ||
| OGL_BRANCH="$BRANCH" |
There was a problem hiding this comment.
Argument validation/usage is inconsistent with how the script is actually parsed: the script reads $1..$4 (and shift 4) but only checks for at least 1 arg and the header comment says it takes only <branch>. Please update the usage + enforce the correct minimum argument count to avoid set -u crashes when called incorrectly.
| GROUP=greole | ||
| HOST="gitlab-ce.lrz.de" | ||
| PROJECT=$1 | ||
| BRANCH=$2 | ||
| CHECK_TOKEN=$3 | ||
| TRIGGER_TOKEN=$4 |
There was a problem hiding this comment.
This script hardcodes GROUP and HOST instead of using LRZ_GROUP / LRZ_HOST from the environment (as described in the header comment and set in the GitHub Actions workflow). This makes the workflow configuration ineffective and harder to reuse across environments.
| # Prepare curl form data for variables | ||
| FORM_DATA="--form ref=$BRANCH --form token=$TRIGGER_TOKEN" | ||
| FORM_DATA="$FORM_DATA --form variables[OGL_BRANCH]=$OGL_BRANCH" | ||
|
|
||
| for var in $VARIABLES; do | ||
| FORM_DATA="$FORM_DATA --form $var" | ||
| done | ||
|
|
||
| echo "FORM_DATA $FORM_DATA" | ||
|
|
||
| response=$(curl -s --request POST $FORM_DATA \ | ||
| "https://${HOST}/api/v4/projects/${GROUP}%2F${PROJECT}/trigger/pipeline") |
There was a problem hiding this comment.
echo "FORM_DATA $FORM_DATA" risks printing the trigger token into logs (and the token is also embedded in the curl args). Avoid logging secrets and pass curl form parameters without constructing a single string (use an array) to prevent accidental leaking and word-splitting issues.
| if [[ "$PROJECT" == "NeoN" ]]; then | ||
| # Case 1: NeoN -> cancel all running/pending pipelines on the branch | ||
| echo "Cancelling pipeline $id (PROJECT=NeoN)..." | ||
| curl -s --request POST \ | ||
| --header "PRIVATE-TOKEN: $TOKEN" \ | ||
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | ||
| continue | ||
| fi | ||
|
|
||
| if [[ "$PROJECT" == "NeoFOAM" ]]; then | ||
| # Case 2: NeoFOAM -> cancel only if TRIGGER_SOURCE == NeoN | ||
| vars=$(curl -s --header "PRIVATE-TOKEN: $TOKEN" \ | ||
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/variables") | ||
|
|
||
| trigger_source=$(echo "$vars" | jq -r '.[] | select(.key=="TRIGGER_SOURCE") | .value' || true) | ||
|
|
||
| if [[ "$trigger_source" == "NeoN" ]]; then | ||
| echo "Cancelling pipeline $id (TRIGGER_SOURCE=NeoN)..." | ||
| curl -s --request POST \ | ||
| --header "PRIVATE-TOKEN: $TOKEN" \ | ||
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | ||
| else | ||
| echo "Skipping pipeline $id (TRIGGER_SOURCE=$trigger_source)." | ||
| fi | ||
| fi |
There was a problem hiding this comment.
This canceller currently only cancels pipelines when PROJECT is exactly NeoN or NeoFOAM. In this repo's workflow it is invoked with PROJECT=ogl, so it will never actually cancel anything (but still prints success). Please add handling for ogl (or a default branch that cancels running/pending pipelines) so the GitHub workflow does what it intends.
| if [[ "$PROJECT" == "NeoN" ]]; then | |
| # Case 1: NeoN -> cancel all running/pending pipelines on the branch | |
| echo "Cancelling pipeline $id (PROJECT=NeoN)..." | |
| curl -s --request POST \ | |
| --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | |
| continue | |
| fi | |
| if [[ "$PROJECT" == "NeoFOAM" ]]; then | |
| # Case 2: NeoFOAM -> cancel only if TRIGGER_SOURCE == NeoN | |
| vars=$(curl -s --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/variables") | |
| trigger_source=$(echo "$vars" | jq -r '.[] | select(.key=="TRIGGER_SOURCE") | .value' || true) | |
| if [[ "$trigger_source" == "NeoN" ]]; then | |
| echo "Cancelling pipeline $id (TRIGGER_SOURCE=NeoN)..." | |
| curl -s --request POST \ | |
| --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | |
| else | |
| echo "Skipping pipeline $id (TRIGGER_SOURCE=$trigger_source)." | |
| fi | |
| fi | |
| case "$PROJECT" in | |
| NeoN|ogl) | |
| # NeoN/ogl -> cancel all running/pending pipelines on the branch | |
| echo "Cancelling pipeline $id (PROJECT=$PROJECT)..." | |
| curl -s --request POST \ | |
| --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | |
| ;; | |
| NeoFOAM) | |
| # NeoFOAM -> cancel only if TRIGGER_SOURCE == NeoN | |
| vars=$(curl -s --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/variables") | |
| trigger_source=$(echo "$vars" | jq -r '.[] | select(.key=="TRIGGER_SOURCE") | .value' || true) | |
| if [[ "$trigger_source" == "NeoN" ]]; then | |
| echo "Cancelling pipeline $id (TRIGGER_SOURCE=NeoN)..." | |
| curl -s --request POST \ | |
| --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | |
| else | |
| echo "Skipping pipeline $id (TRIGGER_SOURCE=$trigger_source)." | |
| fi | |
| ;; | |
| *) | |
| # Default -> cancel all running/pending pipelines on the branch | |
| echo "Cancelling pipeline $id (default handling for PROJECT=$PROJECT)..." | |
| curl -s --request POST \ | |
| --header "PRIVATE-TOKEN: $TOKEN" \ | |
| "https://${LRZ_HOST}/api/v4/projects/${project_path}/pipelines/${id}/cancel" >/dev/null | |
| ;; | |
| esac |
| github.event_name != 'pull_request' || | ||
| !contains(github.event.pull_request.labels.*.name, 'skip-build') |
There was a problem hiding this comment.
This workflow runs on pull_request events but requires secrets to push to LRZ and trigger pipelines; PRs from forks will not have access to these secrets and will fail. Add a guard to only run when the PR head repo matches the base repo (or otherwise skip fork PRs).
| github.event_name != 'pull_request' || | |
| !contains(github.event.pull_request.labels.*.name, 'skip-build') | |
| github.event_name != 'pull_request' || ( | |
| github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name && | |
| !contains(github.event.pull_request.labels.*.name, 'skip-build') | |
| ) |
| git fetch origin ${{ steps.branch.outputs.branch }} | ||
| git checkout -B ${{ steps.branch.outputs.branch }} origin/${{ steps.branch.outputs.branch }} | ||
| git reset --hard origin/${{ steps.branch.outputs.branch }} | ||
| git push --force lrz HEAD:refs/heads/${{ steps.branch.outputs.branch }} |
There was a problem hiding this comment.
git push --force to the LRZ mirror can overwrite remote history if there are unexpected updates on LRZ. Prefer --force-with-lease (or push to a dedicated CI ref namespace) to reduce the risk of clobbering concurrent/manual changes.
| git push --force lrz HEAD:refs/heads/${{ steps.branch.outputs.branch }} | |
| if git ls-remote --exit-code --heads lrz "${{ steps.branch.outputs.branch }}" >/dev/null 2>&1; then | |
| git fetch lrz ${{ steps.branch.outputs.branch }} | |
| git push --force-with-lease=refs/heads/${{ steps.branch.outputs.branch }} lrz HEAD:refs/heads/${{ steps.branch.outputs.branch }} | |
| else | |
| git push lrz HEAD:refs/heads/${{ steps.branch.outputs.branch }} | |
| fi |
| name: LRZ GitLab CI | ||
|
|
||
| on: |
There was a problem hiding this comment.
Repository workflows consistently include SPDX headers (e.g. .github/workflows/format-check.yml:1-3), but this new workflow does not. Add the SPDX copyright and license header at the top so REUSE metadata is self-contained in the file like the others.
| - name: Cancel running/pending NeoFOAM LRZ CI pipelines | ||
| run: | | ||
| ./ci/github/cancel_triggered_pipelines.sh \ | ||
| "${{ env.OGL_REPO }}" \ | ||
| "${{ steps.branch.outputs.branch }}" \ | ||
| "${OGL_PROJECT_TOKEN}" |
There was a problem hiding this comment.
The step name mentions "NeoFOAM" but the script is invoked with the ogl project (env.OGL_REPO is set to ogl). Please rename this step (or fix the project argument) to avoid confusion when reading CI logs.
| License: GPL-3.0-or-later | ||
|
|
||
| Files: .github/workflows/trigger-lrz-gitlab-ci.yaml | ||
| Copyright: 2026 NeoN authors, 2026 ogl authors |
There was a problem hiding this comment.
Copyright holder casing is inconsistent with the rest of this file (uses "OGL authors" elsewhere). Consider changing "ogl authors" to "OGL authors" for consistency.
| Copyright: 2026 NeoN authors, 2026 ogl authors | |
| Copyright: 2026 NeoN authors, 2026 OGL authors |
This PR updates the github workflow and adds runs on LRZ hardware.