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