Skip to content

Commit

Permalink
New command cargoLogin to login in all cargo registries (#153)
Browse files Browse the repository at this point in the history
* cargoSyncConfig logins in all cargo registries

* Add changelog entry

* Placate linters

* Add comment on ignored error in CargoSyncConfigTask

* Move cargo login commands to new CargoLoginTask

* Use cargo:token with least priority

* Add comment on order of cargo credential providers

* Update changelog entry

* Linting

* Apply suggestions from Nicolas

Co-authored-by: Nicolas Trinquier <[email protected]>

* Use TaskStatus for CargoLoginTask error handling

* add log when cargo login command fails

---------

Co-authored-by: Quentin Santos <[email protected]>
Co-authored-by: Nicolas Trinquier <[email protected]>
Co-authored-by: Niklas Rosenstein <[email protected]>
  • Loading branch information
4 people authored Feb 27, 2024
1 parent 3d53936 commit 6de51b3
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 1 deletion.
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)
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}

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

0 comments on commit 6de51b3

Please sign in to comment.