run_bundling.rs

  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}