diff --git a/kraken-build/pyproject.toml b/kraken-build/pyproject.toml index debf3ab7..96224e46 100644 --- a/kraken-build/pyproject.toml +++ b/kraken-build/pyproject.toml @@ -64,6 +64,7 @@ types-requests = "^2.28.0" pytest-xdist = {version = "^3.5.0", extras = ["psutil"]} mitmproxy = "^10.2.4" types-networkx = "^3.2.1.20240703" +requests-mock = "^1.12.1" # Slap configuration # ------------------ diff --git a/kraken-build/src/kraken/std/cargo/tasks/cargo_publish_task.py b/kraken-build/src/kraken/std/cargo/tasks/cargo_publish_task.py index e85a577b..1d2e4993 100644 --- a/kraken-build/src/kraken/std/cargo/tasks/cargo_publish_task.py +++ b/kraken-build/src/kraken/std/cargo/tasks/cargo_publish_task.py @@ -67,8 +67,7 @@ def prepare(self) -> TaskStatus | None: return self._check_package_existence(package_name, version, self.registry.get()) except Exception as e: logger.warn( - f"An error happened while checking for {package_name} existence in {self.registry.get().alias}", - e, + f"An error happened while checking for {package_name} existence in {self.registry.get().alias}, {e}", ) return TaskStatus.pending("Unable to verify package existence") @@ -159,6 +158,7 @@ def _check_package_existence(cls, package_name: str, version: str, registry: Car if not registry.index.startswith("sparse+"): return TaskStatus.pending("Unable to verify package existence - Only sparse registries are supported") index = registry.index.removeprefix("sparse+") + index = index.removesuffix("/") # >> Index authentication session = requests.sessions.Session() diff --git a/kraken-build/tests/kraken_std/integration/cargo/test_cargo_private_registry.py b/kraken-build/tests/kraken_std/integration/cargo/test_cargo_private_registry.py index 2ddace36..82cc9add 100644 --- a/kraken-build/tests/kraken_std/integration/cargo/test_cargo_private_registry.py +++ b/kraken-build/tests/kraken_std/integration/cargo/test_cargo_private_registry.py @@ -37,18 +37,10 @@ class CargoRepositoryWithAuth: creds: tuple[str, str] | None token: str | None - -def publish_lib_and_build_app(repository: CargoRepositoryWithAuth, tempdir: Path) -> None: - # Copy the Cargo project files to a temporary directory. - for item in ["cargo-hello-world-lib", "cargo-hello-world-app"]: - shutil.copytree(example_dir(item), tempdir / item) - - app_dir = tempdir.joinpath("cargo-hello-world-app") +def skip_publish_lib(repository: CargoRepositoryWithAuth, tempdir: Path) -> None: lib_dir = tempdir.joinpath("cargo-hello-world-lib") - + shutil.copytree(example_dir("cargo-hello-world-lib"), lib_dir) cargo_registry_id = "private-repo" - publish_version = ".".join(str(random.randint(0, 999)) for _ in range(3)) - logger.info("==== Publish version is %s", publish_version) with unittest.mock.patch.dict(os.environ, {"CARGO_HOME": str(tempdir)}): # Build the library and publish it to the registry. @@ -70,16 +62,38 @@ def publish_lib_and_build_app(repository: CargoRepositoryWithAuth, tempdir: Path task = cargo_sync_config() task.git_fetch_with_cli.set(True) cargo_check_toolchain_version(minimal_version="1.60") - cargo_publish( + publish_task = cargo_publish( cargo_registry_id, - version=publish_version, + version='0.1.0', cargo_toml_file=project1.directory.joinpath("Cargo.toml"), ) - project1.context.execute(["fmt", "lint", "publish"]) + graph = project1.context.execute(["publish"]) + status = graph.get_status(publish_task) + assert status is not None and status.is_skipped() + + +def publish_lib_and_build_app(repository: CargoRepositoryWithAuth, tempdir: Path) -> None: + # Copy the Cargo project files to a temporary directory. + for item in ["cargo-hello-world-lib", "cargo-hello-world-app"]: + shutil.copytree(example_dir(item), tempdir / item) + + app_dir = tempdir.joinpath("cargo-hello-world-app") + lib_dir = tempdir.joinpath("cargo-hello-world-lib") - # Try to publish the same version again - the task should be skipped and should not fail - with kraken_ctx() as ctx, kraken_project(ctx) as project2: - project2.directory = lib_dir + cargo_registry_id = "private-repo" + publish_version = ".".join(str(random.randint(0, 999)) for _ in range(3)) + logger.info("==== Publish version is %s", publish_version) + + with unittest.mock.patch.dict(os.environ, {"CARGO_HOME": str(tempdir)}): + # Build the library and publish it to the registry. + logger.info( + "Publishing cargo-hello-world-lib to Cargo repository %r (%r)", + repository.name, + repository.index_url, + ) + + with kraken_ctx() as ctx, kraken_project(ctx) as project1: + project1.directory = lib_dir cargo_registry( cargo_registry_id, repository.index_url, @@ -90,14 +104,12 @@ def publish_lib_and_build_app(repository: CargoRepositoryWithAuth, tempdir: Path task = cargo_sync_config() task.git_fetch_with_cli.set(True) cargo_check_toolchain_version(minimal_version="1.60") - public_task = cargo_publish( + cargo_publish( cargo_registry_id, version=publish_version, cargo_toml_file=project1.directory.joinpath("Cargo.toml"), ) - graph = project2.context.execute(["fmt", "lint", "publish"]) - status = graph.get_status(public_task) - assert status is not None and status.is_skipped() + project1.context.execute(["fmt", "lint", "publish"]) num_tries = 3 for idx in range(num_tries): @@ -108,9 +120,9 @@ def publish_lib_and_build_app(repository: CargoRepositoryWithAuth, tempdir: Path repository.name, repository.index_url, ) - with kraken_ctx() as ctx, kraken_project(ctx) as project3: - project3.directory = app_dir - cargo_toml = project3.directory / "Cargo.toml" + with kraken_ctx() as ctx, kraken_project(ctx) as project2: + project2.directory = app_dir + cargo_toml = project2.directory / "Cargo.toml" cargo_toml.write_text(cargo_toml.read_text().replace("$VERSION", publish_version)) cargo_registry( cargo_registry_id, @@ -122,7 +134,7 @@ def publish_lib_and_build_app(repository: CargoRepositoryWithAuth, tempdir: Path sync_task.git_fetch_with_cli.set(True) build_task = cargo_build("debug") build_task.from_project_dir = True - project3.context.execute(["fmt", "build"]) + project2.context.execute(["fmt", "build"]) # Running the application should give "Hello from hello-world-lib!". output = sp.check_output([app_dir / "target" / "debug" / "hello-world-app"]).decode() @@ -173,9 +185,20 @@ def private_registry(docker_service_manager: DockerServiceManager) -> str: time.sleep(5) return index_url - def test__private_cargo_registry_publish_and_consume(tempdir: Path, private_registry: str) -> None: repository = CargoRepositoryWithAuth( "kraken-std-cargo-integration-test", private_registry, None, "xxxxxxxxxxxxxxxxxxxxxx" ) publish_lib_and_build_app(repository, tempdir) + +def test__mock_cargo_registry_skips_publish_if_exists(tempdir: Path, requests_mock) -> None: + registry_url = "http://0.0.0.0:35510" + index_url = f"sparse+{registry_url}/" + + requests_mock.get(f"{registry_url}/config.json", text="{}") + requests_mock.get(f"{registry_url}/he/ll/hello-world-lib", text='{"vers": "0.1.0"}') + + repository = CargoRepositoryWithAuth( + "kraken-std-cargo-integration-test", index_url, None, "xxxxxxxxxxxxxxxxxxxxxx" + ) + skip_publish_lib(repository, tempdir)