diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 192cc09ad..92fbf3cd5 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -65,9 +65,4 @@ jobs: run: | # Publish to crates.io cargo run -p release-operator -- publish \ - --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ - --crate crates/fj-math \ - --crate crates/fj-interop \ - --crate crates/fj-kernel \ - --crate crates/fj-export \ - --crate crates/fj-viewer + --token ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/tools/release-operator/src/main.rs b/tools/release-operator/src/main.rs index 0480e63ce..49e37baf2 100644 --- a/tools/release-operator/src/main.rs +++ b/tools/release-operator/src/main.rs @@ -4,7 +4,7 @@ mod release; use crate::github::{Actions, GitHub}; -use crate::registry::{Crate, Registry}; +use crate::registry::Registry; use crate::release::Release; use clap::{Args, Parser, Subcommand}; use secstr::SecUtf8; @@ -42,10 +42,6 @@ struct PublishArgs { #[clap(short, long, env = "CARGO_REGISTRY_TOKEN")] token: SecUtf8, - /// Repeatable option to provide a list of paths to crates - #[clap(short, long = "crate")] - crates: Vec, - /// Perform all checks without uploading #[clap(long)] dry_run: bool, @@ -77,8 +73,7 @@ fn main() -> anyhow::Result<()> { .detect()?; } Commands::Publish(args) => { - Registry::new(&args.token, &args.crates, args.dry_run) - .publish_crates()?; + Registry::new(&args.token, args.dry_run).publish_crates()?; } } diff --git a/tools/release-operator/src/registry.rs b/tools/release-operator/src/registry.rs index 71fe085d4..a4e3c6606 100644 --- a/tools/release-operator/src/registry.rs +++ b/tools/release-operator/src/registry.rs @@ -1,7 +1,10 @@ use anyhow::{anyhow, bail, Context}; +use cargo_metadata::MetadataCommand; use secstr::SecUtf8; use serde::Deserialize; +use std::collections::{BTreeSet, VecDeque}; use std::fmt::{Display, Formatter}; +use std::fs; use std::path::PathBuf; use std::process::Command; use std::str::FromStr; @@ -16,7 +19,6 @@ enum Error { pub struct Registry { token: SecUtf8, - crates: Vec, dry_run: bool, } @@ -37,16 +39,68 @@ enum CrateState { } impl Registry { - pub fn new(token: &SecUtf8, crates: &[Crate], dry_run: bool) -> Self { + pub fn new(token: &SecUtf8, dry_run: bool) -> Self { Self { token: token.to_owned(), - crates: crates.to_vec(), dry_run, } } pub fn publish_crates(&self) -> anyhow::Result<()> { - for c in &self.crates { + let mut crates = VecDeque::new(); + + for dir_entry in fs::read_dir("crates")? { + let dir_entry = dir_entry?; + let name = dir_entry + .file_name() + .into_string() + .map_err(|err| anyhow!("Error converting string: {err:?}"))?; + + let mut command = MetadataCommand::new(); + command.manifest_path(dir_entry.path().join("Cargo.toml")); + + let metadata = command.exec()?; + + crates.push_back((name, metadata)); + } + + let mut crates_ordered = Vec::new(); + let mut processed_dependencies = BTreeSet::new(); + + while let Some((name, metadata)) = crates.pop_front() { + let mut package = None; + for p in &metadata.packages { + if p.name == name { + package = Some(p.clone()); + } + } + + let package = package.expect("Could not find package"); + + let mut unmet_dependencies = false; + + for dependency in &package.dependencies { + let unmet_dependency = dependency.path.is_some() + && !processed_dependencies.contains(&dependency.name); + + if unmet_dependency { + unmet_dependencies = true; + break; + } + } + + if unmet_dependencies { + crates.push_back((name, metadata)); + } else { + let mut path = package.manifest_path.into_std_path_buf(); + path.pop(); + + processed_dependencies.insert(name); + crates_ordered.push(Crate { path }); + } + } + + for c in crates_ordered { c.validate()?; match c.determine_state()? {