1use gh_workflow::{
2 Event, Expression, Input, Job, Level, Permissions, PullRequest, PullRequestType, Push, Run,
3 Step, UsesJob, Workflow, WorkflowDispatch,
4};
5use indoc::indoc;
6
7use crate::tasks::workflows::{
8 GenerateWorkflowArgs, GitSha,
9 extensions::WithAppSecrets,
10 runners,
11 steps::{CommonJobConditions, NamedJob, named},
12 vars::{JobOutput, StepOutput, one_workflow_per_non_main_branch_and_token},
13};
14
15pub(crate) fn bump_version(args: &GenerateWorkflowArgs) -> Workflow {
16 let (determine_bump_type, bump_type) = determine_bump_type();
17 let bump_type = bump_type.as_job_output(&determine_bump_type);
18
19 let call_bump_version = call_bump_version(args.sha.as_ref(), &determine_bump_type, bump_type);
20
21 named::workflow()
22 .on(Event::default()
23 .push(
24 Push::default()
25 .add_branch("main")
26 .add_ignored_path(".github/**"),
27 )
28 .pull_request(PullRequest::default().add_type(PullRequestType::Labeled))
29 .workflow_dispatch(WorkflowDispatch::default()))
30 .concurrency(one_workflow_per_non_main_branch_and_token("labels"))
31 .add_job(determine_bump_type.name, determine_bump_type.job)
32 .add_job(call_bump_version.name, call_bump_version.job)
33}
34
35pub(crate) fn call_bump_version(
36 target_ref: Option<&GitSha>,
37 depending_job: &NamedJob,
38 bump_type: JobOutput,
39) -> NamedJob<UsesJob> {
40 let job = Job::default()
41 .cond(Expression::new(format!(
42 "github.event.action != 'labeled' || {} != 'patch'",
43 bump_type.expr()
44 )))
45 .permissions(
46 Permissions::default()
47 .contents(Level::Write)
48 .issues(Level::Write)
49 .pull_requests(Level::Write)
50 .actions(Level::Write),
51 )
52 .uses(
53 "zed-industries",
54 "zed",
55 ".github/workflows/extension_bump.yml",
56 target_ref.map_or("main", AsRef::as_ref),
57 )
58 .add_need(depending_job.name.clone())
59 .with(
60 Input::default()
61 .add("bump-type", bump_type.to_string())
62 .add("force-bump", "${{ github.event_name != 'push' }}"),
63 )
64 .with_app_secrets();
65
66 named::job(job)
67}
68
69fn determine_bump_type() -> (NamedJob, StepOutput) {
70 let (get_bump_type, output) = get_bump_type();
71 let job = Job::default()
72 .with_repository_owner_guard()
73 .permissions(Permissions::default())
74 .runs_on(runners::LINUX_SMALL)
75 .add_step(get_bump_type)
76 .outputs([(output.name.to_owned(), output.to_string())]);
77 (named::job(job), output)
78}
79
80fn get_bump_type() -> (Step<Run>, StepOutput) {
81 let step = named::bash(
82 indoc! {r#"
83 if [ "$HAS_MAJOR_LABEL" = "true" ]; then
84 bump_type="major"
85 elif [ "$HAS_MINOR_LABEL" = "true" ]; then
86 bump_type="minor"
87 else
88 bump_type="patch"
89 fi
90 echo "bump_type=$bump_type" >> $GITHUB_OUTPUT
91 "#},
92 )
93 .add_env(("HAS_MAJOR_LABEL",
94 indoc!{
95 "${{ (github.event.action == 'labeled' && github.event.label.name == 'major') ||
96 (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'major')) }}"
97 }))
98 .add_env(("HAS_MINOR_LABEL",
99 indoc!{
100 "${{ (github.event.action == 'labeled' && github.event.label.name == 'minor') ||
101 (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'minor')) }}"
102 }))
103 .id("get-bump-type");
104
105 let step_output = StepOutput::new(&step, "bump_type");
106
107 (step, step_output)
108}