diff --git a/README.md b/README.md index f281f83b..785bea45 100644 --- a/README.md +++ b/README.md @@ -251,18 +251,18 @@ So, if we want to generate packages for ``x86_64`` and ``armv8`` but only for `` There are also two additional parameters of the ``add_common_builds``: -- **pure_c**: (Default True) If your project is C++, pass the **pure_c=False** to add both - combinations using **libstdc** and **libstdc++11** for the setting **compiler.libcxx**. +- **pure_c**: (Default True) If your project is C++, pass the **pure_c=False** to add both + combinations using **libstdc** and **libstdc++11** for the setting **compiler.libcxx**. When True, the default profile value of ``libcxx`` will be applied. - If you don't want ``libcxx`` value to apply + If you don't want ``libcxx`` value to apply to your binary packages you have to use the ``configure`` method to remove it: - + ``` def configure(self): del self.settings.compiler.libcxx ``` -- **shared_option_name**: If your conanfile.py have an option **shared**, the generated builds will contain automatically the "True/False" combination for that option. +- **shared_option_name**: If your conanfile.py have an option **shared**, the generated builds will contain automatically the "True/False" combination for that option. Pass "False" to deactivate it or "lib_name:shared_option_name" to specify a custom option name, e.j: boost:my_shared`` - **dll_with_static_runtime**: Will add also the combination of runtime MT with shared libraries. @@ -322,11 +322,11 @@ And run the build.py: It will generate a set of build configurations (profiles) for gcc 4.9 and will run it inside a container of the ``lasote/conangcc49`` image. -If you want to run the arch="x86" build inside a docker container of 32 bits you can set the parameter ``docker_32_images`` in the +If you want to run the arch="x86" build inside a docker container of 32 bits you can set the parameter ``docker_32_images`` in the ConanMultiPackager constructor or set the environment variable ``CONAN_DOCKER_32_IMAGES``. In this case, the docker image name to use -will be appended with ``-i386``. +will be appended with ``-i386``. -The Docker images used by default both for 64 and 32 bits are pushed to dockerhub and its Dockerfiles are available in the +The Docker images used by default both for 64 and 32 bits are pushed to dockerhub and its Dockerfiles are available in the [conan-docker-tools](https://github.com/conan-io/conan-docker-tools) repository. ### Running scripts and executing commands before to build on Docker @@ -862,27 +862,27 @@ Using **CONAN_CLANG_VERSIONS** env variable in Travis ci or Appveyor: - **login_username**: The login username. Could take two possible values: - String with the login": - + ``` login_username = "my_user" ``` - - - Dict containing the remote name and the login for that remote. Use together with "remotes" variable to specify remote names e.j: - + + - Dict containing the remote name and the login for that remote. Use together with "remotes" variable to specify remote names e.j: + ``` login_username = {"remote1": "my_user", "my_artifactory": "other_user"} ``` - + - **password**. Password to authenticate with the remotes. Could take two possible values: - String with the password: - + ``` password = "my_pass" ``` - - - Dict containing the remote name and the login for that remote. Use together with "remotes" variable to specify remote names e.j: - + + - Dict containing the remote name and the login for that remote. Use together with "remotes" variable to specify remote names e.j: + ``` password = {"remote1": "my_pass", "my_artifactory": "my_pass2"} ``` @@ -890,15 +890,15 @@ Using **CONAN_CLANG_VERSIONS** env variable in Travis ci or Appveyor: - **remotes**: Could take two values: - String of URLs separated by ",": - + ``` remotes = "https://api.bintray.com/conan/conan-community/conan,https://api.bintray.com/conan/other/conan2" ``` - - - List of tuples containing the "url", "use_ssl" flag and "name" . e.j: - + + - List of tuples containing the "url", "use_ssl" flag and "name" . e.j: + ``` - remotes = [("https://api.bintray.com/conan/conan-community/conan", True, "remote1"), + remotes = [("https://api.bintray.com/conan/conan-community/conan", True, "remote1"), ("https://api.bintray.com/conan/other/conan2", False, "remote2")] ``` @@ -927,10 +927,11 @@ Using **CONAN_CLANG_VERSIONS** env variable in Travis ci or Appveyor: - **allow_gcc_minors** Declare this variable if you want to allow gcc >=5 versions with the minor (5.1, 6.3 etc). - **exclude_vcvars_precommand** For Visual Studio builds, it exclude the vcvars call to set the environment. - **build_policy**: Default None. - - "never": No build from sources, only download packages. + - "never": No build from sources, only download packages. - "missing": Build only missing packages. - "outdated": Build only missing or if the available package is not built with the current recipe. Useful to upload new configurations, e.j packages for a new compiler without rebuild all packages. +- **test_folder**: Custom test folder consumed by Conan create, e.j .conan/test_package Upload related parameters: @@ -940,9 +941,9 @@ Upload related parameters: ``` upload = "https://api.bintray.com/conan/conan-community/conan" ``` - - - Tuple containing the "url", "use_ssl" flag and "name". - + + - Tuple containing the "url", "use_ssl" flag and "name". + ``` upload = ("https://api.bintray.com/conan/conan-community/conan", True, "remote1") ``` @@ -989,32 +990,32 @@ This is especially useful for CI integration. - **CONAN_USERNAME**: Your conan username (for the package reference) - **CONAN_REFERENCE**: Reference of the package to upload, e.g. "zlib/1.2.8". Otherwise it will be read from the `conanfile.py` - **CONAN_LOGIN_USERNAME**: Unique login username for all remotes. Will use "CONAN_USERNAME" when not present. -- **CONAN_LOGIN_USERNAME_XXX**: Specify a login for a remote name: - - - `CONAN_LOGIN_USERNAME_MYREPO=my_username` - +- **CONAN_LOGIN_USERNAME_XXX**: Specify a login for a remote name: + + - `CONAN_LOGIN_USERNAME_MYREPO=my_username` + - **CONAN_PASSWORD**: Conan Password, or API key if you are using Bintray. -- **CONAN_PASSWORD_XXX**: Specify a password for a remote name: - - - `CONAN_PASSWORD_MYREPO=mypassword` +- **CONAN_PASSWORD_XXX**: Specify a password for a remote name: + + - `CONAN_PASSWORD_MYREPO=mypassword` - **CONAN_REMOTES**: List of URLs separated by "," for the additional remotes (read). You can specify the SSL verify flag and the remote name using the "@" separator. e.j: - + - `CONAN_REMOTES=url1@True@remote_name, url2@False@remote_name2` - + The remote name is useful in case you want to specify custom credentials for different remotes. See `CONAN_LOGIN_USERNAME_XXX` and `CONAN_PASSWORD_XXX` -- **CONAN_UPLOAD**: URL of the repository where we want to use to upload the packages. +- **CONAN_UPLOAD**: URL of the repository where we want to use to upload the packages. The value can containing the URL, the SSL validation flag and remote name (last two optionals) separated by "@". e.j: - - - `CONAN_UPLOAD=https://api.bintray.com/conan/conan-community/conan` + + - `CONAN_UPLOAD=https://api.bintray.com/conan/conan-community/conan` - `CONAN_UPLOAD=https://api.bintray.com/conan/conan-community/conan@True` - - `CONAN_UPLOAD=https://api.bintray.com/conan/conan-community/conan@True@other_repo_name` - + - `CONAN_UPLOAD=https://api.bintray.com/conan/conan-community/conan@True@other_repo_name` + If a remote name is not specified, `upload_repo` will be used as a remote name. If the SSL validation configuration is not specified, it will use `True` by default. - + - **CONAN_UPLOAD_RETRY**: If defined, in case of fail retries to upload again the specified times - **CONAN_UPLOAD_ONLY_WHEN_STABLE**: If defined, will try to upload the packages only when the current channel is the stable one. @@ -1049,13 +1050,14 @@ This is especially useful for CI integration. - **CONAN_ALLOW_GCC_MINORS** Declare this variable if you want to allow gcc >=5 versions with the minor (5.1, 6.3 etc). - **CONAN_EXCLUDE_VCVARS_PRECOMMAND** For Visual Studio builds, it exclude the vcvars call to set the environment. - **CONAN_BUILD_REQUIRES** You can specify additional build requires for the generated profile with an environment variable following the same profile syntax and separated by "," - i.e ``CONAN_BUILD_REQUIRES: mingw-installer/7.1@conan/stable, pattern: other/1.0@conan/stable`` + i.e ``CONAN_BUILD_REQUIRES: mingw-installer/7.1@conan/stable, pattern: other/1.0@conan/stable`` - **CONAN_BUILD_POLICY**: Default None. - - "never": No build from sources, only download packages. + - "never": No build from sources, only download packages. - "missing": Build only missing packages. - "outdated": Build only missing or if the available package is not built with the current recipe. Useful to upload new configurations, e.j packages for a new compiler without rebuild all packages. - **CONAN_BASE_PROFILE**: Apply options, settings, etc. to this profile instead of `default`. +- **CONAN_TEST_FOLDER**: Custom test_package path, e.j .conan/test_package # Full example diff --git a/cpt/__init__.py b/cpt/__init__.py index d8a0070a..8f94d83b 100644 --- a/cpt/__init__.py +++ b/cpt/__init__.py @@ -1,2 +1,2 @@ -__version__ = '0.17.5' +__version__ = '0.18.0' diff --git a/cpt/packager.py b/cpt/packager.py index 5495989b..a41613e0 100644 --- a/cpt/packager.py +++ b/cpt/packager.py @@ -86,7 +86,8 @@ def __init__(self, args=None, username=None, channel=None, runner=None, conan_api=None, client_cache=None, ci_manager=None, - out=None): + out=None, + test_folder=None): self.printer = Printer(out) self.printer.print_rule() @@ -180,8 +181,23 @@ def __init__(self, args=None, username=None, channel=None, runner=None, elif platform.system() != "Windows": self.sudo_pip_command = "sudo -E" - self.docker_shell = "/bin/sh -c" - self.docker_conan_home = "/home/conan" + self.docker_shell = "" + self.docker_conan_home = "" + + if self.is_wcow: + self.docker_conan_home = "C:/Users/ContainerAdministrator" + self.docker_shell = "cmd /C" + else: + self.docker_conan_home = "/home/conan" + self.docker_shell = "/bin/sh -c" + + self.docker_platform_param = "" + self.lcow_user_workaround = "" + + if self.is_lcow: + self.docker_platform_param = "--platform=linux" + # With LCOW, Docker doesn't respect USER directive in dockerfile yet + self.lcow_user_workaround = "sudo su conan && " self.exclude_vcvars_precommand = (exclude_vcvars_precommand or os.getenv("CONAN_EXCLUDE_VCVARS_PRECOMMAND", False)) @@ -226,6 +242,8 @@ def __init__(self, args=None, username=None, channel=None, runner=None, self.builds_in_current_page = [] + self.test_folder = test_folder or os.getenv("CONAN_TEST_FOLDER", None) + def valid_pair(var, value): return (isinstance(value, six.string_types) or isinstance(value, bool) or @@ -235,6 +253,26 @@ def valid_pair(var, value): for var, value in self.__dict__.items() if valid_pair(var, value)}) + # For Docker on Windows, including Linux containers on Windows + @property + def is_lcow(self): + return self.container_os == "linux" and platform.system() == "Windows" + + @property + def is_wcow(self): + return self.container_os == "windows" and platform.system() == "Windows" + + @property + def container_os(self): + # CONAN_DOCKER_PLATFORM=linux must be specified for LCOW + if self.use_docker: + if "CONAN_DOCKER_PLATFORM" in os.environ: + return os.getenv("CONAN_DOCKER_PLATFORM", "windows").lower() + else: + return "windows" + else: + return "" + @property def items(self): return self._builds @@ -410,7 +448,8 @@ def run_builds(self, curpage=None, total_pages=None, base_profile_name=None): runner=self.runner, abs_folder=abs_folder, printer=self.printer, - upload=self._upload_enabled()) + upload=self._upload_enabled(), + test_folder=self.test_folder) r.run() else: docker_image = self._get_docker_image(build) @@ -427,7 +466,10 @@ def run_builds(self, curpage=None, total_pages=None, base_profile_name=None): upload=self._upload_enabled(), runner=self.runner, docker_shell=self.docker_shell, - docker_conan_home=self.docker_conan_home) + docker_conan_home=self.docker_conan_home, + docker_platform_param=self.docker_platform_param, + lcow_user_workaround=self.lcow_user_workaround, + test_folder=self.test_folder) r.run(pull_image=not pulled_docker_images[docker_image], docker_entry_script=self.docker_entry_script) diff --git a/cpt/run_in_docker.py b/cpt/run_in_docker.py index f44f34f5..7eba9c00 100644 --- a/cpt/run_in_docker.py +++ b/cpt/run_in_docker.py @@ -25,6 +25,7 @@ def run(): uploader = Uploader(conan_api, remotes_manager, auth_manager, printer) args = os.getenv("CPT_ARGS", "") build_policy = unscape_env(os.getenv("CPT_BUILD_POLICY")) + test_folder = unscape_env(os.getenv("CPT_TEST_FOLDER")) reference = ConanFileReference.loads(os.getenv("CONAN_REFERENCE")) profile_text = unscape_env(os.getenv("CPT_PROFILE")) @@ -38,7 +39,8 @@ def run(): upload = os.getenv("CPT_UPLOAD_ENABLED", None) runner = CreateRunner(abs_profile_path, reference, conan_api, uploader, args=args, - build_policy=build_policy, printer=printer, upload=upload) + build_policy=build_policy, printer=printer, upload=upload, + test_folder=test_folder) runner.run() if __name__ == '__main__': diff --git a/cpt/runner.py b/cpt/runner.py index e8b082bf..981c0a9c 100644 --- a/cpt/runner.py +++ b/cpt/runner.py @@ -13,7 +13,7 @@ class CreateRunner(object): def __init__(self, profile_abs_path, reference, conan_api, uploader, args=None, exclude_vcvars_precommand=False, build_policy=None, runner=None, - abs_folder=None, printer=None, upload=False): + abs_folder=None, printer=None, upload=False, test_folder=None): self.printer = printer or Printer() self._abs_folder = abs_folder or os.getcwd() @@ -27,6 +27,7 @@ def __init__(self, profile_abs_path, reference, conan_api, uploader, args=None, self._build_policy = build_policy self._runner = PrintRunner(runner or os.system, self.printer) self._uploader.remote_manager.add_remotes_to_conan() + self._test_folder = test_folder patch_default_base_profile(conan_api, profile_abs_path) self._profile = load_profile(profile_abs_path, self._conan_api._client_cache) @@ -69,7 +70,8 @@ def run(self): self._conan_api.create(".", name=name, version=version, user=user, channel=channel, build_modes=self._build_policy, - profile_name=self._profile_abs_path) + profile_name=self._profile_abs_path, + test_folder=self._test_folder) self._uploader.upload_packages(self._reference, self._upload) @@ -82,7 +84,9 @@ def __init__(self, profile_text, base_profile_text, base_profile_name, reference docker_image_skip_pull=False, always_update_conan_in_docker=False, upload=False, runner=None, - docker_shell=None, docker_conan_home=None): + docker_shell="", docker_conan_home="", + docker_platform_param="", lcow_user_workaround="", + test_folder=None): self.printer = Printer() self._args = args @@ -101,7 +105,10 @@ def __init__(self, profile_text, base_profile_text, base_profile_name, reference self._base_profile_name = base_profile_name self._docker_shell = docker_shell self._docker_conan_home = docker_conan_home + self._docker_platform_param = docker_platform_param + self._lcow_user_workaround = lcow_user_workaround self._runner = PrintRunner(runner, self.printer) + self._test_folder = test_folder def _pip_update_conan_command(self): commands = [] @@ -139,7 +146,7 @@ def run(self, pull_image=True, docker_entry_script=None): self._docker_image, self._docker_shell, self._pip_update_conan_command()) - + ret = self._runner(command) if ret != 0: raise Exception("Error updating the image: %s" % command) @@ -160,14 +167,16 @@ def run(self, pull_image=True, docker_entry_script=None): update_command = self._pip_update_conan_command() + " && " else: update_command = "" - command = ('%s docker run --rm -v %s:%s/project %s %s %s ' - '"cd project && ' + command = ('%s docker run --rm -v %s:%s/project %s %s %s %s ' + '"%s cd project && ' '%s run_create_in_docker "' % (self._sudo_docker_command, os.getcwd(), self._docker_conan_home, env_vars_text, + self._docker_platform_param, self._docker_image, self._docker_shell, + self._lcow_user_workaround, update_command)) # Push entry command before to build @@ -201,6 +210,7 @@ def get_env_vars(self): ret["CONAN_TEMP_TEST_FOLDER"] = "1" # test package folder to a temp one ret["CPT_UPLOAD_ENABLED"] = self._upload ret["CPT_BUILD_POLICY"] = escape_env(self._build_policy) + ret["CPT_TEST_FOLDER"] = escape_env(self._test_folder) ret.update({key: value for key, value in os.environ.items() if key.startswith("PIP_")}) diff --git a/cpt/test/integration/docker_test.py b/cpt/test/integration/docker_test.py index 6efba956..5167373d 100644 --- a/cpt/test/integration/docker_test.py +++ b/cpt/test/integration/docker_test.py @@ -3,6 +3,7 @@ import time import unittest + from conans.client import tools from conans.model.ref import ConanFileReference from cpt import __version__ as version @@ -84,3 +85,4 @@ class Pkg(ConanFile): results = self.api.search_recipes(search_pattern, remote="upload_repo")["results"] self.assertEquals(len(results), 0) self.api.remove(search_pattern, remote="upload_repo", force=True) + diff --git a/cpt/test/unit/packager_test.py b/cpt/test/unit/packager_test.py index 0fd4429f..32d9d093 100644 --- a/cpt/test/unit/packager_test.py +++ b/cpt/test/unit/packager_test.py @@ -587,6 +587,37 @@ def test_build_policy(self): builder.run() self.assertEquals(["missing"], self.conan_api.calls[-1].kwargs["build_modes"]) + def test_test_folder(self): + builder = ConanMultiPackager(username="pepe", channel="testing", + reference="Hello/0.1", password="password", + visual_versions=[], gcc_versions=[], + apple_clang_versions=[], + runner=self.runner, + conan_api=self.conan_api, + remotes="otherurl", + platform_info=platform_mock_for("Darwin"), + test_folder="foobar", + ci_manager=self.ci_manager) + builder.add_common_builds() + builder.run() + self.assertEquals("foobar", self.conan_api.calls[-1].kwargs["test_folder"]) + + with tools.environment_append({"CONAN_BUILD_POLICY": "missing"}): + self.conan_api = MockConanAPI() + builder = ConanMultiPackager(username="pepe", channel="testing", + reference="Hello/0.1", password="password", + visual_versions=[], gcc_versions=[], + apple_clang_versions=[], + runner=self.runner, + conan_api=self.conan_api, + remotes="otherurl", + platform_info=platform_mock_for("Darwin"), + build_policy=None, + ci_manager=self.ci_manager) + builder.add_common_builds() + builder.run() + self.assertEquals(None, self.conan_api.calls[-1].kwargs["test_folder"]) + def test_check_credentials(self): builder = ConanMultiPackager(username="pepe", channel="testing", @@ -652,5 +683,3 @@ def channel_detector_test(self): ci_manager=MockCIManager(current_branch=branch)) self.assertEquals(builder.channel, expected_channel, "Not match for branch %s" % branch) - -