From 507376549cc8c999109bd25b60ddf1e70429277a Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 27 Apr 2018 12:24:43 -0700 Subject: [PATCH 1/9] Improve release automation Signed-off-by: Joffrey F --- script/release/release.py | 17 +++++++++++------ script/release/release.sh | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/script/release/release.py b/script/release/release.py index add8fb2d3..4357e36b9 100755 --- a/script/release/release.py +++ b/script/release/release.py @@ -78,10 +78,9 @@ def monitor_pr_status(pr_data): continue summary[detail.state] += 1 print('{pending} pending, {success} successes, {failure} failures'.format(**summary)) - if status.total_count == 0: - # Mostly for testing purposes against repos with no CI setup - return True - elif summary['pending'] == 0 and summary['failure'] == 0: + if summary['pending'] == 0 and summary['failure'] == 0 and summary['success'] > 0: + # This check assumes at least 1 non-DCO CI check to avoid race conditions. + # If testing on a repo without CI, use --skip-ci-check to avoid looping eternally return True elif summary['failure'] > 0: raise ScriptError('CI failures detected!') @@ -156,7 +155,8 @@ def resume(args): if not pr_data: pr_data = repository.create_release_pull_request(args.release) check_pr_mergeable(pr_data) - monitor_pr_status(pr_data) + if not args.skip_ci: + monitor_pr_status(pr_data) downloader = BinaryDownloader(args.destination) files = downloader.download_all(args.release) if not gh_release: @@ -195,7 +195,8 @@ def start(args): create_initial_branch(repository, args) pr_data = repository.create_release_pull_request(args.release) check_pr_mergeable(pr_data) - monitor_pr_status(pr_data) + if not args.skip_ci: + monitor_pr_status(pr_data) downloader = BinaryDownloader(args.destination) files = downloader.download_all(args.release) gh_release = create_release_draft(repository, args.release, pr_data, files) @@ -310,6 +311,10 @@ def main(): '--no-cherries', '-C', dest='cherries', action='store_false', help='If set, the program will not prompt the user for PR numbers to cherry-pick' ) + parser.add_argument( + '--skip-ci-checks', dest='skip_ci', action='store_true', + help='If set, the program will not wait for CI jobs to complete' + ) args = parser.parse_args() if args.action == 'start': diff --git a/script/release/release.sh b/script/release/release.sh index 2310429aa..f592365d3 100755 --- a/script/release/release.sh +++ b/script/release/release.sh @@ -19,6 +19,7 @@ docker run -e GITHUB_TOKEN=$GITHUB_TOKEN -e BINTRAY_TOKEN=$BINTRAY_TOKEN -it \ --mount type=bind,source=$(pwd),target=/src \ --mount type=bind,source=$(pwd)/.git,target=/src/.git \ --mount type=bind,source=$HOME/.docker,target=/root/.docker \ + --mount type=bind,source=$HOME/.gitconfig,target=/root/.gitconfig --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \ --mount type=bind,source=$HOME/.ssh,target=/root/.ssh \ -v $HOME/.pypirc:/root/.pypirc \ From 7b4603dc22823fefb2cf3143d7017d261649c4a9 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 27 Apr 2018 14:35:13 -0700 Subject: [PATCH 2/9] Finalize fixes Signed-off-by: Joffrey F --- script/release/Dockerfile | 3 ++- script/release/release.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/script/release/Dockerfile b/script/release/Dockerfile index 0d4ec27e1..e5af676a5 100644 --- a/script/release/Dockerfile +++ b/script/release/Dockerfile @@ -3,7 +3,8 @@ RUN mkdir -p /src && pip install -U Jinja2==2.10 \ PyGithub==1.39 \ pypandoc==1.4 \ GitPython==2.1.9 \ - requests==2.18.4 && \ + requests==2.18.4 \ + twine==1.11.0 && \ apt-get update && apt-get install -y pandoc VOLUME /src/script/release diff --git a/script/release/release.py b/script/release/release.py index 4357e36b9..d0545a7e6 100755 --- a/script/release/release.py +++ b/script/release/release.py @@ -27,6 +27,7 @@ from release.utils import ScriptError from release.utils import update_init_py_version from release.utils import update_run_sh_version from release.utils import yesno +from twine.commands.upload import main as twine_upload def create_initial_branch(repository, args): @@ -240,8 +241,8 @@ def finalize(args): if not merge_status.merged: raise ScriptError('Unable to merge PR #{}: {}'.format(pr_data.number, merge_status.message)) print('Uploading to PyPi') - run_setup(os.path.join(REPO_ROOT, 'setup.py'), script_args=['upload']) - img_manager.push_images(args.release) + twine_upload(['dist/*']) + img_manager.push_images() repository.publish_release(gh_release) except ScriptError as e: print(e) From d3ca20074d5eebaec9f9417bbb1f5655731bb113 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 27 Apr 2018 18:36:48 -0700 Subject: [PATCH 3/9] Automatically detect pickable PRs for patch releases Signed-off-by: Joffrey F --- script/release/release.py | 9 +++++++++ script/release/release/repository.py | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/script/release/release.py b/script/release/release.py index d0545a7e6..e9a52c4aa 100755 --- a/script/release/release.py +++ b/script/release/release.py @@ -34,6 +34,15 @@ def create_initial_branch(repository, args): release_branch = repository.create_release_branch(args.release, args.base) if args.base and args.cherries: print('Detected patch version.') + auto_prs = repository.get_prs_in_milestone(args.release) + if auto_prs: + print( + 'Found the following PRs in this release\'s milestone: {}'.format(', '.join(auto_prs)) + ) + proceed = yesno('Automatically cherry-pick detected PRs? Y/n', default=True) + if proceed: + repository.cherry_pick_prs(release_branch, auto_prs) + cherries = input('Indicate (space-separated) PR numbers to cherry-pick then press Enter:\n') repository.cherry_pick_prs(release_branch, cherries.split()) diff --git a/script/release/release/repository.py b/script/release/release/repository.py index d4d1c7201..9a5d432c0 100644 --- a/script/release/release/repository.py +++ b/script/release/release/repository.py @@ -196,6 +196,24 @@ class Repository(object): f.flush() self.git_repo.git.am('--3way', f.name) + def get_prs_in_milestone(self, version): + milestones = self.gh_repo.get_milestones(state='open') + milestone = None + for ms in milestones: + if ms.title == version: + milestone = ms + break + if not milestone: + print('Didn\'t find a milestone matching "{}"'.format(version)) + return None + + issues = self.gh_repo.get_issues(milestone=milestone, state='all') + prs = [] + for issue in issues: + if issue.pull_request is not None: + prs.append(issue.number) + return sorted(prs) + def get_contributors(pr_data): commits = pr_data.get_commits() From d8b4b945859bebea6e5f30abc9b298d0a5381fbd Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 27 Apr 2018 18:43:05 -0700 Subject: [PATCH 4/9] Typo fix Signed-off-by: Joffrey F --- script/release/release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/release/release.sh b/script/release/release.sh index f592365d3..affbce37b 100755 --- a/script/release/release.sh +++ b/script/release/release.sh @@ -19,7 +19,7 @@ docker run -e GITHUB_TOKEN=$GITHUB_TOKEN -e BINTRAY_TOKEN=$BINTRAY_TOKEN -it \ --mount type=bind,source=$(pwd),target=/src \ --mount type=bind,source=$(pwd)/.git,target=/src/.git \ --mount type=bind,source=$HOME/.docker,target=/root/.docker \ - --mount type=bind,source=$HOME/.gitconfig,target=/root/.gitconfig + --mount type=bind,source=$HOME/.gitconfig,target=/root/.gitconfig \ --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \ --mount type=bind,source=$HOME/.ssh,target=/root/.ssh \ -v $HOME/.pypirc:/root/.pypirc \ From f05f1699c4325153e98813d2d740a0727113cf2c Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 27 Apr 2018 18:48:30 -0700 Subject: [PATCH 5/9] Partial revert bc034415501 Signed-off-by: Joffrey F --- script/release/release.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/script/release/release.py b/script/release/release.py index e9a52c4aa..d0545a7e6 100755 --- a/script/release/release.py +++ b/script/release/release.py @@ -34,15 +34,6 @@ def create_initial_branch(repository, args): release_branch = repository.create_release_branch(args.release, args.base) if args.base and args.cherries: print('Detected patch version.') - auto_prs = repository.get_prs_in_milestone(args.release) - if auto_prs: - print( - 'Found the following PRs in this release\'s milestone: {}'.format(', '.join(auto_prs)) - ) - proceed = yesno('Automatically cherry-pick detected PRs? Y/n', default=True) - if proceed: - repository.cherry_pick_prs(release_branch, auto_prs) - cherries = input('Indicate (space-separated) PR numbers to cherry-pick then press Enter:\n') repository.cherry_pick_prs(release_branch, cherries.split()) From 064471e640e2fbf5594844cd1845dfaf3a3cc611 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 1 May 2018 17:11:14 -0700 Subject: [PATCH 6/9] iprange -> ip_range Signed-off-by: Joffrey F --- compose/config/config_schema_v2.0.json | 2 +- compose/config/config_schema_v2.1.json | 2 +- compose/config/config_schema_v2.2.json | 2 +- compose/config/config_schema_v2.3.json | 2 +- compose/config/config_schema_v2.4.json | 2 +- tests/unit/config/config_test.py | 32 ++++++++++++++++++++++++++ 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/compose/config/config_schema_v2.0.json b/compose/config/config_schema_v2.0.json index 793cef1d6..419f2e28c 100644 --- a/compose/config/config_schema_v2.0.json +++ b/compose/config/config_schema_v2.0.json @@ -311,7 +311,7 @@ "type": "object", "properties": { "subnet": {"type": "string"}, - "iprange": {"type": "string"}, + "ip_range": {"type": "string"}, "gateway": {"type": "string"}, "aux_addresses": { "type": "object", diff --git a/compose/config/config_schema_v2.1.json b/compose/config/config_schema_v2.1.json index 5ea763544..3cb1ee213 100644 --- a/compose/config/config_schema_v2.1.json +++ b/compose/config/config_schema_v2.1.json @@ -365,7 +365,7 @@ "type": "object", "properties": { "subnet": {"type": "string"}, - "iprange": {"type": "string"}, + "ip_range": {"type": "string"}, "gateway": {"type": "string"}, "aux_addresses": { "type": "object", diff --git a/compose/config/config_schema_v2.2.json b/compose/config/config_schema_v2.2.json index a19d4c945..8e1f288ba 100644 --- a/compose/config/config_schema_v2.2.json +++ b/compose/config/config_schema_v2.2.json @@ -374,7 +374,7 @@ "type": "object", "properties": { "subnet": {"type": "string"}, - "iprange": {"type": "string"}, + "ip_range": {"type": "string"}, "gateway": {"type": "string"}, "aux_addresses": { "type": "object", diff --git a/compose/config/config_schema_v2.3.json b/compose/config/config_schema_v2.3.json index 78b716a7a..659dbcd1a 100644 --- a/compose/config/config_schema_v2.3.json +++ b/compose/config/config_schema_v2.3.json @@ -418,7 +418,7 @@ "type": "object", "properties": { "subnet": {"type": "string"}, - "iprange": {"type": "string"}, + "ip_range": {"type": "string"}, "gateway": {"type": "string"}, "aux_addresses": { "type": "object", diff --git a/compose/config/config_schema_v2.4.json b/compose/config/config_schema_v2.4.json index a5796d5b1..47e118755 100644 --- a/compose/config/config_schema_v2.4.json +++ b/compose/config/config_schema_v2.4.json @@ -417,7 +417,7 @@ "type": "object", "properties": { "subnet": {"type": "string"}, - "iprange": {"type": "string"}, + "ip_range": {"type": "string"}, "gateway": {"type": "string"}, "aux_addresses": { "type": "object", diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 4562a99ca..085a2d010 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -1344,6 +1344,38 @@ class ConfigTest(unittest.TestCase): assert ('networks.foo.ipam.config contains an invalid type,' ' it should be an object') in excinfo.exconly() + def test_config_valid_ipam_config(self): + ipam_config = { + 'subnet': '172.28.0.0/16', + 'ip_range': '172.28.5.0/24', + 'gateway': '172.28.5.254', + 'aux_addresses': { + 'host1': '172.28.1.5', + 'host2': '172.28.1.6', + 'host3': '172.28.1.7', + }, + } + networks = config.load( + build_config_details( + { + 'version': str(V2_1), + 'networks': { + 'foo': { + 'driver': 'default', + 'ipam': { + 'driver': 'default', + 'config': [ipam_config], + } + } + } + }, + filename='filename.yml', + ) + ).networks + + assert 'foo' in networks + assert networks['foo']['ipam']['config'] == [ipam_config] + def test_config_valid_service_names(self): for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']: services = config.load( From 7db742d3f2be826af002a4a20aded8fe7cf19374 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Sat, 28 Apr 2018 13:42:24 -0700 Subject: [PATCH 7/9] Esnure docker-compose binary is executable (fixes #5917) Signed-off-by: Joffrey F --- script/release/release/images.py | 1 + 1 file changed, 1 insertion(+) diff --git a/script/release/release/images.py b/script/release/release/images.py index 0c7bb2045..d238d4d7f 100644 --- a/script/release/release/images.py +++ b/script/release/release/images.py @@ -23,6 +23,7 @@ class ImageManager(object): distdir = os.path.join(REPO_ROOT, 'dist') os.makedirs(distdir, exist_ok=True) shutil.copy(files['docker-compose-Linux-x86_64'][0], distdir) + os.chmod(os.path.join(distdir, 'docker-compose-Linux-x86_64'), 0o755) print('Building docker/compose image') logstream = docker_client.build( REPO_ROOT, tag='docker/compose:{}'.format(self.version), dockerfile='Dockerfile.run', From f336694912ad603022063b8f5f142d7d7c259c76 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Wed, 2 May 2018 00:30:30 +0000 Subject: [PATCH 8/9] "Bump 1.21.2" Signed-off-by: Joffrey F --- CHANGELOG.md | 8 ++++++++ compose/__init__.py | 2 +- script/run/run.sh | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18742324f..b92117d16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ Change log ========== +1.21.2 (2018-05-03) +------------------- + +### Bugfixes + +- Fixed a bug where the ip_range attirbute in IPAM configs was prevented + from passing validation + 1.21.1 (2018-04-27) ------------------- diff --git a/compose/__init__.py b/compose/__init__.py index 6baeabc14..34974e804 100644 --- a/compose/__init__.py +++ b/compose/__init__.py @@ -1,4 +1,4 @@ from __future__ import absolute_import from __future__ import unicode_literals -__version__ = '1.21.1' +__version__ = '1.21.2' diff --git a/script/run/run.sh b/script/run/run.sh index 45e74febd..60e06996b 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.21.1" +VERSION="1.21.2" IMAGE="docker/compose:$VERSION" From a133471152a3449920ee9f80e8b89e7e7328444c Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 20 Apr 2018 15:29:37 -0700 Subject: [PATCH 9/9] Fix appveyor build Signed-off-by: Joffrey F --- script/build/windows.ps1 | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/script/build/windows.ps1 b/script/build/windows.ps1 index 98a748158..1de9bbfa4 100644 --- a/script/build/windows.ps1 +++ b/script/build/windows.ps1 @@ -44,16 +44,10 @@ virtualenv .\venv # pip and pyinstaller generate lots of warnings, so we need to ignore them $ErrorActionPreference = "Continue" -# Install dependencies -# Fix for https://github.com/pypa/pip/issues/3964 -# Remove-Item -Recurse -Force .\venv\Lib\site-packages\pip -# .\venv\Scripts\easy_install pip==9.0.1 -# .\venv\Scripts\pip install --upgrade pip setuptools -# End fix .\venv\Scripts\pip install pypiwin32==220 .\venv\Scripts\pip install -r requirements.txt .\venv\Scripts\pip install --no-deps . -.\venv\Scripts\pip install --allow-external pyinstaller -r requirements-build.txt +.\venv\Scripts\pip install -r requirements-build.txt git rev-parse --short HEAD | out-file -encoding ASCII compose\GITSHA