Skip to content

Commit fd6a226

Browse files
committed
Plan C
Signed-off-by: itowlson <[email protected]>
1 parent ea595fc commit fd6a226

File tree

15 files changed

+179
-293
lines changed

15 files changed

+179
-293
lines changed

crates/build/src/lib.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ pub async fn build(
7777
build_info.deployment_targets(),
7878
cache_root.clone(),
7979
&app_dir,
80-
profile,
8180
)
8281
.await
8382
.context("unable to check if the application is compatible with deployment targets")?;
@@ -166,7 +165,7 @@ fn build_component(build_info: ComponentBuildInfo, app_dir: &Path) -> Result<()>
166165
);
167166
}
168167

169-
for (index, command) in b.commands().iter().enumerate() {
168+
for (index, command) in b.commands().enumerate() {
170169
if command_count > 1 {
171170
terminal::step!(
172171
"Running build step",
@@ -268,13 +267,7 @@ pub fn warn_if_not_latest_build(manifest_path: &Path, profile: Option<&str>) {
268267

269268
let latest_build = read_last_build_profile(app_dir);
270269

271-
let is_match = match (profile, latest_build) {
272-
(None, None) => true,
273-
(Some(_), None) | (None, Some(_)) => false,
274-
(Some(p), Some(latest)) => p == latest,
275-
};
276-
277-
if !is_match {
270+
if profile != latest_build.as_deref() {
278271
let profile_opt = match profile {
279272
Some(p) => format!(" --profile {p}"),
280273
None => "".to_string(),
@@ -341,7 +334,8 @@ mod tests {
341334
#[tokio::test]
342335
async fn has_meaningful_error_if_target_env_does_not_match() {
343336
let manifest_file = test_data_root().join("bad_target_env.toml");
344-
let manifest = spin_manifest::manifest_from_file(&manifest_file).unwrap();
337+
let mut manifest = spin_manifest::manifest_from_file(&manifest_file).unwrap();
338+
spin_manifest::normalize::normalize_manifest(&mut manifest, None);
345339
let application = spin_environments::ApplicationToValidate::new(
346340
manifest.clone(),
347341
manifest_file.parent().unwrap(),
@@ -355,7 +349,6 @@ mod tests {
355349
&manifest.application.targets,
356350
None,
357351
manifest_file.parent().unwrap(),
358-
None,
359352
)
360353
.await
361354
.context("unable to check if the application is compatible with deployment targets")

crates/build/src/manifest.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ pub async fn component_build_configs(
7575
Ok(mut manifest) => {
7676
manifest.ensure_profile(profile)?;
7777

78-
spin_manifest::normalize::normalize_manifest(&mut manifest);
79-
let components = build_configs_from_manifest(&manifest, profile);
78+
spin_manifest::normalize::normalize_manifest(&mut manifest, profile);
79+
let components = build_configs_from_manifest(&manifest);
8080
let deployment_targets = deployment_targets_from_manifest(&manifest);
8181
Ok(ManifestBuildInfo::Loadable {
8282
components,
@@ -106,14 +106,13 @@ pub async fn component_build_configs(
106106

107107
fn build_configs_from_manifest(
108108
manifest: &spin_manifest::schema::v2::AppManifest,
109-
profile: Option<&str>,
110109
) -> Vec<ComponentBuildInfo> {
111110
manifest
112111
.components
113112
.iter()
114113
.map(|(id, c)| ComponentBuildInfo {
115114
id: id.to_string(),
116-
build: c.build(profile),
115+
build: c.build.clone(),
117116
})
118117
.collect()
119118
}

crates/doctor/src/rustlang/target.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ impl Diagnostic for TargetDiagnostic {
1717
let manifest_str = patient.manifest_doc.to_string();
1818
let manifest = spin_manifest::manifest_from_str(&manifest_str)?;
1919
let uses_rust = manifest.components.values().any(|c| {
20-
c.build_commands(None)
21-
.iter()
22-
.any(|c| c.starts_with("cargo"))
20+
c.build
21+
.as_ref()
22+
.map(|b| b.commands().any(|c| c.starts_with("cargo")))
23+
.unwrap_or_default()
2324
});
2425

2526
if uses_rust {

crates/doctor/src/wasm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ impl PatientWasm {
3333
}
3434

3535
pub fn source_path(&self) -> Option<&Path> {
36-
match &self.component.source(None) {
36+
match &self.component.source {
3737
v2::ComponentSource::Local(path) => Some(Path::new(path)),
3838
_ => None,
3939
}
4040
}
4141

4242
pub fn abs_source_path(&self) -> Option<PathBuf> {
43-
match &self.component.source(None) {
43+
match &self.component.source {
4444
v2::ComponentSource::Local(path) => {
4545
// TODO: We probably need a doctor check to see if the path can be expanded!
4646
// For now, fall back to the literal path.
@@ -54,7 +54,7 @@ impl PatientWasm {
5454
}
5555

5656
pub fn has_build(&self) -> bool {
57-
self.component.build(None).is_some()
57+
self.component.build.is_some()
5858
}
5959
}
6060

crates/environments/src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,13 @@ pub async fn validate_application_against_environment_ids(
3939
env_ids: &[TargetEnvironmentRef],
4040
cache_root: Option<std::path::PathBuf>,
4141
app_dir: &std::path::Path,
42-
profile: Option<&str>,
4342
) -> anyhow::Result<TargetEnvironmentValidation> {
4443
if env_ids.is_empty() {
4544
return Ok(Default::default());
4645
}
4746

4847
let envs = TargetEnvironment::load_all(env_ids, cache_root, app_dir).await?;
49-
validate_application_against_environments(application, &envs, profile).await
48+
validate_application_against_environments(application, &envs).await
5049
}
5150

5251
/// Validates *all* application components against the list of (realised) target enviroments. Each component must conform
@@ -56,7 +55,6 @@ pub async fn validate_application_against_environment_ids(
5655
async fn validate_application_against_environments(
5756
application: &ApplicationToValidate,
5857
envs: &[TargetEnvironment],
59-
profile: Option<&str>,
6058
) -> anyhow::Result<TargetEnvironmentValidation> {
6159
for trigger_type in application.trigger_types() {
6260
if let Some(env) = envs.iter().find(|e| !e.supports_trigger_type(trigger_type)) {
@@ -67,7 +65,7 @@ async fn validate_application_against_environments(
6765
}
6866
}
6967

70-
let components_by_trigger_type = application.components_by_trigger_type(profile).await?;
68+
let components_by_trigger_type = application.components_by_trigger_type().await?;
7169

7270
let mut errs = vec![];
7371

crates/environments/src/loader.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ impl ApplicationToValidate {
6767
fn component_source<'a>(
6868
&'a self,
6969
trigger: &'a spin_manifest::schema::v2::Trigger,
70-
profile: Option<&str>,
7170
) -> anyhow::Result<ComponentSource<'a>> {
7271
let component_spec = trigger
7372
.component
@@ -76,8 +75,8 @@ impl ApplicationToValidate {
7675
let (id, source, dependencies, service_chaining) = match component_spec {
7776
spin_manifest::schema::v2::ComponentSpec::Inline(c) => (
7877
trigger.id.as_str(),
79-
&c.source(profile),
80-
&c.dependencies(profile),
78+
&c.source,
79+
&c.dependencies,
8180
spin_loader::requires_service_chaining(c),
8281
),
8382
spin_manifest::schema::v2::ComponentSpec::Reference(r) => {
@@ -90,8 +89,8 @@ impl ApplicationToValidate {
9089
};
9190
(
9291
id,
93-
&component.source(profile),
94-
&component.dependencies(profile),
92+
&component.source,
93+
&component.dependencies,
9594
spin_loader::requires_service_chaining(component),
9695
)
9796
}
@@ -117,12 +116,11 @@ impl ApplicationToValidate {
117116

118117
pub(crate) async fn components_by_trigger_type(
119118
&self,
120-
profile: Option<&str>,
121119
) -> anyhow::Result<Vec<(String, Vec<ComponentToValidate<'_>>)>> {
122120
use futures::FutureExt;
123121

124122
let components_by_trigger_type_futs = self.triggers().map(|(ty, ts)| {
125-
self.components_for_trigger(ts, profile)
123+
self.components_for_trigger(ts)
126124
.map(|css| css.map(|css| (ty.to_owned(), css)))
127125
});
128126
let components_by_trigger_type = try_join_all(components_by_trigger_type_futs)
@@ -134,20 +132,16 @@ impl ApplicationToValidate {
134132
async fn components_for_trigger<'a>(
135133
&'a self,
136134
triggers: &'a [spin_manifest::schema::v2::Trigger],
137-
profile: Option<&str>,
138135
) -> anyhow::Result<Vec<ComponentToValidate<'a>>> {
139-
let component_futures = triggers
140-
.iter()
141-
.map(|t| self.load_and_resolve_trigger(t, profile));
136+
let component_futures = triggers.iter().map(|t| self.load_and_resolve_trigger(t));
142137
try_join_all(component_futures).await
143138
}
144139

145140
async fn load_and_resolve_trigger<'a>(
146141
&'a self,
147142
trigger: &'a spin_manifest::schema::v2::Trigger,
148-
profile: Option<&str>,
149143
) -> anyhow::Result<ComponentToValidate<'a>> {
150-
let component = self.component_source(trigger, profile)?;
144+
let component = self.component_source(trigger)?;
151145

152146
let loader = ComponentSourceLoader::new(&self.wasm_loader);
153147

crates/loader/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub async fn from_wasm_file(wasm_path: impl AsRef<Path>) -> Result<LockedApp> {
4949
let app_root = std::env::current_dir()?;
5050
let manifest = single_file_manifest(wasm_path)?;
5151
let loader = LocalLoader::new(&app_root, FilesMountStrategy::Direct, None, None).await?;
52-
loader.load_manifest(manifest).await
52+
loader.load_manifest(manifest, None).await
5353
}
5454

5555
/// The strategy to use for mounting WASI files into a guest.

crates/loader/src/local.rs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl LocalLoader {
6262
)
6363
})?;
6464
let mut locked = self
65-
.load_manifest(manifest)
65+
.load_manifest(manifest, self.profile())
6666
.await
6767
.with_context(|| format!("Failed to load Spin app from {}", quoted_path(path)))?;
6868

@@ -82,8 +82,12 @@ impl LocalLoader {
8282
}
8383

8484
// Load the given manifest into a LockedApp, ready for execution.
85-
pub(crate) async fn load_manifest(&self, mut manifest: AppManifest) -> Result<LockedApp> {
86-
spin_manifest::normalize::normalize_manifest(&mut manifest);
85+
pub(crate) async fn load_manifest(
86+
&self,
87+
mut manifest: AppManifest,
88+
profile: Option<&str>,
89+
) -> Result<LockedApp> {
90+
spin_manifest::normalize::normalize_manifest(&mut manifest, profile);
8791

8892
manifest.validate_dependencies()?;
8993

@@ -165,34 +169,29 @@ impl LocalLoader {
165169

166170
let component_requires_service_chaining = requires_service_chaining(&component);
167171

168-
let source = self
169-
.load_component_source(id, component.source(self.profile()).clone())
170-
.await
171-
.with_context(|| {
172-
format!(
173-
"Failed to load Wasm source {}",
174-
component.source(self.profile())
175-
)
176-
})?;
177-
178172
let metadata = ValuesMapBuilder::new()
179-
.string("description", component.description.clone())
173+
.string("description", component.description)
180174
.string_array("allowed_outbound_hosts", allowed_outbound_hosts)
181-
.string_array("key_value_stores", component.key_value_stores.clone())
182-
.string_array("databases", component.sqlite_databases.clone())
183-
.string_array("ai_models", component.ai_models.clone())
184-
.serializable("build", component.build(self.profile()))?
175+
.string_array("key_value_stores", component.key_value_stores)
176+
.string_array("databases", component.sqlite_databases)
177+
.string_array("ai_models", component.ai_models)
178+
.serializable("build", component.build)?
185179
.take();
186180

181+
let source = self
182+
.load_component_source(id, component.source.clone())
183+
.await
184+
.with_context(|| format!("Failed to load Wasm source {}", component.source))?;
185+
187186
let dependencies = self
188187
.load_component_dependencies(
189188
id,
190189
component.dependencies_inherit_configuration,
191-
&component.dependencies(self.profile()),
190+
&component.dependencies,
192191
)
193192
.await?;
194193

195-
let env = component.environment(self.profile()).into_iter().collect();
194+
let env = component.environment.into_iter().collect();
196195

197196
let files = if component.files.is_empty() {
198197
vec![]

crates/manifest/src/normalize.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ use crate::schema::v2::{AppManifest, ComponentSpec, KebabId};
88
/// - Inline components in trigger configs are moved into top-level
99
/// components and replaced with a reference.
1010
/// - Any triggers without an ID are assigned a generated ID.
11-
pub fn normalize_manifest(manifest: &mut AppManifest) {
11+
pub fn normalize_manifest(manifest: &mut AppManifest, profile: Option<&str>) {
1212
normalize_trigger_ids(manifest);
1313
normalize_inline_components(manifest);
14+
apply_profile_overrides(manifest, profile);
1415
}
1516

1617
fn normalize_inline_components(manifest: &mut AppManifest) {
@@ -103,3 +104,45 @@ fn normalize_trigger_ids(manifest: &mut AppManifest) {
103104
}
104105
}
105106
}
107+
108+
fn apply_profile_overrides(manifest: &mut AppManifest, profile: Option<&str>) {
109+
let Some(profile) = profile else {
110+
return;
111+
};
112+
113+
for (_, component) in &mut manifest.components {
114+
let Some(overrides) = component.profile.get(profile) else {
115+
continue;
116+
};
117+
118+
if let Some(profile_build) = overrides.build.as_ref() {
119+
match component.build.as_mut() {
120+
None => {
121+
component.build = Some(crate::schema::v2::ComponentBuildConfig {
122+
command: profile_build.command.clone(),
123+
workdir: None,
124+
watch: vec![],
125+
})
126+
}
127+
Some(build) => {
128+
build.command = profile_build.command.clone();
129+
}
130+
}
131+
}
132+
133+
if let Some(source) = overrides.source.as_ref() {
134+
component.source = source.clone();
135+
}
136+
137+
for (name, value) in &overrides.environment {
138+
component.environment.insert(name.clone(), value.clone());
139+
}
140+
141+
for (reference, value) in &overrides.dependencies.inner {
142+
component
143+
.dependencies
144+
.inner
145+
.insert(reference.clone(), value.clone());
146+
}
147+
}
148+
}

crates/manifest/src/schema/common.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,12 @@ pub struct ComponentBuildConfig {
190190

191191
impl ComponentBuildConfig {
192192
/// The commands to execute for the build
193-
pub fn commands(&self) -> Vec<&String> {
194-
self.command.as_vec()
193+
pub fn commands(&self) -> impl ExactSizeIterator<Item = &String> {
194+
let as_vec = match &self.command {
195+
Commands::Single(cmd) => vec![cmd],
196+
Commands::Multiple(cmds) => cmds.iter().collect(),
197+
};
198+
as_vec.into_iter()
195199
}
196200
}
197201

@@ -212,15 +216,6 @@ pub enum Commands {
212216
Multiple(Vec<String>),
213217
}
214218

215-
impl Commands {
216-
pub(crate) fn as_vec(&self) -> Vec<&String> {
217-
match self {
218-
Self::Single(cmd) => vec![cmd],
219-
Self::Multiple(cmds) => cmds.iter().collect(),
220-
}
221-
}
222-
}
223-
224219
fn is_false(v: &bool) -> bool {
225220
!*v
226221
}

0 commit comments

Comments
 (0)