Skip to content

Test

Test #95

Workflow file for this run

name: Test
on:
# To debug the workflow, uncomment this entry AND comment pull_request_target
# pull_request:
# branches: [ main ]
pull_request_target:
branches: [ main, "migrate**" ]
types: [ labeled, opened, reopened, synchronize ]
schedule:
- cron: "0 5 * * *" # = 06:00 CET = 07:00 CEST
# Cancel previous runs that have not completed
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
gams-version: 43.4.1
label: "safe to test"
python-version: "3.13"
jobs:
check:
name: Check permissions, identify ref to test
runs-on: ubuntu-latest
steps:
- if: >
!(
github.event_name == 'schedule'
|| github.repository == github.event.pull_request.head.repo.full_name
|| contains(github.event.pull_request.labels.*.name, env.label)
)
run: |
echo "Pytest workflow will not run for branch in fork without label \`${{ env.label }}\`." >>$GITHUB_STEP_SUMMARY
exit 1
- name: Identify ref to check out
id: ref
run: echo "ref=${{ github.event_name != 'pull_request_target' && github.ref || github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
outputs:
ref: ${{ steps.ref.outputs.ref }}
warm-lfs-cache:
name: Warm Git LFS cache
needs: check
strategy:
matrix:
os: [ macos-13, macos-latest, ubuntu-latest, windows-latest ]
runs-on: ${{ matrix.os }}
steps:
- uses: francisbilham11/action-cached-lfs-checkout@v3
with:
ref: ${{ needs.check.outputs.ref }}
- name: Cache static data
uses: actions/cache@v4
with:
path: message-static-data
key: static-data-${{ matrix.os }}
- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: |
${{ secrets.MESSAGE_STATIC_DATA_PRIVATE_KEY }}
- name: Check out message-static-data
uses: actions/checkout@v4
with:
repository: iiasa/message-static-data
path: message-static-data
ssh-key: ${{ secrets.MESSAGE_STATIC_DATA_PRIVATE_KEY }}
lfs: true
# Only check out the following directories, in order to limit bandwidth usage:
sparse-checkout: |
iea/eei
ssp
pytest:
needs: [ check, warm-lfs-cache ]
strategy:
matrix:
os:
- macos-13
- macos-latest
- ubuntu-latest
- windows-latest
version:
# In each group:
# - Versions of ixmp and message_ix to test.
# - Latest supported Python version for those or other dependencies.
# Minimum version given in pyproject.toml + earlier version of Python
# For this job only, the oldest version of Python supported by message-ix-models
- { upstream: v3.8.0, python: "3.9" } # Released 2024-01-12
- { upstream: v3.9.0, python: "3.13" } # 2024-06-04
- { upstream: v3.10.0, python: "3.13" } # 2025-02-21
# Latest released version + latest released Python
- { upstream: v3.11.0, python: "3.13" } # 2025-05-27
# Development version + latest released Python
- { upstream: main, python: "3.13" }
exclude:
# Specific version combinations that are invalid / not to be used
# These versions of ixmp are not able locate the arm64 GAMS API binaries
- { os: macos-latest, version: { upstream: v3.8.0 }}
- { os: macos-latest, version: { upstream: v3.9.0 }}
# Redundant with macos-latest
- { os: macos-13, version: { upstream: v3.10.0 }}
- { os: macos-13, version: { upstream: v3.11.0 }}
- { os: macos-13, version: { upstream: main }}
fail-fast: false
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }}-py${{ matrix.version.python }}-upstream-${{ matrix.version.upstream }}
steps:
- name: Cache test data
uses: actions/cache@v4
with:
path: |
local-data
.pytest_cache/d
key: local-data-${{ matrix.os }}-upstream-${{ matrix.version.upstream }}
- name: Check out message-ix-models
uses: francisbilham11/action-cached-lfs-checkout@v3
with:
ref: ${{ needs.check.outputs.ref }}
- name: Restore message-static-data from cache
uses: actions/cache/restore@v4
with:
path: message-static-data
key: static-data-${{ matrix.os }}
- name: Set up uv, Python
uses: astral-sh/setup-uv@v6
with:
activate-environment: true
python-version: ${{ matrix.version.python }}
- uses: iiasa/actions/setup-gams@main
with:
version: ${{ env.gams-version }}
license: ${{ secrets.GAMS_LICENSE }}
- uses: ts-graphviz/setup-graphviz@v2
# Work around ts-graphviz/setup-graphviz#630
if: matrix.os != 'macos-13'
- name: Set Java version on Windows
if: startsWith(matrix.os, 'windows-')
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Install packaging
run: uv pip install packaging
- name: Determine extra dependencies
id: dependencies
run : |
from os import environ
from packaging.version import Version, parse
from pathlib import Path
version_string = "${{ matrix.version.upstream }}"
if version_string != "main":
v, result = parse(version_string), []
for condition, dependency in (
(v < Version("v3.9"), "pytest == 8.0.0"), # Upstream versions < 3.9.0 use a hook argument removed in pytest 8.1.0 (#155)
(Version("v3.8") < v < Version("v3.11"), "ixmp4 < 0.11"), # https://github.com/iiasa/message-ix-models/issues/366
):
result.extend([f'"{dependency}"'] if condition else [])
Path(environ["GITHUB_OUTPUT"]).write_text(f"value={' '.join(result)}\n")
shell: python
- name: Install packages and dependencies
# By default, install:
# - ixmp, message_ix: from GitHub branches/tags per matrix.version.upstream (above)
# - dask: work around https://github.com/khaeru/genno/issues/171
# - other dependencies: from PyPI.
#
# To test against unreleased code (on `main`, or other branches for open PRs),
# temporarily edit or add lines below as needed. DO NOT merge such changes to `main`.
run: |
uv pip install --upgrade \
${{ steps.dependencies.outputs.value }} \
"dask < 2025.4.0" \
"ixmp @ git+https://github.com/iiasa/ixmp.git@${{ matrix.version.upstream }}" \
"message-ix @ git+https://github.com/iiasa/message_ix.git@${{ matrix.version.upstream }}" \
"message-ix-buildings @ git+https://github.com/iiasa/message-ix-buildings@main" \
.[docs,tests]
- name: Configure local data path
run: |
mkdir -p local-data
mix-models config set "message local data" "$(realpath local-data)"
mix-models config show
# Symlink message-static-data into local data path
mkdir -p ${{ github.workspace }}/local-data
cp -rsv $(realpath message-static-data)/* local-data/
- name: Run test suite using pytest
run: |
pytest message_ix_models \
-m "not (ece_db or snapshot)" \
--color=yes --durations=20 -rA --verbose \
--cov-report=term-missing --cov-report=xml \
--numprocesses=auto --dist=loadscope \
--local-cache --jvmargs="-Xmx6G"
- name: Upload test coverage to Codecov.io
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }} # Required
pre-commit:
name: Code quality
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { ref: "${{ needs.check.outputs.ref }}" }
- uses: astral-sh/setup-uv@v6
with: { python-version: "${{ env.python-version }}" }
- name: Clear and re-create the pre-commit environments
run: uvx pre-commit clean
if: github.event_name == 'schedule' # Comment this line to force clear
- run: |
uvx --with=pre-commit-uv \
pre-commit run \
--all-files --color=always --show-diff-on-failure --verbose