1use serde::Deserialize;
2use std::path::PathBuf;
3use std::str::FromStr;
4use structopt::StructOpt;
5
6pub mod compiler;
7pub mod config;
8pub mod display;
9pub mod engine;
10pub mod env;
11pub mod execution_plan;
12pub mod executor;
13pub mod git;
14pub mod gitlab;
15pub mod history;
16pub mod logging;
17pub mod model;
18pub mod naming;
19pub mod pipeline;
20pub mod runner;
21pub mod runtime;
22pub mod secrets;
23pub mod terminal;
24pub mod ui;
25
26#[derive(StructOpt)]
27#[structopt(name = "opal", version = env!("CARGO_PKG_VERSION"))]
28pub struct Cli {
29 #[structopt(
30 short,
31 long,
32 default_value = "info",
33 possible_values = &["trace", "debug", "info", "warn", "error"]
34 )]
35 pub log_level: tracing::Level,
36
37 #[structopt(subcommand)]
38 pub commands: Commands,
39}
40
41#[derive(StructOpt)]
42pub enum Commands {
43 Run(RunArgs),
44 Plan(PlanArgs),
45 View(ViewArgs),
46}
47
48#[derive(StructOpt)]
49pub struct RunArgs {
50 #[structopt(short, long)]
52 pub pipeline: Option<PathBuf>,
53
54 #[structopt(short, long)]
55 pub workdir: Option<PathBuf>,
57
58 #[structopt(short, long)]
59 pub base_image: Option<String>,
61
62 #[structopt(
63 short = "E",
64 long = "env",
65 value_name = "GLOB",
66 help = "Include host env vars matching this glob (e.g. APP_*). Repeat to add more."
67 )]
68 pub env_includes: Vec<String>,
69
70 #[structopt(long = "max-parallel-jobs", default_value = "5")]
71 pub max_parallel_jobs: usize,
73
74 #[structopt(long = "trace-scripts")]
75 pub trace_scripts: bool,
77
78 #[structopt(
79 long = "engine",
80 default_value = "auto",
81 possible_values = EngineChoice::VARIANTS,
82 help = "Container runtime to use (auto, container, docker, podman, nerdctl, orbstack). nerdctl is Linux-specific in Opal."
83 )]
84 pub engine: EngineChoice,
85
86 #[structopt(long = "no-tui")]
87 pub no_tui: bool,
89
90 #[structopt(long = "gitlab-base-url", env = "OPAL_GITLAB_BASE_URL")]
91 pub gitlab_base_url: Option<String>,
93
94 #[structopt(long = "gitlab-token", env = "OPAL_GITLAB_TOKEN")]
95 pub gitlab_token: Option<String>,
97
98 #[structopt(long = "job", value_name = "NAME")]
99 pub jobs: Vec<String>,
101}
102
103#[derive(StructOpt)]
104pub struct ViewArgs {
105 #[structopt(short, long)]
106 pub workdir: Option<PathBuf>,
108}
109
110#[derive(StructOpt)]
111pub struct PlanArgs {
112 #[structopt(short, long)]
114 pub pipeline: Option<PathBuf>,
115
116 #[structopt(short, long)]
117 pub workdir: Option<PathBuf>,
119
120 #[structopt(long = "gitlab-base-url", env = "OPAL_GITLAB_BASE_URL")]
121 pub gitlab_base_url: Option<String>,
123
124 #[structopt(long = "gitlab-token", env = "OPAL_GITLAB_TOKEN")]
125 pub gitlab_token: Option<String>,
127
128 #[structopt(long = "job", value_name = "NAME")]
129 pub jobs: Vec<String>,
131
132 #[structopt(long = "no-pager")]
133 pub no_pager: bool,
135
136 #[structopt(long = "json")]
137 pub json: bool,
139}
140
141#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
142#[serde(rename_all = "lowercase")]
143pub enum EngineChoice {
144 Auto,
145 Container,
146 Docker,
147 Podman,
148 Nerdctl,
149 Orbstack,
150}
151
152impl EngineChoice {
153 pub const VARIANTS: &'static [&'static str] = &[
154 "auto",
155 "container",
156 "docker",
157 "podman",
158 "nerdctl",
159 "orbstack",
160 ];
161}
162
163impl FromStr for EngineChoice {
164 type Err = String;
165
166 fn from_str(s: &str) -> Result<Self, Self::Err> {
167 match s.to_ascii_lowercase().as_str() {
168 "auto" => Ok(Self::Auto),
169 "container" => Ok(Self::Container),
170 "docker" => Ok(Self::Docker),
171 "podman" => Ok(Self::Podman),
172 "nerdctl" => Ok(Self::Nerdctl),
173 "orbstack" => Ok(Self::Orbstack),
174 other => Err(format!("unknown engine '{other}'")),
175 }
176 }
177}
178
179#[derive(Clone, Copy, Debug)]
180pub enum EngineKind {
181 ContainerCli,
182 Docker,
183 Podman,
184 Nerdctl,
185 Orbstack,
186}
187
188#[derive(Debug, Clone)]
189pub struct ExecutorConfig {
190 pub image: Option<String>,
191 pub workdir: PathBuf,
192 pub pipeline: PathBuf,
193 pub env_includes: Vec<String>,
194 pub selected_jobs: Vec<String>,
195 pub max_parallel_jobs: usize,
196 pub enable_tui: bool,
197 pub engine: EngineKind,
198 pub gitlab: Option<GitLabRemoteConfig>,
199 pub settings: config::OpalConfig,
200 pub trace_scripts: bool,
201}
202
203#[derive(Clone, Debug)]
204pub struct GitLabRemoteConfig {
205 pub base_url: String,
206 pub token: String,
207}