Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
feb5eba
Generated uv.lock
explodingdinosaurs Jun 5, 2026
4b2ef3a
Changed linters to uv, ruff and ty. Removed types-pytz from linters
explodingdinosaurs Jun 5, 2026
fed7452
Autoformatting
explodingdinosaurs Jun 5, 2026
6b10474
Autoformatting
explodingdinosaurs Jun 9, 2026
030d837
Updating coverage to work with uv
explodingdinosaurs Jun 9, 2026
d426a89
Replaces linting and testing with uv, ty and ruff
explodingdinosaurs Jun 9, 2026
ddf11ca
changed test to dev where applicable to align with dependency-groups
explodingdinosaurs Jun 9, 2026
66c8fb2
Needed to add optional-dependencies for CICD to work
explodingdinosaurs Jun 9, 2026
6f4bd95
Updating install requirement groups
explodingdinosaurs Jun 9, 2026
d92b862
Fixed typo
explodingdinosaurs Jun 9, 2026
ef94843
removed --extra flag as dev group is included by default using uv
explodingdinosaurs Jun 9, 2026
3fe5e95
made uv sync work somehow
explodingdinosaurs Jun 9, 2026
dc8bbd8
Adding uv lock file
explodingdinosaurs Jun 9, 2026
68a2089
Ran isort
explodingdinosaurs Jun 9, 2026
528a4cc
Ran ruff check --fix
explodingdinosaurs Jun 9, 2026
ae95efd
Ran ruff format
explodingdinosaurs Jun 9, 2026
7c66da5
Updated Port.process_initial_values() and fixed typing. Updated typin…
explodingdinosaurs Jun 9, 2026
89ae21c
Added more nuanced type check. Updated imports
explodingdinosaurs Jun 9, 2026
dd96de0
Updated check to ensure initial_value is None, not 0
explodingdinosaurs Jun 9, 2026
cc833f5
Added type hints
explodingdinosaurs Jun 9, 2026
56c7d94
Added defaults of None for Port.initial_value_ref and initial_scaling…
explodingdinosaurs Jun 9, 2026
865a654
Added basic gas port tests
explodingdinosaurs Jun 9, 2026
c09ce4a
Ran isort
explodingdinosaurs Jun 9, 2026
8b13fe4
Autoformatting
explodingdinosaurs Jun 9, 2026
d2ddc5f
Add tests for Port.process_initial_value()
explodingdinosaurs Jun 9, 2026
84273a7
Added more asserts for process_initial_values
explodingdinosaurs Jun 9, 2026
721f9fb
Defaults Storage.fixed_storage_capacity to None
explodingdinosaurs Jun 9, 2026
5ad3be1
Added np.ndarry to allowed types in InitialValueInput
explodingdinosaurs Jun 9, 2026
ae6bba6
Added check that self.usage isn't None.
explodingdinosaurs Jun 9, 2026
c2b3a4b
Added type hints
explodingdinosaurs Jun 10, 2026
b18e0b5
Updated changelog web address
explodingdinosaurs Jun 10, 2026
218d377
Added round to ensure floating point comparison works.
explodingdinosaurs Jun 11, 2026
08aa7dd
Updating docstrings and typehints
explodingdinosaurs Jun 11, 2026
b263e2a
Autoformatting
explodingdinosaurs Jun 11, 2026
9e45b7c
Updated type hints
explodingdinosaurs Jun 12, 2026
01dd275
Updated type hints
explodingdinosaurs Jun 12, 2026
cc97495
Updated type hints
explodingdinosaurs Jun 12, 2026
1ae25d6
Updated type hints
explodingdinosaurs Jun 15, 2026
debe658
Updated docstring
explodingdinosaurs Jun 15, 2026
46433cc
Autoformatting
explodingdinosaurs Jun 15, 2026
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
275 changes: 144 additions & 131 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,174 +9,187 @@ permissions:
pull-requests: write

jobs:
# This run coverage on the target and source branches before comparing
coverage:
coverage_source:
runs-on: ubuntu-latest
outputs:
source_raw: ${{ steps.extract.outputs.raw }}
steps:
- name: Checkout
uses: actions/checkout@v3.1.0
uses: actions/checkout@v6

- name: Download CPLEX installer from Azure storage account
uses: armanrahman22/azblob-download-action@v0.0.4
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
connection-string: ${{ secrets.BLDDEPS_STORAGE_ACCOUNT_CONN_STR }}
container-name: "solver-blobs"
blob-name: "cplex_22.1.1.0-1_amd64.deb"
download-path: "."

- name: Setup Python
uses: actions/setup-python@v4.2.0
with:
python-version: "3.11"
python-version: "3.13"

- name: Install Dependencies
run: |
pip install --group dev .
# Install CPLEX
sudo apt install -f ./cplex_22.1.1.0-1_amd64.deb
uv sync

