Skip to content
Closed
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
96 changes: 96 additions & 0 deletions .github/workflows/matlab-fixture-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: MATLAB Fixture Publish (manual)

# One-off, human-triggered tool: exports a fresh reference bundle from real
# MATLAB (tests/matlab_export/pyis_export_reference_data.m) and pushes it,
# raw, to a new branch -- nothing else. It does not touch
# tools/fixture_provenance.py's pinned identity constants, regenerate
# tests/fixture_inventory.json, or run the test suite; that follow-up work
# happens after pulling the branch, where the full toolchain is available.
#
# Exists because this session's sandbox can reach github.com (git push
# works) but not the Actions artifact blob-storage host used by
# actions/upload-artifact's download URLs, so getting a real-MATLAB-
# generated bundle out of a GitHub-hosted runner and into a review-able
# git branch has to go through a direct push, not an artifact download.
#
# Not for routine CI use. Run manually (workflow_dispatch) only, with an
# explicit publish_branch, when actually intending to propose a new gold
# fixture bundle (see #344 for the tracking issue this feeds).

on:
workflow_dispatch:
inputs:
instancespace_ref:
description: >-
Git ref (branch, tag, or commit SHA) of andremun/InstanceSpace to
export from.
required: false
default: master
publish_branch:
description: >-
Branch name to push the raw exported bundle to (created from the
current default branch). Required -- there is no default, so an
accidental run can't silently push anywhere.
required: true

permissions:
contents: write

jobs:
publish_fixture_bundle:
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- name: Check out pyInstanceSpace
uses: actions/checkout@v6
with:
# Always from main, regardless of which branch this workflow run was
# dispatched against, so publish_branch's base is always clean.
ref: main
path: pyInstanceSpace
persist-credentials: true

- name: Check out MATLAB source
run: |-
git clone https://github.com/andremun/InstanceSpace.git InstanceSpace
git -C InstanceSpace checkout "${{ github.event.inputs.instancespace_ref }}"

- name: Set up MATLAB R2026a
uses: matlab-actions/setup-matlab@v2
with:
release: R2026a
products: >
Statistics_and_Machine_Learning_Toolbox
Optimization_Toolbox
Global_Optimization_Toolbox
Parallel_Computing_Toolbox
Financial_Toolbox

- name: Export a fresh reference bundle from real MATLAB
uses: matlab-actions/run-command@v2
with:
command: >-
addpath('pyInstanceSpace/tests/matlab_export');
pyis_export_reference_data('InstanceSpace', 'fresh-bundle',
'generatorRoot', 'pyInstanceSpace', 'mode', 'verified');

- name: Push the raw bundle to publish_branch
working-directory: pyInstanceSpace
run: |-
set -e
git config user.name "matlab-fixture-publish[bot]"
git config user.email "actions@github.com"
git checkout -b "${{ github.event.inputs.publish_branch }}"
rm -rf tests/fixtures/matlab/current
mkdir -p tests/fixtures/matlab/current
cp -r ../fresh-bundle/. tests/fixtures/matlab/current/
git add tests/fixtures/matlab/current
git commit -m "chore: raw MATLAB export for fixture bundle refresh (unreviewed)

Raw output of pyis_export_reference_data.m against InstanceSpace@${{ github.event.inputs.instancespace_ref }},
pushed as-is by matlab-fixture-publish.yml. tools/fixture_provenance.py's
pinned identity constants, tests/fixture_inventory.json, and the test
suite have NOT been updated yet -- this commit is raw material for
that follow-up work, not a reviewed fixture bundle on its own."
git push origin "${{ github.event.inputs.publish_branch }}"
154 changes: 154 additions & 0 deletions .github/workflows/matlab-oracle-verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: MATLAB Oracle Verification

# Regenerates the MATLAB reference fixtures directly from a real MATLAB run
# of andremun/InstanceSpace's current master, using tests/matlab_export/
# pyis_export_reference_data.m, then verifies the result with
# tools/fixture_provenance.py. This checks the fixtures actually still match
# what MATLAB produces today, not just that a pinned commit SHA is current
# (see #344, and the "MATLAB oracle is stale" check in validation-tests.yml).
#
# Report-only for now (job-level continue-on-error): this is the exporter's
# first run on a CI runner, and it has never been exercised outside a
# human's local MATLAB (#278). It must prove reliable here before it can
# replace or gate anything in validation-tests.yml.

