diff --git a/eng/pipelines/templates/steps/use-rust.yml b/eng/pipelines/templates/steps/use-rust.yml index 450c7bff2ee..c54d6e60d4a 100644 --- a/eng/pipelines/templates/steps/use-rust.yml +++ b/eng/pipelines/templates/steps/use-rust.yml @@ -15,8 +15,58 @@ parameters: - name: SetDefault type: boolean default: true + - name: ConfigureRegistry + type: boolean + default: true steps: +# `variables/rust.yml` may relocate CARGO_HOME off the OS volume. Cargo finds its own +# subcommands there, but tools invoked directly (taplo, cargo2junit) need it on PATH. +- pwsh: | + $cargoBin = ([System.IO.Path]::Combine($env:CARGO_HOME, 'bin')) + New-Item -ItemType Directory -Force -Path $cargoBin | Out-Null + + if (($env:PATH -split [System.IO.Path]::PathSeparator) -notcontains $cargoBin) { + Write-Host "##vso[task.prependpath]$cargoBin" + } + displayName: Add CARGO_HOME/bin to PATH + condition: and(succeeded(), ne(variables['CARGO_HOME'], '')) + +- ${{ if parameters.ConfigureRegistry }}: + # CI builds run under network isolation with no access to public crates.io. Route + # crates.io traffic through the azure-sdk-for-rust Azure Artifacts feed defined in + # eng/templates/config.toml.template, then authenticate cargo to it. + - pwsh: | + $cargoHome = $env:CARGO_HOME + if (-not $cargoHome) { $cargoHome = ([System.IO.Path]::Combine($HOME, '.cargo')) } + New-Item -ItemType Directory -Force -Path $cargoHome | Out-Null + + $configPath = ([System.IO.Path]::Combine($cargoHome, 'config.toml')) + Copy-Item ` + -Path '$(Build.SourcesDirectory)/eng/templates/config.toml.template' ` + -Destination $configPath ` + -Force + + Write-Host "Wrote cargo config to $configPath" + Get-Content $configPath + Write-Host "##vso[task.setvariable variable=CargoConfigPath]$configPath" + displayName: Configure cargo to use the azure-sdk-for-rust feed + + # Workaround issue in public pipelines. Revert when root cause issue is fixed: + # https://github.com/microsoft/azure-pipelines-tasks/issues/22421 + # NuGetAuthenticate@1 uses the SYSTEMVSSCONNECTION endpoint token, which Azure + # DevOps does deliver to fork builds, and publishes it as VSS_NUGET_ACCESSTOKEN + # for later steps. + - task: NuGetAuthenticate@1 + displayName: Acquire an Azure Artifacts token that fork builds can use + + - task: CargoAuthenticate@0 + displayName: Authenticate cargo to the azure-sdk-for-rust feed + inputs: + configFile: $(CargoConfigPath) + env: + SYSTEM_ACCESSTOKEN: $(VSS_NUGET_ACCESSTOKEN) + - pwsh: | $Toolchain = '${{ parameters.Toolchain }}' $MaxAttempts = ${{ parameters.MaxAttempts }} diff --git a/eng/templates/config.toml.template b/eng/templates/config.toml.template new file mode 100644 index 00000000000..a5d953b180e --- /dev/null +++ b/eng/templates/config.toml.template @@ -0,0 +1,36 @@ +# Cargo configuration used by CI builds to route crates.io traffic through the +# Centralized Feed Service (CFS) instead of the public internet. +# +# This file should be copied to $CARGO_HOME/config.toml +# +# CargoAuthenticate@0 parses the [registries] table below and exports the +# CARGO_REGISTRIES_AZURE_SDK_FOR_RUST_PUBLIC_TOKEN / _CREDENTIAL_PROVIDER variables that +# cargo needs to authenticate against the feed. +# +# The `~force-auth` suffix on the feed name is required. See +# https://learn.microsoft.com/azure/devops/artifacts/cargo/cargo-upstream-source. + +[registries] +azure-sdk-for-rust-public = { index = "sparse+https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-rust-public~force-auth/Cargo/index/" } + +[source.crates-io] +replace-with = "azure-sdk-for-rust-public" + +# Both `cargo package` and `cargo publish` refuse to run while crates-io is replaced +# unless the target registry is named, failing with: +# +# error: crates-io is replaced with remote registry azure-sdk-for-rust-public; +# include `--registry azure-sdk-for-rust-public` or `--registry crates-io` +# +# The target registry must be the replacement, not crates-io. When packaging several +# workspace members at once, cargo satisfies their unpublished inter-member versions +# (for example typespec_client_core depending on typespec ^1.2.0-beta.1) from the crates +# it just packaged. That overlay is only consulted when the target registry matches the +# source deps resolve through, so `--registry crates-io` still fails to find them. +# +# Setting the default here keeps eng/scripts/Pack-Crates.ps1 free of CI-only flags, so +# it behaves identically for local developers. Nothing publishes for real from cargo: +# the only `cargo publish` in the repo is Pack-Crates.ps1's `--dry-run` validation, and +# releases ship through ESRP. +[registry] +default = "azure-sdk-for-rust-public"