1use gh_workflow::{ctx::Context, *};
2use indoc::indoc;
3
4use crate::tasks::workflows::{
5 extension_bump::{RepositoryTarget, generate_token},
6 runners,
7 steps::{self, CommonJobConditions, NamedJob, named},
8 vars::{self, StepOutput},
9};
10
11pub fn publish_extension_cli() -> Workflow {
12 let publish = publish_job();
13 let update_sha_in_zed = update_sha_in_zed(&publish);
14 let update_sha_in_extensions = update_sha_in_extensions(&publish);
15
16 named::workflow()
17 .on(Event::default().push(Push::default().tags(vec!["extension-cli".to_string()])))
18 .add_env(("CARGO_TERM_COLOR", "always"))
19 .add_env(("CARGO_INCREMENTAL", 0))
20 .add_job(publish.name, publish.job)
21 .add_job(update_sha_in_zed.name, update_sha_in_zed.job)
22 .add_job(update_sha_in_extensions.name, update_sha_in_extensions.job)
23}
24
25fn publish_job() -> NamedJob {
26 fn build_extension_cli() -> Step<Run> {
27 named::bash("cargo build --release --package extension_cli")
28 }
29
30 fn upload_binary() -> Step<Run> {
31 named::bash("script/upload-extension-cli ${{ github.sha }}")
32 .add_env((
33 "DIGITALOCEAN_SPACES_ACCESS_KEY",
34 vars::DIGITALOCEAN_SPACES_ACCESS_KEY,
35 ))
36 .add_env((
37 "DIGITALOCEAN_SPACES_SECRET_KEY",
38 vars::DIGITALOCEAN_SPACES_SECRET_KEY,
39 ))
40 }
41
42 named::job(
43 Job::default()
44 .with_repository_owner_guard()
45 .runs_on(runners::LINUX_SMALL)
46 .add_step(steps::checkout_repo())
47 .add_step(steps::cache_rust_dependencies_namespace())
48 .add_step(steps::setup_linux())
49 .add_step(build_extension_cli())
50 .add_step(upload_binary()),
51 )
52}
53
54fn update_sha_in_zed(publish_job: &NamedJob) -> NamedJob {
55 let (generate_token, generated_token) = generate_token(
56 vars::ZED_ZIPPY_APP_ID,
57 vars::ZED_ZIPPY_APP_PRIVATE_KEY,
58 Some(RepositoryTarget::current()),
59 );
60
61 fn replace_sha() -> Step<Run> {
62 named::bash(indoc! {r#"
63 sed -i "s/ZED_EXTENSION_CLI_SHA: &str = \"[a-f0-9]*\"/ZED_EXTENSION_CLI_SHA: \&str = \"${{ github.sha }}\"/" \
64 tooling/xtask/src/tasks/workflows/extension_tests.rs
65 "#})
66 }
67
68 fn regenerate_workflows() -> Step<Run> {
69 named::bash("cargo xtask workflows")
70 }
71
72 let (get_short_sha_step, short_sha) = get_short_sha();
73
74 named::job(
75 Job::default()
76 .with_repository_owner_guard()
77 .needs(vec![publish_job.name.clone()])
78 .runs_on(runners::LINUX_LARGE)
79 .add_step(generate_token)
80 .add_step(steps::checkout_repo())
81 .add_step(steps::cache_rust_dependencies_namespace())
82 .add_step(get_short_sha_step)
83 .add_step(replace_sha())
84 .add_step(regenerate_workflows())
85 .add_step(create_pull_request_zed(&generated_token, &short_sha)),
86 )
87}
88
89fn create_pull_request_zed(generated_token: &StepOutput, short_sha: &StepOutput) -> Step<Use> {
90 let title = format!(
91 "extension_ci: Bump extension CLI version to `{}`",
92 short_sha
93 );
94
95 named::uses("peter-evans", "create-pull-request", "v7").with(
96 Input::default()
97 .add("title", title.clone())
98 .add(
99 "body",
100 indoc! {r#"
101 This PR bumps the extension CLI version used in the extension workflows to `${{ github.sha }}`.
102
103 Release Notes:
104
105 - N/A
106 "#},
107 )
108 .add("commit-message", title)
109 .add("branch", "update-extension-cli-sha")
110 .add(
111 "committer",
112 "zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>",
113 )
114 .add("base", "main")
115 .add("delete-branch", true)
116 .add("token", generated_token.to_string())
117 .add("sign-commits", true)
118 .add("assignees", Context::github().actor().to_string()),
119 )
120}
121
122fn update_sha_in_extensions(publish_job: &NamedJob) -> NamedJob {
123 let extensions_repo = RepositoryTarget::new("zed-industries", &["extensions"]);
124 let (generate_token, generated_token) = generate_token(
125 vars::ZED_ZIPPY_APP_ID,
126 vars::ZED_ZIPPY_APP_PRIVATE_KEY,
127 Some(extensions_repo),
128 );
129
130 fn checkout_extensions_repo(token: &StepOutput) -> Step<Use> {
131 named::uses(
132 "actions",
133 "checkout",
134 "11bd71901bbe5b1630ceea73d27597364c9af683", // v4
135 )
136 .add_with(("repository", "zed-industries/extensions"))
137 .add_with(("token", token.to_string()))
138 }
139
140 fn replace_sha() -> Step<Run> {
141 named::bash(indoc! {r#"
142 sed -i "s/ZED_EXTENSION_CLI_SHA: [a-f0-9]*/ZED_EXTENSION_CLI_SHA: ${{ github.sha }}/" \
143 .github/workflows/ci.yml
144 "#})
145 }
146
147 let (get_short_sha_step, short_sha) = get_short_sha();
148
149 named::job(
150 Job::default()
151 .with_repository_owner_guard()
152 .needs(vec![publish_job.name.clone()])
153 .runs_on(runners::LINUX_SMALL)
154 .add_step(generate_token)
155 .add_step(get_short_sha_step)
156 .add_step(checkout_extensions_repo(&generated_token))
157 .add_step(replace_sha())
158 .add_step(create_pull_request_extensions(&generated_token, &short_sha)),
159 )
160}
161
162fn create_pull_request_extensions(
163 generated_token: &StepOutput,
164 short_sha: &StepOutput,
165) -> Step<Use> {
166 let title = format!("Bump extension CLI version to `{}`", short_sha);
167
168 named::uses("peter-evans", "create-pull-request", "v7").with(
169 Input::default()
170 .add("title", title.clone())
171 .add(
172 "body",
173 indoc! {r#"
174 This PR bumps the extension CLI version to https://github.com/zed-industries/zed/commit/${{ github.sha }}.
175 "#},
176 )
177 .add("commit-message", title)
178 .add("branch", "update-extension-cli-sha")
179 .add(
180 "committer",
181 "zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>",
182 )
183 .add("base", "main")
184 .add("delete-branch", true)
185 .add("token", generated_token.to_string())
186 .add("sign-commits", true)
187 .add("labels", "allow-no-extension")
188 .add("assignees", Context::github().actor().to_string()),
189 )
190}
191
192fn get_short_sha() -> (Step<Run>, StepOutput) {
193 let step = named::bash(indoc::indoc! {r#"
194 echo "sha_short=$(echo "${{ github.sha }}" | cut -c1-7)" >> "$GITHUB_OUTPUT"
195 "#})
196 .id("short-sha");
197
198 let step_output = vars::StepOutput::new(&step, "sha_short");
199
200 (step, step_output)
201}