def test_inherit_image(temp_repo_func): backend = DockerBackend(verbosity=2, inherit_image="python:alpine3.6") arca = Arca(backend=backend, base_dir=BASE_DIR) task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" temp_repo_func.file_path.write_text(RETURN_PLATFORM) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Platform") task = Task("test_file:return_platform") # debian is the default, alpine dist() returns ('', '', '') on - so this fails when the default image is used assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output != "debian" requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add( [str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") colorama_task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.9"
def render(self, page_type, *args, **kwargs): """ Renders a page in the fork, checks the content and registers urls to freeze. """ naucse.utils.routes.forks_raise_if_disabled() task = Task( "naucse.utils.forks:render", args=[page_type, self.slug] + list(args), kwargs=kwargs, ) result = arca.run(self.repo, self.branch, task, reference=Path("."), depth=None) if page_type != "calendar_ics" and result.output["content"] is not None: allowed_elements_parser.reset_and_feed(result.output["content"]) if "urls" in result.output: # freeze urls generated by the code in fork, but only if they start with the slug of the course absolute_urls_to_freeze.extend([ url for url in result.output["urls"] if url.startswith(f"/{self.slug}/") ]) return result.output
def test_keep_container_running(temp_repo_func): backend = DockerBackend(verbosity=2, keep_container_running=True) arca = Arca(backend=backend, base_dir=BASE_DIR) task = Task("test_file:return_str_function") backend.check_docker_access() # init docker client container_count = len(backend.client.containers.list()) assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" count_after_run = len(backend.client.containers.list()) assert count_after_run == container_count + 1 # let's assume no changes are done to containers elsewhere assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" count_after_second_run = len(backend.client.containers.list()) assert count_after_second_run == container_count + 1 # the count is still the same backend.stop_containers() count_after_stop = len(backend.client.containers.list()) assert count_after_stop == container_count
def test_single_pull(temp_repo_func, mocker): backend = CurrentEnvironmentBackend(verbosity=2, current_environment_requirements=None) arca = Arca(backend=backend, base_dir=BASE_DIR, single_pull=True) mocker.spy(arca, "_pull") task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" assert arca._pull.call_count == 1 temp_repo_func.file_path.write_text(SECOND_RETURN_STR_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Updated function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" assert arca._pull.call_count == 1 arca.pull_again(temp_repo_func.url, temp_repo_func.branch) assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == TEST_UNICODE assert arca._pull.call_count == 2
def test_unicode_path(temp_repo_func,): backend = CurrentEnvironmentBackend(verbosity=2) arca = Arca(backend=backend, base_dir=BASE_DIR + "/abčď", single_pull=True) task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string"
def test_cache(mocker, temp_repo_func, cache_backend, arguments): base_dir = Path(BASE_DIR) backend = VenvBackend(verbosity=2) base_dir.mkdir(parents=True, exist_ok=True) arca = Arca(backend=backend, base_dir=BASE_DIR, single_pull=True, settings={ "ARCA_CACHE_BACKEND": cache_backend, "ARCA_CACHE_BACKEND_ARGUMENTS": arguments }) requirements_path = temp_repo_func.repo_path / "requirements.txt" requirements_path.write_text("colorama==0.3.9") temp_repo_func.repo.index.add([str(requirements_path)]) temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Added requirements") colorama_task = Task("test_file:return_str_function") repo = arca.get_repo(temp_repo_func.url, temp_repo_func.branch) cache_key = arca.cache_key(temp_repo_func.url, temp_repo_func.branch, colorama_task, repo) # delete from previous tests arca.region.delete(cache_key) assert arca.region.get(cache_key) is NO_VALUE mocker.spy(arca.backend, "run") # run the first time, check it actually cached assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.9" assert arca.backend.run.call_count == 1 repo = arca.get_repo(temp_repo_func.url, temp_repo_func.branch) assert arca.region.get( arca.cache_key(temp_repo_func.url, temp_repo_func.branch, colorama_task, repo)) is not NO_VALUE assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.9" # check that the result was actually from cache, that run wasn't called again assert arca.backend.run.call_count == 1 arca.pull_again(temp_repo_func.url, temp_repo_func.branch) mocker.spy(arca, "get_files") assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.9" assert arca.get_files.call_count == 1 # check that the repo was pulled
def compute(self, instance): naucse.utils.views.forks_raise_if_disabled() task = Task(**self.process_kwargs(instance)) result = arca.run(getattr(instance, self.repo_prop.name), getattr(instance, self.branch_prop.name), task, reference=Path("."), depth=None) return result.output
def test_push_to_registry(temp_repo_func, mocker): backend = DockerBackend(verbosity=2, use_registry_name="docker.io/mikicz/arca-test") arca = Arca(backend=backend, base_dir=BASE_DIR) temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.repo.index.add( [str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Initial") task = Task("test_file:return_str_function") # even though the image might already exist on the registry, lets pretend it doesn't mocker.patch.object(backend, "try_pull_image_from_registry", lambda *args: None) assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" mocker.stopall() image = backend.get_image_for_repo(temp_repo_func.url, temp_repo_func.branch, temp_repo_func.repo, temp_repo_func.repo_path) backend.client.images.remove(image.id, force=True) mocker.spy(backend, "build_image") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" assert backend.build_image.call_count == 0 # test push disabled mocker.patch.object(backend, "try_pull_image_from_registry", lambda *args: None) # untag the image so Arca thinks the images was just built and that it needs to be pushed for image in backend.client.images.list("docker.io/mikicz/arca-test"): for tag in image.tags: if tag.startswith("docker.io/mikicz/arca-test"): backend.client.images.remove(tag) backend = DockerBackend(verbosity=2, use_registry_name="docker.io/mikicz/arca-test", registry_pull_only=True) arca = Arca(backend=backend, base_dir=BASE_DIR) mocker.spy(backend, "push_to_registry") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" assert backend.push_to_registry.call_count == 0
def test_python_version(temp_repo_func, python_version): backend = DockerBackend(verbosity=2, python_version=python_version) arca = Arca(backend=backend, base_dir=BASE_DIR) temp_repo_func.file_path.write_text(RETURN_PYTHON_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Initial") task = Task("test_file:return_python_version") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == python_version
def test_output(temp_repo_func): arca = Arca(backend=CurrentEnvironmentBackend) temp_repo_func.file_path.write_text(PRINTING_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Initial") result = arca.run(temp_repo_func.url, temp_repo_func.branch, Task("test_file:func")) assert result.output == 1 assert result.stdout == "Printed to stdout\nWritten to stdout" assert result.stderr == "Printed to stderr\nWritten to stderr"
def get_course(self, slug, *, version, path): task = Task( entry_point="naucse_render:get_course", args=[slug], kwargs={ 'version': version, 'path': '.' }, ) with self.wrap_errors('get_course', slug): info = self.arca.run(self.url, self.branch, task).output return info
def get_lessons(self, lesson_slugs, *, vars, path): # Default timeout is 5s; multiply this by the no. of requested lessons timeout = 5 * len(lesson_slugs) task = Task( entry_point="naucse_render:get_lessons", args=[sorted(lesson_slugs)], kwargs={ 'vars': vars, 'path': '.' }, timeout=timeout, ) with self.wrap_errors('get_lessons', lesson_slugs): info = self.arca.run(self.url, self.branch, task).output return info
def get_footer_links(self, lesson_slug, page, **kwargs): """Return links to previous page, current session and the next page. Each link is either a dict with 'url' and 'title' keys or ``None``. If :meth:`render_page` fails and a canonical version is in the base repo, it's used instead with a warning. This method provides the correct footer links for the page, since ``sessions`` is not included in the info provided by forks. """ naucse.utils.views.forks_raise_if_disabled() task = Task("naucse.utils.forks:get_footer_links", args=[self.slug, lesson_slug, page], kwargs=kwargs) result = arca.run(self.repo, self.branch, task, reference=Path("."), depth=None) to_return = [] from naucse.views import logger logger.debug(result.output) if not isinstance(result.output, dict): return None, None, None def validate_link(link, key): return key in link and isinstance(link[key], str) for link_type in "prev_link", "session_link", "next_link": link = result.output.get(link_type) if isinstance(link, dict) and validate_link( link, "url") and validate_link(link, "title"): if link["url"].startswith(f"/{self.slug}/"): absolute_urls_to_freeze.append(link["url"]) to_return.append(link) else: to_return.append(None) logger.debug(to_return) return to_return
def test_apt_dependencies(temp_repo_func): backend = DockerBackend(verbosity=2, apt_dependencies=["libasound2-dev"]) arca = Arca(backend=backend, base_dir=BASE_DIR) requirements_path = temp_repo_func.repo_path / "requirements.txt" requirements_path.write_text("pyalsaaudio==0.8.4") temp_repo_func.file_path.write_text(RETURN_ALSAAUDIO_INSTALLED) temp_repo_func.repo.index.add( [str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to lxml") # pyalsaaudio can't be installed if libasound2-dev is missing task = Task("test_file:return_alsaaudio_installed") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output
def get_course(self, slug, *, version, path): task = Task( entry_point="naucse_render:get_course", args=[slug], kwargs={ 'version': version, 'path': '.' }, ) with self.wrap_errors('get_course', slug): info = self.arca.run(self.url, self.branch, task).output repo = self.arca.get_repo(self.url, self.branch) etag = self.arca.current_git_hash(self.url, self.branch, repo) if 'course' in info: info['course'].setdefault('etag', etag) return info
def test_unicode(mocker, args, kwargs, result): load = mocker.patch("arca._runner.EntryPoint.load") def func(カ): return カ * 2 load.return_value = func _, file = tempfile.mkstemp() file = Path(file) file.write_text(Task("library.mod:func", args=args, kwargs=kwargs).json) output = runner.run(str(file)) assert Result(output).output == result file.unlink()
def render(self, page_type, *args, **kwargs): """Render a page in the fork. Check the content and registers URLs to freeze. """ naucse.utils.views.forks_raise_if_disabled() task = Task( "naucse.utils.forks:render", args=[page_type, self.slug] + list(args), kwargs=kwargs, ) result = arca.run(self.repo, self.branch, task, reference=Path("."), depth=None) if page_type != "calendar_ics" and result.output["content"] is not None: allowed_elements_parser.reset_and_feed(result.output["content"]) return result.output
def test_push_to_registry_fail(temp_repo_func): # when a unused repository name is used, it's created -> different username has to be used backend = DockerBackend( verbosity=2, use_registry_name="docker.io/mikicz-unknown-user/arca-test") arca = Arca(backend=backend, base_dir=BASE_DIR) temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.repo.index.add( [str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Initial") task = Task("test_file:return_str_function") with pytest.raises(PushToRegistryError): assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9"
def test_current_environment_backend(temp_repo_func, requirements_location, file_location): """ Tests the basic stuff around backends, if it can install requirements from more locations, launch stuff with correct cwd, works well with multiple branches, etc """ kwargs = {} if requirements_location is not None: kwargs["requirements_location"] = requirements_location if file_location is not None: kwargs["cwd"] = file_location backend = CurrentEnvironmentBackend(verbosity=2, **kwargs) arca = Arca(backend=backend, base_dir=BASE_DIR) if file_location is None: filepath = temp_repo_func.file_path else: filepath = temp_repo_func.repo_path / file_location / "test_file.py" filepath.parent.mkdir(exist_ok=True, parents=True) temp_repo_func.file_path.replace(filepath) temp_repo_func.repo.index.remove([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Initial") task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" filepath.write_text(SECOND_RETURN_STR_FUNCTION) temp_repo_func.repo.create_head("new_branch") temp_repo_func.repo.create_tag("test_tag") temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Updated function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == TEST_UNICODE # in the other branch there's still the original assert arca.run(temp_repo_func.url, "new_branch", task).output == "Some string" # test that tags work as well assert arca.run(temp_repo_func.url, "test_tag", task).output == "Some string" temp_repo_func.repo.branches.master.checkout() requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.parent.mkdir(exist_ok=True, parents=True) requirements_path.write_text("colorama==0.3.9") filepath.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(filepath), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") # check that it's not installed from previous tests _pip_action("uninstall", "colorama") with pytest.raises(ModuleNotFoundError): import colorama # noqa # CurrentEnv fails because it ignores requirements with pytest.raises(BuildError): assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" # but when it's installed locally then it succeeds _pip_action("install", "colorama==0.3.9") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" # cleanup _pip_action("uninstall", "colorama") with pytest.raises(ModuleNotFoundError): import colorama # noqa
def test_backends(temp_repo_func, backend, requirements_location, file_location): """ Tests the basic stuff around backends, if it can install requirements from more locations, launch stuff with correct cwd, works well with multiple branches, etc """ if os.environ.get("TRAVIS", False) and backend == VenvBackend: pytest.skip("Venv Backend doesn't work on Travis") kwargs = {} if requirements_location is not None: kwargs["requirements_location"] = requirements_location if file_location is not None: kwargs["cwd"] = file_location if backend == DockerBackend: kwargs["disable_pull"] = True if backend == CurrentEnvironmentBackend: kwargs["current_environment_requirements"] = None kwargs["requirements_strategy"] = "install_extra" backend = backend(verbosity=2, **kwargs) arca = Arca(backend=backend, base_dir=BASE_DIR) if file_location is None: filepath = temp_repo_func.file_path else: filepath = temp_repo_func.repo_path / file_location / "test_file.py" filepath.parent.mkdir(exist_ok=True, parents=True) temp_repo_func.file_path.replace(filepath) temp_repo_func.repo.index.remove([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Initial") task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" filepath.write_text(SECOND_RETURN_STR_FUNCTION) temp_repo_func.repo.create_head("new_branch") temp_repo_func.repo.create_tag("test_tag") temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Updated function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == TEST_UNICODE # in the other branch there's still the original assert arca.run(temp_repo_func.url, "new_branch", task).output == "Some string" # test that tags work as well assert arca.run(temp_repo_func.url, "test_tag", task).output == "Some string" temp_repo_func.repo.branches.master.checkout() requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.parent.mkdir(exist_ok=True, parents=True) requirements_path.write_text("colorama==0.3.9") filepath.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(filepath), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" requirements_path.write_text("colorama==0.3.8") temp_repo_func.repo.index.add([str(requirements_path)]) temp_repo_func.repo.index.commit("Updated requirements") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.8" # cleanup if isinstance(backend, CurrentEnvironmentBackend): backend._uninstall("colorama") with pytest.raises(ModuleNotFoundError): import colorama # noqa
def test_advanced_backends(temp_repo_func, backend): """ Tests the more time-intensive stuff, like timeouts or arguments, things multiple for runs with different arguments are not neccessary """ if os.environ.get("TRAVIS", False) and backend == VenvBackend: pytest.skip("Venv Backend doesn't work on Travis") kwargs = {} if backend == DockerBackend: kwargs["disable_pull"] = True if backend == CurrentEnvironmentBackend: kwargs["current_environment_requirements"] = None kwargs["requirements_strategy"] = "install_extra" backend = backend(verbosity=2, **kwargs) arca = Arca(backend=backend, base_dir=BASE_DIR) filepath = temp_repo_func.file_path requirements_path = temp_repo_func.repo_path / backend.requirements_location filepath.write_text(ARG_STR_FUNCTION) temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Argument function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, Task("test_file:return_str_function", args=[TEST_UNICODE])).output == TEST_UNICODE[::-1] filepath.write_text(KWARG_STR_FUNCTION) temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Keyword argument function") assert arca.run( temp_repo_func.url, temp_repo_func.branch, Task("test_file:return_str_function", kwargs={"kwarg": TEST_UNICODE})).output == TEST_UNICODE[::-1] # test task timeout filepath.write_text(WAITING_FUNCTION) temp_repo_func.repo.index.add([str(filepath)]) temp_repo_func.repo.index.commit("Waiting function") task_1_second = Task("test_file:return_str_function", timeout=1) task_3_seconds = Task("test_file:return_str_function", timeout=3) with pytest.raises(BuildTimeoutError): arca.run(temp_repo_func.url, temp_repo_func.branch, task_1_second) assert arca.run(temp_repo_func.url, temp_repo_func.branch, task_3_seconds).output == "Some string" # test requirements timeout requirements_path.write_text("scipy") filepath.write_text(RETURN_STR_FUNCTION) temp_repo_func.repo.index.add([str(filepath), str(requirements_path)]) temp_repo_func.repo.index.commit( "Updated requirements to something that takes > 1 second to install") arca.backend.requirements_timeout = 1 with pytest.raises(BuildTimeoutError): arca.run(temp_repo_func.url, temp_repo_func.branch, Task("test_file:return_str_function"))
def test_vagrant(temp_repo_func, destroy=False): if os.environ.get("TRAVIS", False): pytest.skip("Vagrant doesn't work on Travis") backend = VagrantBackend(verbosity=2, use_registry_name="docker.io/mikicz/arca-test", keep_vm_running=True) arca = Arca(backend=backend, base_dir=BASE_DIR) if destroy: vagrant_location = backend.get_vm_location() if vagrant_location.exists(): vagrant = Vagrant(vagrant_location) vagrant.destroy() shutil.rmtree(vagrant_location) # master branch - return colorama version temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.repo.index.add( [str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Initial") # branch branch - return unicode temp_repo_func.repo.create_head("branch") temp_repo_func.repo.branches.branch.checkout() temp_repo_func.file_path.write_text(SECOND_RETURN_STR_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Test unicode on a separate branch") task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" # halt the VM, checks that the VM can be booted when stopped with the vagrant attribute set backend.stop_vm() assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" # halt the vm and create a new instance of the backend, to check that the vagrant attribute can be set from existing backend.stop_vm() backend = VagrantBackend(verbosity=2, use_registry_name="docker.io/mikicz/arca-test", keep_vm_running=True) arca = Arca(backend=backend, base_dir=BASE_DIR) assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" # test that two branches can work next to each other assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" assert arca.run(temp_repo_func.url, "branch", task).output == TEST_UNICODE # test timeout temp_repo_func.repo.branches.master.checkout() temp_repo_func.file_path.write_text(WAITING_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Waiting function") task_1_second = Task("test_file:return_str_function", timeout=1) task_3_seconds = Task("test_file:return_str_function", timeout=3) with pytest.raises(BuildTimeoutError): assert arca.run(temp_repo_func.url, temp_repo_func.branch, task_1_second).output == "Some string" assert arca.run(temp_repo_func.url, temp_repo_func.branch, task_3_seconds).output == "Some string" backend.stop_vm() if destroy: backend.destroy = True backend.stop_vm()
def test_strategy_ignore(mocker, temp_repo_func, strategy): install_requirements = mocker.patch.object(CurrentEnvironmentBackend, "install_requirements") arca = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=None, requirements_strategy=strategy ), base_dir=BASE_DIR) task = Task("test_file:return_str_function") # nor the current env or the repo has any requirements, install requirements is not called at all assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" assert install_requirements.call_count == 0 # keep a reference to when the repo had no requirements, needed later temp_repo_func.repo.create_head("no_requirements") temp_repo_func.repo.branches.master.checkout() requirements_path = temp_repo_func.repo_path / arca.backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") # now the repository has got requirements # install still not called but the task should fail because colorama is not installed with pytest.raises(BuildError): arca.run(temp_repo_func.url, temp_repo_func.branch, task) assert install_requirements.call_count == 0 current_env_requirements = Path(BASE_DIR) / (str(uuid4()) + ".txt") current_env_requirements_non_existent = Path(BASE_DIR) / (str(uuid4()) + ".txt") with current_env_requirements.open("w") as fl: fl.write("colorama==0.3.9") arca = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=str(current_env_requirements.resolve()), requirements_strategy=strategy ), base_dir=BASE_DIR) arca_nonexistent_req = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=str(current_env_requirements_non_existent.resolve()), requirements_strategy=strategy ), base_dir=BASE_DIR) # now both the current env and the repo have requirements # install still not called but the task should fail because colorama is not installed with pytest.raises(BuildError): arca.run(temp_repo_func.url, temp_repo_func.branch, task) # same result even when the current env requirements don't exist with pytest.raises(BuildError): arca_nonexistent_req.run(temp_repo_func.url, temp_repo_func.branch, task) assert install_requirements.call_count == 0 # even when the requirements are not the same with current_env_requirements.open("w") as fl: fl.write("six") with pytest.raises(BuildError): arca.run(temp_repo_func.url, temp_repo_func.branch, task) assert install_requirements.call_count == 0 # and now we test everything still works when the req. file is missing from repo assert arca.run(temp_repo_func.url, "no_requirements", task).output == "Some string" assert arca_nonexistent_req.run(temp_repo_func.url, "no_requirements", task).output == "Some string" assert install_requirements.call_count == 0
def test_strategy_install_extra(temp_repo_func, mocker, strategy): install_requirements = mocker.spy(CurrentEnvironmentBackend, "install_requirements") arca = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=None, requirements_strategy=strategy ), base_dir=BASE_DIR) arca_non_existent = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=str((Path(BASE_DIR) / (str(uuid4()) + ".txt")).resolve()), requirements_strategy=strategy ), base_dir=BASE_DIR) task = Task("test_file:return_str_function") # nor the current env or the repo has any requirements, install requirements is not called at all assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" # even when the current env file is missing assert arca_non_existent.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" assert install_requirements.call_count == 0 # keep a reference to when the repo had no requirements, needed later temp_repo_func.repo.create_head("no_requirements") temp_repo_func.repo.branches.master.checkout() requirements_path = temp_repo_func.repo_path / arca.backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") # Repository now contains a requirement while the current env has none - install is called with whole file assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" # but raises exception when can't compare because the current env file is missing with pytest.raises(ArcaMisconfigured): arca_non_existent.run(temp_repo_func.url, temp_repo_func.branch, task) assert install_requirements.call_count == 1 current_env_requirements = Path(BASE_DIR) / (str(uuid4()) + ".txt") with current_env_requirements.open("w") as fl: fl.write("colorama==0.3.9") arca = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=str(current_env_requirements.resolve()), requirements_strategy=strategy ), base_dir=BASE_DIR) # now both the current env and the repo have the same requirements, call count shouldn't increase assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" assert install_requirements.call_count == 1 with current_env_requirements.open("w") as fl: fl.write("six") # requirements are now not the same, install is called again assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "0.3.9" assert install_requirements.call_count == 2 # and now we test everything still works when the req. file is missing from repo but env. reqs. are set assert arca.run(temp_repo_func.url, "no_requirements", task).output == "Some string" arca.backend._uninstall("colorama")
def test_strategy_raise(temp_repo_func, strategy): arca = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=None, requirements_strategy=strategy ), base_dir=BASE_DIR) arca_non_existent = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=str((Path(BASE_DIR) / (str(uuid4()) + ".txt")).resolve()), requirements_strategy=strategy ), base_dir=BASE_DIR) task = Task("test_file:return_str_function") # nor the current env or the repo has any requirements, install requirements is not called at all assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" # even when the current env. req. file doesn't exist assert arca_non_existent.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" # keep a reference to when the repo had no requirements, needed later temp_repo_func.repo.create_head("no_requirements") temp_repo_func.repo.branches.master.checkout() requirements_path = temp_repo_func.repo_path / arca.backend.requirements_location requirements_path.write_text("colorama==0.3.9") temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add([str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") # Run should raise a exception because there's now extra requirements in the repo with pytest.raises(RequirementsMismatch): arca.run(temp_repo_func.url, temp_repo_func.branch, task) # raise different exception when can't compare to current env because it's missing with pytest.raises(ArcaMisconfigured): arca_non_existent.run(temp_repo_func.url, temp_repo_func.branch, task) current_env_requirements = Path(BASE_DIR) / (str(uuid4()) + ".txt") current_env_requirements.write_text("colorama==0.3.9") arca = Arca(backend=CurrentEnvironmentBackend( verbosity=2, current_environment_requirements=str(current_env_requirements.resolve()), requirements_strategy=strategy ), base_dir=BASE_DIR) # now both the current env and the repo have the same requirements # run should fail not because of mismatch, but because colorama is not actually installed with pytest.raises(BuildError): arca.run(temp_repo_func.url, temp_repo_func.branch, task) # an extra requirement when current env. reqs. are set with current_env_requirements.open("w") as fl: fl.write("six") with pytest.raises(RequirementsMismatch): arca.run(temp_repo_func.url, temp_repo_func.branch, task) # and now we test everything still works when the req. file is missing from repo but env. reqs. are set assert arca.run(temp_repo_func.url, "no_requirements", task).output == "Some string"
def test_inherit_image(temp_repo_func): backend = DockerBackend(verbosity=2, inherit_image="mikicz/alpine-python-pipenv:latest") arca = Arca(backend=backend, base_dir=BASE_DIR) task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output == "Some string" temp_repo_func.file_path.write_text(RETURN_PLATFORM) temp_repo_func.repo.index.add([str(temp_repo_func.file_path)]) temp_repo_func.repo.index.commit("Platform") task = Task("test_file:return_platform") # debian is the default, alpine dist() returns ('', '', '') on - so this fails when the default image is used assert arca.run(temp_repo_func.url, temp_repo_func.branch, task).output != "debian" requirements_path = temp_repo_func.repo_path / backend.requirements_location requirements_path.write_text("colorama==0.3.8") temp_repo_func.file_path.write_text(RETURN_COLORAMA_VERSION_FUNCTION) temp_repo_func.repo.index.add( [str(temp_repo_func.file_path), str(requirements_path)]) temp_repo_func.repo.index.commit("Added requirements, changed to version") colorama_task = Task("test_file:return_str_function") assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.8" # Pipfile pipfile_path = requirements_path.parent / "Pipfile" pipfile_lock_path = pipfile_path.parent / "Pipfile.lock" pipfile_path.write_text( (Path(__file__).parent / "fixtures/Pipfile").read_text("utf-8")) temp_repo_func.repo.index.remove([str(requirements_path)]) temp_repo_func.repo.index.add([str(pipfile_path)]) temp_repo_func.repo.index.commit("Added Pipfile") with pytest.raises(BuildError): # Only Pipfile arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task) pipfile_lock_path.write_text( (Path(__file__).parent / "fixtures/Pipfile.lock").read_text("utf-8")) temp_repo_func.repo.index.remove([str(pipfile_path)]) temp_repo_func.repo.index.add([str(pipfile_lock_path)]) temp_repo_func.repo.index.commit("Removed Pipfile, added Pipfile.lock") with pytest.raises(BuildError): # Only Pipfile.lock arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task) pipfile_path.write_text( (Path(__file__).parent / "fixtures/Pipfile").read_text("utf-8")) temp_repo_func.repo.index.add([str(pipfile_path)]) temp_repo_func.repo.index.commit("Added back Pipfile") assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.9" # works even when requirements is in the repo requirements_path.write_text("colorama==0.3.8") temp_repo_func.repo.index.add([str(requirements_path)]) temp_repo_func.repo.index.commit("Added back requirements") assert arca.run(temp_repo_func.url, temp_repo_func.branch, colorama_task).output == "0.3.9"