Skip to content

Nightly conda-based installers #234

Nightly conda-based installers

Nightly conda-based installers #234

on:
pull_request:
paths:
- 'installers-conda/**'
- '.github/workflows/installers-conda.yml'
- 'requirements/*.yml'
- 'MANIFEST.in'
- '**.bat'
- '**.py'
- '**.sh'
- '!**.md'
release:
types:
- created
workflow_dispatch:
inputs:
pre:
description: 'Build as release candidate'
required: false
default: true
type: boolean
ssh:
description: 'Enable ssh debugging'
required: false
default: false
type: boolean
mac:
description: 'Build macOS installer'
required: false
default: true
type: boolean
linux:
description: 'Build Linux installer'
required: false
default: true
type: boolean
win:
description: 'Build Windows installer'
required: false
default: true
type: boolean
concurrency:
group: installers-conda-${{ github.ref }}
cancel-in-progress: true
name: Create conda-based installers for Windows, macOS, and Linux
env:
IS_STANDARD_PR: ${{ github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && ! inputs.pre) }}
IS_RELEASE: ${{ github.event_name == 'release' }}
IS_PRE: ${{ github.event_name == 'workflow_dispatch' && inputs.pre }}
BUILD_MAC: ${{ github.event_name != 'workflow_dispatch' || inputs.mac }}
BUILD_LNX: ${{ github.event_name != 'workflow_dispatch' || inputs.linux }}
BUILD_WIN: ${{ github.event_name != 'workflow_dispatch' || inputs.win }}
ENABLE_SSH: ${{ github.event_name == 'workflow_dispatch' && inputs.ssh }}
jobs:
build-matrix:
name: Determine Build Matrix
runs-on: ubuntu-latest
outputs:
target_platform: ${{ steps.build-matrix.outputs.target_platform }}
include: ${{ steps.build-matrix.outputs.include }}
python_version: ${{ steps.build-matrix.outputs.python_version }}
steps:
- name: Determine Build Matrix
id: build-matrix
run: |
if [[ $BUILD_MAC == "true" ]]; then
target_platform="'osx-64'"
include="{'os': 'macos-11', 'target-platform': 'osx-64'}"
fi
if [[ $BUILD_LNX == "true" ]]; then
target_platform=${target_platform:+"$target_platform, "}"'linux-64'"
include=${include:+"$include, "}"{'os': 'ubuntu-latest', 'target-platform': 'linux-64'}"
fi
if [[ $BUILD_WIN == "true" ]]; then
target_platform=${target_platform:+"$target_platform, "}"'win-64'"
include=${include:+"$include, "}"{'os': 'windows-latest', 'target-platform': 'win-64'}"
fi
python_version="'3.10'"
echo "target_platform=[$target_platform]" >> $GITHUB_OUTPUT
echo "include=[$include]" >> $GITHUB_OUTPUT
echo "python_version=[$python_version]" >> $GITHUB_OUTPUT
build-noarch-pkgs:
name: Build ${{ matrix.pkg }} Python-${{ matrix.python-version }}
runs-on: ubuntu-latest
needs:
- build-matrix
if: github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && ! inputs.pre)
strategy:
matrix:
pkg: ["python-lsp-server", "qtconsole"]
python-version: ${{fromJson(needs.build-matrix.outputs.python_version)}}
defaults:
run:
shell: bash -l {0}
working-directory: ${{ github.workspace }}/installers-conda
env:
DISTDIR: ${{ github.workspace }}/installers-conda/dist
pkg: ${{ matrix.pkg }}
artifact_name: ${{ matrix.pkg }}_${{ matrix.python-version }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Build Environment
uses: mamba-org/setup-micromamba@v1
with:
environment-file: installers-conda/build-environment.yml
create-args: python=${{ matrix.python-version }}
cache-downloads: true
cache-environment: true
- name: Env Variables
run: |
echo "CONDA_BLD_PATH=${RUNNER_TEMP}/conda-bld" >> $GITHUB_ENV
env | sort
- name: Cache ${{ matrix.pkg }} Conda Build
id: cache
uses: actions/cache@v3
with:
path: ${{ env.CONDA_BLD_PATH }}/**.tar.bz2
key: ${{ env.pkg }}_${{ hashFiles(format('external-deps/{0}/.gitrepo', env.pkg)) }}
- name: Build ${{ matrix.pkg }} Conda Package
if: steps.cache.outputs.cache-hit != 'true'
run: python build_conda_pkgs.py --build $pkg
build-installers:
name: Build installer for ${{ matrix.target-platform }} Python-${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
needs:
- build-matrix
- build-noarch-pkgs
if: ${{ ! failure() && ! cancelled() }}
strategy:
matrix:
target-platform: ${{fromJson(needs.build-matrix.outputs.target_platform)}}
python-version: ${{fromJson(needs.build-matrix.outputs.python_version)}}
include: ${{fromJson(needs.build-matrix.outputs.include)}}
defaults:
run:
shell: bash -l {0}
working-directory: ${{ github.workspace }}/installers-conda
env:
DISTDIR: ${{ github.workspace }}/installers-conda/dist
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_INSTALLER_CERTIFICATE: ${{ secrets.MACOS_INSTALLER_CERTIFICATE }}
APPLICATION_PWD: ${{ secrets.APPLICATION_PWD }}
CONSTRUCTOR_TARGET_PLATFORM: ${{ matrix.target-platform }}
BNP_STATUS: ${{ needs.build-noarch-pkgs.result }}
MAT_STATUS: ${{ needs.build-matrix.result }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Build Environment
uses: mamba-org/setup-micromamba@v1
with:
environment-file: installers-conda/build-environment.yml
create-args: python=${{ matrix.python-version }}
cache-downloads: true
cache-environment: true
- name: Env Variables
run: |
echo "CONDA_BLD_PATH=${RUNNER_TEMP}/conda-bld" >> $GITHUB_ENV
env | sort
- name: Restore spyder-kernels Cache
id: cache
if: env.IS_STANDARD_PR == 'true'
uses: actions/cache/restore@v3
with:
path: ${{ env.CONDA_BLD_PATH }}
key: spyder-kernels_${{ matrix.target-platform }}_${{ matrix.python-version }}_${{ hashFiles('external-deps/spyder-kernels/.gitrepo') }}
- name: Build ${{ matrix.target-platform }} spyder-kernels Conda Package
if: env.IS_STANDARD_PR == 'true' && steps.cache.outputs.cache-hit != 'true'
run: python build_conda_pkgs.py --build spyder-kernels
- name: Save spyder-kernels Cache
if: env.IS_STANDARD_PR == 'true'
uses: actions/cache/save@v3
with:
path: ${{ env.CONDA_BLD_PATH }}
key: ${{ steps.cache.outputs.cache-primary-key }}
- name: Restore python-lsp-server Cache
if: env.IS_STANDARD_PR == 'true'
uses: actions/cache/restore@v3
with:
path: ${{ env.CONDA_BLD_PATH }}
key: python-lsp-server_${{ hashFiles('external-deps/python-lsp-server/.gitrepo') }}
- name: Restore qtconsole Cache
if: env.IS_STANDARD_PR == 'true'
uses: actions/cache/restore@v3
with:
path: ${{ env.CONDA_BLD_PATH }}
key: qtconsole_${{ hashFiles('external-deps/qtconsole/.gitrepo') }}
- name: Check cache
run: |
ls -al $CONDA_BLD_PATH
- name: Build ${{ matrix.target-platform }} spyder Conda Package
if: env.IS_STANDARD_PR == 'true'
run: python build_conda_pkgs.py --build spyder
- name: Create Local Conda Channel
if: env.IS_STANDARD_PR == 'true'
run: |
files=($(find $ARTIFACTS_PATH -name *.tar.bz2))
echo ${files[@]}
cd $(dirname $CONDA_BLD_PATH)
[[ $RUNNER_OS == "Windows" ]] && opts=("--force-local") || opts=()
for file in ${files[@]}; do
tar -xf $file ${opts[@]}
done
mamba index $CONDA_BLD_PATH
mamba search -c $CONDA_BLD_PATH --override-channels || true
- name: Create Keychain
if: runner.os == 'macOS' && (env.IS_RELEASE == 'true' || env.IS_PRE == 'true')
run: |
./certkeychain.sh "${MACOS_CERTIFICATE_PWD}" "${MACOS_CERTIFICATE}" "${MACOS_INSTALLER_CERTIFICATE}"
CNAME=$(security find-identity -p codesigning -v | pcre2grep -o1 "\(([0-9A-Z]+)\)")
echo "CNAME=$CNAME" >> $GITHUB_ENV
_codesign=$(which codesign)
if [[ $_codesign =~ ${CONDA_PREFIX}.* ]]; then
# Find correct codesign
echo "Moving $_codesign..."
mv $_codesign ${_codesign}.bak
fi
- name: Build Package Installer
run: |
[[ -n $CNAME ]] && args=("--cert-id" "$CNAME") || args=()
python build_installers.py ${args[@]}
PKG_PATH=$(python build_installers.py --artifact-name)
PKG_NAME=$(basename $PKG_PATH)
PKG_GLOB=${PKG_PATH%.*}
PKG_BASE_NAME=${PKG_NAME%.*}
echo "PKG_PATH=$PKG_PATH" >> $GITHUB_ENV
echo "PKG_NAME=$PKG_NAME" >> $GITHUB_ENV
echo "PKG_GLOB=$PKG_GLOB" >> $GITHUB_ENV
echo "PKG_BASE_NAME=$PKG_BASE_NAME" >> $GITHUB_ENV
- name: Test macOS Installer
if: runner.os == 'macOS'
run: |
# Stream install.log to stdout to view all log messages.
tail -F /var/log/install.log & tail_id=$!
trap "kill -s TERM $tail_id" EXIT
installer -pkg $PKG_PATH -target CurrentUserHomeDirectory >/dev/null
root_prefix=$(compgen -G $HOME/Library/spyder-*)
echo "Install info:"
echo "Contents of ${root_prefix}:"
ls -al $root_prefix
echo -e "\nContents of ${root_prefix}/uninstall-spyder.sh:"
cat $root_prefix/uninstall-spyder.sh
app_path=/Applications/Spyder.app
[[ -e ${root_prefix}/.nonadmin ]] && app_path=${HOME}${app_path}
if [[ -e "$app_path" ]]; then
echo "Contents of $app_path/Contents/MacOS:"
ls -al $app_path/Contents/MacOS
echo -e "\nContents of $app_path/Contents/Info.plist:"
cat $app_path/Contents/Info.plist
echo -e "\nContents of $app_path/Contents/MacOS/spyder-script:"
cat $app_path/Contents/MacOS/spyder-script
else
echo "$app_path does not exist"
exit 1
fi
- name: Test Linux Installer
if: runner.os == 'Linux'
run: |
$PKG_PATH -b
root_prefix=$(compgen -G $HOME/.local/spyder-*)
echo "Install info:"
echo "Contents of ${root_prefix}:"
ls -al $root_prefix
echo -e "\nContents of ${root_prefix}/uninstall-spyder.sh:"
cat ${root_prefix}/uninstall-spyder.sh
shortcut_path=/share/applications/spyder_spyder.desktop
[[ -e ${root_prefix}/.nonadmin ]] && shortcut_path=${HOME}/.local${shortcut_path} || shortcut_path=/usr${shortcut_path}
if [[ -e $shortcut_path ]]; then
echo -e "\nContents of ${shortcut_path}:"
cat $shortcut_path
else
echo "$shortcut_path does not exist"
exit 1
fi
- name: Test Windows Installer
if: runner.os == 'Windows'
shell: cmd
run: |
start /wait %PKG_PATH% /InstallationType=JustMe /NoRegistry=1 /S
set "shortcut_path=%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\spyder\Spyder.lnk"
if exist "%shortcut_path%" (
echo "Spyder installed successfully"
) else (
echo "Spyder NOT installed successfully"
EXIT /B 1
)
EXIT /B %ERRORLEVEL%
- name: Notarize or Compute Checksum
if: env.IS_RELEASE == 'true' || env.IS_PRE == 'true'
run: |
if [[ $RUNNER_OS == "macOS" ]]; then
./notarize.sh -p $APPLICATION_PWD $PKG_PATH
else
cd $(dirname $PKG_PATH)
echo $(sha256sum $PKG_NAME) > "${PKG_GLOB}-sha256sum.txt"
fi
- name: Setup Remote SSH Connection
# Notes:
# 1. This only works for conda, probably because it has the necessary
# MSYS2 packages to create the connection.
# 2. Check https://github.com/marketplace/actions/debugging-with-tmate for
# usage.
if: failure() && env.ENABLE_SSH == 'true'
uses: mxschmitt/action-tmate@v3
timeout-minutes: 45
- name: Upload Artifact
if: env.IS_RELEASE == 'false'
uses: actions/upload-artifact@v3
with:
path: ${{ env.PKG_GLOB }}*
name: ${{ env.PKG_BASE_NAME }}
- name: Get Release
if: env.IS_RELEASE == 'true'
uses: bruceadams/[email protected]
id: get_release
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Upload Release Asset
if: env.IS_RELEASE == 'true'
uses: shogo82148/actions-upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ${{ env.PKG_GLOB }}*