on:
push:
branches:
- main
- development
- "*-candidate"
- "v*/development-*"
pull_request: {}
workflow_dispatch:
inputs:
instancespace_ref:
description: >-
Git ref (branch, tag, or commit SHA) of andremun/InstanceSpace to
export from. Defaults to master. Set this to the gold commit
pinned in tests/fixtures/matlab/current/manifest.json for a
control run: if the fresh export still differs from the
committed fixtures at that exact commit, the drift is
platform/run noise, not a MATLAB code change (see #344).
required: false
default: master

permissions:
contents: read

jobs:
verify_against_real_matlab:
runs-on: ubuntu-latest
timeout-minutes: 90
continue-on-error: true

steps:
- name: Check out pyInstanceSpace
uses: actions/checkout@v6
with:
path: pyInstanceSpace
persist-credentials: false

- name: Check out current MATLAB gold source
# A full clone (no --depth/--branch) so instancespace_ref can be an
# arbitrary commit SHA, not just a branch tip.
run: |-
git clone https://github.com/andremun/InstanceSpace.git InstanceSpace
git -C InstanceSpace checkout "${{ github.event.inputs.instancespace_ref || 'master' }}"

- name: Set up MATLAB R2026a
uses: matlab-actions/setup-matlab@v2
with:
# pyis_export_reference_data.m's 'verified' mode hard-requires
# R2026a -- it is the release the currently-installed oracle was
# generated under (see tests/matlab_export/README.md).
release: R2026a
products: >
Statistics_and_Machine_Learning_Toolbox
Optimization_Toolbox
Global_Optimization_Toolbox
Parallel_Computing_Toolbox
Financial_Toolbox

- name: Export a fresh reference bundle from real MATLAB
uses: matlab-actions/run-command@v2
with:
command: >-
addpath('pyInstanceSpace/tests/matlab_export');
pyis_export_reference_data('InstanceSpace', 'fresh-bundle',
'generatorRoot', 'pyInstanceSpace', 'mode', 'verified');

- name: Set up Python 3.12
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install fixture_provenance's dependencies
run: python -m pip install --disable-pip-version-check numpy scipy

- name: Verify the freshly exported bundle
run: python pyInstanceSpace/tools/fixture_provenance.py verify fresh-bundle

- name: Diff the fresh export against the committed oracle
# fixture_provenance.py verify's 'verified v2' identity check hard-fails
# on any MATLAB commit other than the pinned gold SHA (see #344), which
# blocks the step above whenever the oracle is stale -- exactly the
# case this diff exists to inspect. !cancelled() keeps this step
# running after that failure (only a cancelled job skips it), so it
# answers the actual question even when verify never got there: does
# current MATLAB master still produce byte-identical output to the
# committed tests/fixtures/matlab/current bundle, for the same input
# dataset, regardless of whether its commit matches the pinned one?
if: ${{ !cancelled() }}
run: |-
python - <<'PY'
import json
import sys
from pathlib import Path

committed = json.loads(
Path("pyInstanceSpace/tests/fixtures/matlab/current/manifest.json").read_text()
)["files"]
fresh = json.loads(Path("fresh-bundle/manifest.json").read_text())["files"]

committed_by_path = {f["path"]: f["sha256"] for f in committed}
fresh_by_path = {f["path"]: f["sha256"] for f in fresh}

added = sorted(set(fresh_by_path) - set(committed_by_path))
removed = sorted(set(committed_by_path) - set(fresh_by_path))
changed = sorted(
path
for path in set(fresh_by_path) & set(committed_by_path)
if fresh_by_path[path] != committed_by_path[path]
)

if added:
print(f"Added ({len(added)}):")
for path in added:
print(f" {path}")
if removed:
print(f"Removed ({len(removed)}):")
for path in removed:
print(f" {path}")
if changed:
print(f"Changed content ({len(changed)}):")
for path in changed:
print(f" {path}")

if added or removed or changed:
print(
"\nCurrent MATLAB master no longer reproduces the committed "
"oracle bit-for-bit. See #344 and tests/matlab_export/README.md."
)
sys.exit(1)

print("Fresh MATLAB export matches the committed oracle exactly.")
PY

- name: Upload the freshly exported bundle
if: always()
uses: actions/upload-artifact@v4
with:
name: fresh-matlab-reference-bundle
path: fresh-bundle/
retention-days: 14
Loading
Loading