Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New command cargoLogin to login in all cargo registries #153

Merged
merged 13 commits into from
Feb 27, 2024
6 changes: 6 additions & 0 deletions .changelog/_unreleased.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ id = "db65bd12-a9d1-472c-a38b-6f889cdda683"
type = "improvement"
description = "Move bump version into publish"
author = "[email protected]"

[[entries]]
id = "31a52a49-8d26-4dd7-a4bc-84fe9fb37c19"
type = "improvement"
description = "Add task to login in all cargo registries"
author = "[email protected]"
1 change: 1 addition & 0 deletions docs/docs/lang/cargo.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ cargo_registry(
)
cargo_auth_proxy()
cargo_sync_config()
cargo_login()
cargo_build("debug")
cargo_build("release")
cargo_publish("artifactory")
Expand Down
21 changes: 21 additions & 0 deletions kraken-build/src/kraken/std/cargo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .tasks.cargo_deny_task import CargoDenyTask
from .tasks.cargo_fmt_task import CargoFmtTask
from .tasks.cargo_generate_deb import CargoGenerateDebPackage
from .tasks.cargo_login import CargoLoginTask
from .tasks.cargo_publish_task import CargoPublishTask
from .tasks.cargo_sqlx_database_create import CargoSqlxDatabaseCreateTask
from .tasks.cargo_sqlx_database_drop import CargoSqlxDatabaseDropTask
Expand All @@ -35,6 +36,7 @@
"cargo_deny",
"cargo_fmt",
"cargo_generate_deb_package",
"cargo_login",
"cargo_publish",
"cargo_registry",
"cargo_sqlx_migrate",
Expand Down Expand Up @@ -207,6 +209,25 @@ def cargo_sync_config(
return task


def cargo_login(
*,
project: Project | None = None,
) -> CargoLoginTask:
"""Creates a task that will be added to the build and publish support groups
to login in the Cargo registries"""

project = project or Project.current()
cargo = CargoProject.get_or_create(project)
task = project.task("cargoLogin", CargoLoginTask, group="apply")
task.registries = Supplier.of_callable(lambda: list(cargo.registries.values()))
project.group(CARGO_BUILD_SUPPORT_GROUP_NAME).add(task)
qsantos marked this conversation as resolved.
Show resolved Hide resolved
project.group(CARGO_PUBLISH_SUPPORT_GROUP_NAME).add(task)

# We need to have the credentials providers set up by cargoSyncConfig
task.depends_on(":cargoSyncConfig")
return task


def cargo_clippy(
*,
allow: str = "staged",
Expand Down
38 changes: 38 additions & 0 deletions kraken-build/src/kraken/std/cargo/tasks/cargo_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from __future__ import annotations

from subprocess import run

from kraken.core import Property, Task, TaskStatus

from ..config import CargoRegistry


class CargoLoginTask(Task):
"""This task runs cargo login for each registry."""

#: The registries to insert into the configuration.
registries: Property[list[CargoRegistry]] = Property.default_factory(list)

def execute(self) -> TaskStatus:
for registry in self.registries.get():
publish_token = registry.publish_token
if publish_token is None:
continue
p = run(
["cargo", "login", "--registry", registry.alias],
cwd=self.project.directory,
capture_output=True,
input=publish_token.encode(),
)
if p.returncode != 0:
if p.stderr.endswith(b"\nerror: config.json not found in registry\n"):
# This happens when the project's .cargo/config.toml file
# contains a regitry which does not exist (anymore); since
# that means it is not used, we can just skip configuring
# authentication on this registry
pass
else:
# unknown error, fail normally
self.logger.error("cargo login failed: %s", p.stderr.decode())
return TaskStatus.failed("could not run cargo login")
return TaskStatus.succeeded()
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@ def __init__(self, name: str, project: Project) -> None:

def get_file_contents(self, file: Path) -> str | bytes:
content = tomli.loads(file.read_text()) if not self.replace.get() and file.exists() else {}
content.setdefault("registry", {})["global-credential-providers"] = ["cargo:token"]
# It seems like credential provider should be provided in reverse order
# of preference. We put cargo:token first, to always use the keyring if
# it is available.
content.setdefault("registry", {})["global-credential-providers"] = [
"cargo:token",
"cargo:libsecret",
"cargo:macos-keychain",
"cargo:wincred",
]
content.setdefault("registries", {})["crates-io"] = {"protocol": self.crates_io_protocol.get()}
for registry in self.registries.get():
content.setdefault("registries", {})[registry.alias] = {"index": registry.index}

qsantos marked this conversation as resolved.
Show resolved Hide resolved
if self.git_fetch_with_cli.is_filled():
if self.git_fetch_with_cli.get():
content.setdefault("net", {})["git-fetch-with-cli"] = True
Expand Down
Loading