1use std::path::Path;
2
3use crate::tasks::workflows::{
4 release::ReleaseBundleJobs,
5 runners::{Arch, Platform, ReleaseChannel},
6 steps::{FluentBuilder, NamedJob, dependant_job, named},
7 vars::{assets, bundle_envs},
8};
9
10use super::{runners, steps};
11use gh_workflow::*;
12use indoc::indoc;
13
14pub fn run_bundling() -> Workflow {
15 let bundle = ReleaseBundleJobs {
16 linux_aarch64: bundle_linux(Arch::AARCH64, None, &[]),
17 linux_x86_64: bundle_linux(Arch::X86_64, None, &[]),
18 mac_aarch64: bundle_mac(Arch::AARCH64, None, &[]),
19 mac_x86_64: bundle_mac(Arch::X86_64, None, &[]),
20 windows_aarch64: bundle_windows(Arch::AARCH64, None, &[]),
21 windows_x86_64: bundle_windows(Arch::X86_64, None, &[]),
22 };
23 named::workflow()
24 .on(Event::default().pull_request(
25 PullRequest::default().types([PullRequestType::Labeled, PullRequestType::Synchronize]),
26 ))
27 .concurrency(
28 Concurrency::new(Expression::new(
29 "${{ github.workflow }}-${{ github.head_ref || github.ref }}",
30 ))
31 .cancel_in_progress(true),
32 )
33 .add_env(("CARGO_TERM_COLOR", "always"))
34 .add_env(("RUST_BACKTRACE", "1"))
35 .map(|mut workflow| {
36 for job in bundle.into_jobs() {
37 workflow = workflow.add_job(job.name, job.job);
38 }
39 workflow
40 })
41}
42
43fn bundle_job(deps: &[&NamedJob]) -> Job {
44 dependant_job(deps)
45 .when(deps.len() == 0, |job|
46 job.cond(Expression::new(
47 indoc! {
48 r#"(github.event.action == 'labeled' && github.event.label.name == 'run-bundling') ||
49 (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'run-bundling'))"#,
50 })))
51 .timeout_minutes(60u32)
52}
53
54pub(crate) fn bundle_mac(
55 arch: Arch,
56 release_channel: Option<ReleaseChannel>,
57 deps: &[&NamedJob],
58) -> NamedJob {
59 pub fn bundle_mac(arch: Arch) -> Step<Run> {
60 named::bash(&format!("./script/bundle-mac {arch}-apple-darwin"))
61 }
62 let platform = Platform::Mac;
63 let artifact_name = match arch {
64 Arch::X86_64 => assets::MAC_X86_64,
65 Arch::AARCH64 => assets::MAC_AARCH64,
66 };
67 let remote_server_artifact_name = match arch {
68 Arch::X86_64 => assets::REMOTE_SERVER_MAC_X86_64,
69 Arch::AARCH64 => assets::REMOTE_SERVER_MAC_AARCH64,
70 };
71 NamedJob {
72 name: format!("bundle_mac_{arch}"),
73 job: bundle_job(deps)
74 .runs_on(runners::MAC_DEFAULT)
75 .envs(bundle_envs(platform))
76 .add_step(steps::checkout_repo())
77 .when_some(release_channel, |job, release_channel| {
78 job.add_step(set_release_channel(platform, release_channel))
79 })
80 .add_step(steps::setup_node())
81 .add_step(steps::setup_sentry())
82 .add_step(steps::clear_target_dir_if_large(runners::Platform::Mac))
83 .add_step(bundle_mac(arch))
84 .add_step(upload_artifact(&format!(
85 "target/{arch}-apple-darwin/release/{artifact_name}"
86 )))
87 .add_step(upload_artifact(&format!(
88 "target/{remote_server_artifact_name}"
89 ))),
90 }
91}
92
93pub fn upload_artifact(path: &str) -> Step<Use> {
94 let name = Path::new(path).file_name().unwrap().to_str().unwrap();
95 Step::new(format!("@actions/upload-artifact {}", name))
96 .uses(
97 "actions",
98 "upload-artifact",
99 "330a01c490aca151604b8cf639adc76d48f6c5d4", // v5
100 )
101 // N.B. "name" is the name for the asset. The uploaded
102 // file retains its filename.
103 .add_with(("name", name))
104 .add_with(("path", path))
105 .add_with(("if-no-files-found", "error"))
106}
107
108pub(crate) fn bundle_linux(
109 arch: Arch,
110 release_channel: Option<ReleaseChannel>,
111 deps: &[&NamedJob],
112) -> NamedJob {
113 let platform = Platform::Linux;
114 let artifact_name = match arch {
115 Arch::X86_64 => assets::LINUX_X86_64,
116 Arch::AARCH64 => assets::LINUX_AARCH64,
117 };
118 let remote_server_artifact_name = match arch {
119 Arch::X86_64 => assets::REMOTE_SERVER_LINUX_X86_64,
120 Arch::AARCH64 => assets::REMOTE_SERVER_LINUX_AARCH64,
121 };
122 NamedJob {
123 name: format!("bundle_linux_{arch}"),
124 job: bundle_job(deps)
125 .runs_on(arch.linux_bundler())
126 .envs(bundle_envs(platform))
127 .add_step(steps::checkout_repo())
128 .when_some(release_channel, |job, release_channel| {
129 job.add_step(set_release_channel(platform, release_channel))
130 })
131 .add_step(steps::setup_sentry())
132 .map(steps::install_linux_dependencies)
133 .add_step(steps::script("./script/bundle-linux"))
134 .add_step(upload_artifact(&format!("target/release/{artifact_name}")))
135 .add_step(upload_artifact(&format!(
136 "target/{remote_server_artifact_name}"
137 ))),
138 }
139}
140
141pub(crate) fn bundle_windows(
142 arch: Arch,
143 release_channel: Option<ReleaseChannel>,
144 deps: &[&NamedJob],
145) -> NamedJob {
146 let platform = Platform::Windows;
147 pub fn bundle_windows(arch: Arch) -> Step<Run> {
148 let step = match arch {
149 Arch::X86_64 => named::pwsh("script/bundle-windows.ps1 -Architecture x86_64"),
150 Arch::AARCH64 => named::pwsh("script/bundle-windows.ps1 -Architecture aarch64"),
151 };
152 step.working_directory("${{ env.ZED_WORKSPACE }}")
153 }
154 let artifact_name = match arch {
155 Arch::X86_64 => assets::WINDOWS_X86_64,
156 Arch::AARCH64 => assets::WINDOWS_AARCH64,
157 };
158 NamedJob {
159 name: format!("bundle_windows_{arch}"),
160 job: bundle_job(deps)
161 .runs_on(runners::WINDOWS_DEFAULT)
162 .envs(bundle_envs(platform))
163 .add_step(steps::checkout_repo())
164 .when_some(release_channel, |job, release_channel| {
165 job.add_step(set_release_channel(platform, release_channel))
166 })
167 .add_step(steps::setup_sentry())
168 .add_step(bundle_windows(arch))
169 .add_step(upload_artifact(&format!("target/{artifact_name}"))),
170 }
171}
172
173fn set_release_channel(platform: Platform, release_channel: ReleaseChannel) -> Step<Run> {
174 match release_channel {
175 ReleaseChannel::Nightly => set_release_channel_to_nightly(platform),
176 }
177}
178
179fn set_release_channel_to_nightly(platform: Platform) -> Step<Run> {
180 match platform {
181 Platform::Linux | Platform::Mac => named::bash(indoc::indoc! {r#"
182 set -eu
183 version=$(git rev-parse --short HEAD)
184 echo "Publishing version: ${version} on release channel nightly"
185 echo "nightly" > crates/zed/RELEASE_CHANNEL
186 "#}),
187 Platform::Windows => named::pwsh(indoc::indoc! {r#"
188 $ErrorActionPreference = "Stop"
189 $version = git rev-parse --short HEAD
190 Write-Host "Publishing version: $version on release channel nightly"
191 "nightly" | Set-Content -Path "crates/zed/RELEASE_CHANNEL"
192 "#})
193 .working_directory("${{ env.ZED_WORKSPACE }}"),
194 }
195}