Skip to content

Commit

Permalink
Add ability to yank different crate sets to the publisher tool (#2933)
Browse files Browse the repository at this point in the history
This PR adds different crate sets to the publisher tool so that
different groups of crates can be yanked rather than yanking everything.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
  • Loading branch information
jdisanti authored Aug 21, 2023
1 parent 39c6476 commit 99ff449
Showing 1 changed file with 49 additions and 9 deletions.
58 changes: 49 additions & 9 deletions tools/ci-build/publisher/src/subcommand/yank_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@

use crate::cargo;
use anyhow::{anyhow, bail, Context, Result};
use clap::Parser;
use clap::{ArgEnum, Parser};
use dialoguer::Confirm;
use smithy_rs_tool_common::package::PackageCategory;
use smithy_rs_tool_common::release_tag::ReleaseTag;
use smithy_rs_tool_common::shell::ShellOperation;
use smithy_rs_tool_common::versions_manifest::{Release, VersionsManifest};
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;
Expand All @@ -18,6 +20,16 @@ use tracing::info;

const MAX_CONCURRENCY: usize = 5;

#[derive(Copy, Clone, Debug, ArgEnum, Eq, PartialEq, Ord, PartialOrd)]
pub enum CrateSet {
/// (default) Yank all crates associated with the release.
All,
/// Yank all AWS SDK crates.
AllAwsSdk,
/// Yank generated AWS SDK crates.
GeneratedAwsSdk,
}

#[derive(Parser, Debug)]
pub struct YankReleaseArgs {
/// The aws-sdk-rust release tag to yank. The CLI will download the `versions.toml` file
Expand All @@ -28,12 +40,15 @@ pub struct YankReleaseArgs {
/// The `--github-release-tag` option is preferred to this, but this is provided as a fail safe.
#[clap(long, required_unless_present = "github-release-tag")]
versions_toml: Option<PathBuf>,
#[clap(arg_enum)]
crate_set: Option<CrateSet>,
}

pub async fn subcommand_yank_release(
YankReleaseArgs {
github_release_tag,
versions_toml,
crate_set,
}: &YankReleaseArgs,
) -> Result<()> {
// Make sure cargo exists
Expand All @@ -47,8 +62,18 @@ pub async fn subcommand_yank_release(
}
.context("failed to retrieve information about the release to yank")?;

let tag = release
.tag
.as_ref()
.ok_or_else(|| {
anyhow!("Versions manifest doesn't have a release tag. Can only yank tagged releases.")
})?
.clone();
let crates = filter_crates(crate_set.unwrap_or(CrateSet::All), release);
let _ = release;

// Don't proceed unless the user confirms the plan
confirm_plan(&release)?;
confirm_plan(&tag, &crates)?;

// Use a semaphore to only allow a few concurrent yanks
let semaphore = Arc::new(Semaphore::new(MAX_CONCURRENCY));
Expand All @@ -58,7 +83,7 @@ pub async fn subcommand_yank_release(
);

let mut tasks = Vec::new();
for (crate_name, crate_version) in release.crates {
for (crate_name, crate_version) in crates {
let permit = semaphore.clone().acquire_owned().await.unwrap();
tasks.push(tokio::spawn(async move {
info!("Yanking `{}-{}`...", crate_name, crate_version);
Expand All @@ -77,6 +102,25 @@ pub async fn subcommand_yank_release(
Ok(())
}

fn filter_crates(crate_set: CrateSet, release: Release) -> BTreeMap<String, String> {
if crate_set == CrateSet::All {
return release.crates;
}

release
.crates
.into_iter()
.filter(|c| {
let category = PackageCategory::from_package_name(&c.0);
match crate_set {
CrateSet::All => unreachable!(),
CrateSet::AllAwsSdk => category.is_sdk(),
CrateSet::GeneratedAwsSdk => category == PackageCategory::AwsSdk,
}
})
.collect()
}

async fn acquire_release_from_tag(tag: &str) -> Result<Release> {
let tag = ReleaseTag::from_str(tag).context("invalid release tag")?;
let manifest = VersionsManifest::from_github_tag(&tag)
Expand All @@ -98,14 +142,10 @@ fn release_metadata(manifest: VersionsManifest) -> Result<Release> {
}
}

fn confirm_plan(release: &Release) -> Result<()> {
let tag = release.tag.as_ref().ok_or_else(|| {
anyhow!("Versions manifest doesn't have a release tag. Can only yank tagged releases.")
})?;

fn confirm_plan(tag: &str, crates: &BTreeMap<String, String>) -> Result<()> {
info!("This will yank aws-sdk-rust's `{tag}` release from crates.io.");
info!("Crates to yank:");
for (crate_name, crate_version) in &release.crates {
for (crate_name, crate_version) in crates {
info!(" {}-{}", crate_name, crate_version);
}

Expand Down

0 comments on commit 99ff449

Please sign in to comment.