Skip to content

Decompose monolithic neo core into independent CMake sub-targets #1933

Decompose monolithic neo core into independent CMake sub-targets

Decompose monolithic neo core into independent CMake sub-targets #1933

Workflow file for this run

# See https://github.com/Forsti5/Fortran-Unit-Test-Basic/blob/main/.github/workflows/main.yml
name: test
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
GNU:
runs-on: ubuntu-latest
env:
LIBNEO_TESTING: "1"
name: Build and test
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- name: Install system dependencies
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake \
gfortran \
libfftw3-dev \
libgsl-dev \
libhdf5-dev \
libnetcdf-dev \
libnetcdff-dev \
libopenblas-dev \
liblapack-dev \
libopenmpi-dev \
ninja-build \
openmpi-bin \
pkg-config
- name: Install Python build dependencies
run: |
set -euo pipefail
python -m pip install --upgrade pip
python -m pip install -c constraints/ci-python.txt numpy
- name: Build
run: |
make
- name: Install Python dependencies for tests
run: |
python -m pip install -c constraints/ci-python.txt ".[dev]"
- name: Test
run: |
cd build && ctest --output-on-failure
- name: Upload GEQDSK plots
uses: actions/upload-artifact@v4
with:
name: geqdsk-plots
path: build/test_artifacts/*.png
if-no-files-found: ignore
- name: Editable install of libneo
run: |
python -m pip install -e .
- name: Run Python tests (pytest)
env:
PYTHONFAULTHANDLER: "1"
LIBNEO_DEBUG_BOOZER: "1"
run: |
python -m pytest test/python -q
python -m pytest python/tests -vv -s
- name: Build ASCOT5 and install a5py
run: |
git clone --depth 1 --branch 5.6.1 https://github.com/ascot4fusion/ascot5.git build/test/ascot5_compare/ascot5
make -C build/test/ascot5_compare/ascot5 libascot
python -m pip install --force-reinstall build/test/ascot5_compare/ascot5
- name: Compare with ASCOT5 reference
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/build/test/ascot5_compare/ascot5/build
run: |
python test/scripts/test_ascot5_compare.py --build-dir build --output-dir build/test/ascot5_compare
- name: Upload test image artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-images
path: |
build/test/**/*.png
build/test/**/*.jpg
build/test/**/*.jpeg
build/test_artifacts/**/*.png
build/test_artifacts/**/*.jpg
build/test_artifacts/**/*.jpeg
if-no-files-found: warn
docs:
name: Build Sphinx docs
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- name: Install docs dependencies
run: |
python -m pip install --upgrade pip
python -m pip install sphinx sphinx-rtd-theme scipy numpy
- name: Build docs
run: |
cd docs && sphinx-build -b html . _build/html
- name: Upload docs artifact
uses: actions/upload-artifact@v4
with:
name: docs-html
path: docs/_build/html
dashboard:
name: Build test dashboard
needs: [GNU, docs]
if: ${{ needs.GNU.result == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
pull-requests: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dashboard dependencies
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
jq \
rsync \
wget
- name: Download testboard binary
run: |
set -euo pipefail
arch="$(uname -m)"
if [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then
asset="testboard-aarch64"
else
asset="testboard-x86_64"
fi
curl -LO "https://github.com/lazy-fortran/testboard/releases/latest/download/${asset}"
chmod +x "${asset}"
ln -sf "${asset}" testboard
- name: Download image artifacts
uses: actions/download-artifact@v4
with:
name: test-images
path: image-artifacts
- name: Remove ASCOT5 logo files
run: |
set -euo pipefail
find image-artifacts -type f \( -name "logo.png" -o -name "icon.png" \) -delete
echo "Removed ASCOT5 logo and icon files from artifacts"
- name: Restore previously published site
run: |
set -euo pipefail
rm -rf dashboard dashboard_existing
mkdir -p dashboard
BASE_URL="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/test/"
INDEX_URL="${BASE_URL}index.html"
if curl --silent --head --fail "$INDEX_URL" >/dev/null 2>&1; then
echo "Existing site found, restoring..."
mkdir -p dashboard_existing
if wget --quiet --recursive --no-parent --no-host-directories --cut-dirs=2 \
--directory-prefix dashboard_existing "$BASE_URL" 2>&1; then
if [ -n "$(ls -A dashboard_existing)" ]; then
echo "Restoring $(find dashboard_existing -type f | wc -l) files"
rsync -a dashboard_existing/ dashboard/
fi
else
echo "wget failed, starting with empty dashboard"
fi
rm -rf dashboard_existing
else
echo "No existing site found, starting fresh"
fi
- name: Generate dashboard
env:
GH_TOKEN: ${{ github.token }}
PAGES_BASE_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
run: |
set -euo pipefail
./testboard \
--image-root image-artifacts \
--output dashboard \
--branch "${GITHUB_REF_NAME}" \
--commit "${GITHUB_SHA}" \
--run-id "${GITHUB_RUN_ID}" \
--repo "${GITHUB_REPOSITORY}" \
--project-name "libneo" \
--github-pages-url "${PAGES_BASE_URL}"
- name: Prune closed branches
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
BRANCH_JSON="dashboard/test/branches.json"
if [ ! -f "$BRANCH_JSON" ]; then
echo "No branches metadata found; skipping pruning"
exit 0
fi
tmp_json=$(mktemp)
cp "$BRANCH_JSON" "$tmp_json"
for branch in $(jq -r 'keys[]' "$tmp_json"); do
pr_number=$(jq -r --arg b "$branch" '.[$b].pr_info.number // empty' "$tmp_json")
keep=1
if [ -n "$pr_number" ] && [ "$pr_number" != "null" ]; then
pr_state=$(gh pr view "$pr_number" --json state --jq '.state' 2>/dev/null || echo "UNKNOWN")
if [ "$pr_state" = "CLOSED" ] || [ "$pr_state" = "MERGED" ]; then
keep=0
fi
else
if ! git ls-remote --heads origin "$branch" >/dev/null 2>&1; then
if [ "$branch" != "main" ]; then
keep=0
fi
fi
fi
if [ "$keep" -eq 0 ]; then
echo "Pruning branch $branch from dashboard"
jq --arg branch "$branch" 'del(.[$branch])' "$BRANCH_JSON" > "$BRANCH_JSON.tmp"
mv "$BRANCH_JSON.tmp" "$BRANCH_JSON"
rm -rf "dashboard/test/$branch"
fi
done
rm -f "$tmp_json"
- name: Download docs artifact
uses: actions/download-artifact@v4
with:
name: docs-html
path: docs-html
- name: Merge docs with dashboard
run: |
set -euo pipefail
mkdir -p site
if [ -d dashboard/test ]; then
mv dashboard/test site/test
else
mkdir -p site/test
fi
cp -r docs-html/* site/
echo "Site structure:"
find site -type f | head -20 || true
- name: Configure Pages
if: ${{ github.event_name == 'push' }}
uses: actions/configure-pages@v5
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: './site'
deploy:
name: Deploy to GitHub Pages
if: github.event_name == 'push' || github.event_name == 'pull_request'
needs: dashboard
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy
id: deployment
uses: actions/deploy-pages@v4