- name: Coverage (source branch)
run: |
coverage run --data-file=.coverage-source -m pytest
{
echo 'SOURCE_RAW<<EOF'
coverage report --data-file=.coverage-source --omit='tests/**'
echo EOF
} >> "$GITHUB_ENV"
env:
OPTIMISER_ENGINE: "cplex"
OPTIMISER_ENGINE_EXECUTABLE: "/opt/cplex/cplex"
PYTHONPATH: ./
echo "[run]" > .coveragecfg
echo "data_file=.coverage-source" >> .coveragecfg
uv run pytest -n auto --cov=my_app --cov-config=.coveragecfg .

- name: Checkout
uses: actions/checkout@v3.1.0
- name: Extract Coverage
id: extract
run: |
echo 'raw<<EOF' >> $GITHUB_OUTPUT
uv run coverage report --data-file=.coverage-source --omit='tests/**' >> $GITHUB_OUTPUT
echo EOF >> $GITHUB_OUTPUT
uv run coverage html --data-file=.coverage-source --omit='tests/**'

- name: Upload Target Coverage HTML Report Artifact
uses: actions/upload-artifact@v7
with:
name: source-code-coverage-html
path: htmlcov/
overwrite: true

coverage_target:
runs-on: ubuntu-latest
outputs:
target_raw: ${{ steps.extract.outputs.raw }}
steps:
- name: Checkout (target branch)
uses: actions/checkout@v6
with:
ref: ${{ github.base_ref }}

- name: Download CPLEX installer from Azure storage account
uses: armanrahman22/azblob-download-action@v0.0.4
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
connection-string: ${{ secrets.BLDDEPS_STORAGE_ACCOUNT_CONN_STR }}
container-name: "solver-blobs"
blob-name: "cplex_22.1.1.0-1_amd64.deb"
download-path: "."
python-version: "3.13"

- name: Install Dependencies
run: |
pip install --group dev .
# Install CPLEX
sudo apt install -f ./cplex_22.1.1.0-1_amd64.deb
uv sync

- name: Coverage (target branch)
run: |
coverage run --data-file=.coverage-target -m pytest
{
echo 'TARGET_RAW<<EOF'
coverage report --data-file=.coverage-target --omit='tests/**'
echo EOF
} >> "$GITHUB_ENV"
env:
OPTIMISER_ENGINE: "cplex"
OPTIMISER_ENGINE_EXECUTABLE: "/opt/cplex/cplex"
PYTHONPATH: ./

- uses: actions/github-script@v7
env:
ISSUE_NUMBER: ${{ github.event.number }}
echo "[run]" > .coveragecfg
echo "data_file=.coverage-target" >> .coveragecfg
uv run pytest -n auto --cov=my_app --cov-config=.coveragecfg .

- name: Extract Coverage
id: extract
run: |
echo 'raw<<EOF' >> $GITHUB_OUTPUT
uv run coverage report --data-file=.coverage-target --omit='tests/**' >> $GITHUB_OUTPUT
echo EOF >> $GITHUB_OUTPUT
uv run coverage html --data-file=.coverage-target --omit='tests/**'

- name: Upload Target Coverage HTML Report Artifact
uses: actions/upload-artifact@v7
with:
script: |
const { SOURCE_RAW, TARGET_RAW, GITHUB_BASE_REF, GITHUB_HEAD_REF, ISSUE_NUMBER } = process.env

