Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build installer refactor #23287

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
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
11 changes: 5 additions & 6 deletions .github/workflows/installers-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ jobs:
mkdir -p $CONDA_BLD_PATH
conda config --set bld_path $CONDA_BLD_PATH
conda index $CONDA_BLD_PATH
mamba search -c local --override-channels || true
conda search -c local --override-channels || true

- name: Create Keychain
if: runner.os == 'macOS' && env.NOTARIZE == 'true'
Expand All @@ -274,8 +274,8 @@ jobs:
fi

./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
CERT_ID=$(security find-identity -p codesigning -v | pcre2grep -o1 "\(([0-9A-Z]+)\)")
echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV

- name: Load signing certificate (Windows)
if: runner.os == 'Windows' && env.NOTARIZE == 'true'
Expand All @@ -289,11 +289,10 @@ jobs:

- name: Build Package Installer
run: |
[[ -n $CNAME ]] && args=("--cert-id" "$CNAME") || args=()
python build_installers.py ${args[@]}
python build_installers.py

SPYVER=$(python build_installers.py --version)
PKG_PATH=$(python build_installers.py --artifact-name)
PKG_PATH=$(python build_installers.py --installer-path)
PKG_NAME=$(basename $PKG_PATH)
ARTIFACT_NAME=${PKG_NAME%.*}
[[ "$GITHUB_EVENT_NAME" == "schedule" ]] && ARTIFACT_NAME=$ARTIFACT_NAME-$MATRIX_BRANCH
Expand Down
96 changes: 29 additions & 67 deletions installers-conda/build_conda_pkgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
import os
import re
import sys
from argparse import ArgumentParser, RawTextHelpFormatter
from argparse import ArgumentParser
from configparser import ConfigParser
from datetime import timedelta
from logging import Formatter, StreamHandler, getLogger
from pathlib import Path
from subprocess import check_call
from textwrap import dedent
from time import time
Expand All @@ -22,25 +20,16 @@
from ruamel.yaml import YAML
from setuptools_scm import get_version

fmt = Formatter('%(asctime)s [%(levelname)s] [%(name)s] -> %(message)s')
h = StreamHandler()
h.setFormatter(fmt)
logger = getLogger('BuildCondaPkgs')
logger.addHandler(h)
logger.setLevel('INFO')
# Local imports
from utils import logger as logger, HERE, BUILD, DocFormatter

HERE = Path(__file__).parent
BUILD = HERE / "build"
RESOURCES = HERE / "resources"
EXTDEPS = HERE.parent / "external-deps"
SPECS = BUILD / "specs.yaml"
REQUIREMENTS = HERE.parent / "requirements"
REQ_MAIN = REQUIREMENTS / 'main.yml'
REQ_WINDOWS = REQUIREMENTS / 'windows.yml'
REQ_MAC = REQUIREMENTS / 'macos.yml'
REQ_LINUX = REQUIREMENTS / 'linux.yml'

BUILD.mkdir(exist_ok=True)
SPYPATCHFILE = BUILD / "installers-conda.patch"

yaml = YAML()
Expand All @@ -54,21 +43,17 @@ class BuildCondaPkg:
source = None
feedstock = None
feedstock_branch = None
shallow_ver = None

def __init__(self, data={}, debug=False, shallow=False):
self.logger = getLogger(self.__class__.__name__)
if not self.logger.handlers:
self.logger.addHandler(h)
self.logger.setLevel('INFO')
def __init__(self, data={}, debug=False):
self.logger = logger.getChild(self.__class__.__name__)

self.debug = debug

self._bld_src = BUILD / self.name
self._fdstk_path = BUILD / self.feedstock.split("/")[-1]
self._patchfile = self._fdstk_path / "recipe" / "version.patch"

self._get_source(shallow=shallow)
self._get_source()
self._get_version()

self.data = {'version': self.version}
Expand All @@ -79,9 +64,10 @@ def __init__(self, data={}, debug=False, shallow=False):

self._recipe_patched = False

def _get_source(self, shallow=False):
def _get_source(self):
"""Clone source and feedstock to distribution directory for building"""
self._build_cleanup()
BUILD.mkdir(exist_ok=True)
self._cleanup_build()

if self.source == HERE.parent:
self._bld_src = self.source
Expand All @@ -99,12 +85,7 @@ def _get_source(self, shallow=False):

# Clone from source
kwargs = dict(to_path=self._bld_src)
if shallow:
kwargs.update(shallow_exclude=self.shallow_ver)
self.logger.info(
f"Cloning source shallow from tag {self.shallow_ver}...")
else:
self.logger.info("Cloning source...")
self.logger.info("Cloning source...")
self.repo = Repo.clone_from(remote, **kwargs)
self.repo.git.checkout(commit)

