diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d6235dc..c4384b8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -91,10 +91,16 @@ jobs: - name: Extract MNE_INSTALLER_VERSION shell: bash -el {0} run: | - VERSION=$(head -n 1 recipes/mne-python_1.0/construct.yaml | cut -d' ' -f2) - echo "Version: ${VERSION}" - echo "MNE_INSTALLER_VERSION=${VERSION}" >> $GITHUB_ENV - test "$VERSION" != "" + source ./tools/extract_version.sh + echo "Version: ${MNE_INSTALLER_VERSION} (Python=${PYSHORT})" + test "$MNE_INSTALLER_VERSION" != "" + test "$PYSHORT" != "" + test -d "$SCRIPT_DIR" + echo "Recipe: ${RECIPE_DIR}" + test "$RECIPE_DIR" != "" + test -d "$RECIPE_DIR" + echo "MNE_INSTALLER_VERSION=${MNE_INSTALLER_VERSION}" >> $GITHUB_ENV + echo "RECIPE_DIR=${RECIPE_DIR}" >> $GITHUB_ENV - name: Install Micromamba uses: mamba-org/provision-with-micromamba@main @@ -102,19 +108,16 @@ jobs: environment-file: environment.yml micromamba-version: latest - - name: Patch constructor (macOS) - if: ${{ runner.os == 'macOS' }} + - name: Patch constructor shell: bash -el {0} run: | - export PATCH_PATH=`python -c "import pathlib; print(pathlib.Path('./assets/constructor_macOS.patch').resolve())"` - cd $CONDA_PREFIX/lib/python3.9/site-packages/constructor - patch -p1 < ${PATCH_PATH} + ./tools/patch_constructor.sh - name: Patch config (macOS pull request) - if: ${{ runner.os == 'macOS' && github.event_name == 'pull_request' }} + if: ${{ runner.os == 'macOS' && github.event_name != 'pull_request' }} shell: bash -el {0} run: | - sed -i "" "s/9779L28NP8//" recipes/mne-python_1.0/construct.yaml + sed -i "" "s/_name: *# \[osx\]/_name: 9779L28NP8 # \[osx\]/" ${RECIPE_DIR}/construct.yaml - name: Build installer shell: bash -el {0} @@ -123,7 +126,7 @@ jobs: # if something has gone wrong with dependency resolution. timeout-minutes: 20 run: | - PYTHONUTF8=1 constructor recipes/mne-python_1.0 # enforce UTF-8 encoding when reading files even on Windows + ./tools/run_constructor.sh - name: Check installer signature (macOS) if: ${{ runner.os == 'macOS' && github.event_name != 'pull_request' }} diff --git a/README.md b/README.md index 1d6cb79e..ad72d330 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,16 @@ Installers for MNE-Python for macOS, Windows, and Linux. Installer running on macOS Please visit [the installers section of the MNE documentation](https://mne.tools/dev/install/installers.html) for instructions on how to use them. + +## Development + +Locally, installers can be built using `tools/build_local.sh`. Steps: + +1. Set up and activate a `conda` env with a forked version of `constructor`: + ```console + $ conda env create -f environment.yml + $ conda activate constructor-env + ``` +2. Run `./tools/build_local.sh` (which will patch the constructor on macOS if needed) +3. Install the environment for your platform +4. Test it using the `tests/` diff --git a/assets/current_version.txt b/assets/current_version.txt new file mode 100644 index 00000000..9f8e9b69 --- /dev/null +++ b/assets/current_version.txt @@ -0,0 +1 @@ +1.0 \ No newline at end of file diff --git a/recipes/mne-python_1.0/construct.yaml b/recipes/mne-python_1.0/construct.yaml index 986d576b..553180ca 100644 --- a/recipes/mne-python_1.0/construct.yaml +++ b/recipes/mne-python_1.0/construct.yaml @@ -1,6 +1,8 @@ version: 1.0.3_0 name: MNE-Python company: MNE-Python Developers +# When the version above changes to a new major/minor, it needs to be updated +# many places here, and in assets/current_version.txt. license_file: ../../assets/license.txt # [linux] license_file: ../../assets/license.rtf # [not linux] @@ -33,8 +35,8 @@ post_install: ../../assets/post_install_windows.bat # [win] # Create signed macOS .pkg installer installer_type: pkg # [osx] -signing_identity_name: 9779L28NP8 # [osx] Used for productsign -notarization_identity_name: 9779L28NP8 # [osx] Used for codesign +signing_identity_name: # [osx] Used for productsign +notarization_identity_name: # [osx] Used for codesign reverse_domain_identifier: tools.mne # [osx] Used for productbuild --identifier $reverse_domain_identifier.$name # Only create menus for mne-installer-menus diff --git a/tests/test_json_versions.py b/tests/test_json_versions.py index dbf5b535..f939aecc 100644 --- a/tests/test_json_versions.py +++ b/tests/test_json_versions.py @@ -14,7 +14,9 @@ win32='Windows', )[sys.platform] -with open(dir_ / 'recipes' / 'mne-python_1.0' / 'construct.yaml', +with open(dir_ / 'assets' / 'current_version.txt') as fid: + ver = fid.read().strip() +with open(dir_ / 'recipes' / f'mne-python_{ver}' / 'construct.yaml', encoding='utf-8') as fid: params = yaml.safe_load(fid) installer_version = params['version'] diff --git a/tools/build_local.sh b/tools/build_local.sh new file mode 100755 index 00000000..dbbe2f24 --- /dev/null +++ b/tools/build_local.sh @@ -0,0 +1,12 @@ +#!/bin/bash -ef + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; +source ${SCRIPT_DIR}/extract_version.sh +echo "Building installer locally" +echo "--------------------------" +echo "Version: ${MNE_INSTALLER_VERSION}" +echo "Recipe: ${RECIPE_DIR}" +echo "OS: ${MACHINE}" +echo "Architecture: ${PYARCH}" +${SCRIPT_DIR}/patch_constructor.sh +${SCRIPT_DIR}/run_constructor.sh diff --git a/tools/extract_version.sh b/tools/extract_version.sh new file mode 100755 index 00000000..34a4355e --- /dev/null +++ b/tools/extract_version.sh @@ -0,0 +1,21 @@ +#!/bin/bash -ef + +VER=$(cat assets/current_version.txt) +test VER != "" +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; +export MNE_INSTALLER_VERSION=$(head -n 1 recipes/mne-python_${VER}/construct.yaml | cut -d' ' -f2) +export RECIPE_DIR=${SCRIPT_DIR}/../recipes/mne-python_$(echo $MNE_INSTALLER_VERSION | cut -d . -f-2) +export PYSHORT=$(python -c "import sys; print('.'.join(map(str, sys.version_info[:2])))") +UNAME="$(uname -s)" +case "${UNAME}" in + Linux*) MACHINE=Linux;; + Darwin*) MACHINE=macOS;; + MINGW64_NT*) MACHINE=Windows;; + *) MACHINE="UNKNOWN:${UNAME}" +esac +if [[ "$MACHINE" != "macOS" && "$MACHINE" != "Linux" && "$MACHINE" != "Windows" ]]; then + echo "Unknown machine: ${UNAME}" + exit 1 +fi +export MACHINE=$MACHINE +export PYARCH=$(python -c "import platform; print(platform.architecture()[0])") diff --git a/tools/patch_constructor.sh b/tools/patch_constructor.sh new file mode 100755 index 00000000..3fd44485 --- /dev/null +++ b/tools/patch_constructor.sh @@ -0,0 +1,14 @@ +#!/bin/bash -ef + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; +source ${SCRIPT_DIR}/extract_version.sh +if [[ $MACHINE == "macOS" ]]; then + CONSTRUCTOR_DIR=${CONDA_PREFIX}/lib/python${PYSHORT}/site-packages/constructor + PATCHFILE=${SCRIPT_DIR}/../assets/constructor_macOS.patch + if ! patch -Rd ${CONSTRUCTOR_DIR} -p1 -s -f --dry-run < $PATCHFILE; then + echo "Patching constructor ${CONSTRUCTOR_DIR}..." + patch -Nd ${CONSTRUCTOR_DIR} -p1 < $PATCHFILE + else + echo "Constructor already patched: ${CONSTRUCTOR_DIR}" + fi +fi diff --git a/tools/run_constructor.sh b/tools/run_constructor.sh new file mode 100755 index 00000000..c4e799d8 --- /dev/null +++ b/tools/run_constructor.sh @@ -0,0 +1,8 @@ +#!/bin/bash -ef + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; +source ${SCRIPT_DIR}/extract_version.sh +export PYTHONUTF8=1 +# enforce UTF-8 encoding when reading files even on Windows +echo "Running constructor recipe ${RECIPE_DIR}" +constructor ${RECIPE_DIR}