163 lines
5.8 KiB
Python
Executable File
163 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import textwrap
|
|
import time
|
|
from collections import namedtuple
|
|
from glob import glob
|
|
from pathlib import Path
|
|
from subprocess import run
|
|
from urllib.parse import quote
|
|
|
|
import click
|
|
|
|
|
|
def shell(cmd, **kwargs):
|
|
return run([cmd], shell=True, **kwargs)
|
|
|
|
|
|
def git_repo_has_changes():
|
|
unstaged_changes = shell('git diff-index --quiet HEAD --').returncode != 0
|
|
staged_changes = shell('git diff-index --quiet --cached HEAD --').returncode != 0
|
|
return unstaged_changes or staged_changes
|
|
|
|
|
|
def generate_basic_project(path):
|
|
sys.path.insert(0, '')
|
|
from test.test_projects.c import new_c_project
|
|
|
|
project = new_c_project()
|
|
project.generate(path)
|
|
|
|
|
|
CIService = namedtuple('CIService', 'name dst_config_path badge_md')
|
|
services = [
|
|
CIService(
|
|
name='appveyor',
|
|
dst_config_path='appveyor.yml',
|
|
badge_md='[](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/{branch})',
|
|
),
|
|
CIService(
|
|
name='azure-pipelines',
|
|
dst_config_path='azure-pipelines.yml',
|
|
badge_md='[](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=2&branchName={branch})',
|
|
),
|
|
CIService(
|
|
name='circleci',
|
|
dst_config_path='.circleci/config.yml',
|
|
badge_md='[](https://circleci.com/gh/joerick/cibuildwheel/tree/{branch})',
|
|
),
|
|
CIService(
|
|
name='github',
|
|
dst_config_path='.github/workflows/example.yml',
|
|
badge_md='[](https://github.com/joerick/cibuildwheel/actions)',
|
|
),
|
|
CIService(
|
|
name='travis-ci',
|
|
dst_config_path='.travis.yml',
|
|
badge_md='[](https://travis-ci.org/joerick/cibuildwheel)',
|
|
),
|
|
CIService(
|
|
name='gitlab',
|
|
dst_config_path='.gitlab-ci.yml',
|
|
badge_md='[](https://gitlab.com/joerick/cibuildwheel/-/commits/{branch})'
|
|
),
|
|
]
|
|
|
|
|
|
def ci_service_for_config_file(config_file):
|
|
service_name = Path(config_file).name.rsplit('-', 1)[0]
|
|
|
|
for service in services:
|
|
if service.name == service_name:
|
|
return service
|
|
|
|
raise ValueError(f'unknown ci service for config file {config_file}')
|
|
|
|
|
|
@click.command()
|
|
@click.argument('config_files', nargs=-1, type=click.Path())
|
|
def run_example_ci_configs(config_files=None):
|
|
'''
|
|
Test the example configs. If no files are specified, will test
|
|
examples/*-minimal.yml
|
|
'''
|
|
|
|
if len(config_files) == 0:
|
|
config_files = glob('examples/*-minimal.yml')
|
|
|
|
# check each CI service has at most 1 config file
|
|
configs_by_service = {}
|
|
for config_file in config_files:
|
|
service = ci_service_for_config_file(config_file)
|
|
if service.name in configs_by_service:
|
|
raise Exception('You cannot specify more than one config per CI service')
|
|
configs_by_service[service.name] = config_file
|
|
|
|
if git_repo_has_changes():
|
|
print('Your git repo has uncommitted changes. Commit or stash before continuing.')
|
|
exit(1)
|
|
|
|
previous_branch = shell('git rev-parse --abbrev-ref HEAD',
|
|
check=True,
|
|
capture_output=True,
|
|
encoding='utf8').stdout.strip()
|
|
|
|
timestamp = time.strftime('%Y-%m-%dT%H-%M-%S', time.gmtime())
|
|
branch_name = f'example-config-test---{previous_branch}-{timestamp}'
|
|
|
|
try:
|
|
shell(f'git checkout --orphan {branch_name}', check=True)
|
|
|
|
example_project = Path('example_root')
|
|
generate_basic_project(example_project)
|
|
|
|
for config_file in config_files:
|
|
service = ci_service_for_config_file(config_file)
|
|
src_config_file = Path(config_file)
|
|
dst_config_file = example_project / service.dst_config_path
|
|
|
|
dst_config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copyfile(src_config_file, dst_config_file)
|
|
|
|
run(['git', 'add', example_project], check=True)
|
|
run(['git', 'commit', '--no-verify', '-m', textwrap.dedent(f'''
|
|
Test example minimal configs
|
|
|
|
Testing files: {config_files}
|
|
Generated from branch: {previous_branch}
|
|
Time: {timestamp}
|
|
''')], check=True)
|
|
shell(f'git subtree --prefix={example_project} push origin {branch_name}', check=True)
|
|
|
|
print('---')
|
|
print()
|
|
print('> **Examples test run**')
|
|
print('> ')
|
|
print(f'> Branch: [{branch_name}](https://github.com/joerick/cibuildwheel/tree/{branch_name})')
|
|
print('> ')
|
|
print('> | Service | Config | Status |')
|
|
print('> |---|---|---|')
|
|
for config_file in config_files:
|
|
service = ci_service_for_config_file(config_file)
|
|
badge = service.badge_md.format(branch=branch_name, branch_escaped=quote(branch_name, safe=''))
|
|
print(f'> | {service.name} | `{config_file}` | {badge} |')
|
|
print('> ')
|
|
print('> Generated by `bin/run_example_ci_config.py`')
|
|
print()
|
|
print('---')
|
|
finally:
|
|
# remove any local changes
|
|
shutil.rmtree(example_project, ignore_errors=True)
|
|
shell('git checkout -- .')
|
|
shell(f'git checkout {previous_branch}', check=True)
|
|
shell(f'git branch -D --force {branch_name}', check=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
os.chdir(os.path.dirname(__file__))
|
|
os.chdir('..')
|
|
run_example_ci_configs(standalone_mode=True)
|