Skip to content

Instantly share code, notes, and snippets.

@mbdevpl
Last active April 17, 2018 08:59
Show Gist options
  • Save mbdevpl/46d458350f0c9cc7d793b67573e01f7b to your computer and use it in GitHub Desktop.
Save mbdevpl/46d458350f0c9cc7d793b67573e01f7b to your computer and use it in GitHub Desktop.

Deployment config samples

The prepare_bintray_deployment.py script can be used in the following ways.

Travis

before_deploy:
  - pip3 install -U --user version_query || pip3 install -U version_query
  - wget https://gist.githubusercontent.com/mbdevpl/46d458350f0c9cc7d793b67573e01f7b/raw/prepare_bintray_deployment.py
  - python3 prepare_bintray_deployment.py "platform" "pattern1" "pattern2" "pattern3"

deploy:
  - provider: bintray
    file: ".bintray.json"
    user: "bintray_username"
    key:
      secure: "blahblah"
    on:
      all_branches: true
    skip_cleanup: true

AppVeyor

after_test:
  # Bintray archive preparation
  - python -m pip install version_query
  - ps: Invoke-WebRequest "https://gist.githubusercontent.com/mbdevpl/46d458350f0c9cc7d793b67573e01f7b/raw/prepare_bintray_deployment.py" -OutFile "prepare_bintray_deployment.py"
  - python prepare_bintray_deployment.py "platform" "pattern1" "pattern2" "pattern3"
  - set /p BINTRAY_VERSION=<.bintray_version.txt

artifacts:
  - path: pattern1
  - path: pattern2
  - path: pattern3
  - path: '*-bintray.zip'

deploy:
  - provider: BinTray
    username: $(APPVEYOR_ACCOUNT_NAME)
    api_key:
      secure: abcdefgh
    subject: $(APPVEYOR_ACCOUNT_NAME)
    repo: pkgs
    package: $(APPVEYOR_PROJECT_NAME)
    version: $(BINTRAY_VERSION)
    publish: true
    override: true
    explode: true
    artifact: /.*-bintray\.zip/
