Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-docker-compose for openSUSE:Factory checked in at 2022-07-05 12:09:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-docker-compose (Old) and /work/SRC/openSUSE:Factory/.python-docker-compose.new.1548 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-docker-compose" Tue Jul 5 12:09:06 2022 rev:16 rq:986596 version:1.29.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-docker-compose/python-docker-compose.changes 2021-03-15 10:54:50.633212565 +0100 +++ /work/SRC/openSUSE:Factory/.python-docker-compose.new.1548/python-docker-compose.changes 2022-07-05 12:09:40.132572990 +0200 @@ -1,0 +2,52 @@ +Mon Jul 4 09:21:54 UTC 2022 - Matej Cepl <mc...@suse.com> + +- No need to fiddle with versions of PyYAML + +------------------------------------------------------------------- +Wed Jun 29 18:51:12 UTC 2022 - Johannes Kastl <ka...@b1-systems.de> + +- adjust BuildRequires for python-PyYAML so this works on both Tumbleweed and Leap 15.x + +------------------------------------------------------------------- +Wed Jun 29 18:07:30 UTC 2022 - Johannes Kastl <ka...@b1-systems.de> + +- Update to 1.29.2 + + +1.29.2 (2021-05-10) + Miscellaneous + Remove prompt to use docker compose in the up command + Bump py to 1.10.0 in requirements-indirect.txt + + +1.29.1 (2021-04-14) + Bugs + Fix for invalid handler warning on Windows builds + Fix config hash to trigger container recreation on IPC mode updates + Fix conversion map for placement.max_replicas_per_node + Remove extra scan suggestion on build + +1.29.0 (2021-04-06) + Features + Add profile filter to docker-compose config + Add a depends_on condition to wait for successful service completion + Miscellaneous + Add image scan message on build + Update warning message for --no-ansi to mention --ansi never as alternative + Bump docker-py to 5.0.0 + Bump PyYAML to 5.4.1 + Bump python-dotenv to 0.17.0 + +1.28.6 (2021-03-21) + Bugs + Make --env-file relative to the current working directory and error out for invalid paths. Environment file paths set + with --env-file are relative to the current working directory while the default .env file is located in the project + directory which by default is the base directory of the Compose file. + Fix missing service property storage_opt by updating the compose schema + Fix build extra_hosts list format + Remove extra error message on exec + + Miscellaneous + Add compose.yml and compose.yaml to default filename list + +------------------------------------------------------------------- Old: ---- docker-compose-1.28.5.tar.gz New: ---- docker-compose-1.29.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-docker-compose.spec ++++++ --- /var/tmp/diff_new_pack.YOuqhu/_old 2022-07-05 12:09:40.644573725 +0200 +++ /var/tmp/diff_new_pack.YOuqhu/_new 2022-07-05 12:09:40.648573731 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-docker-compose # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,14 +19,14 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-docker-compose -Version: 1.28.5 +Version: 1.29.2 Release: 0 Summary: Tool to define and run complex applications using Docker License: Apache-2.0 Group: System/Management URL: https://pypi.python.org/pypi/docker-compose Source0: https://files.pythonhosted.org/packages/source/d/docker-compose/docker-compose-%{version}.tar.gz -BuildRequires: %{python_module PyYAML >= 5.3.1} +BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module cached-property >= 1.5.1} BuildRequires: %{python_module ddt >= 1.2.2} BuildRequires: %{python_module distro >= 1.5.0} @@ -66,7 +66,7 @@ Requires: python-texttable >= 1.6.2 Requires: python-websocket-client >= 0.57.0 Requires(post): update-alternatives -Requires(postun): update-alternatives +Requires(postun):update-alternatives BuildArch: noarch Provides: docker-compose = %{version} Obsoletes: docker-compose < %{version} ++++++ docker-compose-1.28.5.tar.gz -> docker-compose-1.29.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/CHANGELOG.md new/docker-compose-1.29.2/CHANGELOG.md --- old/docker-compose-1.28.5/CHANGELOG.md 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/CHANGELOG.md 2021-05-10 13:21:57.000000000 +0200 @@ -1,6 +1,74 @@ Change log ========== +1.29.2 (2021-05-10) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/59?closed=1) + +### Miscellaneous + +- Remove advertisement for `docker compose` in the `up` command to avoid annoyance + +- Bump `py` to `1.10.0` in `requirements-indirect.txt` + +1.29.1 (2021-04-13) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/58?closed=1) + +### Bugs + +- Fix for invalid handler warning on Windows builds + +- Fix config hash to trigger container recreation on IPC mode updates + +- Fix conversion map for `placement.max_replicas_per_node` + +- Remove extra scan suggestion on build + +1.29.0 (2021-04-06) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/56?closed=1) + +### Features + +- Add profile filter to `docker-compose config` + +- Add a `depends_on` condition to wait for successful service completion + +### Miscellaneous + +- Add image scan message on build + +- Update warning message for `--no-ansi` to mention `--ansi never` as alternative + +- Bump docker-py to 5.0.0 + +- Bump PyYAML to 5.4.1 + +- Bump python-dotenv to 0.17.0 + +1.28.6 (2021-03-23) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/57?closed=1) + +### Bugs + +- Make `--env-file` relative to the current working directory and error out for invalid paths. Environment file paths set with `--env-file` are relative to the current working directory while the default `.env` file is located in the project directory which by default is the base directory of the Compose file. + +- Fix missing service property `storage_opt` by updating the compose schema + +- Fix build `extra_hosts` list format + +- Remove extra error message on `exec` + +### Miscellaneous + +- Add `compose.yml` and `compose.yaml` to default filename list + 1.28.5 (2021-02-25) ------------------- @@ -129,10 +197,7 @@ - Updates of READMEs -<<<<<<< HEAD -======= ->>>>>>> master 1.27.4 (2020-09-24) ------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/CHANGES.md new/docker-compose-1.29.2/CHANGES.md --- old/docker-compose-1.28.5/CHANGES.md 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/CHANGES.md 2021-05-10 13:21:57.000000000 +0200 @@ -1,6 +1,74 @@ Change log ========== +1.29.2 (2021-05-10) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/59?closed=1) + +### Miscellaneous + +- Remove advertisement for `docker compose` in the `up` command to avoid annoyance + +- Bump `py` to `1.10.0` in `requirements-indirect.txt` + +1.29.1 (2021-04-13) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/58?closed=1) + +### Bugs + +- Fix for invalid handler warning on Windows builds + +- Fix config hash to trigger container recreation on IPC mode updates + +- Fix conversion map for `placement.max_replicas_per_node` + +- Remove extra scan suggestion on build + +1.29.0 (2021-04-06) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/56?closed=1) + +### Features + +- Add profile filter to `docker-compose config` + +- Add a `depends_on` condition to wait for successful service completion + +### Miscellaneous + +- Add image scan message on build + +- Update warning message for `--no-ansi` to mention `--ansi never` as alternative + +- Bump docker-py to 5.0.0 + +- Bump PyYAML to 5.4.1 + +- Bump python-dotenv to 0.17.0 + +1.28.6 (2021-03-23) +------------------- + +[List of PRs / issues for this release](https://github.com/docker/compose/milestone/57?closed=1) + +### Bugs + +- Make `--env-file` relative to the current working directory and error out for invalid paths. Environment file paths set with `--env-file` are relative to the current working directory while the default `.env` file is located in the project directory which by default is the base directory of the Compose file. + +- Fix missing service property `storage_opt` by updating the compose schema + +- Fix build `extra_hosts` list format + +- Remove extra error message on `exec` + +### Miscellaneous + +- Add `compose.yml` and `compose.yaml` to default filename list + 1.28.5 (2021-02-25) ------------------- @@ -129,10 +197,7 @@ - Updates of READMEs -<<<<<<< HEAD -======= ->>>>>>> master 1.27.4 (2020-09-24) ------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/PKG-INFO new/docker-compose-1.29.2/PKG-INFO --- old/docker-compose-1.28.5/PKG-INFO 2021-02-26 10:28:37.244242400 +0100 +++ new/docker-compose-1.29.2/PKG-INFO 2021-05-10 13:22:05.659707800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: docker-compose -Version: 1.28.5 +Version: 1.29.2 Summary: Multi-container orchestration for Docker Home-page: https://www.docker.com/ Author: Docker, Inc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/__init__.py new/docker-compose-1.29.2/compose/__init__.py --- old/docker-compose-1.28.5/compose/__init__.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/__init__.py 2021-05-10 13:21:57.000000000 +0200 @@ -1 +1 @@ -__version__ = '1.28.5' +__version__ = '1.29.2' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/cli/main.py new/docker-compose-1.29.2/compose/cli/main.py --- old/docker-compose-1.28.5/compose/cli/main.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/cli/main.py 2021-05-10 13:21:57.000000000 +0200 @@ -23,6 +23,7 @@ from ..config.environment import Environment from ..config.serialize import serialize_config from ..config.types import VolumeSpec +from ..const import IS_LINUX_PLATFORM from ..const import IS_WINDOWS_PLATFORM from ..errors import StreamParseError from ..metrics.decorator import metrics @@ -78,8 +79,10 @@ try: command_func = dispatch() command_func() + if not IS_LINUX_PLATFORM and command == 'help': + print("\nDocker Compose is now in the Docker CLI, try `docker compose` help") except (KeyboardInterrupt, signals.ShutdownException): - exit_with_metrics(command, "Aborting.", status=Status.FAILURE) + exit_with_metrics(command, "Aborting.", status=Status.CANCELED) except (UserError, NoSuchService, ConfigurationError, ProjectError, OperationFailedError) as e: exit_with_metrics(command, e.msg, status=Status.FAILURE) @@ -98,7 +101,10 @@ e.service.name), status=Status.FAILURE) except NoSuchCommand as e: commands = "\n".join(parse_doc_section("commands:", getdoc(e.supercommand))) - exit_with_metrics(e.command, "No such command: {}\n\n{}".format(e.command, commands)) + if not IS_LINUX_PLATFORM: + commands += "\n\nDocker Compose is now in the Docker CLI, try `docker compose`" + exit_with_metrics("", log_msg="No such command: {}\n\n{}".format( + e.command, commands), status=Status.FAILURE) except (errors.ConnectionError, StreamParseError): exit_with_metrics(command, status=Status.FAILURE) except SystemExit as e: @@ -116,6 +122,10 @@ code = 0 if isinstance(e.code, int): code = e.code + + if not IS_LINUX_PLATFORM and not command: + msg += "\n\nDocker Compose is now in the Docker CLI, try `docker compose`" + exit_with_metrics(command, log_msg=msg, status=status, exit_code=code) @@ -128,7 +138,7 @@ def exit_with_metrics(command, log_msg=None, status=Status.SUCCESS, exit_code=1): - if log_msg: + if log_msg and command != 'exec': if not exit_code: log.info(log_msg) else: @@ -162,7 +172,8 @@ if options.get("--no-ansi"): if options.get("--ansi"): raise UserError("--no-ansi and --ansi cannot be combined.") - log.warning('--no-ansi option is deprecated and will be removed in future versions.') + log.warning('--no-ansi option is deprecated and will be removed in future versions. ' + 'Use `--ansi never` instead.') ansi_mode = AnsiMode.NEVER setup_console_handler(console_handler, @@ -381,6 +392,7 @@ --no-interpolate Don't interpolate environment variables. -q, --quiet Only validate the configuration, don't print anything. + --profiles Print the profile names, one per line. --services Print the service names, one per line. --volumes Print the volume names, one per line. --hash="*" Print the service config hash, one per line. @@ -400,6 +412,15 @@ if options['--quiet']: return + if options['--profiles']: + profiles = set() + for service in compose_config.services: + if 'profiles' in service: + for profile in service['profiles']: + profiles.add(profile) + print('\n'.join(sorted(profiles))) + return + if options['--services']: print('\n'.join(service['name'] for service in compose_config.services)) return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/config/compose_spec.json new/docker-compose-1.29.2/compose/config/compose_spec.json --- old/docker-compose-1.28.5/compose/config/compose_spec.json 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/config/compose_spec.json 2021-05-10 13:21:57.000000000 +0200 @@ -188,7 +188,7 @@ "properties": { "condition": { "type": "string", - "enum": ["service_started", "service_healthy"] + "enum": ["service_started", "service_healthy", "service_completed_successfully"] } }, "required": ["condition"] @@ -335,7 +335,6 @@ "read_only": {"type": "boolean"}, "restart": {"type": "string"}, "runtime": { - "deprecated": true, "type": "string" }, "scale": { @@ -367,6 +366,7 @@ "stdin_open": {"type": "boolean"}, "stop_grace_period": {"type": "string", "format": "duration"}, "stop_signal": {"type": "string"}, + "storage_opt": {"type": "object"}, "tmpfs": {"$ref": "#/definitions/string_or_list"}, "tty": {"type": "boolean"}, "ulimits": { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/config/config.py new/docker-compose-1.29.2/compose/config/config.py --- old/docker-compose-1.28.5/compose/config/config.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/config/config.py 2021-05-10 13:21:57.000000000 +0200 @@ -10,7 +10,11 @@ from operator import itemgetter import yaml -from cached_property import cached_property + +try: + from functools import cached_property +except ImportError: + from cached_property import cached_property from . import types from ..const import COMPOSE_SPEC as VERSION @@ -149,9 +153,14 @@ SUPPORTED_FILENAMES = [ 'docker-compose.yml', 'docker-compose.yaml', + 'compose.yml', + 'compose.yaml', ] -DEFAULT_OVERRIDE_FILENAMES = ('docker-compose.override.yml', 'docker-compose.override.yaml') +DEFAULT_OVERRIDE_FILENAMES = ('docker-compose.override.yml', + 'docker-compose.override.yaml', + 'compose.override.yml', + 'compose.override.yaml') log = logging.getLogger(__name__) @@ -304,7 +313,16 @@ if filenames: filenames = [os.path.join(base_dir, f) for f in filenames] else: + # search for compose files in the base dir and its parents filenames = get_default_config_files(base_dir) + if not filenames and not override_dir: + # none found in base_dir and no override_dir defined + raise ComposeFileNotFound(SUPPORTED_FILENAMES) + if not filenames: + # search for compose files in the project directory and its parents + filenames = get_default_config_files(override_dir) + if not filenames: + raise ComposeFileNotFound(SUPPORTED_FILENAMES) log.debug("Using configuration files: {}".format(",".join(filenames))) return ConfigDetails( @@ -335,7 +353,7 @@ (candidates, path) = find_candidates_in_parent_dirs(SUPPORTED_FILENAMES, base_dir) if not candidates: - raise ComposeFileNotFound(SUPPORTED_FILENAMES) + return None winner = candidates[0] @@ -556,8 +574,7 @@ config_file.version, config, section, - environment - ) + environment) else: return config diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/config/environment.py new/docker-compose-1.29.2/compose/config/environment.py --- old/docker-compose-1.28.5/compose/config/environment.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/config/environment.py 2021-05-10 13:21:57.000000000 +0200 @@ -54,9 +54,10 @@ if base_dir is None: return result if env_file: - env_file_path = os.path.join(base_dir, env_file) - else: - env_file_path = os.path.join(base_dir, '.env') + env_file_path = os.path.join(os.getcwd(), env_file) + return cls(env_vars_from_file(env_file_path)) + + env_file_path = os.path.join(base_dir, '.env') try: return cls(env_vars_from_file(env_file_path)) except EnvFileNotFound: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/config/interpolation.py new/docker-compose-1.29.2/compose/config/interpolation.py --- old/docker-compose-1.28.5/compose/config/interpolation.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/config/interpolation.py 2021-05-10 13:21:57.000000000 +0200 @@ -243,6 +243,7 @@ service_path('healthcheck', 'disable'): to_boolean, service_path('deploy', 'labels', PATH_JOKER): to_str, service_path('deploy', 'replicas'): to_int, + service_path('deploy', 'placement', 'max_replicas_per_node'): to_int, service_path('deploy', 'resources', 'limits', "cpus"): to_float, service_path('deploy', 'update_config', 'parallelism'): to_int, service_path('deploy', 'update_config', 'max_failure_ratio'): to_float, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/const.py new/docker-compose-1.29.2/compose/const.py --- old/docker-compose-1.28.5/compose/const.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/const.py 2021-05-10 13:21:57.000000000 +0200 @@ -5,6 +5,7 @@ DEFAULT_TIMEOUT = 10 HTTP_TIMEOUT = 60 IS_WINDOWS_PLATFORM = (sys.platform == "win32") +IS_LINUX_PLATFORM = (sys.platform == "linux") LABEL_CONTAINER_NUMBER = 'com.docker.compose.container-number' LABEL_ONE_OFF = 'com.docker.compose.oneoff' LABEL_PROJECT = 'com.docker.compose.project' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/errors.py new/docker-compose-1.29.2/compose/errors.py --- old/docker-compose-1.28.5/compose/errors.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/errors.py 2021-05-10 13:21:57.000000000 +0200 @@ -27,3 +27,8 @@ service_name ) ) + + +class CompletedUnsuccessfully(Exception): + def __init__(self, container_id, exit_code): + self.msg = 'Container "{}" exited with code {}.'.format(container_id, exit_code) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/metrics/client.py new/docker-compose-1.29.2/compose/metrics/client.py --- old/docker-compose-1.28.5/compose/metrics/client.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/metrics/client.py 2021-05-10 13:21:57.000000000 +0200 @@ -36,7 +36,7 @@ context_type=None, status=Status.SUCCESS, source=MetricsSource.CLI, uri=None): super().__init__() - self.command = "compose " + command if command else "compose --help" + self.command = ("compose " + command).strip() if command else "compose --help" self.context = context_type or ContextAPI.get_current_context().context_type or 'moby' self.source = source self.status = status.value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/parallel.py new/docker-compose-1.29.2/compose/parallel.py --- old/docker-compose-1.28.5/compose/parallel.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/parallel.py 2021-05-10 13:21:57.000000000 +0200 @@ -16,6 +16,7 @@ from compose.cli.colors import red from compose.cli.signals import ShutdownException from compose.const import PARALLEL_LIMIT +from compose.errors import CompletedUnsuccessfully from compose.errors import HealthCheckFailed from compose.errors import NoHealthCheckConfigured from compose.errors import OperationFailedError @@ -61,7 +62,8 @@ elif isinstance(exception, APIError): errors[get_name(obj)] = exception.explanation writer.write(msg, get_name(obj), 'error', red) - elif isinstance(exception, (OperationFailedError, HealthCheckFailed, NoHealthCheckConfigured)): + elif isinstance(exception, (OperationFailedError, HealthCheckFailed, NoHealthCheckConfigured, + CompletedUnsuccessfully)): errors[get_name(obj)] = exception.msg writer.write(msg, get_name(obj), 'error', red) elif isinstance(exception, UpstreamError): @@ -241,6 +243,12 @@ 'not processing'.format(obj) ) results.put((obj, None, e)) + except CompletedUnsuccessfully as e: + log.debug( + 'Service(s) upstream of {} did not completed successfully - ' + 'not processing'.format(obj) + ) + results.put((obj, None, e)) if state.is_done(): results.put(STOP) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/compose/service.py new/docker-compose-1.29.2/compose/service.py --- old/docker-compose-1.28.5/compose/service.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/compose/service.py 2021-05-10 13:21:57.000000000 +0200 @@ -1,6 +1,5 @@ import enum import itertools -import json import logging import os import re @@ -45,6 +44,7 @@ from .const import NANOCPUS_SCALE from .const import WINDOWS_LONGPATH_PREFIX from .container import Container +from .errors import CompletedUnsuccessfully from .errors import HealthCheckFailed from .errors import NoHealthCheckConfigured from .errors import OperationFailedError @@ -112,6 +112,7 @@ CONDITION_STARTED = 'service_started' CONDITION_HEALTHY = 'service_healthy' +CONDITION_COMPLETED_SUCCESSFULLY = 'service_completed_successfully' class BuildError(Exception): @@ -712,6 +713,7 @@ 'image_id': image_id(), 'links': self.get_link_names(), 'net': self.network_mode.id, + 'ipc_mode': self.ipc_mode.mode, 'networks': self.networks, 'secrets': self.secrets, 'volumes_from': [ @@ -753,6 +755,8 @@ configs[svc] = lambda s: True elif config['condition'] == CONDITION_HEALTHY: configs[svc] = lambda s: s.is_healthy() + elif config['condition'] == CONDITION_COMPLETED_SUCCESSFULLY: + configs[svc] = lambda s: s.is_completed_successfully() else: # The config schema already prevents this, but it might be # bypassed if Compose is called programmatically. @@ -1103,8 +1107,9 @@ 'Impossible to perform platform-targeted builds for API version < 1.35' ) - builder = self.client if not cli else _CLIBuilder(progress) - build_output = builder.build( + builder = _ClientBuilder(self.client) if not cli else _CLIBuilder(progress) + return builder.build( + service=self, path=path, tag=self.image_name, rm=rm, @@ -1125,30 +1130,7 @@ gzip=gzip, isolation=build_opts.get('isolation', self.options.get('isolation', None)), platform=self.platform, - ) - - try: - all_events = list(stream_output(build_output, output_stream)) - except StreamOutputError as e: - raise BuildError(self, str(e)) - - # Ensure the HTTP connection is not reused for another - # streaming command, as the Docker daemon can sometimes - # complain about it - self.client.close() - - image_id = None - - for event in all_events: - if 'stream' in event: - match = re.search(r'Successfully built ([0-9a-f]+)', event.get('stream', '')) - if match: - image_id = match.group(1) - - if image_id is None: - raise BuildError(self, event if all_events else 'Unknown') - - return image_id + output_stream=output_stream) def get_cache_from(self, build_opts): cache_from = build_opts.get('cache_from', None) @@ -1304,6 +1286,21 @@ raise HealthCheckFailed(ctnr.short_id) return result + def is_completed_successfully(self): + """ Check that all containers for this service has completed successfully + Returns false if at least one container does not exited and + raises CompletedUnsuccessfully exception if at least one container + exited with non-zero exit code. + """ + result = True + for ctnr in self.containers(stopped=True): + ctnr.inspect() + if ctnr.get('State.Status') != 'exited': + result = False + elif ctnr.exit_code != 0: + raise CompletedUnsuccessfully(ctnr.short_id, ctnr.exit_code) + return result + def _parse_proxy_config(self): client = self.client if 'proxies' not in client._general_configs: @@ -1790,20 +1787,77 @@ return path +class _ClientBuilder: + def __init__(self, client): + self.client = client + + def build(self, service, path, tag=None, quiet=False, fileobj=None, + nocache=False, rm=False, timeout=None, + custom_context=False, encoding=None, pull=False, + forcerm=False, dockerfile=None, container_limits=None, + decode=False, buildargs=None, gzip=False, shmsize=None, + labels=None, cache_from=None, target=None, network_mode=None, + squash=None, extra_hosts=None, platform=None, isolation=None, + use_config_proxy=True, output_stream=sys.stdout): + build_output = self.client.build( + path=path, + tag=tag, + nocache=nocache, + rm=rm, + pull=pull, + forcerm=forcerm, + dockerfile=dockerfile, + labels=labels, + cache_from=cache_from, + buildargs=buildargs, + network_mode=network_mode, + target=target, + shmsize=shmsize, + extra_hosts=extra_hosts, + container_limits=container_limits, + gzip=gzip, + isolation=isolation, + platform=platform) + + try: + all_events = list(stream_output(build_output, output_stream)) + except StreamOutputError as e: + raise BuildError(service, str(e)) + + # Ensure the HTTP connection is not reused for another + # streaming command, as the Docker daemon can sometimes + # complain about it + self.client.close() + + image_id = None + + for event in all_events: + if 'stream' in event: + match = re.search(r'Successfully built ([0-9a-f]+)', event.get('stream', '')) + if match: + image_id = match.group(1) + + if image_id is None: + raise BuildError(service, event if all_events else 'Unknown') + + return image_id + + class _CLIBuilder: def __init__(self, progress): self._progress = progress - def build(self, path, tag=None, quiet=False, fileobj=None, + def build(self, service, path, tag=None, quiet=False, fileobj=None, nocache=False, rm=False, timeout=None, custom_context=False, encoding=None, pull=False, forcerm=False, dockerfile=None, container_limits=None, decode=False, buildargs=None, gzip=False, shmsize=None, labels=None, cache_from=None, target=None, network_mode=None, squash=None, extra_hosts=None, platform=None, isolation=None, - use_config_proxy=True): + use_config_proxy=True, output_stream=sys.stdout): """ Args: + service (str): Service to be built path (str): Path to the directory containing the Dockerfile buildargs (dict): A dictionary of build arguments cache_from (:py:class:`list`): A list of images used for build @@ -1852,10 +1906,11 @@ configuration file (``~/.docker/config.json`` by default) contains a proxy configuration, the corresponding environment variables will be set in the container being built. + output_stream (writer): stream to use for build logs Returns: A generator for the build output. """ - if dockerfile: + if dockerfile and os.path.isdir(path): dockerfile = os.path.join(path, dockerfile) iidfile = tempfile.mktemp() @@ -1877,38 +1932,25 @@ command_builder.add_arg("--isolation", isolation) if extra_hosts: - for host, ip in extra_hosts.items(): - command_builder.add_arg("--add-host", "{}:{}".format(host, ip)) + if isinstance(extra_hosts, dict): + extra_hosts = ["{}:{}".format(host, ip) for host, ip in extra_hosts.items()] + for host in extra_hosts: + command_builder.add_arg("--add-host", "{}".format(host)) args = command_builder.build([path]) - magic_word = "Successfully built " - appear = False - with subprocess.Popen(args, stdout=subprocess.PIPE, + with subprocess.Popen(args, stdout=output_stream, stderr=sys.stderr, universal_newlines=True) as p: - while True: - line = p.stdout.readline() - if not line: - break - if line.startswith(magic_word): - appear = True - yield json.dumps({"stream": line}) - p.communicate() if p.returncode != 0: - raise StreamOutputError() + raise BuildError(service, "Build failed") with open(iidfile) as f: line = f.readline() image_id = line.split(":")[1].strip() os.remove(iidfile) - # In case of `DOCKER_BUILDKIT=1` - # there is no success message already present in the output. - # Since that's the way `Service::build` gets the `image_id` - # it has to be added `manually` - if not appear: - yield json.dumps({"stream": "{}{}\n".format(magic_word, image_id)}) + return image_id class _CommandBuilder: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/contrib/completion/bash/docker-compose new/docker-compose-1.29.2/contrib/completion/bash/docker-compose --- old/docker-compose-1.28.5/contrib/completion/bash/docker-compose 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/contrib/completion/bash/docker-compose 2021-05-10 13:21:57.000000000 +0200 @@ -138,7 +138,7 @@ ;; esac - COMPREPLY=( $( compgen -W "--hash --help --no-interpolate --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--hash --help --no-interpolate --profiles --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) } @@ -172,6 +172,10 @@ COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) ) return ;; + --profile) + COMPREPLY=( $( compgen -W "$(__docker_compose_q config --profiles)" -- "$cur" ) ) + return + ;; --project-directory) _filedir -d return @@ -618,10 +622,11 @@ --tlskey " - # These options are require special treatment when searching the command. + # These options require special treatment when searching the command. local top_level_options_with_args=" --ansi --log-level + --profile " COMPREPLY=() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/docker_compose.egg-info/PKG-INFO new/docker-compose-1.29.2/docker_compose.egg-info/PKG-INFO --- old/docker-compose-1.28.5/docker_compose.egg-info/PKG-INFO 2021-02-26 10:28:36.000000000 +0100 +++ new/docker-compose-1.29.2/docker_compose.egg-info/PKG-INFO 2021-05-10 13:22:05.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: docker-compose -Version: 1.28.5 +Version: 1.29.2 Summary: Multi-container orchestration for Docker Home-page: https://www.docker.com/ Author: Docker, Inc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/docker_compose.egg-info/SOURCES.txt new/docker-compose-1.29.2/docker_compose.egg-info/SOURCES.txt --- old/docker-compose-1.28.5/docker_compose.egg-info/SOURCES.txt 2021-02-26 10:28:36.000000000 +0100 +++ new/docker-compose-1.29.2/docker_compose.egg-info/SOURCES.txt 2021-05-10 13:22:05.000000000 +0200 @@ -85,6 +85,7 @@ tests/fixtures/build-shm-size/docker-compose.yml tests/fixtures/commands-composefile/docker-compose.yml tests/fixtures/compatibility-mode/docker-compose.yml +tests/fixtures/config-profiles/docker-compose.yml tests/fixtures/default-env-file/.env tests/fixtures/default-env-file/.env2 tests/fixtures/default-env-file/docker-compose.yml @@ -104,6 +105,7 @@ tests/fixtures/env/two.env tests/fixtures/env-file/docker-compose.yml tests/fixtures/env-file/test.env +tests/fixtures/env-file-override/.env tests/fixtures/env-file-override/.env.conf tests/fixtures/env-file-override/.env.override tests/fixtures/env-file-override/docker-compose.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/docker_compose.egg-info/requires.txt new/docker-compose-1.29.2/docker_compose.egg-info/requires.txt --- old/docker-compose-1.28.5/docker_compose.egg-info/requires.txt 2021-02-26 10:28:36.000000000 +0100 +++ new/docker-compose-1.29.2/docker_compose.egg-info/requires.txt 2021-05-10 13:22:05.000000000 +0200 @@ -1,7 +1,6 @@ PyYAML<6,>=3.10 -cached-property<2,>=1.2.0 distro<2,>=1.5.0 -docker[ssh]<5,>=4.4.4 +docker[ssh]>=5 dockerpty<1,>=0.4.1 docopt<1,>=0.6.1 jsonschema<4,>=2.5.1 @@ -13,6 +12,9 @@ [:python_version < "3.5"] backports.ssl_match_hostname<4,>=3.5 +[:python_version < "3.8"] +cached-property<2,>=1.2.0 + [:sys_platform == "win32"] colorama<1,>=0.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/requirements-dev.txt new/docker-compose-1.29.2/requirements-dev.txt --- old/docker-compose-1.28.5/requirements-dev.txt 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/requirements-dev.txt 2021-05-10 13:21:57.000000000 +0200 @@ -1,5 +1,5 @@ Click==7.1.2 -coverage==5.2.1 +coverage==5.5 ddt==1.4.1 flake8==3.8.3 gitpython==3.1.11 @@ -7,4 +7,3 @@ pytest==6.0.1; python_version >= '3.5' pytest==4.6.5; python_version < '3.5' pytest-cov==2.10.1 -PyYAML==5.3.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/requirements-indirect.txt new/docker-compose-1.29.2/requirements-indirect.txt --- old/docker-compose-1.28.5/requirements-indirect.txt 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/requirements-indirect.txt 2021-05-10 13:21:57.000000000 +0200 @@ -11,9 +11,9 @@ mccabe==0.6.1 more-itertools==8.6.0; python_version >= '3.5' more-itertools==5.0.0; python_version < '3.5' -packaging==20.4 +packaging==20.9 pluggy==0.13.1 -py==1.9.0 +py==1.10.0 pycodestyle==2.6.0 pycparser==2.20 pyflakes==2.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/requirements.txt new/docker-compose-1.29.2/requirements.txt --- old/docker-compose-1.28.5/requirements.txt 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/requirements.txt 2021-05-10 13:21:57.000000000 +0200 @@ -1,10 +1,10 @@ backports.shutil_get_terminal_size==1.0.0 -cached-property==1.5.1 +cached-property==1.5.1; python_version < '3.8' certifi==2020.6.20 chardet==3.0.4 colorama==0.4.3; sys_platform == 'win32' distro==1.5.0 -docker==4.4.4 +docker==5.0.0 docker-pycreds==0.4.0 dockerpty==0.4.1 docopt==0.6.2 @@ -13,9 +13,9 @@ jsonschema==3.2.0 paramiko==2.7.1 PySocks==1.7.1 -python-dotenv==0.14.0 +python-dotenv==0.17.0 pywin32==227; sys_platform == 'win32' -PyYAML==5.3.1 +PyYAML==5.4.1 requests==2.24.0 texttable==1.6.2 urllib3==1.25.10; python_version == '3.3' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/setup.py new/docker-compose-1.29.2/setup.py --- old/docker-compose-1.28.5/setup.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/setup.py 2021-05-10 13:21:57.000000000 +0200 @@ -25,14 +25,13 @@ install_requires = [ - 'cached-property >= 1.2.0, < 2', 'docopt >= 0.6.1, < 1', 'PyYAML >= 3.10, < 6', 'requests >= 2.20.0, < 3', 'texttable >= 0.9.0, < 2', 'websocket-client >= 0.32.0, < 1', 'distro >= 1.5.0, < 2', - 'docker[ssh] >= 4.4.4, < 5', + 'docker[ssh] >= 5', 'dockerpty >= 0.4.1, < 1', 'jsonschema >= 2.5.1, < 4', 'python-dotenv >= 0.13.0, < 1', @@ -50,6 +49,7 @@ extras_require = { ':python_version < "3.5"': ['backports.ssl_match_hostname >= 3.5, < 4'], + ':python_version < "3.8"': ['cached-property >= 1.2.0, < 2'], ':sys_platform == "win32"': ['colorama >= 0.4, < 1'], 'socks': ['PySocks >= 1.5.6, != 1.5.7, < 2'], 'tests': tests_require, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/acceptance/cli_test.py new/docker-compose-1.29.2/tests/acceptance/cli_test.py --- old/docker-compose-1.28.5/tests/acceptance/cli_test.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/tests/acceptance/cli_test.py 2021-05-10 13:21:57.000000000 +0200 @@ -237,6 +237,11 @@ result = self.dispatch(['-H=tcp://doesnotexist:8000', 'ps'], returncode=1) assert "Couldn't connect to Docker daemon" in result.stderr + def test_config_list_profiles(self): + self.base_dir = 'tests/fixtures/config-profiles' + result = self.dispatch(['config', '--profiles']) + assert set(result.stdout.rstrip().split('\n')) == {'debug', 'frontend', 'gui'} + def test_config_list_services(self): self.base_dir = 'tests/fixtures/v2-full' result = self.dispatch(['config', '--services']) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/fixtures/config-profiles/docker-compose.yml new/docker-compose-1.29.2/tests/fixtures/config-profiles/docker-compose.yml --- old/docker-compose-1.28.5/tests/fixtures/config-profiles/docker-compose.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/docker-compose-1.29.2/tests/fixtures/config-profiles/docker-compose.yml 2021-05-10 13:21:57.000000000 +0200 @@ -0,0 +1,15 @@ +version: '3.8' +services: + frontend: + image: frontend + profiles: ["frontend", "gui"] + phpmyadmin: + image: phpmyadmin + depends_on: + - db + profiles: + - debug + backend: + image: backend + db: + image: mysql diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/fixtures/env-file-override/.env new/docker-compose-1.29.2/tests/fixtures/env-file-override/.env --- old/docker-compose-1.28.5/tests/fixtures/env-file-override/.env 1970-01-01 01:00:00.000000000 +0100 +++ new/docker-compose-1.29.2/tests/fixtures/env-file-override/.env 2021-05-10 13:21:57.000000000 +0200 @@ -0,0 +1 @@ +WHEREAMI=default diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/integration/environment_test.py new/docker-compose-1.29.2/tests/integration/environment_test.py --- old/docker-compose-1.28.5/tests/integration/environment_test.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/tests/integration/environment_test.py 2021-05-10 13:21:57.000000000 +0200 @@ -1,5 +1,6 @@ import tempfile +import pytest from ddt import data from ddt import ddt @@ -8,6 +9,7 @@ from compose.cli.command import get_project from compose.cli.command import project_from_options from compose.config.environment import Environment +from compose.config.errors import EnvFileNotFound from tests.integration.testcases import DockerClientTestCase @@ -55,13 +57,36 @@ class EnvironmentOverrideFileTest(DockerClientTestCase): def test_env_file_override(self): base_dir = 'tests/fixtures/env-file-override' + # '--env-file' are relative to the current working dir + env = Environment.from_env_file(base_dir, base_dir+'/.env.override') dispatch(base_dir, ['--env-file', '.env.override', 'up']) project = get_project(project_dir=base_dir, config_path=['docker-compose.yml'], - environment=Environment.from_env_file(base_dir, '.env.override'), + environment=env, override_dir=base_dir) containers = project.containers(stopped=True) assert len(containers) == 1 assert "WHEREAMI=override" in containers[0].get('Config.Env') assert "DEFAULT_CONF_LOADED=true" in containers[0].get('Config.Env') dispatch(base_dir, ['--env-file', '.env.override', 'down'], None) + + def test_env_file_not_found_error(self): + base_dir = 'tests/fixtures/env-file-override' + with pytest.raises(EnvFileNotFound) as excinfo: + Environment.from_env_file(base_dir, '.env.override') + + assert "Couldn't find env file" in excinfo.exconly() + + def test_dot_env_file(self): + base_dir = 'tests/fixtures/env-file-override' + # '.env' is relative to the project_dir (base_dir) + env = Environment.from_env_file(base_dir, None) + dispatch(base_dir, ['up']) + project = get_project(project_dir=base_dir, + config_path=['docker-compose.yml'], + environment=env, + override_dir=base_dir) + containers = project.containers(stopped=True) + assert len(containers) == 1 + assert "WHEREAMI=default" in containers[0].get('Config.Env') + dispatch(base_dir, ['down'], None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/integration/project_test.py new/docker-compose-1.29.2/tests/integration/project_test.py --- old/docker-compose-1.28.5/tests/integration/project_test.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/tests/integration/project_test.py 2021-05-10 13:21:57.000000000 +0200 @@ -25,6 +25,7 @@ from compose.const import LABEL_PROJECT from compose.const import LABEL_SERVICE from compose.container import Container +from compose.errors import CompletedUnsuccessfully from compose.errors import HealthCheckFailed from compose.errors import NoHealthCheckConfigured from compose.project import Project @@ -1899,6 +1900,106 @@ with pytest.raises(NoHealthCheckConfigured): svc1.is_healthy() + def test_project_up_completed_successfully_dependency(self): + config_dict = { + 'version': '2.1', + 'services': { + 'svc1': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'true' + }, + 'svc2': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'top', + 'depends_on': { + 'svc1': {'condition': 'service_completed_successfully'}, + } + } + } + } + config_data = load_config(config_dict) + project = Project.from_config( + name='composetest', config_data=config_data, client=self.client + ) + project.up() + + svc1 = project.get_service('svc1') + svc2 = project.get_service('svc2') + + assert 'svc1' in svc2.get_dependency_names() + assert svc2.containers()[0].is_running + assert len(svc1.containers()) == 0 + assert svc1.is_completed_successfully() + + def test_project_up_completed_unsuccessfully_dependency(self): + config_dict = { + 'version': '2.1', + 'services': { + 'svc1': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'false' + }, + 'svc2': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'top', + 'depends_on': { + 'svc1': {'condition': 'service_completed_successfully'}, + } + } + } + } + config_data = load_config(config_dict) + project = Project.from_config( + name='composetest', config_data=config_data, client=self.client + ) + with pytest.raises(ProjectError): + project.up() + + svc1 = project.get_service('svc1') + svc2 = project.get_service('svc2') + assert 'svc1' in svc2.get_dependency_names() + assert len(svc2.containers()) == 0 + with pytest.raises(CompletedUnsuccessfully): + svc1.is_completed_successfully() + + def test_project_up_completed_differently_dependencies(self): + config_dict = { + 'version': '2.1', + 'services': { + 'svc1': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'true' + }, + 'svc2': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'false' + }, + 'svc3': { + 'image': BUSYBOX_IMAGE_WITH_TAG, + 'command': 'top', + 'depends_on': { + 'svc1': {'condition': 'service_completed_successfully'}, + 'svc2': {'condition': 'service_completed_successfully'}, + } + } + } + } + config_data = load_config(config_dict) + project = Project.from_config( + name='composetest', config_data=config_data, client=self.client + ) + with pytest.raises(ProjectError): + project.up() + + svc1 = project.get_service('svc1') + svc2 = project.get_service('svc2') + svc3 = project.get_service('svc3') + assert ['svc1', 'svc2'] == svc3.get_dependency_names() + assert svc1.is_completed_successfully() + assert len(svc3.containers()) == 0 + with pytest.raises(CompletedUnsuccessfully): + svc2.is_completed_successfully() + def test_project_up_seccomp_profile(self): seccomp_data = { 'defaultAction': 'SCMP_ACT_ALLOW', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/unit/config/config_test.py new/docker-compose-1.29.2/tests/unit/config/config_test.py --- old/docker-compose-1.28.5/tests/unit/config/config_test.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/tests/unit/config/config_test.py 2021-05-10 13:21:57.000000000 +0200 @@ -2397,7 +2397,8 @@ 'image': 'busybox', 'depends_on': { 'app1': {'condition': 'service_started'}, - 'app2': {'condition': 'service_healthy'} + 'app2': {'condition': 'service_healthy'}, + 'app3': {'condition': 'service_completed_successfully'} } } override = {} @@ -2409,11 +2410,12 @@ 'image': 'busybox', 'depends_on': { 'app1': {'condition': 'service_started'}, - 'app2': {'condition': 'service_healthy'} + 'app2': {'condition': 'service_healthy'}, + 'app3': {'condition': 'service_completed_successfully'} } } override = { - 'depends_on': ['app3'] + 'depends_on': ['app4'] } actual = config.merge_service_dicts(base, override, VERSION) @@ -2422,7 +2424,8 @@ 'depends_on': { 'app1': {'condition': 'service_started'}, 'app2': {'condition': 'service_healthy'}, - 'app3': {'condition': 'service_started'} + 'app3': {'condition': 'service_completed_successfully'}, + 'app4': {'condition': 'service_started'}, } } @@ -3567,9 +3570,11 @@ @mock.patch.dict(os.environ) def test_config_file_with_options_environment_file(self): project_dir = 'tests/fixtures/default-env-file' + # env-file is relative to current working dir + env = Environment.from_env_file(project_dir, project_dir + '/.env2') service_dicts = config.load( config.find( - project_dir, None, Environment.from_env_file(project_dir, '.env2') + project_dir, None, env ) ).services @@ -5233,6 +5238,8 @@ files = [ 'docker-compose.yml', 'docker-compose.yaml', + 'compose.yml', + 'compose.yaml', ] def test_get_config_path_default_file_in_basedir(self): @@ -5266,8 +5273,10 @@ base_dir = tempfile.mkdtemp(dir=project_dir) else: base_dir = project_dir - filename, = config.get_default_config_files(base_dir) - return os.path.basename(filename) + filenames = config.get_default_config_files(base_dir) + if not filenames: + raise config.ComposeFileNotFound(config.SUPPORTED_FILENAMES) + return os.path.basename(filenames[0]) finally: shutil.rmtree(project_dir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tests/unit/service_test.py new/docker-compose-1.29.2/tests/unit/service_test.py --- old/docker-compose-1.28.5/tests/unit/service_test.py 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/tests/unit/service_test.py 2021-05-10 13:21:57.000000000 +0200 @@ -330,7 +330,7 @@ assert service.options['environment'] == environment assert opts['labels'][LABEL_CONFIG_HASH] == \ - '689149e6041a85f6fb4945a2146a497ed43c8a5cbd8991753d875b165f1b4de4' + '6da0f3ec0d5adf901de304bdc7e0ee44ec5dd7adb08aebc20fe0dd791d4ee5a8' assert opts['environment'] == ['also=real'] def test_get_container_create_options_sets_affinity_with_binds(self): @@ -700,6 +700,7 @@ config_dict = service.config_dict() expected = { 'image_id': 'abcd', + 'ipc_mode': None, 'options': {'image': 'example.com/foo'}, 'links': [('one', 'one')], 'net': 'other', @@ -723,6 +724,7 @@ config_dict = service.config_dict() expected = { 'image_id': 'abcd', + 'ipc_mode': None, 'options': {'image': 'example.com/foo'}, 'links': [], 'networks': {}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-1.28.5/tox.ini new/docker-compose-1.29.2/tox.ini --- old/docker-compose-1.28.5/tox.ini 2021-02-26 10:28:32.000000000 +0100 +++ new/docker-compose-1.29.2/tox.ini 2021-05-10 13:21:57.000000000 +0200 @@ -50,7 +50,7 @@ [flake8] max-line-length = 105 # Set this high for now -max-complexity = 11 +max-complexity = 12 exclude = compose/packages [pytest]