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