1use crate::tasks::workflows::{
  2    run_tests::run_tests_in,
  3    runners::{Arch, Platform},
  4    steps::{FluentBuilder, NamedJob},
  5};
  6
  7use super::{runners, steps, steps::named, vars};
  8use gh_workflow::*;
  9use indoc::indoc;
 10
 11/// Generates the nix.yml workflow
 12pub fn nix_build() -> Workflow {
 13    let linux_x86 = build_nix(
 14        Platform::Linux,
 15        Arch::X86_64,
 16        "debug",
 17        Some("-zed-editor-[0-9.]*-nightly"),
 18        &[],
 19    );
 20    let mac_arm = build_nix(
 21        Platform::Mac,
 22        Arch::ARM64,
 23        "debug",
 24        Some("-zed-editor-[0-9.]*-nightly"),
 25        &[],
 26    );
 27
 28    named::workflow()
 29        .map(|workflow| {
 30            run_tests_in(
 31                &[
 32                    "nix/**",
 33                    "flake.*",
 34                    "Cargo.*",
 35                    "rust-toolchain.toml",
 36                    ".cargo/config.toml",
 37                ],
 38                workflow,
 39            )
 40        })
 41        .add_event(Event::default().workflow_call(WorkflowCall::default()))
 42        .add_job(linux_x86.name, linux_x86.job)
 43        .add_job(mac_arm.name, mac_arm.job)
 44}
 45
 46pub(crate) fn build_nix(
 47    platform: Platform,
 48    arch: Arch,
 49    flake_output: &str,
 50    cachix_filter: Option<&str>,
 51    deps: &[&NamedJob],
 52) -> NamedJob {
 53    let runner = match platform {
 54        Platform::Windows => unimplemented!(),
 55        Platform::Linux => runners::LINUX_X86_BUNDLER,
 56        Platform::Mac => runners::MAC_DEFAULT,
 57    };
 58    let mut job = Job::default()
 59        .timeout_minutes(60u32)
 60        .continue_on_error(true)
 61        .cond(Expression::new(
 62            "github.repository_owner == 'zed-industries'",
 63        ))
 64        .runs_on(runner)
 65        .add_env(("ZED_CLIENT_CHECKSUM_SEED", vars::ZED_CLIENT_CHECKSUM_SEED))
 66        .add_env(("ZED_MINIDUMP_ENDPOINT", vars::ZED_SENTRY_MINIDUMP_ENDPOINT))
 67        .add_env((
 68            "ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON",
 69            vars::ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON,
 70        ))
 71        .add_env(("GIT_LFS_SKIP_SMUDGE", "1")) // breaks the livekit rust sdk examples which we don't actually depend on
 72        .add_step(steps::checkout_repo());
 73
 74    if deps.len() > 0 {
 75        job = job.needs(deps.iter().map(|d| d.name.clone()).collect::<Vec<String>>());
 76    }
 77
 78    job = if platform == Platform::Linux {
 79        job.add_step(install_nix())
 80            .add_step(cachix_action(cachix_filter))
 81            .add_step(build(&flake_output))
 82    } else {
 83        job.add_step(set_path())
 84            .add_step(cachix_action(cachix_filter))
 85            .add_step(build(&flake_output))
 86            .add_step(limit_store())
 87    };
 88
 89    NamedJob {
 90        name: format!("build_nix_{platform}_{arch}"),
 91        job,
 92    }
 93}
 94
 95// on our macs we manually install nix. for some reason the cachix action is running
 96// under a non-login /bin/bash shell which doesn't source the proper script to add the
 97// nix profile to PATH, so we manually add them here
 98pub fn set_path() -> Step<Run> {
 99    named::bash(indoc! {r#"
100            echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH"
101            echo "/Users/administrator/.nix-profile/bin" >> "$GITHUB_PATH"
102        "#})
103}
104
105pub fn install_nix() -> Step<Use> {
106    named::uses(
107        "cachix",
108        "install-nix-action",
109        "02a151ada4993995686f9ed4f1be7cfbb229e56f", // v31
110    )
111    .add_with(("github_access_token", vars::GITHUB_TOKEN))
112}
113
114pub fn cachix_action(cachix_filter: Option<&str>) -> Step<Use> {
115    let mut step = named::uses(
116        "cachix",
117        "cachix-action",
118        "0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad", // v16
119    )
120    .add_with(("name", "zed"))
121    .add_with(("authToken", vars::CACHIX_AUTH_TOKEN))
122    .add_with(("cachixArgs", "-v"));
123    if let Some(cachix_filter) = cachix_filter {
124        step = step.add_with(("pushFilter", cachix_filter));
125    }
126    step
127}
128
129pub fn build(flake_output: &str) -> Step<Run> {
130    named::bash(&format!(
131        "nix build .#{} -L --accept-flake-config",
132        flake_output
133    ))
134}
135
136pub fn limit_store() -> Step<Run> {
137    named::bash(indoc! {r#"
138            if [ "$(du -sm /nix/store | cut -f1)" -gt 50000 ]; then
139                nix-collect-garbage -d || true
140            fi"#
141    })
142}