diff --git a/.gitignore b/.gitignore index 3675d9552..6936270af 100644 --- a/.gitignore +++ b/.gitignore @@ -128,4 +128,4 @@ ENV/ VERSION # Since we use a Jinja Template, we only want this to be created as build time -/conda/ +meta.yaml diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1a412a279..933cbbf2d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -50,7 +50,11 @@ jobs: architecture: '$(architecture)' displayName: 'Setting Python version and system architecture' - - template: build_tools/azure/conda/linux.yml + - bash: echo "##vso[task.prependpath]$CONDA/bin" + displayName: 'Adding conda to PATH' + + - template: build_tools/azure/conda/common.yml + - template: build_tools/azure/conda/unix.yml - template: build_tools/azure/conda/deploy.yml - job: Mac @@ -75,7 +79,13 @@ jobs: architecture: '$(architecture)' displayName: 'Setting Python version and system architecture' - - template: build_tools/azure/conda/mac.yml + - bash: | + echo "##vso[task.prependpath]$CONDA/bin" + sudo chown -R $USER $CONDA + displayName: 'Adding conda to PATH' + + - template: build_tools/azure/conda/common.yml + - template: build_tools/azure/conda/unix.yml - template: build_tools/azure/conda/deploy.yml - job: Windows @@ -100,6 +110,10 @@ jobs: architecture: '$(architecture)' displayName: 'Setting Python version and system architecture' + - powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts" + displayName: 'Adding conda to PATH' + + - template: build_tools/azure/conda/common.yml - template: build_tools/azure/conda/windows.yml - template: build_tools/azure/conda/deploy.yml diff --git a/build_tools/azure/conda/common.yml b/build_tools/azure/conda/common.yml new file mode 100644 index 000000000..76d03bc87 --- /dev/null +++ b/build_tools/azure/conda/common.yml @@ -0,0 +1,21 @@ +steps: + - script: conda update conda --yes + displayName: 'Updating Conda' + + - script: conda install python=$(python.version) --yes + displayName: 'Fixing conda Python version' + + - script: conda install conda-build anaconda-client --yes + displayName: 'Installing conda-build and anaconda-client' + + - bash: | + mkdir conda + python -m pip install jinja2 + python build_tools/azure/render_meta.py + # This line is purely for debugging + conda render --python=$(python.version) conda/ + displayName: 'Rendering meta.yaml file' + + - bash: make version + condition: contains(variables['Build.SourceBranch'], 'refs/tags') + displayName: 'Ensuring VERSION file is created' \ No newline at end of file diff --git a/build_tools/azure/conda/deploy.sh b/build_tools/azure/conda/deploy.sh index ae34875cd..9f14db1c0 100755 --- a/build_tools/azure/conda/deploy.sh +++ b/build_tools/azure/conda/deploy.sh @@ -1,7 +1,6 @@ #!/bin/bash -# This looks like it is running `conda build` again, but it just returns the output file -output_file=$(conda-build --output --python=$(python.version) conda/) +output_file=$1 # Check our VERSION. Basically, if it contains letters, it is a pre-release. Otherwise, # it has to match X.Y or X.Y.Z diff --git a/build_tools/azure/conda/deploy.yml b/build_tools/azure/conda/deploy.yml index 36688b50d..3d5a85bad 100644 --- a/build_tools/azure/conda/deploy.yml +++ b/build_tools/azure/conda/deploy.yml @@ -9,8 +9,11 @@ steps: fi displayName: Checking for VERSION file - - bash: build_tools/azure/conda/deploy.sh - condition: and(succeeded(), eq(variables['VERSION_EXISTS'], 'true'), contains(variables['Build.SourceBranch'], 'refs/tags')) + - bash: | + # This looks like it is running `conda build` again, but it just returns the output file + output_file=$(conda-build --output --python=$(python.version) conda/) + ./build_tools/azure/conda/deploy.sh $output_file + condition: and(succeeded(), eq(variables['LIB_CREATED'], 'true'), eq(variables['VERSION_EXISTS'], 'true'), contains(variables['Build.SourceBranch'], 'refs/tags')) displayName: Deploying to conda env: ANACONDA_API_TOKEN: $(anacondaToken) diff --git a/build_tools/azure/conda/linux.yml b/build_tools/azure/conda/linux.yml deleted file mode 100644 index 6e3fc1d3a..000000000 --- a/build_tools/azure/conda/linux.yml +++ /dev/null @@ -1,37 +0,0 @@ -steps: - - bash: echo "##vso[task.prependpath]$CONDA/bin" - displayName: 'Add conda to PATH' - - - script: conda install python=$(python.version) --yes - displayName: 'Fixing conda Python version' - - - script: conda install conda-build anaconda-client --yes - displayName: 'Installing conda-build and anaconda-client' - - - script: python -m pip install --upgrade pip - displayName: 'Updating pip' - - - script: | - python -m pip install -r build_tools/build_requirements.txt - make requirements - displayName: 'Installing requirements' - - - script: make bdist_wheel - displayName: 'Building wheel file' - - - bash: | - mkdir conda - python -m pip install jinja2 - python build_tools/azure/render_meta.py - displayName: 'Rendering meta.yaml file' - - - bash: conda-build --python=$(python.version) conda/ - displayName: 'Building and testing conda distribution' - - # Run pmdarima.show_versions() because I don't 100% trust the conda builder - # Have to cd .. because pmdarima doesn't like importing from own dir - - bash: | - cd .. - conda install --use-local pmdarima --yes - python -c "import pmdarima; pmdarima.show_versions()" - displayName: 'Testing conda installation' diff --git a/build_tools/azure/conda/mac.yml b/build_tools/azure/conda/mac.yml deleted file mode 100644 index 1b9219da9..000000000 --- a/build_tools/azure/conda/mac.yml +++ /dev/null @@ -1,39 +0,0 @@ -steps: - - bash: | - echo "##vso[task.prependpath]$CONDA/bin" - sudo chown -R $USER $CONDA - displayName: 'Add conda to PATH' - - - script: conda install python=$(python.version) --yes - displayName: 'Fixing conda Python version' - - - script: conda install conda-build anaconda-client --yes - displayName: 'Installing conda-build and anaconda-client' - - - script: python -m pip install --upgrade pip - displayName: 'Updating pip' - - - script: | - python -m pip install -r build_tools/build_requirements.txt - make requirements - displayName: 'Installing requirements' - - - script: make bdist_wheel - displayName: 'Building wheel file' - - - bash: | - mkdir conda - python -m pip install jinja2 - python build_tools/azure/render_meta.py - displayName: 'Rendering meta.yaml file' - - - bash: conda-build --python=$(python.version) conda/ - displayName: 'Building and testing conda distribution' - - # Run pmdarima.show_versions() because I don't 100% trust the conda builder - # Have to cd .. because pmdarima doesn't like importing from own dir - - bash: | - cd .. - conda install --use-local pmdarima --yes - python -c "import pmdarima; pmdarima.show_versions()" - displayName: 'Testing conda installation' diff --git a/build_tools/azure/conda/unix.yml b/build_tools/azure/conda/unix.yml new file mode 100644 index 000000000..ba7864e4b --- /dev/null +++ b/build_tools/azure/conda/unix.yml @@ -0,0 +1,22 @@ +steps: + # A lot of our requirements don't exist on conda (scipy>1.3.3, for instance), so we pip install all of them + - bash: | + conda create --name build-env python=$(python.version) --yes + python -m pip install -r requirements.txt + displayName: 'Creating build environment' + + - bash: | + source activate build-env + conda build --python=$(python.version) conda/ + displayName: 'Building and testing conda distribution' + + - bash: | + output_file=$(conda-build --output --python=$(python.version) conda/) + if tar -tf "$output_file" | grep "lib"; then + echo "##vso[task.setvariable variable=LIB_CREATED]true" + echo "Lib directory created properly" + else + echo "Lib directory not created" + exit 1 + fi + displayName: 'Looking for lib folder' diff --git a/build_tools/azure/conda/windows.yml b/build_tools/azure/conda/windows.yml index 76fbb3daf..85d32d7e8 100644 --- a/build_tools/azure/conda/windows.yml +++ b/build_tools/azure/conda/windows.yml @@ -1,33 +1,20 @@ steps: - - powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts" - displayName: 'Add conda to PATH' - - - script: conda install conda-build anaconda-client --yes - displayName: 'Installing conda-build and anaconda-client' - - - script: make version - displayName: 'Ensuring VERSION file is created' - condition: contains(variables['Build.SourceBranch'], 'refs/tags') - - - bash: | - mkdir conda - python -m pip install jinja2 - python build_tools/azure/render_meta.py - displayName: 'Rendering meta.yaml file' - - # A lot of our requirements don't exist on conda (scipy>1.3.3, for instance), so we pip install all of them + # Windows is weird and fails if we try to do these as separate steps - script: | conda create --name build-env python=$(python.version) --yes call activate build-env - pip install -r requirements.txt + python -m pip install -r requirements.txt conda-build --python=$(python.version) conda/ displayName: 'Building and testing conda distribution' - # Run pmdarima.show_versions() because I don't 100% trust the conda builder - # Have to cd .. because pmdarima doesn't like importing from own dir - bash: | - source activate build-env - cd .. - conda install --use-local pmdarima --yes - python -c "import pmdarima; pmdarima.show_versions()" - displayName: 'Testing conda installation' + output_file=$(conda-build --output --python=$(python.version) conda/) + # Windows has to use --force-local to ignore colons, and `Lib` has to be capitalized + if tar -tf "$output_file" --force-local | grep "Lib"; then + echo "##vso[task.setvariable variable=LIB_CREATED]true" + echo "Lib directory created properly" + else + echo "Lib directory not created" + exit 1 + fi + displayName: 'Looking for lib folder' diff --git a/build_tools/azure/meta_template.yml.j2 b/build_tools/azure/meta_template.yml.j2 index 53f887d00..4dc45d350 100644 --- a/build_tools/azure/meta_template.yml.j2 +++ b/build_tools/azure/meta_template.yml.j2 @@ -1,16 +1,25 @@ {# This is a Jinja2 template that will render out to $ROOT/conda/meta.yaml #} package: - name: 'pmdarima' - version: '{{ VERSION }}' + name: "pmdarima" + version: "{{ VERSION }}" {# Path where setup.py lies from root/conda (since that is where this will be rendered) #} source: - path: ../ + git_url: ../ build: - string: 'py{{ py_version }}' - script: 'python -m pip install dist/{{ wheel }} --no-deps -vv' # [not win] - script: 'python setup.py install' # [win] + {% raw %} + number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} + string: py{{ CONDA_PY }}{{ environ.get('GIT_DESCRIBE_HASH', '') }}_{{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} + {% endraw %} + {# + The first one here installs to the default location (which is where testing happens) + and the second one installs to $PREFIX, which is set by conda-build and is necessary + for the `lib` folder to end up in the tar.bz2 + #} + script: | + python -m pip install --no-deps --ignore-installed . + python -m pip install --prefix $PREFIX --no-deps --ignore-installed . ignore_run_exports: - pip - statsmodels @@ -24,20 +33,23 @@ build: requirements: build: - - {{ numpy_version }} {% raw %} - {{ compiler('c') }} {% endraw %} host: - pip - - python + {% raw %} + - python {{ PY_VER }} + {% endraw %} {% for package in requirements %} - {{ package }} {% endfor %} run: - - python + {% raw %} + - python {{ PY_VER }} + {% endraw %} {% for package in requirements %} - {{ package }} {% endfor %} @@ -48,6 +60,7 @@ test: - pip install pytest pytest-mpl pytest-benchmark {# Cannot use `make` in the meta.yaml file #} - pytest --showlocals --durations=20 --pyargs pmdarima --benchmark-skip + - python -c "import pmdarima; pmdarima.show_versions()" about: home: https://github.com/alkaline-ml/pmdarima diff --git a/build_tools/azure/render_meta.py b/build_tools/azure/render_meta.py index 1163c6c14..66f9a4848 100644 --- a/build_tools/azure/render_meta.py +++ b/build_tools/azure/render_meta.py @@ -1,5 +1,5 @@ import os -import sys +import re from jinja2 import Environment, FileSystemLoader from pathlib import Path @@ -28,26 +28,21 @@ VERSION = '0.0.0' # Find the requirements and versions +# conda puts a space between packages and versions, so we have to match that +requirements = [] with open(str(REQUIREMENTS_FILE.resolve())) as file: - requirements = [line.strip() for line in file.readlines()] - -# We build from source on windows, otherwise, we looks for a wheel -if sys.platform != 'win32': - wheel = next(file for file in os.listdir(str(DIST_PATH.resolve())) - if file.endswith('.whl')) -else: - wheel = None - -# Numpy version is used for building -numpy_version = next(package for package in requirements if 'numpy' in package) + for line in file: + requirement = line.strip() + match = re.match(r'^([A-Za-z\-0-9]+)', requirement) + _, match_end = match.span() + package = match.group(0) + version = requirement[match_end:].replace('==', '') + requirements.append(f'{package} {version}') # Render and write the meta.yaml file to $ROOT/conda/meta.yaml context = { 'requirements': requirements, - 'numpy_version': numpy_version, - 'VERSION': VERSION, - 'wheel': wheel, - 'py_version': '{0.major}{0.minor}'.format(sys.version_info) + 'VERSION': VERSION } # Ensure output directory exists