Expand All @@ -115,11 +96,15 @@ def _get_source(self, shallow=False):
kwargs.update(branch=self.feedstock_branch)
Repo.clone_from(self.feedstock, **kwargs)

def _build_cleanup(self):
def _cleanup_build(self, debug=False):
"""Remove cloned source and feedstock repositories"""
if debug:
self.logger.info("Keeping cloned source and feedstock")
return

for src in [self._bld_src, self._fdstk_path]:
if src.exists() and src != HERE.parent:
logger.info(f"Removing {src}...")
self.logger.info(f"Removing {src}...")
rmtree(src)

def _get_version(self):
Expand Down Expand Up @@ -234,10 +219,7 @@ def build(self):
])
finally:
self._recipe_patched = False
if self.debug:
self.logger.info("Keeping cloned source and feedstock")
else:
self._build_cleanup()
self._cleanup_build(self.debug)

elapse = timedelta(seconds=int(time() - t0))
self.logger.info(f"Build time = {elapse}")
Expand All @@ -249,7 +231,6 @@ class SpyderCondaPkg(BuildCondaPkg):
source = os.environ.get('SPYDER_SOURCE', HERE.parent)
feedstock = "https://github.com/conda-forge/spyder-feedstock"
feedstock_branch = "dev"
shallow_ver = "v5.3.2"

def _patch_source(self):
self.logger.info("Patching Spyder source...")
Expand Down Expand Up @@ -304,23 +285,20 @@ class PylspCondaPkg(BuildCondaPkg):
source = os.environ.get('PYTHON_LSP_SERVER_SOURCE')
feedstock = "https://github.com/conda-forge/python-lsp-server-feedstock"
feedstock_branch = "main"
shallow_ver = "v1.4.1"


class QtconsoleCondaPkg(BuildCondaPkg):
name = "qtconsole"
source = os.environ.get('QTCONSOLE_SOURCE')
feedstock = "https://github.com/conda-forge/qtconsole-feedstock"
feedstock_branch = "main"
shallow_ver = "5.3.1"


class SpyderKernelsCondaPkg(BuildCondaPkg):
name = "spyder-kernels"
source = os.environ.get('SPYDER_KERNELS_SOURCE')
feedstock = "https://github.com/conda-forge/spyder-kernels-feedstock"
feedstock_branch = "rc"
shallow_ver = "v2.3.1"


PKGS = {
Expand All @@ -331,17 +309,15 @@ class SpyderKernelsCondaPkg(BuildCondaPkg):
}

if __name__ == "__main__":
p = ArgumentParser(
description=dedent(
parser = ArgumentParser(
description="Build conda packages to local channel.",
epilog=dedent(
"""
Build conda packages to local channel.

This module builds conda packages for Spyder and external-deps for
inclusion in the conda-based installer. The following classes are
provided for each package:
SpyderCondaPkg
PylspCondaPkg
QdarkstyleCondaPkg
QtconsoleCondaPkg
SpyderKernelsCondaPkg

Expand All @@ -355,43 +331,29 @@ class SpyderKernelsCondaPkg(BuildCondaPkg):
appropriate environment variable from the following:
SPYDER_SOURCE
PYTHON_LSP_SERVER_SOURCE
QDARKSTYLE_SOURCE
QTCONSOLE_SOURCE
SPYDER_KERNELS_SOURCE
"""
),
usage="python build_conda_pkgs.py "
"[--build BUILD [BUILD] ...] [--debug] [--shallow]",
formatter_class=RawTextHelpFormatter
formatter_class=DocFormatter
)
p.add_argument(
parser.add_argument(
'--build', nargs="+", default=list(PKGS.keys()),
help="Space-separated list of packages to build."
)
parser.add_argument(
'--debug', action='store_true', default=False,
help="Do not remove cloned sources and feedstocks"
)
p.add_argument(
'--build', nargs="+", default=PKGS.keys(),
help=("Space-separated list of packages to build. "
f"Default is {list(PKGS.keys())}")
)
p.add_argument(
'--shallow', action='store_true', default=False,
help="Perform shallow clone for build")
args = p.parse_args()

args = parser.parse_args()

logger.info(f"Building local conda packages {list(args.build)}...")
t0 = time()

if SPECS.exists():
specs = yaml.load(SPECS.read_text())
else:
specs = {k: "" for k in PKGS}

for k in args.build:
pkg = PKGS[k](debug=args.debug, shallow=args.shallow)
pkg = PKGS[k](debug=args.debug)
pkg.build()
specs[k] = "=" + pkg.version

yaml.dump(specs, SPECS)

elapse = timedelta(seconds=int(time() - t0))
logger.info(f"Total build time = {elapse}")
Loading
Loading