Try gh-workflow (#41155)

Conrad Irwin created

Experimenting with not writing YAML by hand...

Release Notes:

- N/A

Change summary

.github/workflows/danger.yml                   |  61 +++----
.github/workflows/nix.yml                      | 115 ++++++++-------
Cargo.lock                                     | 107 +++++++++++++++
Cargo.toml                                     |   1 
crates/gpui/Cargo.toml                         |   4 
tooling/xtask/Cargo.toml                       |   3 
tooling/xtask/src/main.rs                      |   2 
tooling/xtask/src/tasks.rs                     |   1 
tooling/xtask/src/tasks/workflows.rs           |  33 ++++
tooling/xtask/src/tasks/workflows/runners.rs   |  11 +
tooling/xtask/src/tasks/workflows/steps.rs     | 142 ++++++++++++++++++++
tooling/xtask/src/tasks/workflows/vars.rs      |  17 ++
tooling/xtask/src/tasks/workflows/workflows.rs | 105 ++++++++++++++
13 files changed, 513 insertions(+), 89 deletions(-)

Detailed changes

.github/workflows/danger.yml 🔗

@@ -1,42 +1,37 @@
+# generated `cargo xtask workflows`. Do not edit.
 name: Danger
-
 on:
   pull_request:
-    branches: [main]
     types:
-      - opened
-      - synchronize
-      - reopened
-      - edited
-
+    - opened
+    - synchronize
+    - reopened
+    - edited
+    branches:
+    - main
 jobs:
   danger:
     if: github.repository_owner == 'zed-industries'
     runs-on: namespace-profile-2x4-ubuntu-2404
-
     steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
-
-      - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
-        with:
-          version: 9
-
-      - name: Setup Node
-        uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
-        with:
-          node-version: "20"
-          cache: "pnpm"
-          cache-dependency-path: "script/danger/pnpm-lock.yaml"
-
-      - run: pnpm install --dir script/danger
-
-      - name: Run Danger
-        run: pnpm run --dir script/danger danger ci
-        env:
-          # This GitHub token is not used, but the value needs to be here to prevent
-          # Danger from throwing an error.
-          GITHUB_TOKEN: "not_a_real_token"
-          # All requests are instead proxied through an instance of
-          # https://github.com/maxdeviant/danger-proxy that allows Danger to securely
-          # authenticate with GitHub while still being able to run on PRs from forks.
-          DANGER_GITHUB_API_BASE_URL: "https://danger-proxy.fly.dev/github"
+    - name: steps::checkout_repo
+      uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+    - name: steps::setup_pnpm
+      uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2
+      with:
+        version: '9'
+    - name: steps::danger::setup_node
+      uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
+      with:
+        node-version: '20'
+        cache: pnpm
+        cache-dependency-path: script/danger/pnpm-lock.yaml
+    - name: steps::danger::install_deps
+      run: pnpm install --dir script/danger
+      shell: bash -euxo pipefail {0}
+    - name: steps::danger::run
+      run: pnpm run --dir script/danger danger ci
+      shell: bash -euxo pipefail {0}
+      env:
+        GITHUB_TOKEN: not_a_real_token
+        DANGER_GITHUB_API_BASE_URL: https://danger-proxy.fly.dev/github

.github/workflows/nix.yml 🔗

@@ -1,69 +1,76 @@
-name: "Nix build"
-
+# generated `cargo xtask workflows`. Do not edit.
+name: Nix build
 on:
   workflow_call:
     inputs:
       flake-output:
         type: string
-        default: "default"
+        default: default
       cachix-filter:
         type: string
-        default: ""
-
 jobs:
-  nix-build:
+  nix-build-linux-x86:
+    if: github.repository_owner == 'zed-industries'
+    runs-on: namespace-profile-16x32-ubuntu-2204
+    env:
+      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
+      ZED_MINIDUMP_ENDPOINT: ${{ secrets.ZED_MINIDUMP_ENDPOINT }}
+      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
+      GIT_LFS_SKIP_SMUDGE: '1'
+    steps:
+    - name: steps::checkout_repo
+      uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      with:
+        clean: 'false'
+    - name: steps::nix::install_nix
+      uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f
+      with:
+        github_access_token: ${{ secrets.GITHUB_TOKEN }}
+    - name: steps::nix::cachix_action
+      uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad
+      with:
+        name: zed
+        authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
+        pushFilter: ${{ inputs.cachix-filter }}
+        cachixArgs: -v
+    - name: steps::nix::build
+      run: nix build .#${{ inputs.flake-output }} -L --accept-flake-config
+      shell: bash -euxo pipefail {0}
     timeout-minutes: 60
-    name: (${{ matrix.system.os }}) Nix Build
-    continue-on-error: true # TODO: remove when we want this to start blocking CI
-    strategy:
-      fail-fast: false
-      matrix:
-        system:
-          - os: x86 Linux
-            runner: namespace-profile-16x32-ubuntu-2204
-            install_nix: true
-          - os: arm Mac
-            runner: [macOS, ARM64, test]
-            install_nix: false
+    continue-on-error: true
+  nix-build-mac-arm:
     if: github.repository_owner == 'zed-industries'
-    runs-on: ${{ matrix.system.runner }}
+    runs-on: self-mini-macos
     env:
       ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
-      ZED_MINIDUMP_ENDPOINT: ${{ secrets.ZED_SENTRY_MINIDUMP_ENDPOINT }}
+      ZED_MINIDUMP_ENDPOINT: ${{ secrets.ZED_MINIDUMP_ENDPOINT }}
       ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
-      GIT_LFS_SKIP_SMUDGE: 1 # breaks the livekit rust sdk examples which we don't actually depend on
+      GIT_LFS_SKIP_SMUDGE: '1'
     steps:
-      - name: Checkout repo
-        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
-        with:
-          clean: false
-
-      # on our macs we manually install nix. for some reason the cachix action is running
-      # under a non-login /bin/bash shell which doesn't source the proper script to add the
-      # nix profile to PATH, so we manually add them here
-      - name: Set path
-        if: ${{ ! matrix.system.install_nix }}
-        run: |
-          echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH"
-          echo "/Users/administrator/.nix-profile/bin" >> "$GITHUB_PATH"
-
-      - uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31
-        if: ${{ matrix.system.install_nix }}
-        with:
-          github_access_token: ${{ secrets.GITHUB_TOKEN }}
-
-      - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
-        with:
-          name: zed
-          authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
-          pushFilter: "${{ inputs.cachix-filter }}"
-          cachixArgs: "-v"
-
-      - run: nix build .#${{ inputs.flake-output }} -L --accept-flake-config
-
-      - name: Limit /nix/store to 50GB on macs
-        if: ${{ ! matrix.system.install_nix }}
-        run: |
-          if [ "$(du -sm /nix/store | cut -f1)" -gt 50000 ]; then
+    - name: steps::checkout_repo
+      uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      with:
+        clean: 'false'
+    - name: steps::nix::set_path
+      run: |
+        echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH"
+        echo "/Users/administrator/.nix-profile/bin" >> "$GITHUB_PATH"
+      shell: bash -euxo pipefail {0}
+    - name: steps::nix::cachix_action
+      uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad
+      with:
+        name: zed
+        authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
+        pushFilter: ${{ inputs.cachix-filter }}
+        cachixArgs: -v
+    - name: steps::nix::build
+      run: nix build .#${{ inputs.flake-output }} -L --accept-flake-config
+      shell: bash -euxo pipefail {0}
+    - name: steps::nix::limit_store
+      run: |-
+        if [ "$(du -sm /nix/store | cut -f1)" -gt 50000 ]; then
             nix-collect-garbage -d || true
-          fi
+        fi
+      shell: bash -euxo pipefail {0}
+    timeout-minutes: 60
+    continue-on-error: true

Cargo.lock 🔗

@@ -4902,6 +4902,18 @@ dependencies = [
  "syn 2.0.106",
 ]
 
+[[package]]
+name = "derive_setters"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae5c625eda104c228c06ecaf988d1c60e542176bd7a490e60eeda3493244c0c9"
+dependencies = [
+ "darling 0.20.11",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
 [[package]]
 name = "deunicode"
 version = "1.6.2"
@@ -6942,6 +6954,33 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "gh-workflow"
+version = "0.8.0"
+source = "git+https://github.com/zed-industries/gh-workflow?rev=a0b197dd77c0ed2390c150e601f9d4f9a0ca7105#a0b197dd77c0ed2390c150e601f9d4f9a0ca7105"
+dependencies = [
+ "async-trait",
+ "derive_more 2.0.1",
+ "derive_setters",
+ "gh-workflow-macros",
+ "indexmap 2.11.4",
+ "merge",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "strum_macros 0.27.2",
+]
+
+[[package]]
+name = "gh-workflow-macros"
+version = "0.8.0"
+source = "git+https://github.com/zed-industries/gh-workflow?rev=a0b197dd77c0ed2390c150e601f9d4f9a0ca7105#a0b197dd77c0ed2390c150e601f9d4f9a0ca7105"
+dependencies = [
+ "heck 0.5.0",
+ "quote",
+ "syn 2.0.106",
+]
+
 [[package]]
 name = "gif"
 version = "0.13.3"
@@ -9811,6 +9850,28 @@ dependencies = [
  "gpui",
 ]
 
+[[package]]
+name = "merge"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9"
+dependencies = [
+ "merge_derive",
+ "num-traits",
+]
+
+[[package]]
+name = "merge_derive"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
 [[package]]
 name = "metal"
 version = "0.29.0"
@@ -12800,6 +12861,30 @@ dependencies = [
  "toml_edit 0.23.7",
 ]
 
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
 [[package]]
 name = "proc-macro-error-attr2"
 version = "2.0.0"
@@ -15224,6 +15309,19 @@ dependencies = [
  "syn 2.0.106",
 ]
 
+[[package]]
+name = "serde_yaml"
+version = "0.9.34+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
+dependencies = [
+ "indexmap 2.11.4",
+ "itoa",
+ "ryu",
+ "serde",
+ "unsafe-libyaml",
+]
+
 [[package]]
 name = "serial2"
 version = "0.2.33"
@@ -18411,6 +18509,12 @@ version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
 
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
+
 [[package]]
 name = "untrusted"
 version = "0.9.0"
@@ -20818,9 +20922,12 @@ name = "xtask"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "backtrace",
  "cargo_metadata",
  "cargo_toml",
  "clap",
+ "gh-workflow",
+ "indexmap 2.11.4",
  "indoc",
  "toml 0.8.23",
  "toml_edit 0.22.27",

Cargo.toml 🔗

@@ -508,6 +508,7 @@ fork = "0.2.0"
 futures = "0.3"
 futures-batch = "0.6.1"
 futures-lite = "1.13"
+gh-workflow = { git = "https://github.com/zed-industries/gh-workflow", rev = "a0b197dd77c0ed2390c150e601f9d4f9a0ca7105" }
 git2 = { version = "0.20.1", default-features = false }
 globset = "0.4"
 handlebars = "4.3"

crates/gpui/Cargo.toml 🔗

@@ -85,7 +85,7 @@ doctest = false
 [dependencies]
 anyhow.workspace = true
 async-task = "4.7"
-backtrace = { version = "0.3", optional = true }
+backtrace = { workspace = true, optional = true }
 blade-graphics = { workspace = true, optional = true }
 blade-macros = { workspace = true, optional = true }
 blade-util = { workspace = true, optional = true }
@@ -234,7 +234,7 @@ windows-numerics = "0.2"
 windows-registry = "0.5"
 
 [dev-dependencies]
-backtrace = "0.3"
+backtrace.workspace = true
 collections = { workspace = true, features = ["test-support"] }
 env_logger.workspace = true
 http_client = { workspace = true, features = ["test-support"] }

tooling/xtask/Cargo.toml 🔗

@@ -10,9 +10,12 @@ workspace = true
 
 [dependencies]
 anyhow.workspace = true
+backtrace.workspace = true
 cargo_metadata.workspace = true
 cargo_toml.workspace = true
 clap = { workspace = true, features = ["derive"] }
 toml.workspace = true
 indoc.workspace = true
+indexmap.workspace = true
 toml_edit.workspace = true
+gh-workflow.workspace = true

tooling/xtask/src/main.rs 🔗

@@ -20,6 +20,7 @@ enum CliCommand {
     PackageConformity(tasks::package_conformity::PackageConformityArgs),
     /// Publishes GPUI and its dependencies to crates.io.
     PublishGpui(tasks::publish_gpui::PublishGpuiArgs),
+    Workflows(tasks::workflows::GenerateWorkflowArgs),
 }
 
 fn main() -> Result<()> {
@@ -32,5 +33,6 @@ fn main() -> Result<()> {
             tasks::package_conformity::run_package_conformity(args)
         }
         CliCommand::PublishGpui(args) => tasks::publish_gpui::run_publish_gpui(args),
+        CliCommand::Workflows(args) => tasks::workflows::run_workflows(args),
     }
 }

tooling/xtask/src/tasks.rs 🔗

@@ -2,3 +2,4 @@ pub mod clippy;
 pub mod licenses;
 pub mod package_conformity;
 pub mod publish_gpui;
+pub mod workflows;

tooling/xtask/src/tasks/workflows.rs 🔗

@@ -0,0 +1,33 @@
+use anyhow::{Context, Result};
+use clap::Parser;
+use std::fs;
+use std::path::Path;
+
+mod runners;
+mod steps;
+mod vars;
+mod workflows;
+
+use workflows::*;
+
+#[derive(Parser)]
+pub struct GenerateWorkflowArgs {}
+
+pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> {
+    let dir = Path::new(".github/workflows");
+
+    let workflows = vec![("danger.yml", danger()), ("nix.yml", nix())];
+    fs::create_dir_all(dir)
+        .with_context(|| format!("Failed to create directory: {}", dir.display()))?;
+
+    for (filename, workflow) in workflows {
+        let content = workflow
+            .to_string()
+            .map_err(|e| anyhow::anyhow!("{}: {:?}", filename, e))?;
+        let content = format!("# generated `cargo xtask workflows`. Do not edit.\n{content}");
+        let file_path = dir.join(filename);
+        fs::write(&file_path, content)?;
+    }
+
+    Ok(())
+}

tooling/xtask/src/tasks/workflows/runners.rs 🔗

@@ -0,0 +1,11 @@
+pub const LINUX_CHEAP: Runner = Runner("namespace-profile-2x4-ubuntu-2404");
+pub const LINUX_DEFAULT: Runner = Runner("namespace-profile-16x32-ubuntu-2204");
+pub const MAC_DEFAULT: Runner = Runner("self-mini-macos");
+
+pub struct Runner(&'static str);
+
+impl Into<gh_workflow::RunsOn> for Runner {
+    fn into(self) -> gh_workflow::RunsOn {
+        self.0.into()
+    }
+}

tooling/xtask/src/tasks/workflows/steps.rs 🔗

@@ -0,0 +1,142 @@
+use gh_workflow::*;
+
+pub fn checkout_repo() -> Step<Use> {
+    named::uses(
+        "actions",
+        "checkout",
+        "11bd71901bbe5b1630ceea73d27597364c9af683", // v4
+    )
+}
+
+pub fn setup_pnpm() -> Step<Use> {
+    named::uses(
+        "pnpm",
+        "action-setup",
+        "fe02b34f77f8bc703788d5817da081398fad5dd2", // v4.0.0
+    )
+    .add_with(("version", "9"))
+}
+
+pub mod danger {
+    use super::*;
+
+    pub fn setup_node() -> Step<Use> {
+        named::uses(
+            "actions",
+            "setup-node",
+            "49933ea5288caeca8642d1e84afbd3f7d6820020", // v4
+        )
+        .add_with(("node-version", "20"))
+        .add_with(("cache", "pnpm"))
+        .add_with(("cache-dependency-path", "script/danger/pnpm-lock.yaml"))
+    }
+
+    pub fn install_deps() -> Step<Run> {
+        named::run("pnpm install --dir script/danger")
+    }
+
+    pub fn run() -> Step<Run> {
+        named::run("pnpm run --dir script/danger danger ci")
+            // This GitHub token is not used, but the value needs to be here to prevent
+            // Danger from throwing an error.
+            .add_env(("GITHUB_TOKEN", "not_a_real_token"))
+            // All requests are instead proxied through an instance of
+            // https://github.com/maxdeviant/danger-proxy that allows Danger to securely
+            // authenticate with GitHub while still being able to run on PRs from forks.
+            .add_env((
+                "DANGER_GITHUB_API_BASE_URL",
+                "https://danger-proxy.fly.dev/github",
+            ))
+    }
+}
+
+pub mod nix {
+    use indoc::indoc;
+
+    use crate::tasks::workflows::vars;
+
+    use super::*;
+
+    // on our macs we manually install nix. for some reason the cachix action is running
+    // under a non-login /bin/bash shell which doesn't source the proper script to add the
+    // nix profile to PATH, so we manually add them here
+    pub fn set_path() -> Step<Run> {
+        named::run(indoc! {r#"
+            echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH"
+            echo "/Users/administrator/.nix-profile/bin" >> "$GITHUB_PATH"
+        "#})
+    }
+
+    pub fn install_nix() -> Step<Use> {
+        named::uses(
+            "cachix",
+            "install-nix-action",
+            "02a151ada4993995686f9ed4f1be7cfbb229e56f", // v31
+        )
+        .add_with(("github_access_token", vars::GITHUB_TOKEN))
+    }
+
+    pub fn cachix_action(cachix_filter: &str) -> Step<Use> {
+        named::uses(
+            "cachix",
+            "cachix-action",
+            "0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad", // v16
+        )
+        .add_with(("name", "zed"))
+        .add_with(("authToken", vars::CACHIX_AUTH_TOKEN))
+        .add_with(("pushFilter", cachix_filter))
+        .add_with(("cachixArgs", "-v"))
+    }
+
+    pub fn build(flake_output: &str) -> Step<Run> {
+        named::run(&format!(
+            "nix build .#{} -L --accept-flake-config",
+            flake_output
+        ))
+    }
+
+    pub fn limit_store() -> Step<Run> {
+        named::run(indoc! {r#"
+            if [ "$(du -sm /nix/store | cut -f1)" -gt 50000 ]; then
+                nix-collect-garbage -d || true
+            fi"#
+        })
+    }
+}
+
+// (janky) helpers to generate steps with a name that corresponds
+// to the name of the calling function.
+mod named {
+    use gh_workflow::*;
+
+    pub(super) fn uses(owner: &str, repo: &str, ref_: &str) -> Step<Use> {
+        Step::new(function_name(1)).uses(owner, repo, ref_)
+    }
+
+    pub(super) fn run(script: &str) -> Step<Run> {
+        Step::new(function_name(1))
+            .run(script)
+            .shell("bash -euxo pipefail {0}")
+    }
+
+    fn function_name(i: usize) -> String {
+        let mut name = "<unknown>".to_string();
+        let mut count = 0;
+        backtrace::trace(|frame| {
+            if count < i + 3 {
+                count += 1;
+                return true;
+            }
+            backtrace::resolve_frame(frame, |cb| {
+                if let Some(s) = cb.name() {
+                    name = s.to_string()
+                }
+            });
+            false
+        });
+        name.split("::")
+            .skip_while(|s| s != &"steps")
+            .collect::<Vec<_>>()
+            .join("::")
+    }
+}

tooling/xtask/src/tasks/workflows/vars.rs 🔗

@@ -0,0 +1,17 @@
+use gh_workflow::WorkflowCallInput;
+
+macro_rules! secret {
+    ($secret_name:ident) => {
+        pub const $secret_name: &str = concat!("${{ secrets.", stringify!($secret_name), " }}");
+    };
+}
+
+secret!(GITHUB_TOKEN);
+secret!(CACHIX_AUTH_TOKEN);
+secret!(ZED_CLIENT_CHECKSUM_SEED);
+secret!(ZED_MINIDUMP_ENDPOINT);
+secret!(ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON);
+
+pub fn input(name: &str, input: WorkflowCallInput) -> (String, (&str, WorkflowCallInput)) {
+    return (format!("${{{{ inputs.{name} }}}}"), (name, input));
+}

tooling/xtask/src/tasks/workflows/workflows.rs 🔗

@@ -0,0 +1,105 @@
+use gh_workflow::*;
+use indexmap::IndexMap;
+
+use super::{runners, steps, vars};
+
+/// Generates the danger.yml workflow
+pub fn danger() -> Workflow {
+    Workflow::default()
+        .name("Danger")
+        .on(
+            Event::default().pull_request(PullRequest::default().add_branch("main").types([
+                PullRequestType::Opened,
+                PullRequestType::Synchronize,
+                PullRequestType::Reopened,
+                PullRequestType::Edited,
+            ])),
+        )
+        .add_job(
+            "danger",
+            Job::default()
+                .cond(Expression::new(
+                    "github.repository_owner == 'zed-industries'",
+                ))
+                .runs_on(runners::LINUX_CHEAP)
+                .add_step(steps::checkout_repo())
+                .add_step(steps::setup_pnpm())
+                .add_step(steps::danger::setup_node())
+                .add_step(steps::danger::install_deps())
+                .add_step(steps::danger::run()),
+        )
+}
+
+/// Generates the nix.yml workflow
+pub fn nix() -> Workflow {
+    let env: IndexMap<_, _> = [
+        ("ZED_CLIENT_CHECKSUM_SEED", vars::ZED_CLIENT_CHECKSUM_SEED),
+        ("ZED_MINIDUMP_ENDPOINT", vars::ZED_MINIDUMP_ENDPOINT),
+        (
+            "ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON",
+            vars::ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON,
+        ),
+        ("GIT_LFS_SKIP_SMUDGE", "1"), // breaks the livekit rust sdk examples which we don't actually depend on
+    ]
+    .into_iter()
+    .map(|(key, value)| (key.into(), value.into()))
+    .collect();
+
+    // todo(ci) instead of having these as optional YAML inputs,
+    // should we just generate two copies of the job (one for release-nightly
+    // and one for CI?)
+    let (input_flake_output, flake_output) = vars::input(
+        "flake-output",
+        WorkflowCallInput {
+            input_type: "string".into(),
+            default: Some("default".into()),
+            ..Default::default()
+        },
+    );
+    let (input_cachix_filter, cachix_filter) = vars::input(
+        "cachix-filter",
+        WorkflowCallInput {
+            input_type: "string".into(),
+            ..Default::default()
+        },
+    );
+
+    Workflow::default()
+        .name("Nix build")
+        .on(Event::default().workflow_call(
+            WorkflowCall::default()
+                .add_input(flake_output.0, flake_output.1)
+                .add_input(cachix_filter.0, cachix_filter.1),
+        ))
+        .add_job(
+            "nix-build-linux-x86",
+            Job::default()
+                .timeout_minutes(60u32)
+                .continue_on_error(true)
+                .cond(Expression::new(
+                    "github.repository_owner == 'zed-industries'",
+                ))
+                .runs_on(runners::LINUX_DEFAULT)
+                .env(env.clone())
+                .add_step(steps::checkout_repo().add_with(("clean", "false")))
+                .add_step(steps::nix::install_nix())
+                .add_step(steps::nix::cachix_action(&input_cachix_filter))
+                .add_step(steps::nix::build(&input_flake_output)),
+        )
+        .add_job(
+            "nix-build-mac-arm",
+            Job::default()
+                .timeout_minutes(60u32)
+                .continue_on_error(true)
+                .cond(Expression::new(
+                    "github.repository_owner == 'zed-industries'",
+                ))
+                .runs_on(runners::MAC_DEFAULT)
+                .env(env)
+                .add_step(steps::checkout_repo().add_with(("clean", "false")))
+                .add_step(steps::nix::set_path())
+                .add_step(steps::nix::cachix_action(&input_cachix_filter))
+                .add_step(steps::nix::build(&input_flake_output))
+                .add_step(steps::nix::limit_store()),
+        )
+}