Skip to content

Commit 346da05

Browse files
committed
Use -Zpackage-workspace
1 parent 15b7d27 commit 346da05

File tree

7 files changed

+144
-68
lines changed

7 files changed

+144
-68
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ members = [
2020
]
2121
exclude = [
2222
"eng/scripts",
23+
"target",
2324
]
2425

2526
[workspace.package]

eng/pipelines/templates/jobs/pack.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ jobs:
3535
WorkingDirectory: $(System.DefaultWorkingDirectory)/eng/tools/generate_api_report
3636
SetDefault: false
3737

38-
- template: /eng/pipelines/templates/steps/use-rust.yml@self
39-
parameters:
40-
Toolchain: stable
41-
4238
- ${{ if eq(parameters.TestPipeline, 'true') }}:
4339
- template: /eng/common/pipelines/templates/steps/set-test-pipeline-version.yml
4440
parameters:

eng/pipelines/templates/stages/archetype-rust-release.yml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,30 @@ stages:
9292
$additionalOwners = @('heaths', 'hallipr')
9393
$token = $env:CARGO_REGISTRY_TOKEN
9494
$crateName = '${{artifact.name}}'
95+
$artifactPath = "$(Pipeline.Workspace)/drop/$crateName"
96+
97+
Write-Host "Dry-run verifying '$crateName'"
98+
99+
# remove Cargo.toml.orig before calling dry-run as it causes a reserved file name error
100+
Remove-Item -Path "$artifactPath/contents/Cargo.toml.orig" -Force -ErrorAction Ignore
101+
102+
$command = "cargo publish --manifest-path '$artifactPath/contents/Cargo.toml' --dry-run"
103+
Write-Host "> $command"
104+
Invoke-Expression $command
95105
96-
$manifestPath = "$(Pipeline.Workspace)/drop/$crateName/contents/Cargo.toml"
97-
Write-Host "> cargo publish --manifest-path `"$manifestPath`""
98-
cargo publish --manifest-path $manifestPath
99106
if (!$?) {
100-
Write-Error "Failed to publish package: '$crateName'"
107+
Write-Error "Dry-run failed for '$crateName'"
101108
exit 1
102109
}
103110
111+
Write-Host "Publishing package '$crateName'"
112+
113+
# https://doc.rust-lang.org/cargo/reference/registry-web-api.html#publish
114+
Invoke-WebRequest -Method Put -Uri 'https://crates.io/api/v1/crates/new' `
115+
-Headers @{ Accept = 'application/json'; Authorization = $token } `
116+
-ContentType 'application/json' `
117+
-InFile "$artifactPath/$crateName.bin"
118+
104119
$existingOwners = (cargo owner --list $crateName) -replace " \(.*", ""
105120
$missingOwners = $additionalOwners | Where-Object { $existingOwners -notcontains $_ }
106121

eng/scripts/Pack-Crates.ps1

Lines changed: 101 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ param(
88
[string[]]$PackageNames,
99
[Parameter(ParameterSetName = 'PackageInfo')]
1010
[string]$PackageInfoDirectory,
11-
[switch]$NoVerify
11+
[switch]$Verify
1212
)
1313

1414
$ErrorActionPreference = 'Stop'
@@ -80,8 +80,8 @@ function Get-CargoPackages() {
8080
}
8181

