Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .github/workflows/make_bundle_conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ jobs:
recipe/recipe.yaml
# make sure the recipe.yaml points to the local source, in case we break
# this when updating from upstream
git diff
grep -e "sdist_path: /home/conda" recipe/recipe.yaml

conda-smithy rerender
Expand Down Expand Up @@ -293,6 +294,7 @@ jobs:
DISPLAY: ":99.0"
CONDA_BLD_PATH: ${{ github.workspace }}/conda-bld
CONDA_NUMBER_CHANNEL_NOTICES: 0
CONSTRUCTOR_PYTHON_VERSION: "${{ matrix.python-version }}"

outputs:
licenses-artifact: ${{ steps.licenses.outputs.licenses_artifact }}
Expand All @@ -318,7 +320,6 @@ jobs:
uses: mamba-org/setup-micromamba@add3a49764cedee8ee24e82dfde87f5bc2914462 # v2.0.7
with:
environment-file: napari-packaging/environments/ci_installers_environment.yml
create-args: python=${{ matrix.python-version }}

- name: Conda info
shell: bash -el {0}
Expand Down
74 changes: 71 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,76 @@ You can find more information in the following resources:
* [Napari docs about creating installers using this repo and the constructor tool](https://napari.org/dev/developers/coredev/packaging.html#installers)
* [NAP-2: Distributing napari with conda-based packaging](https://napari.org/stable/naps/2-conda-based-packaging.html)

<!---
## Usage

TODO: add basics
-->
### Quickstart

This is how to build an installer for the latest napari release. We assume that `napari/napari` and `napari/packaging` will be cloned as siblings to `napari/` and `napari-packaging`, respectively:

```bash
git clone https://github.com/napari/napari.git napari # skip if cloned already
cd napari
git checkout <latest-tag> # only needed for some resources like images, not the code itself
cd ..
git clone https://github.com/napari/packaging.git napari-packaging
cd napari-packaging
conda env create -n napari-packaging-installers --file environments/ci_installers_environment.yml
conda activate napari-packaging-installers
pip install -e ../napari --no-deps
CONSTRUCTOR_PYTHON_VERSION="3.11" python build_installers.py --location ../napari
# Installers will be generated under `_work/`.
```

For any other versions, it's probably easier to [run a `workflow_dispatch` trigger on `.github/workflows/make_bundle_conda.yml`](https://github.com/napari/packaging/actions/workflows/make_bundle_conda.yml).

### Locally built packages

napari installers are created from conda packages _exclusively_, using `constructor`. This means that we need to have conda packages for the napari version we want to distribute. We get those from conda channels: `conda-forge`, `napari`, `napari/label/nightly`, or our own local channel.

Our Github workflows rely on conda-forge feedstock scripts to have the closes possible setup, but for debugging installers we can take a few shortcuts. We only need to know which version we have cloned:

```bash
conda activate napari-packaging-installers
CONSTRUCTOR_USE_LOCAL=1 python build_installers.py --version
# e.g. 0.6.5dev18+gc9111b7bb
```

Now, let's edit the `recipe.yaml` file so it points to our cloned version:

```diff
context:
name: napari
- version: "REPLACE_ME"
+ version: "0.6.5dev18+gc9111b7bb"
python_min: "3.10"
build_number: 0

recipe:
name: ${{ name|lower }}
version: ${{ version }}

source:
- # This section has been patched from the original conda-forge feedstock
- # so it uses the mounted volume of the cloned repo in a Docker image
- - path: /home/conda/feedstock_root/napari-source
+ - path: ../../napari
```

Now build the recipe, making sure packages are generated in `_work/packages/`:

```bash
conda create -n rattler-build rattler-build
conda activate rattler-build
CONDA_BLD_PATH=_work/packages/ rattler-build build --recipe conda-recipe/
```

> Tip: You may skip tests with `--test=skip`

The installers can now be built from the local packages with:

```bash
conda activate napari-packaging-installers
CONSTRUCTOR_USE_LOCAL=1 CONDA_BLD_PATH=_work/packages/ CONSTRUCTOR_PYTHON_VERSION="3.11" python build_installers.py --location ../napari
```

The artifacts will be available in `_work/`.
21 changes: 15 additions & 6 deletions build_installers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
This will have an effect on the default install locations in future
releases.
CONSTRUCTOR_TARGET_PLATFORM:
conda-style platform (as in `platform` in `conda info -a` output)
conda-style platform (as in `platform` in `conda info -a` output;
e.g. `linux-64` or `osx-arm64`).
CONSTRUCTOR_PYTHON_VERSION:
Python version that will be shipped in the installer. Defaults to
the version of the interpreter running this script.
CONSTRUCTOR_USE_LOCAL:
whether to use the local channel (populated by `conda-build` actions)
CONSTRUCTOR_CONDA_EXE:
Expand Down Expand Up @@ -88,7 +92,10 @@
ARCH = arch
else:
ARCH = (platform.machine() or 'generic').lower().replace('amd64', 'x86_64')
PY_VER = f'{sys.version_info.major}.{sys.version_info.minor}'
PY_VER = os.environ.get(
'CONSTRUCTOR_PYTHON_VERSION',
f'{sys.version_info.major}.{sys.version_info.minor}',
)
PYSIDE_VER = os.environ.get('CONSTRUCTOR_PYSIDE_VER', '*')
if WINDOWS:
EXT, OS = 'exe', 'Windows'
Expand Down Expand Up @@ -233,7 +240,7 @@ def _base_env(python_version=PY_VER):
'conda-forge',
],
'specs': [
f'python={python_version}.*=*_cpython',
f'python={python_version}.*',
*CONDA_TOOL_DEPS,
],
}
Expand All @@ -249,7 +256,7 @@ def _napari_env(
'name': f'napari-{napari_version}',
# "channels": same as _base_env(), omit to inherit :)
'specs': [
f'python={python_version}.*=*_cpython',
f'python={python_version}.*',
f'napari={napari_version}',
f'napari-menu={napari_version}',
'napari-plugin-manager',
Expand Down Expand Up @@ -560,7 +567,6 @@ def cli(argv=None):
)
p.add_argument(
'--location',
default=HERE,
help='Path to napari source repository',
type=os.path.abspath,
)
Expand Down Expand Up @@ -593,7 +599,10 @@ def cli(argv=None):
if args.images:
_generate_background_images(napari_repo=args.location)
sys.exit()

if not args.location:
sys.exit(
'Must provide --location pointing to a cloned napari/napari repository.'
)
print(
'Created',
main(extra_specs=args.extra_specs, napari_repo=args.location),
Expand Down
6 changes: 5 additions & 1 deletion environments/ci_installers_environment.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Use this file to create an environment to build the installers. You will
# need to `pip install -e path/to/napari/source --no-deps` too.
name: build-bundle
channels:
- conda-forge
dependencies:
- python
- python 3.11.*
- pip
- constructor >=3.11.0
- conda-build >=3.28
Expand All @@ -13,3 +15,5 @@ dependencies:
# only needed to import napari and get the path to the logo.png file
- lazy_loader >=0.2
- numpy >=1.22.2
# - pip:
# - -e ../napari --no-deps
7 changes: 6 additions & 1 deletion environments/ci_packages_environment.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# This environment is used to provision a conda-forge-like context to
# clone napari-feedstock and patch it with our in-repo recipe. We then
# use conda-forge's scripts to actually build the packages. That's why
# you don't see rattler-build here; it'll be installed by the conda-forge
# scrips that come with the feedstock. See `.github/workflows/make_bundle_conda.yml`.
name: packages
channels:
- conda-forge
dependencies:
- conda-smithy >=3.37.0
- python 3.10.*
- python 3.11.*
- pip
- tomlkit
- ruamel.yaml
Expand Down