Decompose monolithic neo core into independent CMake sub-targets #1933
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 |