Skip to content

Commit

Permalink
feat(ci): allow adding user-created publish jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
mistydemeo committed Sep 18, 2023
1 parent 095cfcf commit ddada20
Show file tree
Hide file tree
Showing 7 changed files with 2,490 additions and 6 deletions.
4 changes: 4 additions & 0 deletions cargo-dist/src/backend/ci/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub struct GithubCiInfo {
pub tap: Option<String>,
/// publish jobs
pub publish_jobs: Vec<String>,
/// user-specified publish jobs
pub user_publish_jobs: Vec<String>,
/// whether to create the release or assume an existing one
pub create_release: bool,
/// \[unstable\] whether to add ssl.com windows binary signing
Expand Down Expand Up @@ -94,6 +96,7 @@ impl GithubCiInfo {

let tap = dist.tap.clone();
let publish_jobs = dist.publish_jobs.iter().map(|j| j.to_string()).collect();
let user_publish_jobs = dist.user_publish_jobs.clone();

// Figure out what Local Artifact tasks we need
let local_runs = if dist.merge_tasks {
Expand Down Expand Up @@ -123,6 +126,7 @@ impl GithubCiInfo {
fail_fast,
tap,
publish_jobs,
user_publish_jobs,
artifacts_matrix: GithubMatrix { include: tasks },
pr_run_mode,
global_task,
Expand Down
39 changes: 34 additions & 5 deletions cargo-dist/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,19 +523,48 @@ impl std::fmt::Display for InstallerStyle {
}

/// The publish jobs we should run
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
pub enum PublishStyle {
/// Publish a Homebrew formula to a tap repository
#[serde(rename = "homebrew")]
Homebrew,
/// User-supplied value
User(String),
}

impl std::str::FromStr for PublishStyle {
type Err = DistError;
fn from_str(s: &str) -> DistResult<Self> {
if s.starts_with("./") {
Ok(Self::User(s.strip_prefix("./").unwrap().to_owned()))
} else if s == "homebrew" {
Ok(Self::Homebrew)
} else {
Err(DistError::UnrecognizedStyle {
style: s.to_owned(),
})
}
}
}

impl<'de> serde::Deserialize<'de> for PublishStyle {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;

let path = String::deserialize(deserializer)?;
path.parse().map_err(|e| D::Error::custom(format!("{e}")))
}
}

impl std::fmt::Display for PublishStyle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let string = match self {
PublishStyle::Homebrew => "homebrew",
};
string.fmt(f)
match self {
PublishStyle::Homebrew => write!(f, "homebrew"),
PublishStyle::User(s) => write!(f, "./{s}"),
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions cargo-dist/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ pub enum DistError {
/// The missing keys
keys: &'static [&'static str],
},
/// unrecognized style
#[error("{style} is not a recognized value")]
#[diagnostic(help("Styles that do not come with cargo-dist should be prefixed with an @"))]
UnrecognizedStyle {
/// Name of the msi
style: String,
},
}

impl From<minijinja::Error> for DistError {
Expand Down
25 changes: 24 additions & 1 deletion cargo-dist/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ pub struct DistGraph {
pub ci: CiInfo,
/// List of publish jobs to run
pub publish_jobs: Vec<PublishStyle>,
/// Extra user-specified publish jobs to run
pub user_publish_jobs: Vec<String>,
/// Whether to publish prerelease builds to package managers
pub publish_prereleases: bool,
/// A GitHub repo to publish the Homebrew formula to
Expand Down Expand Up @@ -705,7 +707,27 @@ impl<'pkg_graph> DistGraphBuilder<'pkg_graph> {
};

let templates = Templates::new()?;
let publish_jobs = workspace_metadata.publish_jobs.clone().unwrap_or(vec![]);
let publish_jobs: Vec<PublishStyle>;
let user_publish_jobs: Vec<PublishStyle>;
(publish_jobs, user_publish_jobs) = workspace_metadata
.publish_jobs
.clone()
.unwrap_or(vec![])
.into_iter()
.partition(|s| !matches!(s, PublishStyle::User(_)));
let user_publish_jobs = user_publish_jobs
.into_iter()
// Remove the @ suffix for later; we only have user jobs at this
// point so we no longer need to distinguish
.map(|s| {
let string = s.to_string();
if let Some(stripped) = string.strip_prefix("./") {
stripped.to_owned()
} else {
string
}
})
.collect();
let publish_prereleases = publish_prereleases.unwrap_or(false);

let allow_dirty = if allow_all_dirty {
Expand Down Expand Up @@ -745,6 +767,7 @@ impl<'pkg_graph> DistGraphBuilder<'pkg_graph> {
pr_run_mode: workspace_metadata.pr_run_mode.unwrap_or_default(),
tap: workspace_metadata.tap.clone(),
publish_jobs,
user_publish_jobs,
publish_prereleases,
allow_dirty,
},
Expand Down
11 changes: 11 additions & 0 deletions cargo-dist/templates/ci/github_ci.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,17 @@ jobs:
{{%- endif %}}
{{%- for job in user_publish_jobs %}}
user-publish-job-{{{ job|safe }}}:
needs: [plan, should-publish]
if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
uses: ./.github/workflows/{{{ job|safe }}}.yml
with:
plan: ${{ needs.plan.outputs.val }}
secrets: inherit
{{%- endfor %}}
# Create a Github Release with all the results once everything is done,
publish-release:
needs: [plan, should-publish]
Expand Down
31 changes: 31 additions & 0 deletions cargo-dist/tests/integration-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,37 @@ path-guid = "BFD25009-65A4-4D1E-97F1-0030465D90D6"
})
}

#[test]
fn axolotlsay_user_publish_job() -> Result<(), miette::Report> {
let test_name = _function_name!();
AXOLOTLSAY.run_test(|ctx| {
let dist_version = ctx.tools.cargo_dist.version().unwrap();
ctx.patch_cargo_toml(format!(r#"
[workspace.metadata.dist]
cargo-dist-version = "{dist_version}"
installers = ["shell", "powershell", "homebrew", "npm"]
tap = "axodotdev/homebrew-packages"
publish-jobs = ["homebrew", "./custom-task"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-pc-windows-msvc", "aarch64-apple-darwin"]
ci = ["github"]
unix-archive = ".tar.gz"
windows-archive = ".tar.gz"
scope = "@axodotdev"
"#
))?;

// Run generate to make sure stuff is up to date before running other commands
let ci_result = ctx.cargo_dist_generate(test_name)?;
let ci_snap = ci_result.check_all()?;
// Do usual build+plan checks
let main_result = ctx.cargo_dist_build_and_plan(test_name)?;
let main_snap = main_result.check_all(ctx, ".cargo/bin/")?;
// snapshot all
main_snap.join(ci_snap).snap();
Ok(())
})
}

#[test]
fn akaikatana_basic() -> Result<(), miette::Report> {
let test_name = _function_name!();
Expand Down
Loading

0 comments on commit ddada20

Please sign in to comment.