Skip to content

Commit 7273f11

Browse files
authored
move away from directory listings for finding generated crates (#1509)
As identified in #1479, we do not currently handle deleted/renamed specifications well. This update addresses this via the following: * Moves to using parsing `cargo_toml` to parse services/Cargo.toml to know what crates already exist * Replaces all uses of `list_crate_names` with using the results of `gen_crates` As a byproduct, this identifies that the previously existing spec that would result in `azure_svc_codesigning` was removed. ref: Azure/azure-rest-api-specs#26635
1 parent e04f5c3 commit 7273f11

File tree

6 files changed

+79
-66
lines changed

6 files changed

+79
-66
lines changed

.github/workflows/check-all-services.yml

Lines changed: 0 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ members = [
258258
"svc/attestation",
259259
"svc/batch",
260260
"svc/blobstorage",
261-
"svc/codesigning",
262261
"svc/confidentialledger",
263262
"svc/containerregistry",
264263
"svc/datalakeanalytics",

services/autorust/azure-autorust/src/main.rs

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
// cargo run --release -p azure-autorust -- -p azure_svc_queuestorage
44

55
use autorust_codegen::{
6-
crates::{list_crate_names, list_dirs},
6+
crates::list_crates,
77
gen, get_mgmt_readmes, get_svc_readmes,
88
jinja::{CheckAllServicesYml, PublishSdksYml, PublishServicesYml, WorkspaceCargoToml},
99
Error, ErrorKind, Result, ResultExt, RunConfig, SpecReadme,
1010
};
1111
use clap::Parser;
1212
use rayon::prelude::*;
13+
use std::{collections::BTreeSet, path::PathBuf};
1314

1415
#[derive(Debug, clap::Parser)]
1516
struct Args {
@@ -35,15 +36,34 @@ impl Args {
3536
fn main() -> Result<()> {
3637
let args = Args::parse();
3738
let packages = &args.packages();
38-
gen_crates(packages)?;
39-
gen_services_workspace(packages)?;
39+
40+
let existing_crates = list_crates(&PathBuf::from("../"))?;
41+
let generated = gen_crates(packages)?;
42+
gen_services_workspace(&generated)?;
43+
4044
if packages.is_empty() {
41-
gen_workflow_check_all_services()?;
45+
gen_workflow_check_all_services(&generated)?;
4246
if args.publish {
4347
gen_workflow_publish_sdks()?;
44-
gen_workflow_publish_services()?;
48+
gen_workflow_publish_services(&generated)?;
49+
}
50+
51+
let removed = existing_crates.difference(&generated).collect::<Vec<_>>();
52+
let added = generated.difference(&existing_crates).collect::<Vec<_>>();
53+
if !removed.is_empty() {
54+
println!("the following crates are no longer generated:");
55+
for name in removed {
56+
println!("- {name}");
57+
}
58+
}
59+
if !added.is_empty() {
60+
println!("the following crates are newly generated:");
61+
for name in added {
62+
println!("- {name}");
63+
}
4564
}
4665
}
66+
4767
Ok(())
4868
}
4969

@@ -63,7 +83,7 @@ fn gen_crate(only_packages: &[&str], crate_type: &str, spec: &SpecReadme) -> Res
6383
}
6484
}
6585

66-
fn gen_crates(only_packages: &[&str]) -> Result<()> {
86+
fn gen_crates(only_packages: &[&str]) -> Result<BTreeSet<String>> {
6787
let svc = get_svc_readmes()?.into_iter().map(|x| ("svc".to_string(), x));
6888
let mgmt = get_mgmt_readmes()?.into_iter().map(|x| ("mgmt".to_string(), x));
6989
let crate_iters = svc.chain(mgmt).collect::<Vec<_>>();
@@ -77,12 +97,17 @@ fn gen_crates(only_packages: &[&str]) -> Result<()> {
7797

7898
let mut errors = vec![];
7999
let mut completed = vec![];
100+
let mut skipped = vec![];
80101

81102
for result in results {
82103
match result {
83104
Ok(result) => {
84-
if let Some(result) = result {
85-
completed.push(result);
105+
if let Some((name, tags)) = result {
106+
if tags.is_empty() {
107+
skipped.push(name);
108+
} else {
109+
completed.push((name, tags));
110+
}
86111
}
87112
}
88113
Err(err) => {
@@ -98,40 +123,34 @@ fn gen_crates(only_packages: &[&str]) -> Result<()> {
98123
return Err(Error::new(ErrorKind::CodeGen, "Failed to generate some crates"));
99124
}
100125

101-
for (package_name, tags) in completed {
126+
for (package_name, tags) in &completed {
102127
println!("{package_name}");
103-
if tags.is_empty() {
104-
println!(" No tags");
105-
} else {
106-
for tag in tags {
107-
println!("- {tag}");
108-
}
128+
for tag in tags {
129+
println!("- {tag}");
109130
}
110131
}
111132

112-
Ok(())
113-
}
133+
if !skipped.is_empty() {
134+
println!("the following crates were not generated due to configuration:");
135+
for name in &skipped {
136+
println!("- {name}");
137+
}
138+
}
114139

115-
fn gen_services_workspace(only_packages: &[&str]) -> Result<()> {
116-
let dirs: Vec<String> = if only_packages.is_empty() {
117-
list_dirs()?
118-
.iter()
119-
.map(|dir| dir.as_str().replace('\\', "/").replace("../", ""))
120-
.collect()
121-
} else {
122-
only_packages
123-
.iter()
124-
.map(|p| p.replace("azure_mgmt_", "mgmt/").replace("azure_svc_", "svc/"))
125-
.collect()
126-
};
140+
Ok(completed.into_iter().map(|(package_name, _)| package_name).collect())
141+
}
127142

143+
fn gen_services_workspace(only_packages: &BTreeSet<String>) -> Result<()> {
144+
let dirs = only_packages
145+
.iter()
146+
.map(|p| p.replace("azure_mgmt_", "mgmt/").replace("azure_svc_", "svc/"))
147+
.collect();
128148
let toml = WorkspaceCargoToml { dirs };
129149
toml.create("../Cargo.toml")?;
130150
Ok(())
131151
}
132152

133-
fn gen_workflow_check_all_services() -> Result<()> {
134-
let packages = list_crate_names()?;
153+
fn gen_workflow_check_all_services(packages: &BTreeSet<String>) -> Result<()> {
135154
let packages = &packages.iter().map(String::as_str).collect();
136155

137156
let yml = CheckAllServicesYml { packages };
@@ -159,8 +178,7 @@ fn gen_workflow_publish_sdks() -> Result<()> {
159178
Ok(())
160179
}
161180

162-
fn gen_workflow_publish_services() -> Result<()> {
163-
let packages = list_crate_names()?;
181+
fn gen_workflow_publish_services(packages: &BTreeSet<String>) -> Result<()> {
164182
let packages = &packages.iter().map(String::as_str).collect();
165183
let yml = PublishServicesYml { packages };
166184
yml.create("../../.github/workflows/publish-services.yml")?;

services/autorust/codegen/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ camino = "1.1"
2626
askama = "0.12"
2727
toml = "0.8"
2828
qstring = "0.7"
29+
cargo_toml = "0.17"
2930

3031
[dev-dependencies]
3132
thiserror = "1.0"

services/autorust/codegen/src/crates.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use crate::{ErrorKind, Result, ResultExt};
22
use camino::{Utf8Path, Utf8PathBuf};
3+
use cargo_toml::Manifest;
34
use serde::Deserialize;
4-
use std::io::BufRead;
55
use std::{
6+
collections::BTreeSet,
67
fs::{self, File},
7-
io::BufReader,
8+
io::{BufRead, BufReader},
9+
path::Path,
810
str::FromStr,
911
};
1012

@@ -22,27 +24,30 @@ fn list_dirs_in(dir: impl AsRef<Utf8Path>) -> Result<Vec<Utf8PathBuf>> {
2224
Ok(dirs)
2325
}
2426

27+
pub fn list_crates(services_dir: &Path) -> Result<BTreeSet<String>> {
28+
let mut package_names = BTreeSet::new();
29+
let base_path = services_dir.join("Cargo.toml");
30+
let manifest = Manifest::from_path(base_path)?;
31+
if let Some(workspaces) = manifest.workspace {
32+
for member in workspaces.members {
33+
let member_path = services_dir.join(member).join("Cargo.toml");
34+
let Ok(manifest) = Manifest::from_path(member_path) else { continue };
35+
let Some(package) = manifest.package else {
36+
continue;
37+
};
38+
package_names.insert(package.name);
39+
}
40+
}
41+
Ok(package_names)
42+
}
43+
2544
pub fn list_dirs() -> Result<Vec<Utf8PathBuf>> {
2645
let mut names: Vec<_> = list_dirs_in("../mgmt")?.into_iter().collect();
2746
names.extend(list_dirs_in("../svc")?);
2847
names.sort();
2948
Ok(names)
3049
}
3150

32-
pub fn list_crate_names() -> Result<Vec<String>> {
33-
let mut names: Vec<_> = list_dirs_in("../mgmt")?
34-
.into_iter()
35-
.filter_map(|d| d.file_name().map(|d| format!("azure_mgmt_{d}")))
36-
.collect();
37-
names.extend(
38-
list_dirs_in("../svc")?
39-
.into_iter()
40-
.filter_map(|d| d.file_name().map(|d| format!("azure_svc_{d}"))),
41-
);
42-
names.sort();
43-
Ok(names)
44-
}
45-
4651
pub fn has_version(name: &str, version: &str) -> Result<bool> {
4752
Ok(get_versions(name)?.iter().any(|v| v.vers.as_str() == version))
4853
}

services/autorust/codegen/src/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ impl From<syn::Error> for Error {
208208
}
209209
}
210210

211+
impl From<cargo_toml::Error> for Error {
212+
fn from(error: cargo_toml::Error) -> Self {
213+
Self::new(ErrorKind::Parse, error)
214+
}
215+
}
216+
211217
impl From<autorust_openapi::Error> for Error {
212218
fn from(error: autorust_openapi::Error) -> Self {
213219
Self::new(ErrorKind::Parse, error)

0 commit comments

Comments
 (0)