1use serde::{Deserialize, Serialize};
7#[cfg(feature = "openapi")]
8use utoipa::ToSchema;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum CargoBuildStrategy {
13 Native,
15 Zigbuild,
17 Xwin,
19}
20
21impl CargoBuildStrategy {
22 pub fn cargo_subcommand(&self) -> &'static str {
24 match self {
25 Self::Native => "build",
26 Self::Zigbuild => "zigbuild",
27 Self::Xwin => "xwin",
28 }
29 }
30
31 pub fn cargo_args(&self) -> Vec<&'static str> {
33 match self {
34 Self::Native => vec!["build"],
35 Self::Zigbuild => vec!["zigbuild"],
36 Self::Xwin => vec!["xwin", "build"],
37 }
38 }
39
40 pub fn display_name(&self) -> &'static str {
42 match self {
43 Self::Native => "cargo build",
44 Self::Zigbuild => "cargo zigbuild",
45 Self::Xwin => "cargo xwin build",
46 }
47 }
48
49 pub fn install_package(&self) -> Option<&'static str> {
51 match self {
52 Self::Native => None,
53 Self::Zigbuild => Some("cargo-zigbuild"),
54 Self::Xwin => Some("cargo-xwin"),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
61#[cfg_attr(feature = "openapi", derive(ToSchema))]
62#[serde(rename_all = "kebab-case")]
63pub enum SourceBinaryType {
64 Cli,
66 Terraform,
68 Agent,
70}
71
72impl SourceBinaryType {
73 pub fn binary_name(&self) -> &'static str {
75 match self {
76 SourceBinaryType::Cli => "alien-deploy",
77 SourceBinaryType::Terraform => "alien-terraform",
78 SourceBinaryType::Agent => "alien-agent",
79 }
80 }
81}
82
83impl std::fmt::Display for SourceBinaryType {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 match self {
86 SourceBinaryType::Cli => write!(f, "cli"),
87 SourceBinaryType::Terraform => write!(f, "terraform"),
88 SourceBinaryType::Agent => write!(f, "agent"),
89 }
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
98#[cfg_attr(feature = "openapi", derive(ToSchema))]
99#[serde(rename_all = "kebab-case")]
100pub enum BinaryTarget {
101 WindowsX64,
103 LinuxX64,
105 LinuxArm64,
107 DarwinArm64,
109}
110
111impl BinaryTarget {
112 pub const ALL: &'static [BinaryTarget] = &[
114 BinaryTarget::WindowsX64,
115 BinaryTarget::LinuxX64,
116 BinaryTarget::LinuxArm64,
117 BinaryTarget::DarwinArm64,
118 ];
119
120 pub const LINUX: &'static [BinaryTarget] = &[BinaryTarget::LinuxX64, BinaryTarget::LinuxArm64];
122
123 pub fn rust_target_triple(&self) -> &'static str {
125 match self {
126 Self::WindowsX64 => "x86_64-pc-windows-msvc",
127 Self::LinuxX64 => "x86_64-unknown-linux-musl",
128 Self::LinuxArm64 => "aarch64-unknown-linux-musl",
129 Self::DarwinArm64 => "aarch64-apple-darwin",
130 }
131 }
132
133 pub fn cargo_build_strategy(&self) -> CargoBuildStrategy {
140 match self {
141 Self::LinuxX64 | Self::LinuxArm64 => CargoBuildStrategy::Zigbuild,
142 Self::WindowsX64 => {
143 if cfg!(target_os = "windows") {
144 CargoBuildStrategy::Native
145 } else {
146 CargoBuildStrategy::Xwin
147 }
148 }
149 Self::DarwinArm64 => CargoBuildStrategy::Native,
150 }
151 }
152
153 pub fn binary_extension(&self) -> &'static str {
155 match self {
156 Self::WindowsX64 => ".exe",
157 _ => "",
158 }
159 }
160
161 pub fn runtime_platform_id(&self) -> &'static str {
163 match self {
164 Self::WindowsX64 => "windows-x64",
165 Self::LinuxX64 => "linux-x64",
166 Self::LinuxArm64 => "linux-aarch64",
167 Self::DarwinArm64 => "darwin-aarch64",
168 }
169 }
170
171 pub fn oci_os(&self) -> &'static str {
173 match self {
174 Self::WindowsX64 => "windows",
175 Self::LinuxX64 | Self::LinuxArm64 => "linux",
176 Self::DarwinArm64 => "darwin",
177 }
178 }
179
180 pub fn oci_arch(&self) -> &'static str {
182 match self {
183 Self::WindowsX64 | Self::LinuxX64 => "amd64",
184 Self::LinuxArm64 | Self::DarwinArm64 => "arm64",
185 }
186 }
187
188 pub fn bun_target(&self) -> &'static str {
190 match self {
191 Self::WindowsX64 => "bun-windows-x64",
192 Self::LinuxX64 => "bun-linux-x64",
193 Self::LinuxArm64 => "bun-linux-arm64",
194 Self::DarwinArm64 => "bun-darwin-arm64",
195 }
196 }
197
198 pub fn terraform_key(&self) -> &'static str {
200 match self {
201 BinaryTarget::LinuxX64 => "linux_amd64",
202 BinaryTarget::LinuxArm64 => "linux_arm64",
203 BinaryTarget::DarwinArm64 => "darwin_arm64",
204 BinaryTarget::WindowsX64 => "windows_amd64",
205 }
206 }
207
208 pub fn terraform_os(&self) -> &'static str {
210 match self {
211 BinaryTarget::LinuxX64 | BinaryTarget::LinuxArm64 => "linux",
212 BinaryTarget::DarwinArm64 => "darwin",
213 BinaryTarget::WindowsX64 => "windows",
214 }
215 }
216
217 pub fn terraform_arch(&self) -> &'static str {
219 match self {
220 BinaryTarget::LinuxX64 | BinaryTarget::WindowsX64 => "amd64",
221 BinaryTarget::LinuxArm64 | BinaryTarget::DarwinArm64 => "arm64",
222 }
223 }
224
225 pub fn is_darwin(&self) -> bool {
227 matches!(self, Self::DarwinArm64)
228 }
229
230 pub fn is_windows(&self) -> bool {
232 matches!(self, Self::WindowsX64)
233 }
234
235 pub fn linux_container_target() -> Self {
239 match Self::current_os() {
240 Self::DarwinArm64 | Self::LinuxArm64 => Self::LinuxArm64,
241 Self::LinuxX64 | Self::WindowsX64 => Self::LinuxX64,
242 }
243 }
244
245 pub fn all() -> Vec<Self> {
247 Self::ALL.to_vec()
248 }
249
250 pub fn defaults_for_platform(platform: crate::Platform) -> Vec<Self> {
252 match platform {
253 crate::Platform::Aws => vec![Self::LinuxArm64],
254 crate::Platform::Gcp => vec![Self::LinuxX64],
255 crate::Platform::Azure => vec![Self::LinuxX64],
256 crate::Platform::Kubernetes => Self::LINUX.to_vec(),
257 crate::Platform::Local => vec![Self::current_os()],
258 crate::Platform::Test => vec![Self::LinuxX64],
259 }
260 }
261
262 pub fn current_os() -> Self {
264 #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
265 return Self::WindowsX64;
266
267 #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
268 return Self::LinuxX64;
269
270 #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
271 return Self::LinuxArm64;
272
273 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
274 return Self::DarwinArm64;
275
276 #[cfg(not(any(
277 all(target_os = "windows", target_arch = "x86_64"),
278 all(target_os = "linux", target_arch = "x86_64"),
279 all(target_os = "linux", target_arch = "aarch64"),
280 all(target_os = "macos", target_arch = "aarch64")
281 )))]
282 {
283 Self::LinuxX64
284 }
285 }
286}
287
288impl std::fmt::Display for BinaryTarget {
289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290 match self {
291 BinaryTarget::WindowsX64 => write!(f, "windows-x64"),
292 BinaryTarget::LinuxX64 => write!(f, "linux-x64"),
293 BinaryTarget::LinuxArm64 => write!(f, "linux-arm64"),
294 BinaryTarget::DarwinArm64 => write!(f, "darwin-arm64"),
295 }
296 }
297}
298
299impl std::str::FromStr for BinaryTarget {
300 type Err = String;
301
302 fn from_str(s: &str) -> Result<Self, Self::Err> {
303 match s {
304 "windows-x64" => Ok(BinaryTarget::WindowsX64),
305 "linux-x64" => Ok(BinaryTarget::LinuxX64),
306 "linux-arm64" => Ok(BinaryTarget::LinuxArm64),
307 "darwin-arm64" => Ok(BinaryTarget::DarwinArm64),
308 _ => Err(format!("Unknown binary target: {}", s)),
309 }
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::BinaryTarget;
316 use crate::Platform;
317
318 #[test]
319 fn local_platform_defaults_to_current_host_target() {
320 assert_eq!(
321 BinaryTarget::defaults_for_platform(Platform::Local),
322 vec![BinaryTarget::current_os()]
323 );
324 }
325
326 #[test]
327 fn cloud_platform_defaults_remain_stable() {
328 assert_eq!(
329 BinaryTarget::defaults_for_platform(Platform::Aws),
330 vec![BinaryTarget::LinuxArm64]
331 );
332 assert_eq!(
333 BinaryTarget::defaults_for_platform(Platform::Gcp),
334 vec![BinaryTarget::LinuxX64]
335 );
336 assert_eq!(
337 BinaryTarget::defaults_for_platform(Platform::Azure),
338 vec![BinaryTarget::LinuxX64]
339 );
340 assert_eq!(
341 BinaryTarget::defaults_for_platform(Platform::Kubernetes),
342 vec![BinaryTarget::LinuxX64, BinaryTarget::LinuxArm64]
343 );
344 }
345}