release_nightly.rs

  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}