From 131c241bfd22edef02074af9713d2c2b6f62c0ea Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Mon, 22 Jan 2024 14:53:42 +0100 Subject: [PATCH 1/3] Reimplement 'portable' installer without conda [skip cirrus] --- .github/workflows/build-conda-installer.yml | 39 ------ .github/workflows/build-win-portable.yml | 125 ++++++++++++++++++++ ci/appveyor-make-portable.bat | 66 ----------- scripts/windows/build-win-portable.sh | 125 ++++++++++++++++++++ {ci => scripts/windows}/create_shortcut.py | 0 {ci => scripts/windows}/orangerc.conf | 0 6 files changed, 250 insertions(+), 105 deletions(-) create mode 100644 .github/workflows/build-win-portable.yml delete mode 100644 ci/appveyor-make-portable.bat create mode 100755 scripts/windows/build-win-portable.sh rename {ci => scripts/windows}/create_shortcut.py (100%) rename {ci => scripts/windows}/orangerc.conf (100%) diff --git a/.github/workflows/build-conda-installer.yml b/.github/workflows/build-conda-installer.yml index 4e50d3d..3f7a103 100644 --- a/.github/workflows/build-conda-installer.yml +++ b/.github/workflows/build-conda-installer.yml @@ -166,42 +166,3 @@ jobs: D:\test-install\Scripts\conda.bat info D:\test-install\Scripts\activate.bat echo %CONDA_PREFIX% - - package_portable: - name: Package a portable install - needs: [build, test] - runs-on: windows-2019 - steps: - - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - - name: Download installer - uses: actions/download-artifact@v3 - with: - name: orange-win-conda-installer - - - name: Extract installer contents - shell: cmd - run: | - rem # Install in silent mode. Output has to be piped somewhere so the installer - rem # runs 'attached' to the console. - for %%s in ( Orange3*.exe ) do ( set "INSTALLER=%%s" ) - echo INSTALLER = %INSTALLER% - %INSTALLER% /S /D=D:\test-install > nul - - - name: Package portable installer - shell: cmd - run: | - mkdir dist - ci\appveyor-make-portable.bat D:\test-install %CD%\dist\Orange.zip - - - name: Upload portable installer - uses: actions/upload-artifact@v4 - with: - name: orange-win-portable-installer - path: dist/Orange*.zip - if-no-files-found: error diff --git a/.github/workflows/build-win-portable.yml b/.github/workflows/build-win-portable.yml new file mode 100644 index 0000000..c2e4503 --- /dev/null +++ b/.github/workflows/build-win-portable.yml @@ -0,0 +1,125 @@ +name : Build Windows Portable Installer + +on: + pull_request: + workflow_dispatch: + push: + branches: + - 'master' + - 'releases/**' + - 'testing/**' + +jobs: + build: + runs-on: windows-2019 + timeout-minutes: 30 + env: + REPO: https://github.com/biolab/orange3.git + BUILD_BRANCH: master + BUILD_COMMIT: FETCH_HEAD + BUILD_LOCAL: 1 + + PYTHONFAULTHANDLER: 1 + PIP_NO_PIP_VERSION_CHECK: 1 + PIP_CACHE_DIR: .pip-cache + PIP_PREFER_BINARY: 1 + + BUILD_DEPS: "wheel~=0.37.0 pip~=23.2.1" + ENVSPEC: ./specs/win/PY310.txt + + strategy: + fail-fast: False + matrix: + include: + - python-version: "3.10.11" + + steps: + - uses: actions/checkout@v3 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Checkout orange3 + shell: bash + run: | + set -e + git clone -q $REPO + cd orange3 + git fetch origin $BUILD_BRANCH + git checkout $BUILD_COMMIT + + - name: Setup Pip Cache + uses: actions/cache@v3 + with: + path: .pip-cache + key: ${{ runner.os }}-py-${{ matrix.python-version }}-pip-${{ hashFiles('.github/workflows/build-win-portable.yml') }} + restore-keys: | + ${{ runner.os }}-py-${{ matrix.python-version }}-pip + + - name: Prepare wheels + shell: bash + run: | + python -m pip install $BUILD_DEPS + if [[ $BUILD_LOCAL ]]; then + PIP_ARGS=( -r $ENVSPEC ./orange3 ); + else + PIP_ARGS=( -r $ENVSPEC Orange3==$BUILD_COMMIT ); + fi + python -m pip wheel -w ./wheels -f ./wheels "${PIP_ARGS[@]}" orange3 + ls ./wheels + + - name: Build installer + shell: bash + env: + PYTHON_VERSION: ${{ matrix.python-version }} + run: | + export PATH="$(cygpath -u C:\\msys64\\usr\\bin):$PATH" + echo PATH=$PATH + mkdir dist + + ./scripts/windows/build-win-portable.sh --no-index --find-links=./wheels --python-version $PYTHON_VERSION --pip-arg=--pre --pip-arg=-r --pip-arg=$ENVSPEC --pip-arg=Orange3 + + INSTALLER=( dist/Orange*.zip ) + SHA256=$( sha256sum -b $INSTALLER ) + echo INSTALLER = $INSTALLER + echo SHA256 = $( sha256sum -b $INSTALLER ) + + - name: Upload installer + uses: actions/upload-artifact@v4 + with: + name: orange-win-portable-installer + path: dist/Orange*.zip + if-no-files-found: error + + test: + name: Test + needs: build + runs-on: windows-2019 + steps: + - name: Download installer + uses: actions/download-artifact@v4 + with: + name: orange-win-portable-installer + + - name: Install + shell: bash + run: | + 7z x "-oD:\\test-install" Orange*.zip + - name: Run tests + shell: bash + run: | + PYTHON=$(cygpath -u "D:\\test-install\\Orange\\python.exe") + $PYTHON --version + $PYTHON -m pip --version + $PYTHON -m pip list --format=freeze + # Test that orange and all dependencies are installed in a + # consistent state + $PYTHON -m pip install --no-index --no-cache-dir orange3 + + # Run test suite in the installed environment. + export ORANGE_DEPRECATIONS_ERROR=1 + export PYTHONWARNINGS=module + + $PYTHON -m unittest -v Orange.tests Orange.widgets.tests diff --git a/ci/appveyor-make-portable.bat b/ci/appveyor-make-portable.bat deleted file mode 100644 index acf291e..0000000 --- a/ci/appveyor-make-portable.bat +++ /dev/null @@ -1,66 +0,0 @@ -setlocal - -rem Install prefix -set "PREFIX=%~1" - -rem Output filename -set "OUTPUT=%~2" -set "__PATH=%PATH%" - -set "PATH=C:\Python37-x64;C:\msys64\usr\bin;%PATH%" -python -m pip install pywin32 - -set "THISHEREDIR=%~dp0" -set "TEMP=%CD%\temp\Orange" -mkdir "%TEMP%" - -xcopy /q /s /i "%PREFIX%" "%TEMP%" -del "%TEMP%\Orange-Uninstall.exe" -del "%TEMP%\Orange Command Prompt.lnk" -del "%TEMP%\Scripts\conda.bat" -del "%TEMP%\Scripts\activate.bat" - -set "QT_CONF=%TEMP%\qt.conf" -echo [Paths]> "%QT_CONF%" -echo Prefix = ./Library>> "%QT_CONF%" -echo Binaries = ./Library/bin>> "%QT_CONF%" -echo Libraries = ./Library/lib>> "%QT_CONF%" -echo Headers = ./Library/include/qt>> "%QT_CONF%" - -set "QT_CONF=%TEMP%\Library\bin\qt.conf" -echo [Paths]> "%QT_CONF%" -echo Prefix = ../>> "%QT_CONF%" -echo Binaries = ../bin>> "%QT_CONF%" -echo Libraries = ../lib>> "%QT_CONF%" -echo Headers = ../include/qt>> "%QT_CONF%" - -mkdir "%TEMP%\etc" -copy "%THISHEREDIR%\orangerc.conf" "%TEMP%\etc\orangerc.conf" - -python "%THISHEREDIR%\create_shortcut.py" ^ - --target %%COMSPEC%% ^ - --arguments "/C start pythonw.exe -m Orange.canvas" ^ - --working-directory "" ^ - --window-style Minimized ^ - --shortcut "%TEMP%\Orange.lnk" - -python "%THISHEREDIR%\create_shortcut.py" ^ - --target %%COMSPEC%% ^ - --arguments "/K python.exe -m Orange.canvas -l4" ^ - --working-directory "" ^ - --shortcut "%TEMP%\Orange Debug.lnk" - -python "%THISHEREDIR%\create_shortcut.py" ^ - --target %%COMSPEC%% ^ - --arguments "/C start Orange\pythonw.exe -m Orange.canvas" ^ - --working-directory "" ^ - --window-style Minimized ^ - --shortcut "%TEMP%\..\Orange.lnk" - - -pushd "%TEMP%\.." -zip --quiet -9 -r temp.zip Orange Orange.lnk -x 'Orange/pkgs/*' '*.pyc' '*.pyo' '*/__pycache__/*'' -popd - -move /y "%TEMP%\..\temp.zip" "%OUTPUT%" -set "PATH=%__PATH%" diff --git a/scripts/windows/build-win-portable.sh b/scripts/windows/build-win-portable.sh new file mode 100755 index 0000000..13f8dde --- /dev/null +++ b/scripts/windows/build-win-portable.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +NAME=Orange3 + +BUILDBASE=./build +DISTDIR=./dist +CACHEDIR=build/download-cache + +PIP_INDEX_ARGS=() +PIP_ARGS=() + +PYTHON_VERSION=${PYTHON_VERSION:-"3.10.11"} + + +while [[ "${1:0:1}" = "-" ]]; do + case $1 in + -b|--build-base) + BUILDBASE=${2:?}; shift 2;; + --build-base=*) + BUILDBASE=${1#*=}; shift 1;; + -d|--dist-dir) + DISTDIR=${2:?}; shift 2;; + --dist-dir=*) + DISTDIR=${1#*=}; shift 1;; + --cache-dir) + CACHEDIR=${2:?}; shift 2;; + --cache-dir=*) + CACHEDIR=${1#*=}; shift 1;; + --python-version) + PYTHON_VERSION=${2:?}; shift 2;; + --python-version=*) + PYTHON_VERSION=${1#*=}; shift 1;; + -f|--find-links) + PIP_INDEX_ARGS+=(--find-links "${2:?}"); shift 2;; + --find-links=*) + PIP_INDEX_ARGS+=(--find-links "${1#*=}"); shift 1;; + --extra-index-url) + PIP_INDEX_ARGS+=(--extra-index-url "${2:?}"); shift 2;; + --extra-index-url=*) + PIP_INDEX_ARGS+=(--extra-index-url "${1#*=}"); shift 1;; + --no-index) + PIP_INDEX_ARGS+=( --no-index ); shift 1;; + --pip-arg) + PIP_ARGS+=( "${2:?}" ); shift 2;; + --pip-arg=*) + PIP_ARGS+=( "${1#*=}" ); shift 1;; + -h|--help) + usage; exit 0;; + -*) + echo "Unknown option: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +DIR=$(dirname "$0") +BUILDDIR="${BUILDBASE}/build/Orange" +PYTHON_NUPKG="${CACHEDIR}/python-${PYTHON_VERSION}.nupkg" + +function download { + local url=${1:?} + local dest=${2:?} + local tmpname="" + mkdir -p $(dirname "${dest}") + if [[ ! -f "${dest}" ]]; then + tmpname=$(mktemp "${dest}.XXXXX") + if curl -fSL -o "${tmpname}" "${url}"; then + mv "${tmpname}" "${dest}" + else + return $? + fi + fi +} + + +download https://www.nuget.org/api/v2/package/python/${PYTHON_VERSION} \ + "${PYTHON_NUPKG}" + +if [[ -e "${BUILDDIR}" ]]; then + rm -r "${BUILDDIR}" +fi + +7z x '-i!tools' -y -o"${BUILDBASE}/tmp" "${PYTHON_NUPKG}" +mkdir -p $(dirname "${BUILDDIR}") +mv "${BUILDBASE}/tmp/tools" "${BUILDDIR}" + +PYTHON="${BUILDDIR}/python.exe" + +"${PYTHON}" -m ensurepip +"${PYTHON}" -m pip install "pip==23.3.*" wheel +"${PYTHON}" -m pip install "${PIP_INDEX_ARGS[@]}" "${PIP_ARGS[@]}" + +mkdir -p "${BUILDDIR}/etc" +cp "${DIR}/orangerc.conf" "${BUILDDIR}/etc/orangerc.conf" + +BUILDDIR_WIN="$(cygpath -w "${BUILDDIR}")" + +python -m pip install pywin32 +python "${DIR}/create_shortcut.py" \ + --target '%COMSPEC%' \ + --arguments '"/C start pythonw.exe -m Orange.canvas"' \ + --working-directory "" \ + --window-style Minimized \ + --shortcut "${BUILDDIR_WIN}\Orange.lnk" + +python "${DIR}/create_shortcut.py" \ + --target '%COMSPEC%' \ + --arguments '"/K python.exe -m Orange.canvas -l4"' \ + --working-directory "" \ + --shortcut "${BUILDDIR_WIN}/Orange Debug.lnk" + +python "${DIR}/create_shortcut.py" \ + --target '%COMSPEC%' \ + --arguments '"/C start Orange\\pythonw.exe -m Orange.canvas"' \ + --working-directory "" \ + --window-style Minimized \ + --shortcut "${BUILDDIR_WIN}/../Orange.lnk" + +pushd "${BUILDBASE}/build" +zip --quiet -9 -r temp.zip Orange Orange.lnk -x '*.pyc' '*.pyo' '*/__pycache__/*' +popd +VERSION=$("${PYTHON}" -m pip show Orange3 | grep Version: | cut -d " " -f2) + +mv -f "${BUILDBASE}/build/temp.zip" "${DISTDIR}"/"${NAME}-${VERSION}.zip" diff --git a/ci/create_shortcut.py b/scripts/windows/create_shortcut.py similarity index 100% rename from ci/create_shortcut.py rename to scripts/windows/create_shortcut.py diff --git a/ci/orangerc.conf b/scripts/windows/orangerc.conf similarity index 100% rename from ci/orangerc.conf rename to scripts/windows/orangerc.conf From 72d8f90d70d88c3647724072dfdafd63b4fff93c Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Mon, 22 Jan 2024 14:53:42 +0100 Subject: [PATCH 2/3] Replace %COMSPEC% with cmd.exe [skip cirrus] --- scripts/windows/build-win-portable.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/windows/build-win-portable.sh b/scripts/windows/build-win-portable.sh index 13f8dde..ce61340 100755 --- a/scripts/windows/build-win-portable.sh +++ b/scripts/windows/build-win-portable.sh @@ -98,21 +98,21 @@ BUILDDIR_WIN="$(cygpath -w "${BUILDDIR}")" python -m pip install pywin32 python "${DIR}/create_shortcut.py" \ - --target '%COMSPEC%' \ + --target 'cmd.exe' \ --arguments '"/C start pythonw.exe -m Orange.canvas"' \ --working-directory "" \ --window-style Minimized \ --shortcut "${BUILDDIR_WIN}\Orange.lnk" python "${DIR}/create_shortcut.py" \ - --target '%COMSPEC%' \ + --target 'cmd.exe' \ --arguments '"/K python.exe -m Orange.canvas -l4"' \ --working-directory "" \ --shortcut "${BUILDDIR_WIN}/Orange Debug.lnk" python "${DIR}/create_shortcut.py" \ - --target '%COMSPEC%' \ - --arguments '"/C start Orange\\pythonw.exe -m Orange.canvas"' \ + --target 'cmd.exe' \ + --arguments '"/C start Orange\pythonw.exe -m Orange.canvas"' \ --working-directory "" \ --window-style Minimized \ --shortcut "${BUILDDIR_WIN}/../Orange.lnk" From e6a1260d0d2c76773f9409d0e8fc033b81daa22d Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Tue, 23 Jan 2024 14:02:11 +0100 Subject: [PATCH 3/3] build-win-portable.sh: Add a global env pip config file [skip cirrus] --- scripts/windows/build-win-portable.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/windows/build-win-portable.sh b/scripts/windows/build-win-portable.sh index ce61340..764b77c 100755 --- a/scripts/windows/build-win-portable.sh +++ b/scripts/windows/build-win-portable.sh @@ -118,6 +118,10 @@ python "${DIR}/create_shortcut.py" \ --shortcut "${BUILDDIR_WIN}/../Orange.lnk" pushd "${BUILDBASE}/build" + +echo [global] > Orange/pip.ini +echo prefer-binary=1 >> Orange/pip.ini + zip --quiet -9 -r temp.zip Orange Orange.lnk -x '*.pyc' '*.pyo' '*/__pycache__/*' popd VERSION=$("${PYTHON}" -m pip show Orange3 | grep Version: | cut -d " " -f2)