Skip to content

Commit

Permalink
Support publishing prereleases even if there are only custom publish …
Browse files Browse the repository at this point in the history
…jobs

Fixes axodotdev#1744
  • Loading branch information
jackkleeman committed Feb 4, 2025
1 parent b96f4b7 commit 366bd46
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 4 deletions.
2 changes: 1 addition & 1 deletion cargo-dist/src/backend/ci/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ impl GithubCiInfo {
}

let mut publish_jobs = vec![];
if let Some(PublisherConfig { homebrew, npm }) = &dist.global_publishers {
if let Some(PublisherConfig { homebrew, npm, .. }) = &dist.global_publishers {
if homebrew.is_some() {
publish_jobs.push(PublishStyle::Homebrew.to_string());
}
Expand Down
27 changes: 27 additions & 0 deletions cargo-dist/src/config/v0_to_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,15 +339,20 @@ impl DistMetadata {
list_to_bool_layer(is_global, &publish_jobs, PublishStyle::Homebrew, || None);
let npm_publisher_layer =
list_to_bool_layer(is_global, &publish_jobs, PublishStyle::Npm, || None);
let user_layer = list_to_bool_layer_predicate(is_global, &publish_jobs, |job| {
matches!(job, PublishStyle::User(_))
});
let needs_publisher_layer = homebrew_publisher_layer.is_some()
|| npm_publisher_layer.is_some()
|| user_layer.is_some()
|| publish_prereleases.is_some();
let publisher_layer = needs_publisher_layer.then_some(PublisherLayer {
common: CommonPublisherLayer {
prereleases: publish_prereleases,
},
homebrew: homebrew_publisher_layer,
npm: npm_publisher_layer,
user: user_layer,
});

// done!
Expand Down Expand Up @@ -394,3 +399,25 @@ where
Some(BoolOr::Bool(is_in_list))
}
}

fn list_to_bool_layer_predicate<I, T>(
is_global: bool,
list: &Option<Vec<I>>,
predicate: impl FnMut(&&I) -> bool,
) -> Option<BoolOr<T>>
where
I: Eq,
{
// If the list doesn't exist, don't mention it
let list = list.as_ref()?;
// Otherwise treat "is in the list" as a simple boolean
let is_in_list = list.iter().find(predicate).is_some();
if is_global && !is_in_list {
// ... with the exception of an omitted value in the global list.
// here None and Some(false) are the same, so Some(false) is Noise
// we want to hide.
None
} else {
Some(BoolOr::Bool(is_in_list))
}
}
24 changes: 23 additions & 1 deletion cargo-dist/src/config/v1/publishers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
pub mod homebrew;
pub mod npm;
pub mod user;

use super::*;

use homebrew::*;
use npm::*;
use user::*;

/// the final publisher config
#[derive(Debug, Default, Clone, PartialEq, Eq)]
Expand All @@ -15,6 +17,8 @@ pub struct PublisherConfig {
pub homebrew: Option<HomebrewPublisherConfig>,
/// npm publisher
pub npm: Option<NpmPublisherConfig>,
/// user specified publisher
pub user: Option<UserPublisherConfig>,
}

/// the publisher config
Expand All @@ -28,6 +32,8 @@ pub struct PublisherConfigInheritable {
pub homebrew: Option<HomebrewPublisherLayer>,
/// npm publisher
pub npm: Option<NpmPublisherLayer>,
/// user specified publisher
pub user: Option<UserPublisherLayer>,
}

/// "raw" publisher config from presum
Expand All @@ -40,6 +46,8 @@ pub struct PublisherLayer {
pub homebrew: Option<BoolOr<HomebrewPublisherLayer>>,
/// npm publisher
pub npm: Option<BoolOr<NpmPublisherLayer>>,
/// user-specified publisher
pub user: Option<BoolOr<UserPublisherLayer>>,
}
impl PublisherConfigInheritable {
/// get the defaults for a given package
Expand All @@ -48,6 +56,7 @@ impl PublisherConfigInheritable {
common: CommonPublisherConfig::defaults_for_package(workspaces, pkg_idx),
homebrew: None,
npm: None,
user: None,
}
}
/// fold the inherited fields in to get the final publisher config
Expand All @@ -60,6 +69,7 @@ impl PublisherConfigInheritable {
common,
homebrew,
npm,
user,
} = self;
let homebrew = homebrew.map(|homebrew| {
let mut default =
Expand All @@ -73,7 +83,17 @@ impl PublisherConfigInheritable {
default.apply_layer(npm);
default
});
PublisherConfig { homebrew, npm }
let user = user.map(|user| {
let mut default =
UserPublisherConfig::defaults_for_package(workspaces, pkg_idx, &common);
default.apply_layer(user);
default
});
PublisherConfig {
homebrew,
npm,
user,
}
}
}
impl ApplyLayer for PublisherConfigInheritable {
Expand All @@ -84,11 +104,13 @@ impl ApplyLayer for PublisherConfigInheritable {
common,
homebrew,
npm,
user,
}: Self::Layer,
) {
self.common.apply_layer(common);
self.homebrew.apply_bool_layer(homebrew);
self.npm.apply_bool_layer(npm);
self.user.apply_bool_layer(user);
}
}

Expand Down
49 changes: 49 additions & 0 deletions cargo-dist/src/config/v1/publishers/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! user specified publisher config
use super::*;

/// Options for user specified publishes
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct UserPublisherLayer {
/// Common options
pub common: CommonPublisherLayer,
}
/// Options for user specified publishes
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct UserPublisherConfig {
/// Common options
pub common: CommonPublisherConfig,
}

impl UserPublisherConfig {
/// Get defaults for the given package
pub fn defaults_for_package(
_workspaces: &WorkspaceGraph,
_pkg_idx: PackageIdx,
common: &CommonPublisherConfig,
) -> Self {
Self {
common: common.clone(),
}
}
}

impl ApplyLayer for UserPublisherConfig {
type Layer = UserPublisherLayer;
fn apply_layer(&mut self, Self::Layer { common }: Self::Layer) {
self.common.apply_layer(common);
}
}
impl ApplyLayer for UserPublisherLayer {
type Layer = UserPublisherLayer;
fn apply_layer(&mut self, Self::Layer { common }: Self::Layer) {
self.common.apply_layer(common);
}
}

impl std::ops::Deref for UserPublisherConfig {
type Target = CommonPublisherConfig;
fn deref(&self) -> &Self::Target {
&self.common
}
}
9 changes: 7 additions & 2 deletions cargo-dist/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,10 +1140,15 @@ impl<'pkg_graph> DistGraphBuilder<'pkg_graph> {
.as_ref()
.map(|p| {
// until we have `dist publish` we need to enforce everyone agreeing on `prereleases`
let PublisherConfig { homebrew, npm } = p;
let PublisherConfig {
homebrew,
npm,
user,
} = p;
let h_pre = homebrew.as_ref().map(|p| p.prereleases);
let npm_pre = npm.as_ref().map(|p| p.prereleases);
let choices = [h_pre, npm_pre];
let user_pre = user.as_ref().map(|p| p.prereleases);
let choices = [h_pre, npm_pre, user_pre];
let mut global_choice = None;
#[allow(clippy::manual_flatten)]
for choice in choices {
Expand Down

0 comments on commit 366bd46

Please sign in to comment.