├── .gitignore ├── circle.yml ├── recipe ├── run_conda_forge_build_setup_win.bat ├── run_conda_forge_build_setup_linux ├── run_conda_forge_build_setup_osx ├── meta.yaml └── upload_or_check_non_existence.py ├── conda-forge.yml ├── LICENSE ├── ci_support ├── run_docker_build.sh └── upload_or_check_non_existence.py ├── .travis.yml ├── appveyor.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | 3 | build_artefacts 4 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | services: 3 | - docker 4 | 5 | dependencies: 6 | # Note, we used to use the naive caching of docker images, but found that it was quicker 7 | # just to pull each time. #rollondockercaching 8 | override: 9 | - docker pull condaforge/linux-anvil 10 | 11 | test: 12 | override: 13 | # Run, test and (if we have a BINSTAR_TOKEN) upload the distributions. 14 | - ./ci_support/run_docker_build.sh 15 | -------------------------------------------------------------------------------- /recipe/run_conda_forge_build_setup_win.bat: -------------------------------------------------------------------------------- 1 | 2 | :: 2 cores available on Appveyor workers: https://www.appveyor.com/docs/build-configuration/#build-environment 3 | :: CPU_COUNT is passed through conda build: https://github.com/conda/conda-build/pull/1149 4 | set CPU_COUNT=2 5 | 6 | set PYTHONUNBUFFERED=1 7 | 8 | conda config --set show_channel_urls true 9 | conda config --set add_pip_as_python_dependency false 10 | 11 | conda update -n root --yes --quiet conda 12 | conda install -n root --yes --quiet jinja2 conda-build anaconda-client 13 | 14 | :: KLUDGE to work around changes in conda-build 2.0.0 15 | conda install -n root --yes --quiet conda-build=1 16 | 17 | conda info 18 | conda config --get 19 | -------------------------------------------------------------------------------- /recipe/run_conda_forge_build_setup_linux: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 2 cores available on CircleCI workers: https://discuss.circleci.com/t/what-runs-on-the-node-container-by-default/1443 4 | # CPU_COUNT is passed through conda build: https://github.com/conda/conda-build/pull/1149 5 | export CPU_COUNT=2 6 | 7 | export PYTHONUNBUFFERED=1 8 | 9 | conda config --set show_channel_urls true 10 | conda config --set add_pip_as_python_dependency false 11 | 12 | conda update -n root --yes --quiet conda conda-build 13 | conda install -n root --yes --quiet jinja2 anaconda-client 14 | 15 | # KLUDGE to work around changes in conda-build 2.0.0 16 | conda install -n root --yes --quiet conda-build=1 17 | 18 | conda info 19 | conda config --get 20 | -------------------------------------------------------------------------------- /recipe/run_conda_forge_build_setup_osx: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 1 core available on Travis CI OS X workers: https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments 4 | # CPU_COUNT is passed through conda build: https://github.com/conda/conda-build/pull/1149 5 | export CPU_COUNT=1 6 | 7 | export PYTHONUNBUFFERED=1 8 | 9 | conda config --set show_channel_urls true 10 | conda config --set add_pip_as_python_dependency false 11 | 12 | conda update -n root --yes --quiet conda 13 | conda install -n root --yes --quiet jinja2 conda-build anaconda-client 14 | 15 | # KLUDGE to work around changes in conda-build 2.0.0 16 | conda install -n root --yes --quiet conda-build=1 17 | 18 | conda info 19 | conda config --get 20 | -------------------------------------------------------------------------------- /conda-forge.yml: -------------------------------------------------------------------------------- 1 | travis: 2 | secure: 3 | BINSTAR_TOKEN: D1ZSq6vdkjuDXW+MWSPR3A7mmp5ASwA1HGHRjpG5GA/FxoK012XWTWeQW6qcVDTPGEkAXdAtrxdkg9Fn7s7C2efxfMZvLdH4F+nBuqCiTzBFqAwwkL0CeP2rMfZc8mo5fPpnaoZMA4zKm6ssyO1XUPhzlv0WKQOdBe3h04fXQZGF4ar630e4LDVUgfE5HMFUivxpm09AW9QJ53n4AaCcpW379Qa8IGaO3g53IZN4JqtZ8sXvDkCDHPnEZUAgzS+pgq4DS7Gj2T79o1PfZwpLuSwPVO9cAtRFQ5EfAIPH9oUFuW9TNYtX3ruRSuPl6cjCp7jG9XoggGae5VMElUDwtTlfJadOaHQJNlxQUN0WZBPSetitdcVc2IGDNS4aFBSWhBGh/FdrMSRqv7dvdLreLCBTQ8AWz9tW/IB6LvfqngdaWSNGLb4Ntbft1yWx1t5d9TlsLmpWL0MBIbg16vd2Yccfe4out85aSa9UyZXsvVoEmsoeOJ+XvonYLHB2PfC90miSIGElLWt1ncoUASIZ1iv86iTnamFnaKCq2T4XebllDOVeQ7iASvZmDfs5om23VNZqVBtEx2MUz4bHGOH/gnqkxXwHdVsX1N7NYJwO7g03dJW/xGlKR+UxCsa9C8Bx48ubsvhn/u/VXnc68mN20DCMNHptQQts5MVUEZNocAU= 4 | appveyor: 5 | secure: 6 | BINSTAR_TOKEN: MP4hZYylDyUWEsrt3u3cod2sbFeRwUziH02mvQOdbjsTO/l1yIxDkP/76rSIjcGC 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-clause license 2 | Copyright (c) conda-forge 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /ci_support/run_docker_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # PLEASE NOTE: This script has been automatically generated by conda-smithy. Any changes here 4 | # will be lost next time ``conda smithy rerender`` is run. If you would like to make permanent 5 | # changes to this script, consider a proposal to conda-smithy so that other feedstocks can also 6 | # benefit from the improvement. 7 | 8 | FEEDSTOCK_ROOT=$(cd "$(dirname "$0")/.."; pwd;) 9 | RECIPE_ROOT=$FEEDSTOCK_ROOT/recipe 10 | 11 | docker info 12 | 13 | config=$(cat < ~/.condarc 39 | # A lock sometimes occurs with incomplete builds. The lock file is stored in build_artefacts. 40 | conda clean --lock 41 | 42 | conda update --yes --all 43 | conda install --yes conda-build 44 | conda install --yes conda-build=1 45 | conda info 46 | 47 | # Embarking on 1 case(s). 48 | conda build /recipe_root --quiet || exit 1 49 | /feedstock_root/ci_support/upload_or_check_non_existence.py /recipe_root conda-forge --channel=main || exit 1 50 | EOF 51 | -------------------------------------------------------------------------------- /recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: conda-forge-build-setup 3 | version: 3.2.0 4 | 5 | build: 6 | number: 0 7 | script: 8 | - if not exist "%LIBRARY_BIN%" mkdir "%LIBRARY_BIN%" # [win] 9 | - mkdir -p "${PREFIX}/bin" # [unix] 10 | - COPY "%RECIPE_DIR%\\run_conda_forge_build_setup_win.bat" "%SCRIPTS%\\run_conda_forge_build_setup.bat" # [win] 11 | - cp "${RECIPE_DIR}/run_conda_forge_build_setup_osx" "${PREFIX}/bin/run_conda_forge_build_setup" # [osx] 12 | - cp "${RECIPE_DIR}/run_conda_forge_build_setup_linux" "${PREFIX}/bin/run_conda_forge_build_setup" # [linux] 13 | - COPY "%RECIPE_DIR%\\upload_or_check_non_existence.py" "%SCRIPTS%\\upload_or_check_non_existence.py" # [win] 14 | - cp "${RECIPE_DIR}/upload_or_check_non_existence.py" "${PREFIX}/bin/upload_or_check_non_existence.py" # [osx] 15 | 16 | test: 17 | commands: 18 | - if not exist "%SCRIPTS%\\run_conda_forge_build_setup.bat" exit 1 # [win] 19 | - test -f "${PREFIX}/bin/run_conda_forge_build_setup" # [unix] 20 | 21 | about: 22 | home: https://github.com/conda-forge/conda-forge-build-setup-feedstock 23 | summary: A package installed by conda-forge each time a build is run on CI. This package has side-effects to your conda config. 24 | license: BSD 3-clause 25 | 26 | extra: 27 | recipe-maintainers: 28 | - jakirkham 29 | - ocefpaf 30 | - pelson 31 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This file was generated automatically from conda-smithy. To update this configuration, 2 | # update the conda-forge.yaml and/or the recipe/meta.yaml. 3 | 4 | language: objective-c 5 | 6 | env: 7 | global: 8 | # The BINSTAR_TOKEN secure variable. This is defined canonically in conda-forge.yml. 9 | - secure: "D1ZSq6vdkjuDXW+MWSPR3A7mmp5ASwA1HGHRjpG5GA/FxoK012XWTWeQW6qcVDTPGEkAXdAtrxdkg9Fn7s7C2efxfMZvLdH4F+nBuqCiTzBFqAwwkL0CeP2rMfZc8mo5fPpnaoZMA4zKm6ssyO1XUPhzlv0WKQOdBe3h04fXQZGF4ar630e4LDVUgfE5HMFUivxpm09AW9QJ53n4AaCcpW379Qa8IGaO3g53IZN4JqtZ8sXvDkCDHPnEZUAgzS+pgq4DS7Gj2T79o1PfZwpLuSwPVO9cAtRFQ5EfAIPH9oUFuW9TNYtX3ruRSuPl6cjCp7jG9XoggGae5VMElUDwtTlfJadOaHQJNlxQUN0WZBPSetitdcVc2IGDNS4aFBSWhBGh/FdrMSRqv7dvdLreLCBTQ8AWz9tW/IB6LvfqngdaWSNGLb4Ntbft1yWx1t5d9TlsLmpWL0MBIbg16vd2Yccfe4out85aSa9UyZXsvVoEmsoeOJ+XvonYLHB2PfC90miSIGElLWt1ncoUASIZ1iv86iTnamFnaKCq2T4XebllDOVeQ7iASvZmDfs5om23VNZqVBtEx2MUz4bHGOH/gnqkxXwHdVsX1N7NYJwO7g03dJW/xGlKR+UxCsa9C8Bx48ubsvhn/u/VXnc68mN20DCMNHptQQts5MVUEZNocAU=" 10 | 11 | 12 | before_install: 13 | # Remove homebrew. 14 | - brew remove --force $(brew list) 15 | - brew cleanup -s 16 | - rm -rf $(brew --cache) 17 | 18 | install: 19 | - | 20 | MINICONDA_URL="http://repo.continuum.io/miniconda" 21 | MINICONDA_FILE="Miniconda3-latest-MacOSX-x86_64.sh" 22 | curl -O "${MINICONDA_URL}/${MINICONDA_FILE}" 23 | bash $MINICONDA_FILE -b 24 | 25 | export PATH=/Users/travis/miniconda3/bin:$PATH 26 | 27 | conda config --set show_channel_urls true 28 | conda update --yes conda 29 | conda install --yes conda-build jinja2 anaconda-client 30 | conda config --add channels conda-forge 31 | conda install --yes conda-build=1 32 | 33 | 34 | script: 35 | - conda build ./recipe 36 | 37 | after_success: 38 | 39 | - ./ci_support/upload_or_check_non_existence.py ./recipe conda-forge --channel=main 40 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by conda-smithy. To update a component of this 2 | # file, make changes to conda-forge.yaml and/or recipe/meta.yaml, and run 3 | # "conda-smithy regenerate". 4 | 5 | environment: 6 | 7 | CONDA_INSTALL_LOCN: "C:\\conda" 8 | 9 | # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the 10 | # /E:ON and /V:ON options are not enabled in the batch script intepreter 11 | # See: http://stackoverflow.com/a/13751649/163740 12 | CMD_IN_ENV: "cmd /E:ON /V:ON /C obvci_appveyor_python_build_env.cmd" 13 | 14 | # We set a default Python version for the miniconda that is to be installed. This can be 15 | # overridden in the matrix definition where appropriate. 16 | CONDA_PY: "27" 17 | BINSTAR_TOKEN: 18 | # The BINSTAR_TOKEN secure variable. This is defined canonically in conda-forge.yml. 19 | secure: MP4hZYylDyUWEsrt3u3cod2sbFeRwUziH02mvQOdbjsTO/l1yIxDkP/76rSIjcGC 20 | 21 | matrix: 22 | - TARGET_ARCH: x86 23 | 24 | - TARGET_ARCH: x64 25 | 26 | 27 | # We always use a 64-bit machine, but can build x86 distributions 28 | # with the TARGET_ARCH variable. 29 | platform: 30 | - x64 31 | 32 | install: 33 | # If there is a newer build queued for the same PR, cancel this one. 34 | # The AppVeyor 'rollout builds' option is supposed to serve the same 35 | # purpose but it is problematic because it tends to cancel builds pushed 36 | # directly to master instead of just PR builds (or the converse). 37 | # credits: JuliaLang developers. 38 | - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` 39 | https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` 40 | Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` 41 | throw "There are newer queued builds for this pull request, failing early." } 42 | 43 | # Cywing's git breaks conda-build. (See https://github.com/conda-forge/conda-smithy-feedstock/pull/2.) 44 | - cmd: rmdir C:\cygwin /s /q 45 | - appveyor DownloadFile "https://raw.githubusercontent.com/pelson/Obvious-CI/master/bootstrap-obvious-ci-and-miniconda.py" 46 | - cmd: python bootstrap-obvious-ci-and-miniconda.py %CONDA_INSTALL_LOCN% %TARGET_ARCH% %CONDA_PY:~0,1% --without-obvci 47 | - cmd: set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH% 48 | - cmd: set PYTHONUNBUFFERED=1 49 | 50 | - cmd: conda config --set show_channel_urls true 51 | - cmd: conda install -c pelson/channel/development --yes --quiet obvious-ci 52 | - cmd: conda config --add channels conda-forge 53 | - cmd: conda info 54 | - cmd: conda install -n root --quiet --yes conda-build anaconda-client jinja2 setuptools 55 | # Workaround for Python 3.4 and x64 bug in latest conda-build. 56 | # FIXME: Remove once there is a release that fixes the upstream issue 57 | # ( https://github.com/conda/conda-build/issues/895 ). 58 | - cmd: if "%TARGET_ARCH%" == "x64" if "%CONDA_PY%" == "34" conda install conda-build=1.20.0 --yes 59 | - cmd: conda install -n root --quiet --yes conda-build=1 60 | 61 | # Skip .NET project specific build phase. 62 | build: off 63 | 64 | test_script: 65 | - "%CMD_IN_ENV% conda build recipe --quiet" 66 | deploy_script: 67 | 68 | - 'python ci_support\upload_or_check_non_existence.py .\recipe conda-forge --channel=main' 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | About conda-forge-build-setup 2 | ============================= 3 | 4 | Home: https://github.com/conda-forge/conda-forge-build-setup-feedstock 5 | 6 | Package license: BSD 3-clause 7 | 8 | Feedstock license: BSD 3-Clause 9 | 10 | Summary: A package installed by conda-forge each time a build is run on CI. This package has side-effects to your conda config. 11 | 12 | 13 | 14 | Installing conda-forge-build-setup 15 | ================================== 16 | 17 | Installing conda-forge-build-setup from the conda-forge channel can be achieved by adding conda-forge to your channels with: 18 | 19 | ``` 20 | conda config --add channels conda-forge 21 | ``` 22 | 23 | Once the conda-forge channel has been enabled, conda-forge-build-setup can be installed with: 24 | 25 | ``` 26 | conda install conda-forge-build-setup 27 | ``` 28 | 29 | It is possible to list all of the versions of conda-forge-build-setup available on your platform with: 30 | 31 | ``` 32 | conda search conda-forge-build-setup --channel conda-forge 33 | ``` 34 | 35 | 36 | About conda-forge 37 | ================= 38 | 39 | conda-forge is a community-led conda channel of installable packages. 40 | In order to provide high-quality builds, the process has been automated into the 41 | conda-forge GitHub organization. The conda-forge organization contains one repository 42 | for each of the installable packages. Such a repository is known as a *feedstock*. 43 | 44 | A feedstock is made up of a conda recipe (the instructions on what and how to build 45 | the package) and the necessary configurations for automatic building using freely 46 | available continuous integration services. Thanks to the awesome service provided by 47 | [CircleCI](https://circleci.com/), [AppVeyor](http://www.appveyor.com/) 48 | and [TravisCI](https://travis-ci.org/) it is possible to build and upload installable 49 | packages to the [conda-forge](https://anaconda.org/conda-forge) 50 | [Anaconda-Cloud](http://docs.anaconda.org/) channel for Linux, Windows and OSX respectively. 51 | 52 | To manage the continuous integration and simplify feedstock maintenance 53 | [conda-smithy](http://github.com/conda-forge/conda-smithy) has been developed. 54 | Using the ``conda-forge.yml`` within this repository, it is possible to regenerate all of 55 | this feedstock's supporting files (e.g. the CI configuration files) with ``conda smithy regenerate``. 56 | 57 | 58 | Terminology 59 | =========== 60 | 61 | **feedstock** - the conda recipe (raw material), supporting scripts and CI configuration. 62 | 63 | **conda-smithy** - the tool which helps orchestrate the feedstock. 64 | Its primary use is in the construction of the CI ``.yml`` files 65 | and simplify the management of *many* feedstocks. 66 | 67 | **conda-forge** - the place where the feedstock and smithy live and work to 68 | produce the finished article (built conda distributions) 69 | 70 | Current build status 71 | ==================== 72 | 73 | Linux: [![Circle CI](https://circleci.com/gh/conda-forge/conda-forge-build-setup-feedstock.svg?style=svg)](https://circleci.com/gh/conda-forge/conda-forge-build-setup-feedstock) 74 | OSX: [![TravisCI](https://travis-ci.org/conda-forge/conda-forge-build-setup-feedstock.svg?branch=master)](https://travis-ci.org/conda-forge/conda-forge-build-setup-feedstock) 75 | Windows: [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/conda-forge/conda-forge-build-setup-feedstock?svg=True)](https://ci.appveyor.com/project/conda-forge/conda-forge-build-setup-feedstock/branch/master) 76 | 77 | Current release info 78 | ==================== 79 | Version: [![Anaconda-Server Badge](https://anaconda.org/conda-forge/conda-forge-build-setup/badges/version.svg)](https://anaconda.org/conda-forge/conda-forge-build-setup) 80 | Downloads: [![Anaconda-Server Badge](https://anaconda.org/conda-forge/conda-forge-build-setup/badges/downloads.svg)](https://anaconda.org/conda-forge/conda-forge-build-setup) 81 | 82 | 83 | Updating conda-forge-build-setup-feedstock 84 | ========================================== 85 | 86 | If you would like to improve the conda-forge-build-setup recipe, please take the normal 87 | route of forking this repository and submitting a PR. Upon submission, your changes will 88 | be run on the appropriate platforms to give the reviewer an opportunity to confirm that the 89 | changes result in a successful build. Once merged, the recipe will be re-built and uploaded 90 | automatically to the conda-forge channel, whereupon they will be available for everybody to 91 | install and use. 92 | 93 | In order to produce a uniquely identifiable distribution: 94 | * If the version of a package **is not** being increased, please add or increase 95 | the [``build/number``](http://conda.pydata.org/docs/building/meta-yaml.html#build-number-and-string). 96 | * If the version of a package **is** being increased, please remember to return 97 | the [``build/number``](http://conda.pydata.org/docs/building/meta-yaml.html#build-number-and-string) 98 | back to 0. 99 | -------------------------------------------------------------------------------- /ci_support/upload_or_check_non_existence.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | 4 | import argparse 5 | import hashlib 6 | import os 7 | import subprocess 8 | import sys 9 | 10 | from binstar_client.utils import get_binstar 11 | import binstar_client.errors 12 | import conda.config 13 | from conda_build.metadata import MetaData 14 | from conda_build.build import bldpkg_path 15 | 16 | 17 | def built_distribution_already_exists(cli, meta, owner): 18 | """ 19 | Checks to see whether the built recipe (aka distribution) already 20 | exists on the owner/user's binstar account. 21 | 22 | """ 23 | distro_name = '{}/{}.tar.bz2'.format(conda.config.subdir, meta.dist()) 24 | fname = bldpkg_path(meta) 25 | try: 26 | dist_info = cli.distribution(owner, meta.name(), meta.version(), 27 | distro_name) 28 | except binstar_client.errors.NotFound: 29 | dist_info = {} 30 | 31 | exists = bool(dist_info) 32 | # Unfortunately, we cannot check the md5 quality of the built distribution, as 33 | # this will depend on fstat information such as modification date (because 34 | # distributions are tar files). Therefore we can only assume that the distribution 35 | # just built, and the one on anaconda.org are the same. 36 | # if exists: 37 | # md5_on_binstar = dist_info.get('md5') 38 | # with open(fname, 'rb') as fh: 39 | # md5_of_build = hashlib.md5(fh.read()).hexdigest() 40 | # 41 | # if md5_on_binstar != md5_of_build: 42 | # raise ValueError('This build ({}), and the build already on binstar ' 43 | # '({}) are different.'.format(md5_of_build, md5_on_binstar)) 44 | return exists 45 | 46 | 47 | def upload(cli, meta, owner, channels): 48 | try: 49 | with open('binstar.token', 'w') as fh: 50 | fh.write(cli.token) 51 | subprocess.check_call(['anaconda', '--quiet', '-t', 'binstar.token', 52 | 'upload', bldpkg_path(meta), 53 | '--user={}'.format(owner), 54 | '--channel={}'.format(channels)], 55 | env=os.environ) 56 | finally: 57 | os.remove('binstar.token') 58 | 59 | 60 | def distribution_exists_on_channel(binstar_cli, meta, owner, channel='main'): 61 | """ 62 | Determine whether a distribution exists on a specific channel. 63 | 64 | Note from @pelson: As far as I can see, there is no easy way to do this on binstar. 65 | 66 | """ 67 | fname = '{}/{}.tar.bz2'.format(conda.config.subdir, meta.dist()) 68 | distributions_on_channel = [dist['basename'] for dist in 69 | binstar_cli.show_channel(owner=owner, channel=channel)['files']] 70 | return fname in distributions_on_channel 71 | 72 | 73 | def add_distribution_to_channel(binstar_cli, meta, owner, channel='main'): 74 | """ 75 | Add a(n already existing) distribution on binstar to another channel. 76 | 77 | Note - the addition is done based on name and version - no build strings etc. 78 | so if you have a foo-0.1-np18 and foo-0.1-np19 *both* will be added to the channel. 79 | 80 | """ 81 | package_fname = '{}/{}.tar.bz2'.format(conda.config.subdir, meta.dist()) 82 | binstar_cli.add_channel(channel, owner, meta.name(), meta.version()) 83 | 84 | 85 | def main(): 86 | token = os.environ.get('BINSTAR_TOKEN') 87 | 88 | description = ('Upload or check consistency of a built version of a ' 89 | 'conda recipe with binstar. Note: The existence of the ' 90 | 'BINSTAR_TOKEN environment variable determines ' 91 | 'whether the upload should actually take place.') 92 | parser = argparse.ArgumentParser(description=description) 93 | parser.add_argument('recipe_dir', help='the conda recipe directory') 94 | parser.add_argument('owner', help='the binstar owner/user') 95 | parser.add_argument('--channel', help='the binstar channel', default='main') 96 | args = parser.parse_args() 97 | recipe_dir, owner, channel = args.recipe_dir, args.owner, args.channel 98 | 99 | cli = get_binstar(argparse.Namespace(token=token, site=None)) 100 | meta = MetaData(recipe_dir) 101 | if meta.skip(): 102 | print("No upload to take place - this configuration was skipped in build/skip.") 103 | return 104 | exists = built_distribution_already_exists(cli, meta, owner) 105 | if token: 106 | on_channel = distribution_exists_on_channel(cli, meta, owner, channel) 107 | if not exists: 108 | upload(cli, meta, owner, channel) 109 | print('Uploaded {}'.format(bldpkg_path(meta))) 110 | elif not on_channel: 111 | print('Adding distribution {} to {}\'s {} channel' 112 | ''.format(bldpkg_path(meta), owner, channel)) 113 | add_distribution_to_channel(cli, meta, owner, channel) 114 | else: 115 | print('Distribution {} already \nexists on {}\'s {} channel.' 116 | ''.format(bldpkg_path(meta), owner, channel)) 117 | else: 118 | print("No BINSTAR_TOKEN present, so no upload is taking place. " 119 | "The distribution just built {} already available on {}'s " 120 | "{} channel.".format('is' if exists else 'is not', 121 | owner, channel)) 122 | 123 | if __name__ == '__main__': 124 | main() 125 | -------------------------------------------------------------------------------- /recipe/upload_or_check_non_existence.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | 4 | import argparse 5 | import hashlib 6 | import os 7 | import subprocess 8 | import sys 9 | 10 | from binstar_client.utils import get_binstar 11 | import binstar_client.errors 12 | import conda.config 13 | from conda.api import get_index 14 | from conda_build.metadata import MetaData 15 | from conda_build.build import bldpkg_path 16 | 17 | 18 | def built_distribution_already_exists(cli, meta, owner): 19 | """ 20 | Checks to see whether the built recipe (aka distribution) already 21 | exists on the owner/user's binstar account. 22 | 23 | """ 24 | distro_name = '{}/{}.tar.bz2'.format(conda.config.subdir, meta.dist()) 25 | fname = bldpkg_path(meta) 26 | try: 27 | dist_info = cli.distribution(owner, meta.name(), meta.version(), 28 | distro_name) 29 | except binstar_client.errors.NotFound: 30 | dist_info = {} 31 | 32 | exists = bool(dist_info) 33 | # Unfortunately, we cannot check the md5 quality of the built distribution, as 34 | # this will depend on fstat information such as modification date (because 35 | # distributions are tar files). Therefore we can only assume that the distribution 36 | # just built, and the one on anaconda.org are the same. 37 | # if exists: 38 | # md5_on_binstar = dist_info.get('md5') 39 | # with open(fname, 'rb') as fh: 40 | # md5_of_build = hashlib.md5(fh.read()).hexdigest() 41 | # 42 | # if md5_on_binstar != md5_of_build: 43 | # raise ValueError('This build ({}), and the build already on binstar ' 44 | # '({}) are different.'.format(md5_of_build, md5_on_binstar)) 45 | return exists 46 | 47 | 48 | def upload(cli, meta, owner, channels): 49 | try: 50 | with open('binstar.token', 'w') as fh: 51 | fh.write(cli.token) 52 | subprocess.check_call(['anaconda', '--quiet', '-t', 'binstar.token', 53 | 'upload', bldpkg_path(meta), 54 | '--user={}'.format(owner), 55 | '--channel={}'.format(channels)], 56 | env=os.environ) 57 | finally: 58 | os.remove('binstar.token') 59 | 60 | 61 | def distribution_exists_on_channel(binstar_cli, meta, owner, channel='main'): 62 | """ 63 | Determine whether a distribution exists on a specific channel. 64 | 65 | Note from @pelson: As far as I can see, there is no easy way to do this on binstar. 66 | 67 | """ 68 | fname = '{}.tar.bz2'.format(meta.dist()) 69 | channel_url = '/'.join([owner, 'label', channel]) 70 | 71 | distributions_on_channel = get_index([channel_url], 72 | prepend=False, use_cache=False) 73 | 74 | try: 75 | on_channel = (distributions_on_channel[fname]['subdir'] == 76 | conda.config.subdir) 77 | except KeyError: 78 | on_channel = False 79 | 80 | return on_channel 81 | 82 | 83 | def add_distribution_to_channel(binstar_cli, meta, owner, channel='main'): 84 | """ 85 | Add a(n already existing) distribution on binstar to another channel. 86 | 87 | Note - the addition is done based on name and version - no build strings etc. 88 | so if you have a foo-0.1-np18 and foo-0.1-np19 *both* will be added to the channel. 89 | 90 | """ 91 | package_fname = '{}/{}.tar.bz2'.format(conda.config.subdir, meta.dist()) 92 | binstar_cli.add_channel(channel, owner, meta.name(), meta.version()) 93 | 94 | 95 | def main(): 96 | token = os.environ.get('BINSTAR_TOKEN') 97 | 98 | description = ('Upload or check consistency of a built version of a ' 99 | 'conda recipe with binstar. Note: The existence of the ' 100 | 'BINSTAR_TOKEN environment variable determines ' 101 | 'whether the upload should actually take place.') 102 | parser = argparse.ArgumentParser(description=description) 103 | parser.add_argument('recipe_dir', help='the conda recipe directory') 104 | parser.add_argument('owner', help='the binstar owner/user') 105 | parser.add_argument('--channel', help='the binstar channel', default='main') 106 | args = parser.parse_args() 107 | recipe_dir, owner, channel = args.recipe_dir, args.owner, args.channel 108 | 109 | cli = get_binstar(argparse.Namespace(token=token, site=None)) 110 | meta = MetaData(recipe_dir) 111 | if meta.skip(): 112 | print("No upload to take place - this configuration was skipped in build/skip.") 113 | return 114 | exists = built_distribution_already_exists(cli, meta, owner) 115 | if token: 116 | on_channel = distribution_exists_on_channel(cli, meta, owner, channel) 117 | if not exists: 118 | upload(cli, meta, owner, channel) 119 | print('Uploaded {}'.format(bldpkg_path(meta))) 120 | elif not on_channel: 121 | print('Adding distribution {} to {}\'s {} channel' 122 | ''.format(bldpkg_path(meta), owner, channel)) 123 | add_distribution_to_channel(cli, meta, owner, channel) 124 | else: 125 | print('Distribution {} already \nexists on {}\'s {} channel.' 126 | ''.format(bldpkg_path(meta), owner, channel)) 127 | else: 128 | print("No BINSTAR_TOKEN present, so no upload is taking place. " 129 | "The distribution just built {} already available on {}'s " 130 | "{} channel.".format('is' if exists else 'is not', 131 | owner, channel)) 132 | 133 | if __name__ == '__main__': 134 | main() 135 | --------------------------------------------------------------------------------