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
4 changes: 2 additions & 2 deletions .github/workflows/branch_push_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
#in the body of a pull request merged into a non-default branch.
issue_closer:
if: github.repository == 'ESCOMP/CAM-SIMA' # Only run on main repo
runs-on: ubuntu-latest
runs-on: ubuntu-slim
steps:
# Acquire github action routines
- uses: actions/checkout@v5
- uses: actions/checkout@v6
# Acquire specific version of python
- name: Set up Python 3.11
uses: actions/setup-python@v6
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/build_and_run_cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ concurrency:
jobs:
build-and-run-on-CIRRUS:
name: Run ${{ matrix.image }} on ${{ matrix.runner }}
if: ${{ github.repository == 'ESCOMP/CAM-SIMA' }}
env:
TMP_DIR: tmp
TMP_OUTPUT: case_output.log
Expand Down Expand Up @@ -84,7 +85,7 @@ jobs:
fi

- name: Upload logs to GitHub artifacts when the CI test fails
if: failure()
if: failure()
uses: actions/upload-artifact@v7
with:
name: logs.${{ matrix.test_type }}.${{ matrix.compset }}.${{ matrix.compiler }}.${{ matrix.runner }}
Expand Down
300 changes: 300 additions & 0 deletions .github/workflows/cam_sima_fortran_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
name: CAM-SIMA Fortran CI

permissions:
contents: read

