Merge pull request #1900 from hannobraun/release-operator

Determine crates to publish automatically
This commit is contained in:
Hanno Braun 2023-06-20 11:31:43 +02:00 committed by GitHub
commit 14af84a7a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 17 deletions

View File

@ -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 }}

View File

@ -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<Crate>,
/// 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()?;
}
}

View File

@ -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<Crate>,
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()? {