Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T06:51:14.398Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

nix_build.rs

185 lines · 7.0 KB · rust
1use crate::tasks::workflows::{
2    runners::{Arch, Platform},
3    steps::{CommonJobConditions, CommonPermissionSets, DEFAULT_REPOSITORY_OWNER_GUARD, NamedJob},
4};
5
6use super::{runners, steps, steps::named, vars};
7use gh_workflow::*;
8
9/// Generates the nix_build.yml workflow, which builds the Nix package on PRs
10/// that carry the `run-nix` or `run-bundling` label. The Nix jobs live only
11/// here (not in run_bundling.yml) so that setting both labels doesn't build
12/// them twice.
13pub fn nix_build() -> Workflow {
14    let [nix_linux_x86_64, nix_mac_aarch64] = nix_pr_jobs(&["run-nix", "run-bundling"]);
15    named::workflow()
16        .with_minimal_permissions()
17        .on(Event::default().pull_request(
18            PullRequest::default().types([PullRequestType::Labeled, PullRequestType::Synchronize]),
19        ))
20        .concurrency(
21            Concurrency::new(Expression::new(
22                "${{ github.workflow }}-${{ github.head_ref || github.ref }}",
23            ))
24            .cancel_in_progress(true),
25        )
26        .add_env(("CARGO_TERM_COLOR", "always"))
27        .add_env(("RUST_BACKTRACE", "1"))
28        .add_job(nix_linux_x86_64.name, nix_linux_x86_64.job)
29        .add_job(nix_mac_aarch64.name, nix_mac_aarch64.job)
30}
31
32/// Builds the pair of PR Nix jobs (Linux x86_64 + macOS aarch64), each gated so
33/// they run when any of the given PR `labels` is present (on
34/// `labeled`/`synchronize` events).
35fn nix_pr_jobs(labels: &[&str]) -> [NamedJob; 2] {
36    let labeled = labels
37        .iter()
38        .map(|label| format!("github.event.label.name == '{label}'"))
39        .collect::<Vec<_>>()
40        .join(" || ");
41    let synchronized = labels
42        .iter()
43        .map(|label| format!("contains(github.event.pull_request.labels.*.name, '{label}')"))
44        .collect::<Vec<_>>()
45        .join(" || ");
46    [
47        (Platform::Linux, Arch::X86_64),
48        (Platform::Mac, Arch::AARCH64),
49    ]
50    .map(|(platform, arch)| {
51        let mut job = build_nix(
52            platform,
53            arch,
54            "default",
55            // don't push PR builds to the cache
56            Some("-zed-editor-[0-9.]*"),
57            &[],
58        );
59        job.job = job.job.cond(Expression::new(format!(
60            "{DEFAULT_REPOSITORY_OWNER_GUARD} && \
61            ((github.event.action == 'labeled' && ({labeled})) || \
62            (github.event.action == 'synchronize' && ({synchronized})))"
63        )));
64        job
65    })
66}
67
68pub(crate) fn build_nix(
69    platform: Platform,
70    arch: Arch,
71    flake_output: &str,
72    cachix_filter: Option<&str>,
73    deps: &[&NamedJob],
74) -> NamedJob {
75    pub fn install_nix() -> Step<Use> {
76        named::uses(
77            "cachix",
78            "install-nix-action",
79            "02a151ada4993995686f9ed4f1be7cfbb229e56f", // v31
80        )
81        .add_with(("github_access_token", vars::GITHUB_TOKEN))
82    }
83
84    pub fn cachix_action(cachix_filter: Option<&str>) -> Step<Use> {
85        let mut step = named::uses(
86            "cachix",
87            "cachix-action",
88            "0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad", // v16
89        )
90        .add_with(("name", "zed"))
91        .add_with(("authToken", vars::CACHIX_AUTH_TOKEN))
92        .add_with(("cachixArgs", "-v"));
93        if let Some(cachix_filter) = cachix_filter {
94            step = step.add_with(("pushFilter", cachix_filter));
95        }
96        step
97    }
98
99    pub fn build(flake_output: &str) -> Step<Run> {
100        named::bash(&format!(
101            "nix build .#{} -L --accept-flake-config",
102            flake_output
103        ))
104    }
105
106    // After install-nix, register ~/nix-cache as a local binary cache
107    // substituter so nix pulls from it on demand during builds (no bulk
108    // import). Also restart the daemon so it picks up the new config.
109    pub fn configure_local_nix_cache() -> Step<Run> {
110        named::bash(indoc::indoc! {r#"
111            mkdir -p ~/nix-cache
112            echo "extra-substituters = file://$HOME/nix-cache?priority=10" | sudo tee -a /etc/nix/nix.conf
113            echo "require-sigs = false" | sudo tee -a /etc/nix/nix.conf
114            sudo launchctl kickstart -k system/org.nixos.nix-daemon
115        "#})
116    }
117
118    // Incrementally copy only new store paths from the build result's
119    // closure into the local binary cache for the next run.
120    pub fn export_to_local_nix_cache() -> Step<Run> {
121        named::bash(indoc::indoc! {r#"
122            if [ -L result ]; then
123              echo "Copying build closure to local binary cache..."
124              nix copy --to "file://$HOME/nix-cache" ./result || echo "Warning: nix copy to local cache failed"
125            else
126              echo "No build result found, skipping cache export."
127            fi
128        "#})
129        .if_condition(Expression::new("always()"))
130    }
131
132    let runner = match platform {
133        Platform::Windows => unimplemented!(),
134        Platform::Linux => runners::LINUX_X86_BUNDLER,
135        Platform::Mac => runners::MAC_DEFAULT,
136    };
137    let mut job = Job::default()
138        .timeout_minutes(60u32)
139        .continue_on_error(true)
140        .with_repository_owner_guard()
141        .runs_on(runner)
142        .add_env(("ZED_CLIENT_CHECKSUM_SEED", vars::ZED_CLIENT_CHECKSUM_SEED))
143        .add_env(("ZED_MINIDUMP_ENDPOINT", vars::ZED_SENTRY_MINIDUMP_ENDPOINT))
144        .add_env((
145            "ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON",
146            vars::ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON,
147        ))
148        .add_env(("GIT_LFS_SKIP_SMUDGE", "1")) // breaks the livekit rust sdk examples which we don't actually depend on
149        .add_step(steps::checkout_repo());
150
151    if deps.len() > 0 {
152        job = job.needs(deps.iter().map(|d| d.name.clone()).collect::<Vec<String>>());
153    }
154
155    // On Linux, `cache: nix` uses bind-mounts so the /nix store is available
156    // before install-nix-action runs — no extra steps needed.
157    //
158    // On macOS, `/nix` lives on a read-only root filesystem and the nscloud
159    // cache action cannot mount or symlink there. Instead we cache a
160    // user-writable directory (~/nix-cache) as a local binary cache and
161    // register it as a nix substituter. Nix then pulls paths from it on
162    // demand during builds (zero-copy at startup), and after building we
163    // incrementally copy new paths into the cache for the next run.
164    job = match platform {
165        Platform::Linux => job
166            .add_step(steps::cache_nix_dependencies_namespace())
167            .add_step(install_nix())
168            .add_step(cachix_action(cachix_filter))
169            .add_step(build(&flake_output)),
170        Platform::Mac => job
171            .add_step(steps::cache_nix_store_macos())
172            .add_step(install_nix())
173            .add_step(configure_local_nix_cache())
174            .add_step(cachix_action(cachix_filter))
175            .add_step(build(&flake_output))
176            .add_step(export_to_local_nix_cache()),
177        Platform::Windows => unimplemented!(),
178    };
179
180    NamedJob {
181        name: format!("build_nix_{platform}_{arch}"),
182        job,
183    }
184}
185
Served at tenant.openagents/omega Member data and write actions are omitted.