on:
pull_request:
types:
- opened
- reopened
- synchronize
push:
branches:
- staging/**
- development
workflow_dispatch:

concurrency:
cancel-in-progress: true
group: ${{ github.workflow }} - ${{ github.ref }}

jobs:
# This check is the stepped leader to determine if the rest of jobs should run. We unfortunately cannot use path filtering
# due to the peculiar limitations of GitHub Actions, quoted below for reference:
#
# "If a workflow is skipped due to path filtering, then checks associated with that workflow will remain in a "Pending" state.
# A pull request that requires those checks to be successful will be blocked from merging."
conditional-check:
name: Check if jobs should run
runs-on: ubuntu-slim
outputs:
should-run: ${{ steps.conditional.outputs.result }}
timeout-minutes: 1
steps:
- name: Checkout CAM-SIMA
uses: actions/checkout@v6

- name: Check if there are changes to Fortran source code
id: conditional
run: |
set -euo pipefail

write_result_and_exit() {
case "$1" in
false)
echo "Result: Skip jobs."
echo "result=$1" >> "$GITHUB_OUTPUT"
exit 0
;;
true)
echo "Result: Run jobs."
echo "result=$1" >> "$GITHUB_OUTPUT"
exit 0
;;
error|*)
echo "Error occurred!"
exit 1
;;
esac
}

case "${{ github.event_name }}" in
pull_request)
echo "Event is pull request."

HEAD_COMMIT="${{ github.sha }}"

if [ -z "$HEAD_COMMIT" ]; then
echo "HEAD_COMMIT is empty."
write_result_and_exit false
fi

echo "Fetching $HEAD_COMMIT with parents..."
git fetch --depth=2 origin "$HEAD_COMMIT" || write_result_and_exit error

BASE_COMMIT="$(git rev-parse $HEAD_COMMIT^1)" || write_result_and_exit error
;;
push)
echo "Event is push."

BASE_COMMIT="${{ github.event.before }}"
HEAD_COMMIT="${{ github.event.after }}"

if [ -z "$BASE_COMMIT" ] || [ -z "$HEAD_COMMIT" ]; then
echo "BASE_COMMIT or HEAD_COMMIT is empty."
write_result_and_exit false
fi

if [ -z "${BASE_COMMIT//0/}" ] || [ -z "${HEAD_COMMIT//0/}" ]; then
echo "BASE_COMMIT or HEAD_COMMIT is null."
write_result_and_exit false
fi

echo "Fetching $BASE_COMMIT..."
git fetch --depth=1 origin "$BASE_COMMIT" || write_result_and_exit error

echo "Fetching $HEAD_COMMIT..."
git fetch --depth=1 origin "$HEAD_COMMIT" || write_result_and_exit error
;;
workflow_dispatch)
echo "Event is workflow dispatch."

# Always run jobs when triggered manually.
write_result_and_exit true
;;
*)
echo "Event is unknown."

# Always skip jobs for any other events.
write_result_and_exit false
;;
esac

echo "Finding changed paths between $BASE_COMMIT..$HEAD_COMMIT..."
git diff --name-only "$BASE_COMMIT..$HEAD_COMMIT" | tee changed-paths.txt || write_result_and_exit error

if grep -E -q '(^\.github\/workflows\/cam_sima_fortran_ci\.yml$|^share$|^src\/.+$|^test\/unit\/.+$)' changed-paths.txt; then
write_result_and_exit true
else
write_result_and_exit false
fi
# This job evaluates the overall status of CAM-SIMA Fortran CI for the purpose of inclusion as a required status check.
# It exists solely due to, again, the peculiar limitations of GitHub Actions, quoted below for reference:
#
# "The `jobs.<job_id>.if` conditional is evaluated before `jobs.<job_id>.strategy.matrix` is applied." This implies that
# when a matrix job is set as a required status check, skipping it due to the conditional will cause a pull request to be
# blocked from merging.
overall-status:
name: Overall status (CAM-SIMA Fortran CI)
needs:
- conditional-check
- unit-tests
if: ${{ always() }}
runs-on: ubuntu-slim
timeout-minutes: 1
steps:
- name: Evaluate overall status
run: |
set -euo pipefail

write_result_and_exit() {
case "$1" in
false)
echo "Result: Failure."
exit 1
;;
true)
echo "Result: Success."
exit 0
;;
error|*)
echo "Error occurred!"
exit 1
;;
esac
}

case "${{ needs.conditional-check.result }}" in
success)
:
;;
cancelled|failure|skipped)
write_result_and_exit false
;;
*)
write_result_and_exit error
;;
esac

case "${{ needs.unit-tests.result }}" in
skipped|success)
:
;;
cancelled|failure)
write_result_and_exit false
;;
*)
write_result_and_exit error
;;
esac

write_result_and_exit true
unit-tests:
name: Build and run unit tests (${{ matrix.compiler }})
needs: conditional-check
if: ${{ needs.conditional-check.outputs.should-run == 'true' }}
runs-on: ubuntu-24.04
container:
image: ghcr.io/kuanchihwang/atm-sci-container:2026-06-12_${{ matrix.compiler }}_${{ matrix.mpi }}
env:
CONTAINER_PRESET: cesm
CONTAINER_ENVIRONMENT: pfunit
RRTMGP_DATA_REFERENCE: v1.9
UNIT_TESTS_BUILD_TYPE: Debug
UNIT_TESTS_PATH: ${{ github.workspace }}/test/unit/fortran
strategy:
fail-fast: false
matrix:
compiler:
- gnu-11
- gnu-12
- gnu-13
- gnu-14
- gnu-15
- intel-2024
- intel-2025
# Uncomment the following lines to test with more MPI implementations. Currently only `open-mpi-5`
# (Open MPI 5.0.x series) is enabled. We may expand this matrix as our test coverage grows in the future.
mpi:
# - mpich-4
# - open-mpi-4
- open-mpi-5
# include:
# - compiler: intel-2024
# mpi: intel-mpi
# - compiler: intel-2025
# mpi: intel-mpi
timeout-minutes: 10
steps:
- name: Checkout CAM-SIMA
uses: actions/checkout@v6

- name: Checkout dependencies
run: |
./bin/git-fleximod update ncar-physics share

- name: Checkout rrtmgp-data for PIO file reader tests
uses: actions/checkout@v6
with:
repository: earth-system-radiation/rrtmgp-data
ref: ${{ env.RRTMGP_DATA_REFERENCE }}
path: ${{ env.UNIT_TESTS_PATH }}/rrtmgp-data

- name: Build unit tests
run: |
source "$(command -v container-entrypoint-hook.sh)"
cmake \
-D CMAKE_BUILD_TYPE="$UNIT_TESTS_BUILD_TYPE" \
-D CAM_SIMA_ENABLE_CODE_COVERAGE=ON \
-D CAM_SIMA_ENABLE_IO_TESTS=ON \
-D CAM_SIMA_ENABLE_TESTS=ON \
-B "$UNIT_TESTS_PATH/build" \
-S "$UNIT_TESTS_PATH"
cmake \
--build "$UNIT_TESTS_PATH/build" \
--config "$UNIT_TESTS_BUILD_TYPE"

- name: Run unit tests
run: |
source "$(command -v container-entrypoint-hook.sh)"
ctest \
--build-config "$UNIT_TESTS_BUILD_TYPE" \
--output-junit "$UNIT_TESTS_PATH/build/unit-tests.xml" \
--output-on-failure \
--test-dir "$UNIT_TESTS_PATH/build" \
--test-output-size-failed 524288 \
--test-output-size-passed 524288 \
--verbose

- name: Upload unit test results
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
if-no-files-found: ignore
name: unit-tests-xml-${{ matrix.compiler }}
path: ${{ env.UNIT_TESTS_PATH }}/build/unit-tests.xml
retention-days: 7

# Code coverage analysis only works reliably with the GNU Compiler Collection.
# Do it only with the latest version to save CI time.

- name: Install Gcovr
if: ${{ matrix.compiler == 'gnu-15' }}
run: |
python3 -m venv venv-gcovr
source venv-gcovr/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install gcovr

- name: Run Gcovr
if: ${{ matrix.compiler == 'gnu-15' }}
run: |
source venv-gcovr/bin/activate
export SOURCE_PATH="$PWD"
cd "$UNIT_TESTS_PATH/build"
gcovr \
--filter "$SOURCE_PATH/src" \
--html code-coverage.html \
--root "$SOURCE_PATH" \
--verbose \
.

- name: Upload code coverage results
if: ${{ always() && matrix.compiler == 'gnu-15' }}
uses: actions/upload-artifact@v7
with:
if-no-files-found: ignore
name: code-coverage-html
path: ${{ env.UNIT_TESTS_PATH }}/build/code-coverage.html
retention-days: 7
4 changes: 2 additions & 2 deletions .github/workflows/fleximod_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ on:
pull_request:
jobs:
fleximod-test:
runs-on: ubuntu-latest
runs-on: ubuntu-slim
strategy:
fail-fast: false
matrix:
# oldest supported and latest supported
python-version: ["3.8", "3.x"]
steps:
- id: checkout-CESM
uses: actions/checkout@v5
uses: actions/checkout@v6
- id: run-fleximod
run: |
$GITHUB_WORKSPACE/bin/git-fleximod update -o
Expand Down
Loading