diff --git a/docs/usage/rust.md b/docs/usage/rust.md index cf7494e0b41293..45365bbfa46c76 100644 --- a/docs/usage/rust.md +++ b/docs/usage/rust.md @@ -11,7 +11,7 @@ Renovate supports upgrading dependencies in `Cargo.toml` files and their accompa 1. Renovate searches in each repository for any `Cargo.toml` files 1. Renovate extracts existing dependencies from `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]` and `[workspace.dependencies]` -1. Renovate tries to find and parse a `.cargo/config.toml` file to discover index URLs for private registries +1. Renovate looks up Cargo configuration to find index URLs for private registries 1. Renovate resolves the dependency's version using the crates.io API or by cloning the index URL 1. If Renovate finds an update, Renovate will use `cargo update` to update both `Cargo.toml` and `Cargo.lock` @@ -19,6 +19,16 @@ Renovate supports upgrading dependencies in `Cargo.toml` files and their accompa Renovate updates Rust crates by default. +## Cargo configuration and private registry discovery + +Renovate can find private registry URLs in these Cargo configuration files: + +- `.cargo/config.toml` +- `.cargo/config` (legacy) + +Renovate can also find private registry URLs via a `CARGO_REGISTRIES__INDEX` environment variable. +Read the [Rust environment variables docs](https://doc.rust-lang.org/cargo/reference/environment-variables.html#configuration-environment-variables) to learn more. + ## Private crate registries and private Git dependencies If any dependencies are hosted in private Git repositories, [Git Authentication for cargo](https://doc.rust-lang.org/cargo/appendix/git-authentication.html) must be set up. diff --git a/lib/modules/manager/cargo/extract.spec.ts b/lib/modules/manager/cargo/extract.spec.ts index 1800fc57da3d29..457e92ef8716ed 100644 --- a/lib/modules/manager/cargo/extract.spec.ts +++ b/lib/modules/manager/cargo/extract.spec.ts @@ -31,6 +31,8 @@ describe('modules/manager/cargo/extract', () => { }; GlobalConfig.set(adminConfig); + delete process.env.CARGO_REGISTRIES_PRIVATE_CRATES_INDEX; + delete process.env.CARGO_REGISTRIES_MCORBIN_INDEX; }); afterEach(async () => { @@ -113,6 +115,50 @@ describe('modules/manager/cargo/extract', () => { expect(res?.deps).toHaveLength(3); }); + it('extracts registry urls from environment', async () => { + process.env.CARGO_REGISTRIES_PRIVATE_CRATES_INDEX = + 'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git'; + process.env.CARGO_REGISTRIES_MCORBIN_INDEX = + 'https://github.com/mcorbin/testregistry'; + const res = await extractPackageFile(cargo6toml, 'Cargo.toml', { + ...config, + }); + + expect(res?.deps).toEqual([ + { + currentValue: '0.1.0', + datasource: 'crate', + depName: 'proprietary-crate', + depType: 'dependencies', + managerData: { + nestedVersion: true, + }, + registryUrls: [ + 'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git', + ], + }, + { + currentValue: '3.0.0', + datasource: 'crate', + depName: 'mcorbin-test', + depType: 'dependencies', + managerData: { + nestedVersion: true, + }, + registryUrls: ['https://github.com/mcorbin/testregistry'], + }, + { + currentValue: '0.2', + datasource: 'crate', + depName: 'tokio', + depType: 'dependencies', + managerData: { + nestedVersion: false, + }, + }, + ]); + }); + it('extracts workspace dependencies', async () => { const cargoToml = codeBlock` [package] diff --git a/lib/modules/manager/cargo/extract.ts b/lib/modules/manager/cargo/extract.ts index 4da8fa5e4939ae..89ea94bee4c842 100644 --- a/lib/modules/manager/cargo/extract.ts +++ b/lib/modules/manager/cargo/extract.ts @@ -15,6 +15,11 @@ import type { CargoSection, } from './types'; +function getCargoIndexEnv(registryName: string): string | null { + const registry = registryName.toUpperCase().replaceAll('-', '_'); + return process.env[`CARGO_REGISTRIES_${registry}_INDEX`] ?? null; +} + function extractFromSection( parsedContent: CargoSection, section: keyof CargoSection, @@ -47,7 +52,9 @@ function extractFromSection( currentValue = version; nestedVersion = true; if (registryName) { - const registryUrl = cargoRegistries[registryName]; + const registryUrl = + cargoRegistries[registryName] ?? getCargoIndexEnv(registryName); + if (registryUrl) { registryUrls = [registryUrl]; } else {