Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
87 changes: 76 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: Test and build

on:
push:
branches: [main]
Expand All @@ -9,30 +8,96 @@ on:

jobs:
test:
runs-on: ${{matrix.os}}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
python-version: ['3.14']
include:
- os: ubuntu-latest
python-version: '3.14'
muse2_asset: muse2_linux.tar.gz
muse2_exe: muse2
- os: windows-latest
python-version: '3.14'
muse2_asset: muse2_windows.zip
muse2_exe: muse2.exe
- os: macos-latest
python-version: '3.14'
muse2_asset: muse2_macos_arm.tar.gz
muse2_exe: muse2

steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v5
Comment thread
Aurashk marked this conversation as resolved.
Outdated
with:
enable-cache: true
prune-cache: false
activate-environment: true
Comment thread
Aurashk marked this conversation as resolved.
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync

# Query the GitHub API for the latest MUSE2 release tag (e.g. "v2.0.0").
# The tag is written to GITHUB_OUTPUT so subsequent steps can reference it.
- name: Get latest MUSE2 release tag
id: muse2_release
shell: bash
run: |
TAG=$(curl -sSf \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
Comment thread
Aurashk marked this conversation as resolved.
Outdated
https://api.github.com/repos/EnergySystemsModellingLab/MUSE2/releases/latest \
| jq -r '.tag_name')
Comment on lines +44 to +52
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the moving target endpoint .../releases/latest makes CI non-reproducible and can introduce unexpected failures when MUSE2 publishes a new release (or if the API is temporarily unavailable). Consider pinning to a specific tag (optionally configurable via workflow input/env) so CI behavior is deterministic, or add a fallback to a known-good tag when the API lookup fails.

Copilot uses AI. Check for mistakes.

if [[ -z "$TAG" || "$TAG" == "null" ]]; then
echo "::error::Failed to retrieve latest MUSE2 release tag."
exit 1
fi

echo "Resolved latest MUSE2 release: $TAG"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

# Download the platform-appropriate MUSE2 release asset.
# 'shell: bash' is used on all platforms
- name: Download MUSE2 release asset
shell: bash
run: |
curl -sSfL \
"https://github.com/EnergySystemsModellingLab/MUSE2/releases/download/${{ steps.muse2_release.outputs.tag }}/${{ matrix.muse2_asset }}" \
--output "muse2_asset_download"

Comment on lines +67 to +70
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow downloads and executes an external prebuilt muse2 binary, but there is no integrity verification of the downloaded asset. To reduce supply-chain and corruption risk, consider validating the download (e.g., verify a published SHA256/SHA512 checksum or signature) before extracting/using it.

Suggested change
curl -sSfL \
"https://github.com/EnergySystemsModellingLab/MUSE2/releases/download/${{ steps.muse2_release.outputs.tag }}/${{ matrix.muse2_asset }}" \
--output "muse2_asset_download"
set -euo pipefail
ASSET_URL="https://github.com/EnergySystemsModellingLab/MUSE2/releases/download/${{ steps.muse2_release.outputs.tag }}/${{ matrix.muse2_asset }}"
CHECKSUM_URL="${ASSET_URL}.sha256"
echo "Downloading MUSE2 asset from: ${ASSET_URL}"
curl -sSfL "${ASSET_URL}" --output "muse2_asset_download"
echo "Downloading MUSE2 asset checksum from: ${CHECKSUM_URL}"
curl -sSfL "${CHECKSUM_URL}" --output "muse2_asset_download.sha256"
echo "Verifying checksum for downloaded MUSE2 asset..."
sha256sum -c "muse2_asset_download.sha256"
echo "MUSE2 asset checksum verification succeeded."

Copilot uses AI. Check for mistakes.
- name: Extract MUSE2 and set environment variable (Linux / macOS)
if: runner.os == 'Linux' || runner.os == 'macOS'
shell: bash
run: |
mkdir -p muse2_bin
tar -xf muse2_asset_download -C muse2_bin
chmod +x "muse2_bin/${{ matrix.muse2_exe }}"
echo "MUSE2_PATH=${{ github.workspace }}/muse2_bin/${{ matrix.muse2_exe }}" >> "$GITHUB_ENV"

- name: Extract MUSE2 and set environment variable (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path muse2_bin | Out-Null
Rename-Item -Path "muse2_asset_download" -NewName "muse2_asset_download.zip"
Expand-Archive -Path "muse2_asset_download.zip" -DestinationPath muse2_bin -Force
$exePath = "${{ github.workspace }}\muse2_bin\${{ matrix.muse2_exe }}"
echo "MUSE2_PATH=$exePath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

# Confirm the muse2 executable is present and the environment variable is set correctly.
- name: Verify MUSE2 installation
shell: bash
run: |
if [[ ! -f "$MUSE2_PATH" ]]; then
echo "::error::MUSE2 executable not found at: $MUSE2_PATH"
exit 1
fi
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify MUSE2 installation uses shell: bash on all OSes, but on Windows MUSE2_PATH is written as a Windows path with backslashes (e.g. C:\...). Bash file tests can behave inconsistently with Windows-style paths depending on the runner shell. Consider making this step OS-specific (use pwsh on Windows) or normalizing the path (e.g. via cygpath) before testing it to avoid false negatives.

Copilot uses AI. Check for mistakes.
echo "MUSE2_PATH is set to: $MUSE2_PATH"

- name: Run mypy
run: mypy .

- name: Run tests
run: pytest
run: pytest --nbmake
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow calls mypy/pytest directly after uv sync. Unless the virtual environment is explicitly activated by setup-uv, those executables may not be on PATH (README suggests using uv run or activating .venv). Consider running these as uv run mypy . / uv run pytest --nbmake, or re-enabling environment activation in the setup-uv step if supported, to make the workflow robust across runner shells/OSes.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add this flag to the other pytest options in pyproject.toml. But maybe we want to keep it as a separate option if it's somewhat long-running. What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good idea, for now it's instant. We can always separate the notebook testing later on if we need to.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dev = [
"pytest>=9.0.2",
"pytest-cov>=7.0.0",
"pytest-mock>=3.15.1",
"nbmake>=1.5.5",
]


Expand Down
18 changes: 18 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading