Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
37ff4b3
WIP: Add pixi CI runner
scott-huberty Feb 22, 2026
9bf2882
FIX: syntax
scott-huberty Feb 22, 2026
e736f17
TST: test branch
scott-huberty Feb 22, 2026
07ff86e
FIX: skip cache for now
scott-huberty Feb 22, 2026
7fa7b7d
FIX: create pixi.toml
scott-huberty Feb 22, 2026
c26c307
check
scott-huberty Feb 22, 2026
1ff8624
try
scott-huberty Feb 22, 2026
03b2f29
dont install
scott-huberty Feb 22, 2026
8b73058
try again
scott-huberty Feb 22, 2026
962a49e
activate environment
scott-huberty Feb 22, 2026
05359d8
FIX: rm cruft
scott-huberty Feb 22, 2026
460c24a
debug
scott-huberty Feb 23, 2026
5a16daa
arg
scott-huberty Feb 23, 2026
dc25bec
more debug
scott-huberty Feb 23, 2026
d1c45e2
tests
scott-huberty Feb 23, 2026
14c0687
more
scott-huberty Feb 23, 2026
0376aae
try
scott-huberty Feb 23, 2026
a207603
hack: prepend path with executable
scott-huberty Feb 23, 2026
4f0770f
FIX: wrong var
scott-huberty Feb 23, 2026
e0d0865
FIX: shell
scott-huberty Feb 23, 2026
7c44343
Found the issue (login shell). Now try to remove previous hack
scott-huberty Feb 23, 2026
fe5a459
now debug failiing conda-ish CI's
scott-huberty Feb 23, 2026
c2f8a97
arggh GH YAML syntax doesnt allow double quotes
scott-huberty Feb 23, 2026
de6704c
try using shell wrapper
scott-huberty Feb 23, 2026
6e651d8
more
scott-huberty Feb 23, 2026
a46fc3b
remove branch
scott-huberty Feb 28, 2026
0e6aeaf
restore login shell
scott-huberty Mar 18, 2026
1ca07e7
specify manifest path
scott-huberty Mar 18, 2026
79291ff
do install
scott-huberty Mar 18, 2026
e246da4
revert tmp conda tweaks
scott-huberty Mar 18, 2026
c0e16a2
revert pixi toml creation
scott-huberty Mar 18, 2026
83c66f5
remove cruft
scott-huberty Mar 18, 2026
cb0f159
remove micromamba shell [skip actions] [skip az[] [ci skip]
scott-huberty Mar 18, 2026
d798ce9
checkpoint before rebase
scott-huberty Apr 7, 2026
43f4b96
Merge remote-tracking branch 'upstream/main' into pixi2
scott-huberty Apr 7, 2026
2422d58
add lock file
scott-huberty Apr 7, 2026
676a845
for debugging
scott-huberty Apr 7, 2026
b56aa5c
FIX: filename
scott-huberty Apr 7, 2026
ad9df3f
FIX: try toml
scott-huberty Apr 8, 2026
38dd081
guard
scott-huberty Apr 8, 2026
f40a537
cruft
scott-huberty Apr 8, 2026
e1dba77
temp debugging statements
scott-huberty Apr 8, 2026
9f747ae
triage
scott-huberty Apr 8, 2026
e10c59a
debug
scott-huberty Apr 8, 2026
ca03ac8
TMP: triage python/pytest command
scott-huberty Apr 8, 2026
bb8e9a7
Revert "TMP: triage python/pytest command"
scott-huberty Apr 8, 2026
336495e
reveal PATH
scott-huberty Apr 8, 2026
649e2b2
fix: cruft
scott-huberty Apr 8, 2026
a09b734
foo
scott-huberty Apr 8, 2026
ab625ba
bar
scott-huberty Apr 8, 2026
22ba9eb
baz
scott-huberty Apr 8, 2026
279fa65
shell-hook
scott-huberty Apr 8, 2026
e08d2cd
persist across steps?
scott-huberty Apr 8, 2026
25073c6
pipe
scott-huberty Apr 8, 2026
a3db53d
wrapper
scott-huberty Apr 8, 2026
ad04dec
oops.. typo
scott-huberty Apr 8, 2026
ed263ed
just use erics line of code and also run gh_actions_deps
scott-huberty Apr 9, 2026
92e30fa
Pixi run prefix
scott-huberty Apr 15, 2026
0cd364a
FIX: syntax
scott-huberty Apr 15, 2026
69d264c
try storing value without quotes
scott-huberty Apr 15, 2026
2a645f0
Merge remote-tracking branch 'upstream/main' into pixi2
scott-huberty Apr 15, 2026
b02265c
activate environment false
scott-huberty Apr 15, 2026
019ddf4
FIX: syntax
scott-huberty Apr 15, 2026
f4eab60
activate environment
scott-huberty Apr 15, 2026
c856ffa
Fixes for Pixi
scott-huberty Apr 20, 2026
4fc7fb6
WIP: Try solving gen lock file from Pyprojec.toml
scott-huberty Apr 22, 2026
4a03f47
Revert "WIP: Try solving gen lock file from Pyprojec.toml"
scott-huberty Apr 22, 2026
ea8861d
WIP pixi from pyproj [ci skip]
drammock Apr 22, 2026
4025a14
Remove PREFIX strategy
scott-huberty Apr 29, 2026
4446fca
work around for macOS login shells
scott-huberty Apr 29, 2026
d28bda6
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 29, 2026
a441306
FIX: do prepend path hack AFTER pixi setup
scott-huberty Apr 29, 2026
b7ed6ff
Merge remote-tracking branch 'origin/pixi' into pixi
scott-huberty Apr 29, 2026
803e324
move/rename manifest and lockfile
drammock Apr 29, 2026
7d20814
visibility [skip circle] [skip azp]
scott-huberty Apr 29, 2026
93e2dff
Merge remote-tracking branch 'origin/pixi' into pixi
scott-huberty Apr 29, 2026
8996abd
FIX: path
scott-huberty Apr 29, 2026
95a5266
FIX: guard [skip circle] [skip azp]
scott-huberty Apr 29, 2026
132aa53
Merge remote-tracking branch 'upstream/main' into pixi [skip circle] …
scott-huberty May 2, 2026
1b0b26f
restore pixi [skip circle] [skip azp]
scott-huberty May 2, 2026
3a031ba
add pixi to verify python [skip circle] [skip azp]
scott-huberty May 2, 2026
1cfaeb5
pixi path [skip circle] [skip azp]
scott-huberty May 2, 2026
b7971c3
fix syntax [skip circle] [skip azp]
scott-huberty May 2, 2026
105f23a
doh [skip circle] [skip azp]
scott-huberty May 2, 2026
ca4ba7f
udpate lockfile to match want python
scott-huberty May 2, 2026
5130043
skip [skip azp] [skip circle]
scott-huberty May 2, 2026
0cc9aa8
handle pypi deps
scott-huberty Jun 3, 2026
471efe4
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 3, 2026
2dc89ca
convert pip-style specifiers to dict
drammock Jun 3, 2026
e53eae5
write to correct file loc
drammock Jun 10, 2026
8a352cf
fix pypi/cf name mismatch; comments
drammock Jun 10, 2026
fd1f275
regen toml and lock files
drammock Jun 10, 2026
c221707
add macos-intel pixi ci lockfile update to spec-zero workflow
drammock Jun 10, 2026
e70b44d
update lockfile (again)
drammock Jun 10, 2026
c8628ba
bump py
drammock Jun 24, 2026
a0b21d4
skip gh_actions_deps.sh for pixi
drammock Jun 24, 2026
814e1d1
[skip circle][skip azp] specify python version
scott-huberty Jul 9, 2026
5739306
Merge branch 'main' into pixi
scott-huberty Jul 9, 2026
1f9e87d
update pixi toml/lock
scott-huberty Jul 9, 2026
bd5538e
[circle skip][skip azp] need pyside6
scott-huberty Jul 9, 2026
d805238
Dont set MNE_TEST_ALLOW_SKIP in Pixi job
scott-huberty Jul 9, 2026
181f76b
merge
scott-huberty Jul 22, 2026
8bc139b
regen pixi toml/lock
scott-huberty Jul 22, 2026
e5bd471
comment
scott-huberty Jul 27, 2026
a62727c
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 27, 2026
9cd7b0d
ping
scott-huberty Jul 27, 2026
a7f21c7
Merge branch 'pixi' of github.com:scott-huberty/mne-python into pixi
scott-huberty Jul 27, 2026
8a00162
ping
scott-huberty Jul 27, 2026
179229b
Merge remote-tracking branch 'upstream/main' into pixi
scott-huberty Jul 29, 2026
e4dbfc3
Apply suggestion from @drammock
drammock Jul 29, 2026
cef741d
try...
scott-huberty Jul 29, 2026
cbc7847
flag
scott-huberty Jul 29, 2026
da2988d
fix
scott-huberty Jul 29, 2026
29565b9
fix
scott-huberty Jul 29, 2026
949c14f
try manifest path
scott-huberty Aug 5, 2026
371fefa
WIP: force mne directory
scott-huberty Aug 5, 2026
649ef49
WIP: remove step to add mne dev dep in pixi job
scott-huberty Aug 5, 2026
dc692c3
remove lock file
scott-huberty Aug 7, 2026
d2bc0bc
try moving mne-qt-browser to pypi channel
scott-huberty Aug 12, 2026
6dd3350
Merge remote-tracking branch 'upstream/main' into pixi
scott-huberty Aug 12, 2026
16c7db7
move mne-qt-browser to pypi channel
scott-huberty Aug 12, 2026
e87d8cb
Merge remote-tracking branch 'upstream/main' into pixi
scott-huberty Aug 12, 2026
1e17ea4
add lockfile back [circle skip]
scott-huberty Aug 12, 2026
7042a70
strip down to a single setup pixi [circle skip]
scott-huberty Aug 12, 2026
777737c
clean up
scott-huberty Aug 12, 2026
2e7827a
rm cruft comments
scott-huberty Aug 13, 2026
495caf5
Merge branch 'main' into pixi
scott-huberty Aug 13, 2026
4f24eab
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 13, 2026
1ed6217
ping
scott-huberty Aug 13, 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
8 changes: 8 additions & 0 deletions .github/workflows/scheduled_updates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ jobs:
echo "dirty=true" >> $GITHUB_OUTPUT
fi
id: status
- name: Setup Pixi
uses: prefix-dev/setup-pixi@v0.9.4
if: steps.status.outputs.dirty == 'true'
- name: Update pixi.toml and pixi.lock for macos-intel CI job
run: |
pixi run python tools/write-pixi-toml.py
pixi lock --no-install --manifest-path tools/ci/macos-intel/
if: steps.status.outputs.dirty == 'true'
Comment thread
drammock marked this conversation as resolved.
- uses: j178/prek-action@v3.0.0
if: steps.status.outputs.dirty == 'true'
- name: Create PR
Expand Down
24 changes: 21 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
kind: pip
- os: macos-15-intel # Intel
python: '3.13'
kind: pip
kind: pixi
- os: ubuntu-latest
python: '3.12'
kind: minimal
Expand Down Expand Up @@ -104,9 +104,26 @@ jobs:
python-version: ${{ matrix.python }}
if: startswith(matrix.kind, 'pip') || matrix.kind == 'minimal'
id: setup-python
# Python (if pixi)
- uses: prefix-dev/setup-pixi@v0.10.0
with:
manifest-path: tools/ci/macos-intel/pixi.toml
# https://github.com/prefix-dev/setup-pixi/issues/139
activate-environment: true
frozen: true
if: matrix.kind == 'pixi'
# Workaround macOS path behavior with login shells (which puts system Python first)
- run: echo "export PATH=\"$(dirname ${{ steps.setup-python.outputs.python-path }}):$PATH\"" | tee -a ~/.bash_profile # zizmor: ignore[template-injection]
if: startswith(matrix.kind, 'pip') && startswith(matrix.os, 'macos')
- run: | # zizmor: ignore[template-injection]
if [[ $MNE_CI_KIND == "pip" ]]; then
prepend_path="$(dirname ${{ steps.setup-python.outputs.python-path }})"
elif [[ $MNE_CI_KIND == "pixi" ]]; then
prepend_path="${{ github.workspace }}/tools/ci/macos-intel/.pixi/envs/default/bin"
else
echo "Unsupported CI Kind: $MNE_CI_KIND"
exit 1
fi
echo "export PATH=\"$prepend_path:$PATH\"" | tee -a ~/.bash_profile
if: (startswith(matrix.kind, 'pip') || matrix.kind == 'pixi') && startswith(matrix.os, 'macos')
# Python (if conda)
- uses: mamba-org/setup-micromamba@v3
with:
Expand All @@ -130,6 +147,7 @@ jobs:
- run: bash ./tools/github_actions_verify_python.sh "${{ matrix.python }}"
- run: bash ./tools/github_actions_dependencies.sh
timeout-minutes: 10
if: matrix.kind != 'pixi'
- name: Check 'old' CI environment
uses: mne-tools/mne-tools/actions/check-environment@main
with:
Expand Down
7,371 changes: 7,371 additions & 0 deletions tools/ci/macos-intel/pixi.lock

Large diffs are not rendered by default.

91 changes: 91 additions & 0 deletions tools/ci/macos-intel/pixi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# THIS FILE IS AUTO-GENERATED BY tools/write_pixi_toml.py AND WILL BE OVERWRITTEN

[workspace]
Comment thread
drammock marked this conversation as resolved.
authors = ["MNE-Python contributors"]
channels = ["conda-forge"]
name = "mne"
platforms = ["osx-64"]
version = "0.1.0"

[dependencies]
antio = ">=0.5.0"
codespell = "*"
curryreader = ">=0.1.2"
darkdetect = "*"
decorator = ">=5.1"
defusedxml = "*"
dipy = ">=1.9"
edfio = ">=0.4.10"
eeglabio = "*"
filelock = ">=3.18.0"
h5io = ">=0.2.4"
h5py = ">=2.4"
imageio = ">=2.6.1"
imageio-ffmpeg = ">=0.4.1"
ipyevents = "*"
ipympl = "*"
ipython = ">=8.20"
ipywidgets = "*"
jinja2 = ">=3.1"
joblib = ">=0.8"
jupyter = "*"
jupyter_client = "*"
lazy_loader = ">=0.3"
matplotlib = ">=3.9"
mffpy = ">=0.11.0"
nbclient = "*"
nest-asyncio2 = "*"
nibabel = ">=5.2"
nilearn = ">=0.10"
nitime = ">=0.7"
numba = ">=0.60"
numpy = "<3,>=2.0"
numpydoc = ">=1.6"
openmeeg = ">=2.5.7"
packaging = "*"
pandas = "!=3.0.4,>=2.2"
pillow = ">=10.2"
pip = ">=25.1"
pooch = ">=1.5"
pre-commit = "*"
pyarrow = "*"
pybv = "*"
pymatreader = "*"
pyobjc-framework-Cocoa = ">=5.2.0"
pyside6 = ">=6.11.1"
pytest = "!=9.1.0,>=8.0"
pytest-cov = ">=4.1"
pytest-qt = ">=4.3"
pytest-rerunfailures = "*"
pytest-timeout = ">=2.2"
pytest-xdist = ">=3.6.1"
python-neo = "*"
python-picard = ">=0.4"
pyvista = ">=0.44"
pyvistaqt = ">=0.11"
qdarkstyle = "!=3.2.2"
qtpy = "*"
rcssmin = ">=1.1"
refleak = ">=0.2.1"
ruff = ">=0.1"
scikit-learn = ">=1.5"
scipy = ">=1.14"
sip = "*"
snirf = "*"
statsmodels = ">=0.6"
threadpoolctl = "*"
tqdm = ">=4.66"
traitlets = "*"
trame = "*"
trame-pyvista = "*"
trame-vtk = "*"
trame-vuetify = "!=3.2.3"
twine = "*"
vtk = ">=9.2"
vulture = "*"
xlrd = "*"
python = "3.13.*"

[pypi-dependencies]
mne-qt-browser = "*"
pymef = "*"
8 changes: 8 additions & 0 deletions tools/github_actions_env_vars.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ elif [[ "$MNE_CI_KIND" == "conda" ]]; then
echo "MNE_LOGGING_LEVEL=warning" | tee -a $GITHUB_ENV
echo "MNE_TEST_ALLOW_SKIP=.*(on conda|Requires (spm|brainstorm|misc) dataset|CUDA not|Flakey verbose behavior|PySide6 causes segfaults|SCIPY_ARRAY_API).*" | tee -a $GITHUB_ENV
echo "MNE_QT_BACKEND=PySide6" | tee -a $GITHUB_ENV
elif [[ "$MNE_CI_KIND" == "pixi" ]]; then
echo "Setting env vars for $MNE_CI_KIND"
echo "MNE_LOGGING_LEVEL=warning" | tee -a $GITHUB_ENV
echo "MNE_QT_BACKEND=PySide6" | tee -a $GITHUB_ENV
# Our cache_dir test has problems when the path is too long, so prevent it from getting too long
if [[ "$RUNNER_OS" == "macOS" ]]; then
echo "PYTEST_DEBUG_TEMPROOT=/tmp" | tee -a $GITHUB_ENV
fi
else
echo "✕ ERROR: Unrecognized MNE_CI_KIND=${MNE_CI_KIND}"
exit 1
Expand Down
2 changes: 2 additions & 0 deletions tools/github_actions_verify_python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ elif [[ "${MNE_CI_KIND}" == "old" ]]; then
WANT="mne-python/mne-python/.venv/bin"
elif [[ "${MNE_CI_KIND}" == 'pip'* ]] || [[ "${MNE_CI_KIND}" == "minimal" ]]; then
WANT="/hostedtoolcache/"
elif [[ "${MNE_CI_KIND}" == "pixi" ]]; then
WANT="mne-python/mne-python/tools/ci/macos-intel/.pixi/"
else
echo "✕ ERROR: Unrecognized MNE_CI_KIND=${MNE_CI_KIND}"
exit 1
Expand Down
102 changes: 102 additions & 0 deletions tools/write-pixi-toml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

from pathlib import Path

import tomlkit
import yaml
from packaging.requirements import Requirement


def pip_to_pixi(dependencies_list):
"""Convert pip dependency specifier strings to a pixi-style dict."""
out = dict()
for dep in dependencies_list:
out[dep.name] = str(dep.specifier) if str(dep.specifier) != "" else "*"
return out
Comment thread
drammock marked this conversation as resolved.


pypi_dependencies = sorted(["mne-qt-browser", "pymef"])

repo_root = Path(__file__).resolve().parent.parent
tests_yaml_fpath = repo_root / ".github" / "workflows" / "tests.yml"
pyproject_fpath = repo_root / "pyproject.toml"
pyproject = tomlkit.loads(pyproject_fpath.read_bytes())
outfile = repo_root / "tools" / "ci" / "macos-intel" / "pixi.toml"

# handle naming differences between PyPI and conda-forge
remapping = dict(neo="python-neo")

# Specify the python version that our pixi job wants
with open(tests_yaml_fpath) as fid:
test_yaml = yaml.safe_load(fid)

foo = test_yaml["jobs"]["pytest"]["strategy"]["matrix"]["include"]
for job in foo:
if job["os"] == "macos-15-intel":
python_version = job["python"]
# Pixi complains if we don't specify a patch version
if len(python_version.split(".")) <= 2:
python_version += ".*"
break

# in keys: build-system, dependency-groups, project, tool
# out keys: workspace, dependencies, pypi-dependencies (may need tasks)
out = dict()
workspace = dict(
authors=["MNE-Python contributors"],
channels=["conda-forge"],
name=pyproject["project"]["name"],
platforms=["osx-64"],
version="0.1.0",
)
dependencies = pyproject["project"]["dependencies"]
dependencies.extend(pyproject["dependency-groups"]["dev"])
dependencies.extend(pyproject["dependency-groups"]["test"])
dependencies.extend(pyproject["dependency-groups"]["test_extra"])
dependencies.extend(pyproject["project"]["optional-dependencies"]["hdf5"])
dependencies.extend(pyproject["project"]["optional-dependencies"]["full-no-qt"])
dependencies.extend(pyproject["project"]["optional-dependencies"]["full-pyside6"])
# exclude recursive MNE deps
dependencies = list(
filter(lambda x: isinstance(x, str) and "mne[" not in x, dependencies)
)
# strip out platform specifiers; for now this affects only pyobj-framework-cocoa, and
# since this pixi.toml is destined for macos-intel job, we want it in there so we're
# skipping writing the logic to parse the platform spec.
for ix, dep in enumerate(dependencies):
if (split_ix := dep.find(";")) >= 0:
dependencies[ix] = dep[:split_ix].strip()
# handle mismatch between names on PyPI and conda-forge
dependencies = [remapping.get(dep, dep) for dep in dependencies]
dependencies.sort()

# exclude pypi-only deps
dependencies = [Requirement(dep) for dep in dependencies]
pypi_dependencies = [Requirement(dep) for dep in pypi_dependencies]

dependencies = [
dep
for dep in dependencies
if dep.name not in {pdep.name for pdep in pypi_dependencies}
]

out = {
"workspace": workspace,
"dependencies": pip_to_pixi(dependencies),
"pypi-dependencies": pip_to_pixi(pypi_dependencies),
}
out["dependencies"].update(python=python_version)

doc = tomlkit.document()
doc.add(
tomlkit.comment(
"THIS FILE IS AUTO-GENERATED BY tools/write_pixi_toml.py AND WILL BE OVERWRITTEN" # noqa E501
)
)
doc.update(out)
# write the file
outfile.parent.mkdir(parents=True, exist_ok=True)
with open(outfile, "w") as fid:
tomlkit.dump(doc, fid, sort_keys=False)
Loading