8282
function Get-PackagesToBuild() {
83-
$packages = Get-CargoPackages
84-
$outputPackageNames = Get-OutputPackageNames $packages
83+
[array]$packages = Get-CargoPackages
84+
[array]$outputPackageNames = Get-OutputPackageNames $packages
8585

8686
# We start with output packages, then recursively add unreleased dependencies to the list of packages that need to be built
8787
[array]$packagesToBuild = $packages | Where-Object { $outputPackageNames.Contains($_.name) }
@@ -126,26 +126,65 @@ function Get-PackagesToBuild() {
126126
return $buildOrder
127127
}
128128

129-
function Initialize-VendorDirectory() {
130-
$path = "$RepoRoot/target/vendor"
131-
Invoke-LoggedCommand "cargo vendor $path" -GroupOutput | Out-Host
132-
return $path
133-
}
129+
# https://doc.rust-lang.org/cargo/reference/registry-web-api.html#publish
130+
# https://github.com/rust-lang/cargo/blob/5c87c14f9a162daf10d4133fdaab35c72d67b018/crates/crates-io/lib.rs#L42
131+
function Get-ApiMetadata($package) {
132+
$packagePath = Split-Path -Path $package.manifest_path -Parent
133+
$readmePath = $package.readme ? (Join-Path -Path $packagePath -ChildPath $package.readme) : $null
134+
135+
$jsonBody = [ordered]@{
136+
'name' = $package.name
137+
'vers' = $package.version
138+
'deps' = @()
139+
'features' = $package.features
140+
'authors' = $package.authors
141+
'description' = $package.description
142+
'documentation' = $package.documentation
143+
'homepage' = $package.homepage
144+
'readme' = if ($readmePath -and (Test-Path -Path $readmePath)) {
145+
Get-Content -Path $readmePath -Raw
146+
}
147+
else {
148+
$null
149+
}
150+
'readme_file' = $package.readme
151+
'keywords' = $package.keywords
152+
'categories' = $package.categories
153+
'license' = $package.license
154+
'license_file' = $package.license_file
155+
'repository' = $package.repository
156+
'links' = $package.links
157+
'rust_version' = $package.rust_version
158+
}
134159

135-
function Add-CrateToLocalRegistry($LocalRegistryPath, $Package) {
136-
$packageName = $Package.name
137-
$packageVersion = $Package.version
160+
foreach ($dependency in $package.dependencies) {
161+
$jsonBody.deps += @{
162+
'name' = $dependency.name
163+
'version_req' = $dependency.req
164+
'features' = $dependency.features
165+
'optional' = $dependency.optional
166+
'default_features' = $dependency.default_features
167+
'target' = $dependency.target
168+
'kind' = $dependency.kind
169+
'explicit_name_in_toml' = $dependency.rename
170+
}
171+
}
138172

139-
# create an index entry for the package
140-
$packagePath = "$RepoRoot/target/package/$packageName-$packageVersion"
173+
return $jsonBody
174+
}
141175

142-
Write-Host "Copying package '$packageName' to vendor directory '$LocalRegistryPath'"
143-
Copy-Item -Path $packagePath -Destination $LocalRegistryPath -Recurse
176+
function New-ApiPutFile($crateMetadata, $crateFilePath) {
177+
$metadataBytes = [Text.Encoding]::Utf8.GetBytes($crateMetadata)
178+
$metadataLengthBytes = [BitConverter]::GetBytes([UInt32]$metadataBytes.Length)
179+
$crateBytes = [IO.File]::ReadAllBytes($crateFilePath)
180+
$crateLengthBytes = [BitConverter]::GetBytes([UInt32]$crateBytes.Length)
144181

145-
#write an empty checksum file
146-
'{"files":{}}' | Out-File -FilePath "$LocalRegistryPath/$packageName-$packageVersion/.cargo-checksum.json" -Encoding utf8
182+
$bytes += $metadataLengthBytes + $metadataBytes + $crateLengthBytes + $crateBytes
183+
184+
return $bytes
147185
}
148186

187+
149188
function Create-ApiViewFile($package) {
150189
$packageName = $package.name
151190
$command = "cargo run --manifest-path $RepoRoot/eng/tools/generate_api_report/Cargo.toml -- --package $packageName"
@@ -158,61 +197,77 @@ function Create-ApiViewFile($package) {
158197

159198
Push-Location $RepoRoot
160199
try {
161-
$localRegistryPath = Initialize-VendorDirectory
162-
163200
[array]$packages = Get-PackagesToBuild
164201

165-
Write-Host "Building packages in the following order:"
202+
$command = "cargo +nightly -Zpackage-workspace package --allow-dirty --locked"
203+
204+
Write-Host "Building packages:"
166205
foreach ($package in $packages) {
167206
$packageName = $package.name
168207
$type = if ($package.OutputPackage) { "output" } else { "dependency" }
169208
Write-Host " $packageName ($type)"
209+
$command += " --package $packageName"
170210
}
171211

172-
foreach ($package in $packages) {
173-
Write-Host ""
174-
175-
$packageName = $package.name
176-
$packageVersion = $package.version
177-
178-
$command = "cargo publish --locked --dry-run --package $packageName --registry crates-io --config `"source.crates-io.replace-with='local'`" --config `"source.local.directory='$localRegistryPath'`" --allow-dirty"
212+
if (!$Verify) {
213+
$command += " --no-verify"
214+
}
179215

180-
if ($NoVerify) {
181-
$command += " --no-verify"
182-
}
216+
if ($env:SYSTEM_DEBUG -eq 'true') {
217+
Write-Host "##[group] $RepoRoot/Cargo.lock"
218+
Get-Content "$RepoRoot/Cargo.lock"
219+
Write-Host "##[endgroup]"
220+
}
183221

184-
Invoke-LoggedCommand -Command $command -GroupOutput
222+
Invoke-LoggedCommand -Command $command -GroupOutput
185223

224+
if ($env:SYSTEM_DEBUG -eq 'true') {
225+
Write-Host "##[group] $RepoRoot/Cargo.lock"
226+
Get-Content "$RepoRoot/Cargo.lock"
227+
Write-Host "##[endgroup]"
228+
}
186229

187-
# copy the package to the local registry
188-
Add-CrateToLocalRegistry `
189-
-LocalRegistryPath $localRegistryPath `
190-
-Package $package
230+
if ($OutputPath) {
231+
foreach ($package in $packages | Where-Object { $_.OutputPackage }) {
232+
$packageName = $package.name
233+
$packageVersion = $package.version
234+
235+
Write-Host "`nProcessing package '$packageName'"
191236

192-
if ($OutputPath -and $package.OutputPackage) {
193-
$sourcePath = "$RepoRoot/target/package/$packageName-$packageVersion"
237+
$sourcePath = "$RepoRoot/target/package/$packageName-$packageVersion.crate"
194238
$targetPath = "$OutputPath/$packageName"
195239
$targetContentsPath = "$targetPath/contents"
196240
$targetApiReviewFile = "$targetPath/$packageName.rust.json"
241+
$targetCrateFile = "$targetPath/$packageName-$packageVersion.crate"
242+
$targetJsonFile = "$targetPath/$packageName-$packageVersion.json"
243+
$targetBinFile = "$targetPath/$packageName.bin"
197244

198-
if (Test-Path -Path $targetContentsPath) {
199-
Remove-Item -Path $targetContentsPath -Recurse -Force
200-
}
201-
202-
Write-Host "Copying package '$packageName' to '$targetContentsPath'"
245+
Remove-Item -Path $targetPath -Recurse -Force -ErrorAction SilentlyContinue
203246
New-Item -ItemType Directory -Path $targetContentsPath -Force | Out-Null
204-
Copy-Item -Path $sourcePath/* -Destination $targetContentsPath -Recurse -Exclude "Cargo.toml.orig"
205247

248+
Write-Host "Copying crate file to '$targetCrateFile'"
249+
Copy-Item -Path $sourcePath -Destination $targetCrateFile -Force
250+
251+
$crateMetadata = Get-ApiMetadata $package | ConvertTo-Json -Depth 10
252+
253+
Write-Host "Writing crates.io request metadata to '$targetJsonFile'"
254+
$crateMetadata | Out-File -FilePath "$targetJsonFile" -Encoding utf8
255+
256+
$uploadBytes = New-ApiPutFile $crateMetadata $sourcePath
257+
Write-Host "Writing crates.io request bundle to '$targetBinFile'"
258+
[IO.File]::WriteAllBytes($targetBinFile, $uploadBytes)
259+
260+
Write-Host "Exctracting crate file to '$targetContentsPath'"
261+
New-Item -ItemType Directory -Path $targetContentsPath -Force | Out-Null
262+
tar -xf $sourcePath --directory $targetContentsPath --strip-components=1 | Out-Null
263+
206264
Write-Host "Creating API review file"
207265
$apiReviewFile = Create-ApiViewFile $package
208266

209267
Write-Host "Copying API review file to '$targetApiReviewFile'"
210268
Copy-Item -Path $apiReviewFile -Destination $targetApiReviewFile -Force
211269
}
212270
}
213-
214-
Write-Host "Removing local registry"
215-
Remove-Item -Path $localRegistryPath -Recurse -Force | Out-Null
216271
}
217272
finally {
218273
Pop-Location

eng/scripts/Update-PackageVersion.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ if ($content -ne $updated) {
8484
Write-Host "Updated version in $tomlPath from $($pkgProperties.Version) to $packageSemVer."
8585

8686
Write-Host "Updaging dependencies in Cargo.toml files."
87-
Invoke-LoggedCommand "cargo +nightly -Zscript '$RepoRoot/eng/scripts/update-pathversions.rs' update" | Out-Null
87+
Invoke-LoggedCommand "cargo +nightly -Zscript '$RepoRoot/eng/scripts/update-pathversions.rs' update"
8888

8989
Write-Host "Updating Cargo.lock using 'cargo update --workspace'."
9090
Invoke-LoggedCommand "cargo update --workspace" | Out-Null

eng/scripts/Yank-Crates.ps1

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,4 @@ foreach ($crateName in $crateNames) {
3131
}
3232
}
3333

34-
if ($hasErrors) {
35-
exit 1
36-
}
34+
exit $hasErrors ? 1 : 0

eng/scripts/update-pathversions.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
2424
.expect("requires 'add' or 'update' mode argument");
2525

2626
let script_root = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
27-
let repo_root = script_root.join("../../..").canonicalize()?;
27+
let repo_root = script_root.join("../..").canonicalize()?;
2828

2929
// find all Cargo.toml files in the repo_root directory
3030
let exclude_dirs = vec![
@@ -38,13 +38,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3838

3939
for mut toml_file in toml_files {
4040
let should_add = add_mode && !toml_file.is_publish_disabled;
41-
42-
update_package_versions(toml_file.document.as_table_mut(), &package_versions, should_add);
41+
println!("Processing {}", toml_file.path.display());
42+
update_package_versions(toml_file.document.as_table_mut(), &package_versions, None, should_add);
4343

4444
// if the toml file has a workspace table, update the workspace table
4545
if let Some(workspace) = toml_file.document.get_mut("workspace") {
4646
if let Some(table) = workspace.as_table_mut() {
47-
update_package_versions(table, &package_versions, should_add);
47+
update_package_versions(table, &package_versions, Some("workspace"), should_add);
4848
}
4949
}
5050

@@ -57,6 +57,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
5757
}
5858

5959
fn load_cargo_toml_files(repo_root: &PathBuf, exclude_dirs: &Vec<PathBuf>) -> Result<Vec<TomlInfo>, Box<dyn Error>> {
60+
println!("Loading Cargo.toml files in {}", repo_root.display());
6061
let mut toml_paths = Vec::new();
6162
find_cargo_toml_files(repo_root, exclude_dirs, &mut toml_paths)?;
6263

@@ -109,7 +110,7 @@ fn get_package_versions(toml_files: &Vec<TomlInfo>) -> Vec<(String, String, bool
109110
package_versions
110111
}
111112

112-
fn update_package_versions(toml: &mut Table, package_versions: &Vec<(String, String, bool)>, add: bool) {
113+
fn update_package_versions(toml: &mut Table, package_versions: &Vec<(String, String, bool)>, prefix: Option<&str>, add: bool) {
113114
// for each dependency table, for each package in package_versions
114115
// if the package is in the dependency table
115116
// if the dependency has both path and version properties, update the version property
@@ -121,16 +122,26 @@ fn update_package_versions(toml: &mut Table, package_versions: &Vec<(String, Str
121122
let dependency_tables = get_dependency_tables(toml);
122123

123124
for (table_name, table) in dependency_tables {
125+
let table_display_name = if prefix.is_some() {
126+
format!("{}.{}", prefix.unwrap(), table_name)
127+
} else {
128+
table_name.clone()
129+
};
124130
for (package, version, is_publish_disabled) in package_versions {
125131
if let Some(dependency) = table.get_mut(package) {
126132
// azure_idenentity will only be a transitive dev-dependency
127133
let should_add = add && table_name != "dev-dependencies" && !is_publish_disabled && package != "azure_identity";
128134

129-
let has_path_property = dependency.get("path").is_some();
130-
let has_version_property = dependency.get("version").is_some();
131-
132-
if has_path_property && (has_version_property || should_add) {
133-
dependency["version"] = value(version);
135+
if dependency.get("path").is_some() {
136+
if let Some(current_version) = dependency.get("version") {
137+
if current_version.as_str() != Some(version) {
138+
dependency["version"] = value(version);
139+
println!(" Updating {table_display_name}.{package} to {version}");
140+
}
141+
} else if should_add {
142+
dependency["version"] = value(version);
143+
println!(" Adding {table_display_name}.{package} version {version}");
144+
}
134145
}
135146
}
136147
}

0 commit comments

Comments
 (0)