// returns dict keyed by file name with code coverage percent integers
function split_coverage(raw) {
let result = {};
for (let l of raw.split('\n')) {
if (l && l.endsWith('%')) {
let line_parts = l.split(' ');
result[line_parts[0]] = parseInt(line_parts.pop());
name: target-code-coverage-html
path: htmlcov/
overwrite: true

compare_coverage:
runs-on: ubuntu-latest
needs: [coverage_source, coverage_target]
env:
SOURCE_RAW: ${{ needs.coverage_source.outputs.source_raw }}
TARGET_RAW: ${{ needs.coverage_target.outputs.target_raw }}
ISSUE_NUMBER: ${{ github.event.number }}
steps:
- uses: actions/github-script@v7
with:
script: |
const { SOURCE_RAW, TARGET_RAW, GITHUB_BASE_REF, GITHUB_HEAD_REF, ISSUE_NUMBER } = process.env

// returns dict keyed by file name with code coverage percent integers
function split_coverage(raw) {
let result = {};
for (let l of raw.split('\n')) {
if (l && l.endsWith('%')) {
let line_parts = l.split(' ');
result[line_parts[0]] = parseInt(line_parts.pop());
}
}
return result;
}
return result;
}
const source = split_coverage(SOURCE_RAW)
const target = split_coverage(TARGET_RAW)
const source_total_percent = source["TOTAL"]
const target_total_percent = target["TOTAL"]

const file_reductions = []
for (let [k, target_pc] of Object.entries(target)) {
if (k in source) {
source_pc = source[k]
if (source_pc < target_pc) {
let diff = target_pc - source_pc
file_reductions.push(`|\`${k}\` | 🔻 ${diff}% (${target_pc}% → ${source_pc}%) |`)
const source = split_coverage(SOURCE_RAW)
const target = split_coverage(TARGET_RAW)
const source_total_percent = source["TOTAL"]
const target_total_percent = target["TOTAL"]

const file_reductions = []
for (let [k, target_pc] of Object.entries(target)) {
if (k in source) {
source_pc = source[k]
if (source_pc < target_pc) {
let diff = target_pc - source_pc
file_reductions.push(`|\`${k}\` | 🔻 ${diff}% (${target_pc}% → ${source_pc}%) |`)
}
}
}
}

const file_adds = []
for (let [k, source_pc] of Object.entries(source)) {
if (!(k in target)) {
if (source_pc >= target_total_percent) {
file_adds.push(`|\`${k}\` | ✅ Coverage at ${source_pc}% |`)
} else {
file_adds.push(`|\`${k}\` | ⚠️ Coverage at ${source_pc}% |`)
const file_adds = []
for (let [k, source_pc] of Object.entries(source)) {
if (!(k in target)) {
if (source_pc >= target_total_percent) {
file_adds.push(`|\`${k}\` | ✅ Coverage at ${source_pc}% |`)
} else {
file_adds.push(`|\`${k}\` | ⚠️ Coverage at ${source_pc}% |`)
}
}
}
}

let body = ''
if (source_total_percent >= target_total_percent) {
body += `✅ Code coverage on \`${GITHUB_HEAD_REF}\` is at ${source_total_percent}% (compared to \`${GITHUB_BASE_REF}\` being at ${target_total_percent}%)\n`
} else {
body += `💔 Code coverage on \`${GITHUB_HEAD_REF}\` has **reduced** to ${source_total_percent}% (compared to \`${GITHUB_BASE_REF}\` being at ${target_total_percent}%)\n`
}
let body = ''
if (source_total_percent >= target_total_percent) {
body += `✅ Code coverage on \`${GITHUB_HEAD_REF}\` is at ${source_total_percent}% (compared to \`${GITHUB_BASE_REF}\` being at ${target_total_percent}%)\n`
} else {
body += `💔 Code coverage on \`${GITHUB_HEAD_REF}\` has **reduced** to ${source_total_percent}% (compared to \`${GITHUB_BASE_REF}\` being at ${target_total_percent}%)\n`
}

if (file_reductions.length > 0) {
body += "## File Reductions\n"
body += "| File | Details |\n"
body += "| ---- | ------- |\n"
body += file_reductions.join("\n")
} else {
body += "\n🎉 No files have reduced coverage 🎉\n"
}
if (file_reductions.length > 0) {
body += "## File Reductions\n"
body += "| File | Details |\n"
body += "| ---- | ------- |\n"
body += file_reductions.join("\n")
} else {
body += "\n🎉 No files have reduced coverage 🎉\n"
}

if (file_adds.length > 0) {
body += "\n<details>\n"
body += "<summary><h2>Coverage for new files</h2></summary>\n\n"
body += "| File | Details |\n"
body += "| ---- | ------- |\n"
body += file_adds.join("\n")
body += "\n</details>\n"
}

if (file_adds.length > 0) {
body += "\n<details>\n"
body += "<summary><h2>Coverage for new files</h2></summary>\n\n"
body += "<summary><h2>Full Coverage Report</h2></summary>\n\n"
body += "| File | Details |\n"
body += "| ---- | ------- |\n"
body += file_adds.join("\n")
body += "\n</details>\n"
}

body += "\n<details>\n"
body += "<summary><h2>Full Coverage Report</h2></summary>\n\n"
body += "| File | Details |\n"
body += "| ---- | ------- |\n"
for (let [k, source_pc] of Object.entries(source)) {
if (k in target) {
target_pc = target[k]
if (source_pc < target_pc) {
let diff = target_pc - source_pc
body += `|\`${k}\` | 🔻 ${diff}% (${target_pc}% → ${source_pc}%) |\n`
for (let [k, source_pc] of Object.entries(source)) {
if (k in target) {
target_pc = target[k]
if (source_pc < target_pc) {
let diff = target_pc - source_pc
body += `|\`${k}\` | 🔻 ${diff}% (${target_pc}% → ${source_pc}%) |\n`
} else {
body += `|\`${k}\` | ✅ ${target_pc}% → ${source_pc}% |\n`
}
} else {
body += `|\`${k}\` | ✅ ${target_pc}% → ${source_pc}% |\n`
body += `|\`${k}\` | 🆕 ${source_pc}% |\n`
}
} else {
body += `|\`${k}\` | 🆕 ${source_pc}% |\n`
}
}
body += "\n</details>\n"

const fs = require('fs');
fs.mkdirSync("coverage-report-data/");
fs.writeFileSync("coverage-report-data/coverage-report.txt", body);
fs.writeFileSync("coverage-report-data/issue-number.txt", ISSUE_NUMBER);
body += "\n</details>\n"

- name: Upload Coverage Report Artifact
uses: actions/upload-artifact@v4
with:
name: code-coverage-report
path: coverage-report-data/
overwrite: true
const fs = require('fs');
fs.mkdirSync("coverage-report-data/");
fs.writeFileSync("coverage-report-data/coverage-report.txt", body);
fs.writeFileSync("coverage-report-data/issue-number.txt", ISSUE_NUMBER);

- name: Upload Coverage Report Artifact
uses: actions/upload-artifact@v7
with:
name: code-coverage-report
path: coverage-report-data/
overwrite: true
Loading
Loading