Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support to conditionally add components #100

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 64 additions & 82 deletions crates/gh-workflow-tailcall/src/workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,67 @@ impl Workflow {

/// Converts the workflow into a Github workflow.
pub fn to_github_workflow(&self) -> GHWorkflow {
self.clone().into()
let flags = RustFlags::deny("warnings");

let event = Event::default()
.push(Push::default().add_branch("main"))
.pull_request(
PullRequest::default()
.add_type(PullRequestType::Opened)
.add_type(PullRequestType::Synchronize)
.add_type(PullRequestType::Reopened)
.add_branch("main"),
);

let is_main = Context::github().ref_().eq("refs/heads/main".into());
let is_push = Context::github().event_name().eq("push".into());
let cond = is_main.and(is_push);

// Jobs
let build = self.build_and_test();
let permissions = Permissions::default()
.pull_requests(Level::Write)
.packages(Level::Write)
.contents(Level::Write);
let release = Job::new("Release")
.cond(cond.clone())
.add_needs(build.clone())
.add_env(Env::github())
.add_env(Env::new(
"CARGO_REGISTRY_TOKEN",
"${{ secrets.CARGO_REGISTRY_TOKEN }}",
))
.permissions(permissions.clone())
.add_step(Step::checkout())
.add_step(Release::default().command(Command::Release));

let release_pr = Job::new("Release PR")
.cond(cond.clone())
.concurrency(
Concurrency::new(Expression::new("release-${{github.ref}}"))
.cancel_in_progress(false),
)
.add_needs(build.clone())
.add_env(Env::github())
.add_env(Env::new(
"CARGO_REGISTRY_TOKEN",
"${{ secrets.CARGO_REGISTRY_TOKEN }}",
))
.permissions(permissions)
.add_step(Step::checkout())
.add_step(Release::default().command(Command::ReleasePR));

GHWorkflow::new(self.name.clone())
.add_env(flags)
.on(event)
.add_job("build", build.clone())
.add_job_when(self.auto_release, "release", release)
.add_job_when(self.auto_release, "release-pr", release_pr)
}

/// Creates the "Build and Test" job for the workflow.
pub fn build_and_test(&self) -> Job {
let mut job = Job::new("Build and Test")
fn build_and_test(&self) -> Job {
Job::new("Build and Test")
.permissions(Permissions::default().contents(Level::Read))
.add_step(Step::checkout())
.add_step(
Expand All @@ -72,89 +127,16 @@ impl Workflow {
.nightly()
.args("--all-features --workspace -- -D warnings")
.name("Cargo Clippy"),
);

if self.benchmarks {
job = job.add_step(
Cargo::new("bench")
.args("--workspace")
.name("Cargo Bench"),
);
}

job
)
.add_step_when(
self.benchmarks,
Cargo::new("bench").args("--workspace").name("Cargo Bench"),
)
}
}

impl From<Workflow> for GHWorkflow {
fn from(value: Workflow) -> Self {
let flags = RustFlags::deny("warnings");

let event = Event::default()
.push(Push::default().add_branch("main"))
.pull_request(
PullRequest::default()
.add_type(PullRequestType::Opened)
.add_type(PullRequestType::Synchronize)
.add_type(PullRequestType::Reopened)
.add_branch("main"),
);

let is_main = Context::github().ref_().eq("refs/heads/main".into());
let is_push = Context::github().event_name().eq("push".into());
let cond = is_main.and(is_push);

// Jobs
let build = value.build_and_test();
let mut workflow = GHWorkflow::new(value.name)
.add_env(flags)
.on(event)
.add_job("build", build.clone());

if value.auto_release {
let permissions = Permissions::default()
.pull_requests(Level::Write)
.packages(Level::Write)
.contents(Level::Write);

let release = release_job(&cond, &build, &permissions);
let release_pr = release_pr_job(cond, &build, permissions);
workflow = workflow
.add_job("release", release)
.add_job("release-pr", release_pr);
}

workflow
value.to_github_workflow()
}
}

fn release_pr_job(cond: Context<bool>, build: &Job, permissions: Permissions) -> Job {
Job::new("Release PR")
.cond(cond.clone())
.concurrency(
Concurrency::new(Expression::new("release-${{github.ref}}")).cancel_in_progress(false),
)
.add_needs(build.clone())
.add_env(Env::github())
.add_env(Env::new(
"CARGO_REGISTRY_TOKEN",
"${{ secrets.CARGO_REGISTRY_TOKEN }}",
))
.permissions(permissions)
.add_step(Step::checkout())
.add_step(Release::default().command(Command::ReleasePR))
}

fn release_job(cond: &Context<bool>, build: &Job, permissions: &Permissions) -> Job {
Job::new("Release")
.cond(cond.clone())
.add_needs(build.clone())
.add_env(Env::github())
.add_env(Env::new(
"CARGO_REGISTRY_TOKEN",
"${{ secrets.CARGO_REGISTRY_TOKEN }}",
))
.permissions(permissions.clone())
.add_step(Step::checkout())
.add_step(Release::default().command(Command::Release))
}
63 changes: 63 additions & 0 deletions crates/gh-workflow/src/workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ impl Workflow {
Ok(serde_yaml::to_string(self)?)
}

/// Adds a job to the workflow when a condition is met.
pub fn add_job_when<T: ToString, J: Into<Job>>(self, cond: bool, id: T, job: J) -> Self {
if cond {
self.add_job(id, job)
} else {
self
}
}

/// Adds a job to the workflow with the specified ID and job configuration.
pub fn add_job<T: ToString, J: Into<Job>>(mut self, id: T, job: J) -> Self {
let key = id.to_string();
Expand Down Expand Up @@ -133,6 +142,15 @@ impl Workflow {
self
}

/// Adds an event to the workflow when a condition is met.
pub fn add_event_when<T: Into<Event>>(self, cond: bool, that: T) -> Self {
if cond {
self.add_event(that)
} else {
self
}
}

/// Adds an environment variable to the workflow.
pub fn add_env<T: Into<Env>>(mut self, new_env: T) -> Self {
let mut env = self.env.unwrap_or_default();
Expand All @@ -142,6 +160,15 @@ impl Workflow {
self
}

/// Adds an environment variable to the workflow when a condition is met.
pub fn add_env_when<T: Into<Env>>(self, cond: bool, new_env: T) -> Self {
if cond {
self.add_env(new_env)
} else {
self
}
}

/// Performs a reverse lookup to get the ID of a job.
pub fn get_id(&self, job: &Job) -> Option<&str> {
self.jobs
Expand Down Expand Up @@ -237,6 +264,15 @@ impl Job {
}
}

/// Adds a step to the job when a condition is met.
pub fn add_step_when<S: Into<Step<Run>>>(self, cond: bool, step: S) -> Self {
if cond {
self.add_step(step)
} else {
self
}
}

/// Adds a step to the job.
pub fn add_step<S: Into<Step<T>>, T: StepType>(mut self, step: S) -> Self {
let mut steps = self.steps.unwrap_or_default();
Expand All @@ -256,13 +292,31 @@ impl Job {
self
}

/// Adds an environment variable to the job when a condition is met.
pub fn add_env_when<T: Into<Env>>(self, cond: bool, new_env: T) -> Self {
if cond {
self.add_env(new_env)
} else {
self
}
}

pub fn add_needs<J: Into<Job>>(mut self, needs: J) -> Self {
let job: Job = needs.into();
let mut needs = self.tmp_needs.unwrap_or_default();
needs.push(job);
self.tmp_needs = Some(needs);
self
}

/// Adds a dependency to the job when a condition is met.
pub fn add_needs_when<T: Into<Job>>(self, cond: bool, needs: T) -> Self {
if cond {
self.add_needs(needs)
} else {
self
}
}
}

/// Represents a step in the workflow.
Expand Down Expand Up @@ -524,6 +578,15 @@ impl Step<Use> {

self
}

/// Adds a new input to the step when a condition is met.
pub fn add_with_when<I: Into<Input>>(self, cond: bool, new_with: I) -> Self {
if cond {
self.add_with(new_with)
} else {
self
}
}
}

/// Represents a key-value pair for inputs.
Expand Down
Loading