1use crate::tasks::workflows::{
2 nix_build::build_nix,
3 run_bundling::{bundle_mac, bundle_windows},
4 run_tests::run_platform_tests,
5 runners::{Arch, Platform},
6 steps::NamedJob,
7 vars::{mac_bundle_envs, windows_bundle_envs},
8};
9
10use super::{runners, steps, steps::named, vars};
11use gh_workflow::*;
12use indexmap::IndexMap;
13
14/// Generates the release_nightly.yml workflow
15pub fn release_nightly() -> Workflow {
16 let env: IndexMap<_, _> = [
17 ("CARGO_TERM_COLOR", "always"),
18 ("CARGO_INCREMENTAL", "0"),
19 ("RUST_BACKTRACE", "1"),
20 ("ZED_CLIENT_CHECKSUM_SEED", vars::ZED_CLIENT_CHECKSUM_SEED),
21 ("ZED_MINIDUMP_ENDPOINT", vars::ZED_SENTRY_MINIDUMP_ENDPOINT),
22 (
23 "DIGITALOCEAN_SPACES_ACCESS_KEY",
24 vars::DIGITALOCEAN_SPACES_ACCESS_KEY,
25 ),
26 (
27 "DIGITALOCEAN_SPACES_SECRET_KEY",
28 vars::DIGITALOCEAN_SPACES_SECRET_KEY,
29 ),
30 ]
31 .into_iter()
32 .map(|(key, value)| (key.into(), value.into()))
33 .collect();
34
35 let style = check_style();
36 let tests = run_platform_tests(Platform::Mac);
37 let windows_tests = run_platform_tests(Platform::Windows);
38 let bundle_mac_x86 = bundle_mac_nightly(Arch::X86_64, &[&style, &tests]);
39 let bundle_mac_arm = bundle_mac_nightly(Arch::ARM64, &[&style, &tests]);
40 let linux_x86 = bundle_linux_nightly(Arch::X86_64, &[&style, &tests]);
41 let linux_arm = bundle_linux_nightly(Arch::ARM64, &[&style, &tests]);
42 let windows_x86 = bundle_windows_nightly(Arch::X86_64, &[&style, &windows_tests]);
43 let windows_arm = bundle_windows_nightly(Arch::ARM64, &[&style, &windows_tests]);
44
45 let nix_linux_x86 = build_nix(
46 Platform::Linux,
47 Arch::X86_64,
48 "default",
49 None,
50 &[&style, &tests],
51 );
52 let nix_mac_arm = build_nix(
53 Platform::Mac,
54 Arch::ARM64,
55 "default",
56 None,
57 &[&style, &tests],
58 );
59 let update_nightly_tag = update_nightly_tag_job(&[
60 &bundle_mac_x86,
61 &bundle_mac_arm,
62 &linux_x86,
63 &linux_arm,
64 &windows_x86,
65 &windows_arm,
66 ]);
67
68 named::workflow()
69 .on(Event::default()
70 // Fire every day at 7:00am UTC (Roughly before EU workday and after US workday)
71 .schedule([Schedule::new("0 7 * * *")])
72 .push(Push::default().add_tag("nightly")))
73 .envs(env)
74 .add_job(style.name, style.job)
75 .add_job(tests.name, tests.job)
76 .add_job(windows_tests.name, windows_tests.job)
77 .add_job(bundle_mac_x86.name, bundle_mac_x86.job)
78 .add_job(bundle_mac_arm.name, bundle_mac_arm.job)
79 .add_job(linux_x86.name, linux_x86.job)
80 .add_job(linux_arm.name, linux_arm.job)
81 .add_job(windows_x86.name, windows_x86.job)
82 .add_job(windows_arm.name, windows_arm.job)
83 .add_job(nix_linux_x86.name, nix_linux_x86.job)
84 .add_job(nix_mac_arm.name, nix_mac_arm.job)
85 .add_job(update_nightly_tag.name, update_nightly_tag.job)
86}
87
88fn check_style() -> NamedJob {
89 let job = release_job(&[])
90 .runs_on(runners::MAC_DEFAULT)
91 .add_step(
92 steps::checkout_repo()
93 .add_with(("clean", false))
94 .add_with(("fetch-depth", 0)),
95 )
96 .add_step(steps::cargo_fmt())
97 .add_step(steps::script("./script/clippy"));
98
99 named::job(job)
100}
101
102fn release_job(deps: &[&NamedJob]) -> Job {
103 let job = Job::default()
104 .cond(Expression::new(
105 "github.repository_owner == 'zed-industries'",
106 ))
107 .timeout_minutes(60u32);
108 if deps.len() > 0 {
109 job.needs(deps.iter().map(|j| j.name.clone()).collect::<Vec<_>>())
110 } else {
111 job
112 }
113}
114
115fn bundle_mac_nightly(arch: Arch, deps: &[&NamedJob]) -> NamedJob {
116 let platform = Platform::Mac;
117 NamedJob {
118 name: format!("bundle_mac_nightly_{arch}"),
119 job: release_job(deps)
120 .runs_on(runners::MAC_DEFAULT)
121 .envs(mac_bundle_envs())
122 .add_step(steps::checkout_repo())
123 .add_step(steps::setup_node())
124 .add_step(steps::setup_sentry())
125 .add_step(steps::clear_target_dir_if_large(platform))
126 .add_step(set_release_channel_to_nightly(platform))
127 .add_step(bundle_mac(arch))
128 .add_step(upload_zed_nightly(platform, arch)),
129 }
130}
131
132fn bundle_linux_nightly(arch: Arch, deps: &[&NamedJob]) -> NamedJob {
133 let platform = Platform::Linux;
134 let mut job = steps::release_job(deps)
135 .runs_on(arch.linux_bundler())
136 .add_step(steps::checkout_repo())
137 .add_step(steps::setup_sentry())
138 .add_step(steps::script("./script/linux"));
139
140 // todo(ci) can we do this on arm too?
141 if arch == Arch::X86_64 {
142 job = job.add_step(steps::script("./script/install-mold"));
143 }
144 job = job
145 .add_step(steps::clear_target_dir_if_large(platform))
146 .add_step(set_release_channel_to_nightly(platform))
147 .add_step(steps::script("./script/bundle-linux"))
148 .add_step(upload_zed_nightly(platform, arch));
149 NamedJob {
150 name: format!("bundle_linux_nightly_{arch}"),
151 job,
152 }
153}
154
155fn bundle_windows_nightly(arch: Arch, deps: &[&NamedJob]) -> NamedJob {
156 let platform = Platform::Windows;
157 NamedJob {
158 name: format!("bundle_windows_nightly_{arch}"),
159 job: steps::release_job(deps)
160 .runs_on(runners::WINDOWS_DEFAULT)
161 .envs(windows_bundle_envs())
162 .add_step(steps::checkout_repo())
163 .add_step(steps::setup_sentry())
164 .add_step(set_release_channel_to_nightly(platform))
165 .add_step(bundle_windows(arch))
166 .add_step(upload_zed_nightly(platform, arch)),
167 }
168}
169
170fn update_nightly_tag_job(deps: &[&NamedJob]) -> NamedJob {
171 fn update_nightly_tag() -> Step<Run> {
172 named::bash(indoc::indoc! {r#"
173 if [ "$(git rev-parse nightly)" = "$(git rev-parse HEAD)" ]; then
174 echo "Nightly tag already points to current commit. Skipping tagging."
175 exit 0
176 fi
177 git config user.name github-actions
178 git config user.email github-actions@github.com
179 git tag -f nightly
180 git push origin nightly --force
181 "#})
182 }
183
184 fn create_sentry_release() -> Step<Use> {
185 named::uses(
186 "getsentry",
187 "action-release",
188 "526942b68292201ac6bbb99b9a0747d4abee354c", // v3
189 )
190 .add_env(("SENTRY_ORG", "zed-dev"))
191 .add_env(("SENTRY_PROJECT", "zed"))
192 .add_env(("SENTRY_AUTH_TOKEN", vars::SENTRY_AUTH_TOKEN))
193 .add_with(("environment", "production"))
194 }
195
196 NamedJob {
197 name: "update_nightly_tag".to_owned(),
198 job: steps::release_job(deps)
199 .runs_on(runners::LINUX_SMALL)
200 .add_step(steps::checkout_repo().add_with(("fetch-depth", 0)))
201 .add_step(update_nightly_tag())
202 .add_step(create_sentry_release()),
203 }
204}
205
206fn set_release_channel_to_nightly(platform: Platform) -> Step<Run> {
207 match platform {
208 Platform::Linux | Platform::Mac => named::bash(indoc::indoc! {r#"
209 set -eu
210 version=$(git rev-parse --short HEAD)
211 echo "Publishing version: ${version} on release channel nightly"
212 echo "nightly" > crates/zed/RELEASE_CHANNEL
213 "#}),
214 Platform::Windows => named::pwsh(indoc::indoc! {r#"
215 $ErrorActionPreference = "Stop"
216 $version = git rev-parse --short HEAD
217 Write-Host "Publishing version: $version on release channel nightly"
218 "nightly" | Set-Content -Path "crates/zed/RELEASE_CHANNEL"
219 "#})
220 .working_directory("${{ env.ZED_WORKSPACE }}"),
221 }
222}
223
224fn upload_zed_nightly(platform: Platform, arch: Arch) -> Step<Run> {
225 match platform {
226 Platform::Linux => named::bash(&format!("script/upload-nightly linux-targz {arch}")),
227 Platform::Mac => named::bash(&format!("script/upload-nightly macos {arch}")),
228 Platform::Windows => {
229 let cmd = match arch {
230 Arch::X86_64 => "script/upload-nightly.ps1 -Architecture x86_64",
231 Arch::ARM64 => "script/upload-nightly.ps1 -Architecture aarch64",
232 };
233 named::pwsh(cmd).working_directory("${{ env.ZED_WORKSPACE }}")
234 }
235 }
236}