1use std::cell::RefCell;
2
3use gh_workflow::{Concurrency, Env, Expression, Step, WorkflowDispatchInput};
4
5use crate::tasks::workflows::{runners::Platform, steps::NamedJob};
6
7macro_rules! secret {
8 ($secret_name:ident) => {
9 pub const $secret_name: &str = concat!("${{ secrets.", stringify!($secret_name), " }}");
10 };
11}
12
13macro_rules! var {
14 ($secret_name:ident) => {
15 pub const $secret_name: &str = concat!("${{ vars.", stringify!($secret_name), " }}");
16 };
17}
18
19secret!(ANTHROPIC_API_KEY);
20secret!(OPENAI_API_KEY);
21secret!(GOOGLE_API_KEY);
22secret!(GOOGLE_CLOUD_PROJECT);
23secret!(APPLE_NOTARIZATION_ISSUER_ID);
24secret!(APPLE_NOTARIZATION_KEY);
25secret!(APPLE_NOTARIZATION_KEY_ID);
26secret!(AZURE_SIGNING_CLIENT_ID);
27secret!(AZURE_SIGNING_CLIENT_SECRET);
28secret!(AZURE_SIGNING_TENANT_ID);
29secret!(CACHIX_AUTH_TOKEN);
30secret!(DIGITALOCEAN_SPACES_ACCESS_KEY);
31secret!(DIGITALOCEAN_SPACES_SECRET_KEY);
32secret!(GITHUB_TOKEN);
33secret!(MACOS_CERTIFICATE);
34secret!(MACOS_CERTIFICATE_PASSWORD);
35secret!(SENTRY_AUTH_TOKEN);
36secret!(ZED_CLIENT_CHECKSUM_SEED);
37secret!(ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON);
38secret!(ZED_SENTRY_MINIDUMP_ENDPOINT);
39secret!(SLACK_APP_ZED_UNIT_EVALS_BOT_TOKEN);
40secret!(ZED_ZIPPY_APP_ID);
41secret!(ZED_ZIPPY_APP_PRIVATE_KEY);
42secret!(DISCORD_WEBHOOK_RELEASE_NOTES);
43secret!(WINGET_TOKEN);
44secret!(VERCEL_TOKEN);
45
46// todo(ci) make these secrets too...
47var!(AZURE_SIGNING_ACCOUNT_NAME);
48var!(AZURE_SIGNING_CERT_PROFILE_NAME);
49var!(AZURE_SIGNING_ENDPOINT);
50
51pub fn bundle_envs(platform: Platform) -> Env {
52 let env = Env::default()
53 .add("CARGO_INCREMENTAL", 0)
54 .add("ZED_CLIENT_CHECKSUM_SEED", ZED_CLIENT_CHECKSUM_SEED)
55 .add("ZED_MINIDUMP_ENDPOINT", ZED_SENTRY_MINIDUMP_ENDPOINT);
56
57 match platform {
58 Platform::Linux => env,
59 Platform::Mac => env
60 .add("MACOS_CERTIFICATE", MACOS_CERTIFICATE)
61 .add("MACOS_CERTIFICATE_PASSWORD", MACOS_CERTIFICATE_PASSWORD)
62 .add("APPLE_NOTARIZATION_KEY", APPLE_NOTARIZATION_KEY)
63 .add("APPLE_NOTARIZATION_KEY_ID", APPLE_NOTARIZATION_KEY_ID)
64 .add("APPLE_NOTARIZATION_ISSUER_ID", APPLE_NOTARIZATION_ISSUER_ID),
65 Platform::Windows => env
66 .add("AZURE_TENANT_ID", AZURE_SIGNING_TENANT_ID)
67 .add("AZURE_CLIENT_ID", AZURE_SIGNING_CLIENT_ID)
68 .add("AZURE_CLIENT_SECRET", AZURE_SIGNING_CLIENT_SECRET)
69 .add("ACCOUNT_NAME", AZURE_SIGNING_ACCOUNT_NAME)
70 .add("CERT_PROFILE_NAME", AZURE_SIGNING_CERT_PROFILE_NAME)
71 .add("ENDPOINT", AZURE_SIGNING_ENDPOINT)
72 .add("FILE_DIGEST", "SHA256")
73 .add("TIMESTAMP_DIGEST", "SHA256")
74 .add("TIMESTAMP_SERVER", "http://timestamp.acs.microsoft.com"),
75 }
76}
77
78pub(crate) fn one_workflow_per_non_main_branch() -> Concurrency {
79 Concurrency::default()
80 .group("${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}")
81 .cancel_in_progress(true)
82}
83
84// Represents a pattern to check for changed files and corresponding output variable
85pub(crate) struct PathCondition {
86 pub name: &'static str,
87 pub pattern: &'static str,
88 pub invert: bool,
89 pub set_by_step: RefCell<Option<String>>,
90}
91impl PathCondition {
92 pub fn new(name: &'static str, pattern: &'static str) -> Self {
93 Self {
94 name,
95 pattern,
96 invert: false,
97 set_by_step: Default::default(),
98 }
99 }
100 pub fn inverted(name: &'static str, pattern: &'static str) -> Self {
101 Self {
102 name,
103 pattern,
104 invert: true,
105 set_by_step: Default::default(),
106 }
107 }
108 pub fn guard(&self, job: NamedJob) -> NamedJob {
109 let set_by_step = self
110 .set_by_step
111 .borrow()
112 .clone()
113 .unwrap_or_else(|| panic!("condition {},is never set", self.name));
114 NamedJob {
115 name: job.name,
116 job: job
117 .job
118 .add_need(set_by_step.clone())
119 .cond(Expression::new(format!(
120 "needs.{}.outputs.{} == 'true'",
121 &set_by_step, self.name
122 ))),
123 }
124 }
125}
126
127pub(crate) struct StepOutput {
128 name: &'static str,
129 step_id: String,
130}
131
132impl StepOutput {
133 pub fn new<T>(step: &Step<T>, name: &'static str) -> Self {
134 Self {
135 name,
136 step_id: step
137 .value
138 .id
139 .clone()
140 .expect("Steps that produce outputs must have an ID"),
141 }
142 }
143}
144
145impl serde::Serialize for StepOutput {
146 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
147 where
148 S: serde::Serializer,
149 {
150 serializer.serialize_str(&self.to_string())
151 }
152}
153
154impl std::fmt::Display for StepOutput {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 write!(f, "${{{{ steps.{}.outputs.{} }}}}", self.step_id, self.name)
157 }
158}
159
160pub(crate) struct Input {
161 pub input_type: &'static str,
162 pub name: &'static str,
163 pub default: Option<String>,
164}
165
166impl Input {
167 pub fn string(name: &'static str, default: Option<String>) -> Self {
168 Self {
169 input_type: "string",
170 name,
171 default,
172 }
173 }
174
175 pub fn input(&self) -> WorkflowDispatchInput {
176 WorkflowDispatchInput {
177 description: self.name.to_owned(),
178 required: self.default.is_none(),
179 input_type: self.input_type.to_owned(),
180 default: self.default.clone(),
181 }
182 }
183}
184
185impl std::fmt::Display for Input {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 write!(f, "${{{{ inputs.{} }}}}", self.name)
188 }
189}
190
191impl serde::Serialize for Input {
192 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193 where
194 S: serde::Serializer,
195 {
196 serializer.serialize_str(&self.to_string())
197 }
198}
199
200pub mod assets {
201 // NOTE: these asset names also exist in the zed.dev codebase.
202 pub const MAC_AARCH64: &str = "Zed-aarch64.dmg";
203 pub const MAC_X86_64: &str = "Zed-x86_64.dmg";
204 pub const LINUX_AARCH64: &str = "zed-linux-aarch64.tar.gz";
205 pub const LINUX_X86_64: &str = "zed-linux-x86_64.tar.gz";
206 pub const WINDOWS_X86_64: &str = "Zed-x86_64.exe";
207 pub const WINDOWS_AARCH64: &str = "Zed-aarch64.exe";
208
209 pub const REMOTE_SERVER_MAC_AARCH64: &str = "zed-remote-server-macos-aarch64.gz";
210 pub const REMOTE_SERVER_MAC_X86_64: &str = "zed-remote-server-macos-x86_64.gz";
211 pub const REMOTE_SERVER_LINUX_AARCH64: &str = "zed-remote-server-linux-aarch64.gz";
212 pub const REMOTE_SERVER_LINUX_X86_64: &str = "zed-remote-server-linux-x86_64.gz";
213
214 pub fn all() -> Vec<&'static str> {
215 vec![
216 MAC_AARCH64,
217 MAC_X86_64,
218 LINUX_AARCH64,
219 LINUX_X86_64,
220 WINDOWS_X86_64,
221 WINDOWS_AARCH64,
222 REMOTE_SERVER_MAC_AARCH64,
223 REMOTE_SERVER_MAC_X86_64,
224 REMOTE_SERVER_LINUX_AARCH64,
225 REMOTE_SERVER_LINUX_X86_64,
226 ]
227 }
228}