run_bundling.rs

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