#!/usr/bin/env python3
"""Automate preparation of files for deployment to Bintray from CI.
Currently works with:
- Travis CI
- AppVeyor
"""
import json
import logging
import os
import pathlib
import sys
import zipfile
from version_query import predict_version_str
__updated__ = '2018-04-16'
_LOG = logging.getLogger(__name__)
BINTRAY_DESCRIPTOR_PATH = pathlib.Path('.bintray.json')
BINTRAY_ARCHIVE_SUFFIX = '-bintray.zip'
BINTRAY_VERSION_PATH = pathlib.Path('.bintray_version.txt')
def preprocess_git_version_tag(tag: str):
"""Remove a prefix from a version tag."""
# TODO: this will be in version_query
if tag.startswith('ver'):
return tag[3:]
if tag.startswith('v'):
return tag[1:]
if tag and tag[0] in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'):
return tag
raise ValueError('given tag "{}" does not appear to be a version tag'.format(tag))
def query_provider():
"""Determine on which CI this script is running."""
if os.environ.get('TRAVIS', None):
return "travis"
if os.environ.get('APPVEYOR', None):
return "appveyor"
raise NotImplementedError('could not detect the provider')
def query_build_metadata(provider: str):
"""Gather build metadata to prepare deployment."""
provider = provider.lower()
if provider == 'travis':
owner, _, project = os.environ['TRAVIS_REPO_SLUG'].partition('/')
return {
'owner': owner,
'project': project,
'sha': os.environ['TRAVIS_COMMIT'],
'tag': os.environ.get('TRAVIS_TAG', None)}
if provider == 'appveyor':
return {
'owner': os.environ['APPVEYOR_ACCOUNT_NAME'],
'project': os.environ['APPVEYOR_PROJECT_NAME'],
'sha': os.environ['APPVEYOR_REPO_COMMIT'],
'tag': os.environ.get('APPVEYOR_REPO_TAG_NAME', None)}
raise NotImplementedError('provider {} is not supported'.format(provider))
def determine_deployed_version(metadata):
"""Prepare exact version identifier for the deployed package."""
if metadata['tag']:
try:
return preprocess_git_version_tag(metadata['tag'])
except ValueError:
_LOG.warning('keeping non-version tag %s as-is', metadata['tag'])
return metadata['tag']
default_version = predict_version_str()
if '+' in default_version:
return default_version
return '{}+{}'.format(default_version, metadata['sha'][:8])
def prepare_for_deployment(platform: str, *artifact_patterns):
"""Prepare for Bintray deployment."""
provider = query_provider()
_LOG.info('executing on %s', provider)
metadata = query_build_metadata(provider)
_LOG.info('gathered build metadata %s', metadata)
version = determine_deployed_version(metadata)
if provider == 'travis':
vcs_label = metadata['tag'] if metadata['tag'] else metadata['sha']
make_travis_bintray_descriptor(metadata['owner'], metadata['project'], version, platform,
vcs_label, *artifact_patterns)
elif provider == 'appveyor':
make_appveyor_bintray_archive(metadata['project'], version, platform, *artifact_patterns)
with BINTRAY_VERSION_PATH.open('w') as version_file:
print(version, file=version_file)
_LOG.info('prepared AppVeyor bintray version file at "%s"', BINTRAY_VERSION_PATH.resolve())
with BINTRAY_VERSION_PATH.open('r') as version_file:
_LOG.debug('the version in the bintray version file:\n%s', version_file.read())
def make_travis_bintray_descriptor(subject: str, package: str, version: str, platform: str,
vcs_label: str, *artifact_patterns):
"""Generate the Bintray descriptor file for Travis CI deployment."""
_LOG.info('making Travis bintray descriptor')
upload_path = pathlib.Path('{}-v{}'.format(package, version), platform)
files = []
for artifact_pattern in artifact_patterns:
for pth in pathlib.Path('.').glob(artifact_pattern):
if not pth.is_file():
continue
moved_pth = pth
if '+' in str(pth):
moved_pth = pathlib.Path(str(pth).replace('+', '_'))
_LOG.warning('renaming "%s" to "%s" because of "+" in the path', pth, moved_pth)
pth.rename(moved_pth)
files.append({'includePattern': str(moved_pth),
'uploadPattern': str(upload_path.joinpath(pth.name))})
if files:
_LOG.debug('files to be uploaded: %s', files)
else:
_LOG.error('no files to be uploaded')
data = {
'package': {'subject': subject, 'repo': 'pkgs', 'name': package},
'version': {
'name': version, 'desc': '', 'released': '',
'vcs_tag': vcs_label,
'attributes': [], 'gpgSign': False},
'files': files,
'publish': True}
with BINTRAY_DESCRIPTOR_PATH.open('w') as desc_file:
json.dump(data, desc_file, indent='\t')
_LOG.info('prepared Travis bintray descriptor at "%s"', BINTRAY_DESCRIPTOR_PATH.resolve())
with BINTRAY_DESCRIPTOR_PATH.open('r') as desc_file:
_LOG.debug('the descriptor file:\n%s', desc_file.read())
def make_appveyor_bintray_archive(package: str, version: str, platform: str, *artifact_patterns):
"""Generate the Bintray archive for AppVeyor deployment."""
_LOG.info('making AppVeyor bintray archive')
zip_path = '{}-v{}-{}{}'.format(package, version, platform, BINTRAY_ARCHIVE_SUFFIX)
archive_dir = pathlib.Path('{}-v{}'.format(package, version), platform)
with zipfile.ZipFile(zip_path, 'w' if sys.version_info < (3, 5) else 'x') as zip_file:
for artifact_pattern in artifact_patterns:
for pth in pathlib.Path('.').glob(artifact_pattern):
if pth.is_file():
archived_path = archive_dir.joinpath(pth.name)
zip_file.write(str(pth), str(archived_path))
_LOG.debug('added "%s" to archive as "%s"', pth, archived_path)
_LOG.info('prepared AppVeyor bintray archive at "%s"', pathlib.Path(zip_path).resolve())
def main(args=None):
if args is None:
args = sys.argv[1:]
_LOG.info('using script args: %s', args)
prepare_for_deployment(*args)
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment