Skip to content

Commit 8245ca5

Browse files
committed
We don't really want consumers consulting profile-able fields directly
Signed-off-by: itowlson <[email protected]>
1 parent 1fb5178 commit 8245ca5

File tree

9 files changed

+51
-29
lines changed

9 files changed

+51
-29
lines changed

crates/build/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub async fn build(
7777
build_info.deployment_targets(),
7878
cache_root.clone(),
7979
&app_dir,
80+
profile,
8081
)
8182
.await
8283
.context("unable to check if the application is compatible with deployment targets")?;
@@ -354,6 +355,7 @@ mod tests {
354355
&manifest.application.targets,
355356
None,
356357
manifest_file.parent().unwrap(),
358+
None,
357359
)
358360
.await
359361
.context("unable to check if the application is compatible with deployment targets")

crates/build/src/manifest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ fn build_configs_from_manifest(
113113
.iter()
114114
.map(|(id, c)| ComponentBuildInfo {
115115
id: id.to_string(),
116-
build: c.build_config(profile),
116+
build: c.build(profile),
117117
})
118118
.collect()
119119
}

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 {
36+
match &self.component.source(None) {
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 {
43+
match &self.component.source(None) {
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.is_some()
57+
self.component.build(None).is_some()
5858
}
5959
}
6060

crates/environments/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@ 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>,
4243
) -> anyhow::Result<TargetEnvironmentValidation> {
4344
if env_ids.is_empty() {
4445
return Ok(Default::default());
4546
}
4647

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

5152
/// Validates *all* application components against the list of (realised) target enviroments. Each component must conform
@@ -55,6 +56,7 @@ pub async fn validate_application_against_environment_ids(
5556
async fn validate_application_against_environments(
5657
application: &ApplicationToValidate,
5758
envs: &[TargetEnvironment],
59+
profile: Option<&str>,
5860
) -> anyhow::Result<TargetEnvironmentValidation> {
5961
for trigger_type in application.trigger_types() {
6062
if let Some(env) = envs.iter().find(|e| !e.supports_trigger_type(trigger_type)) {
@@ -65,7 +67,7 @@ async fn validate_application_against_environments(
6567
}
6668
}
6769

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

7072
let mut errs = vec![];
7173

crates/environments/src/loader.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl ApplicationToValidate {
6767
fn component_source<'a>(
6868
&'a self,
6969
trigger: &'a spin_manifest::schema::v2::Trigger,
70+
profile: Option<&str>,
7071
) -> anyhow::Result<ComponentSource<'a>> {
7172
let component_spec = trigger
7273
.component
@@ -75,7 +76,7 @@ impl ApplicationToValidate {
7576
let (id, source, dependencies, service_chaining) = match component_spec {
7677
spin_manifest::schema::v2::ComponentSpec::Inline(c) => (
7778
trigger.id.as_str(),
78-
&c.source,
79+
&c.source(profile),
7980
&c.dependencies,
8081
spin_loader::requires_service_chaining(c),
8182
),
@@ -89,7 +90,7 @@ impl ApplicationToValidate {
8990
};
9091
(
9192
id,
92-
&component.source,
93+
&component.source(profile),
9394
&component.dependencies,
9495
spin_loader::requires_service_chaining(component),
9596
)
@@ -116,11 +117,12 @@ impl ApplicationToValidate {
116117

117118
pub(crate) async fn components_by_trigger_type(
118119
&self,
120+
profile: Option<&str>,
119121
) -> anyhow::Result<Vec<(String, Vec<ComponentToValidate<'_>>)>> {
120122
use futures::FutureExt;
121123

122124
let components_by_trigger_type_futs = self.triggers().map(|(ty, ts)| {
123-
self.components_for_trigger(ts)
125+
self.components_for_trigger(ts, profile)
124126
.map(|css| css.map(|css| (ty.to_owned(), css)))
125127
});
126128
let components_by_trigger_type = try_join_all(components_by_trigger_type_futs)
@@ -132,16 +134,20 @@ impl ApplicationToValidate {
132134
async fn components_for_trigger<'a>(
133135
&'a self,
134136
triggers: &'a [spin_manifest::schema::v2::Trigger],
137+
profile: Option<&str>,
135138
) -> anyhow::Result<Vec<ComponentToValidate<'a>>> {
136-
let component_futures = triggers.iter().map(|t| self.load_and_resolve_trigger(t));
139+
let component_futures = triggers
140+
.iter()
141+
.map(|t| self.load_and_resolve_trigger(t, profile));
137142
try_join_all(component_futures).await
138143
}
139144

140145
async fn load_and_resolve_trigger<'a>(
141146
&'a self,
142147
trigger: &'a spin_manifest::schema::v2::Trigger,
148+
profile: Option<&str>,
143149
) -> anyhow::Result<ComponentToValidate<'a>> {
144-
let component = self.component_source(trigger)?;
150+
let component = self.component_source(trigger, profile)?;
145151

146152
let loader = ComponentSourceLoader::new(&self.wasm_loader);
147153

crates/loader/src/local.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,17 +166,22 @@ impl LocalLoader {
166166
let component_requires_service_chaining = requires_service_chaining(&component);
167167

168168
let source = self
169-
.load_component_source(id, component.source(self.profile.as_ref()).clone())
169+
.load_component_source(id, component.source(self.profile()).clone())
170170
.await
171-
.with_context(|| format!("Failed to load Wasm source {}", component.source))?;
171+
.with_context(|| {
172+
format!(
173+
"Failed to load Wasm source {}",
174+
component.source(self.profile())
175+
)
176+
})?;
172177

173178
let metadata = ValuesMapBuilder::new()
179+
.serializable("build", component.build(self.profile()))?
174180
.string("description", component.description)
175181
.string_array("allowed_outbound_hosts", allowed_outbound_hosts)
176182
.string_array("key_value_stores", component.key_value_stores)
177183
.string_array("databases", component.sqlite_databases)
178184
.string_array("ai_models", component.ai_models)
179-
.serializable("build", component.build)?
180185
.take();
181186

182187
let dependencies = self
@@ -548,6 +553,10 @@ impl LocalLoader {
548553
path: dest.into(),
549554
})
550555
}
556+
557+
fn profile(&self) -> Option<&str> {
558+
self.profile.as_deref()
559+
}
551560
}
552561

553562
fn explain_file_mount_source_error(e: anyhow::Error, src: &Path) -> anyhow::Error {

crates/manifest/src/schema/v2.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ pub struct Component {
298298
/// Example: `source = "bin/cart.wasm"`
299299
///
300300
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
301-
pub source: ComponentSource,
301+
pub(crate) source: ComponentSource,
302302
/// A human-readable description of the component.
303303
///
304304
/// Example: `description = "Shopping cart"`
@@ -397,7 +397,7 @@ pub struct Component {
397397
///
398398
/// Learn more: https://spinframework.dev/build
399399
#[serde(default, skip_serializing_if = "Option::is_none")]
400-
pub build: Option<ComponentBuildConfig>,
400+
pub(crate) build: Option<ComponentBuildConfig>,
401401
/// Settings for custom tools or plugins. Spin ignores this field.
402402
#[serde(default, skip_serializing_if = "Map::is_empty")]
403403
#[schemars(schema_with = "json_schema::map_of_toml_tables")]
@@ -414,9 +414,11 @@ pub struct Component {
414414
/// Learn more: https://spinframework.dev/writing-apps#using-component-dependencies
415415
#[serde(default, skip_serializing_if = "ComponentDependencies::is_empty")]
416416
pub dependencies: ComponentDependencies,
417-
/// TODO: profile docs
417+
/// Override values to use when building or running a named build profile.
418+
///
419+
/// Example: `profile.debug.build.command = "npm run build-debug"`
418420
#[serde(default, skip_serializing_if = "Map::is_empty")]
419-
pub profile: Map<String, ComponentProfileOverride>,
421+
pub(crate) profile: Map<String, ComponentProfileOverride>,
420422
}
421423

422424
/// Customisations for a Spin component in a non-default profile.
@@ -429,13 +431,13 @@ pub struct ComponentProfileOverride {
429431
///
430432
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
431433
#[serde(default, skip_serializing_if = "Option::is_none")]
432-
pub source: Option<ComponentSource>,
434+
source: Option<ComponentSource>,
433435

434436
/// The command or commands for building the component in non-default profiles.
435437
/// If a component has no special build instructions for a profile, the
436438
/// default build command is used.
437439
#[serde(default, skip_serializing_if = "Option::is_none")]
438-
pub build: Option<ComponentProfileBuildOverride>,
440+
build: Option<ComponentProfileBuildOverride>,
439441
}
440442

441443
/// Customisations for a Spin component build in a non-default profile.
@@ -448,7 +450,7 @@ pub struct ComponentProfileBuildOverride {
448450
/// Example: `build.command = "cargo build"`
449451
///
450452
/// Learn more: https://spinframework.dev/build#setting-up-for-spin-build
451-
pub command: super::common::Commands,
453+
command: super::common::Commands,
452454
}
453455

454456
impl Component {
@@ -470,7 +472,7 @@ impl Component {
470472
}
471473

472474
/// The build configuration for the component
473-
pub fn build_config(&self, profile: Option<impl AsRef<str>>) -> Option<ComponentBuildConfig> {
475+
pub fn build(&self, profile: Option<&str>) -> Option<ComponentBuildConfig> {
474476
let build_config = self.build.clone();
475477
let build_profile = self.profile(profile).and_then(|o| o.build.as_ref());
476478

@@ -491,8 +493,8 @@ impl Component {
491493
Some(build_config)
492494
}
493495

494-
/// TODO: docs! docs! docs!
495-
pub fn source(&self, profile: Option<impl AsRef<str>>) -> &ComponentSource {
496+
/// The source for the component Wasm binary (e.g. local file, registry reference, etc.).
497+
pub fn source(&self, profile: Option<&str>) -> &ComponentSource {
496498
let profile_source = self.profile(profile).and_then(|o| o.source.as_ref());
497499

498500
match profile_source {

src/commands/watch/filters.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl FilterFactory for BuildFilterFactory {
9090
manifest_file: &Path,
9191
manifest_dir: &Path,
9292
manifest: &v2::AppManifest,
93-
_profile: Option<&str>,
93+
profile: Option<&str>,
9494
) -> anyhow::Result<Arc<dyn Filterer>> {
9595
let mut filterers: Vec<Box<dyn Filterer>> =
9696
Vec::with_capacity(manifest.components.len() + 1);
@@ -101,7 +101,7 @@ impl FilterFactory for BuildFilterFactory {
101101
filterers.push(Box::new(manifest_filterer));
102102

103103
for (cid, c) in &manifest.components {
104-
if let Some(build_globs) = create_source_globs(cid.as_ref(), c) {
104+
if let Some(build_globs) = create_source_globs(cid.as_ref(), c, profile) {
105105
let build_filterer = globset_filter(manifest_dir, build_globs).await?;
106106
filterers.push(Box::new(build_filterer));
107107
}
@@ -113,8 +113,8 @@ impl FilterFactory for BuildFilterFactory {
113113
}
114114
}
115115

116-
fn create_source_globs(cid: &str, c: &v2::Component) -> Option<Vec<String>> {
117-
let build = c.build.as_ref()?;
116+
fn create_source_globs(cid: &str, c: &v2::Component, profile: Option<&str>) -> Option<Vec<String>> {
117+
let build = c.build(profile)?;
118118
if build.watch.is_empty() {
119119
eprintln!(
120120
"You haven't configured what to watch for the component: '{cid}'. Learn how to configure Spin watch at https://developer.fermyon.com/common/cli-reference#watch"

tests/integration.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,8 @@ route = "/..."
11591159
.components
11601160
.iter()
11611161
.map(|(id, component)| {
1162-
let spin_manifest::schema::v2::ComponentSource::Local(file) = &component.source
1162+
let spin_manifest::schema::v2::ComponentSource::Local(file) =
1163+
&component.source(None)
11631164
else {
11641165
panic!(
11651166
"{}.{}: source is not a file reference",

0 commit comments

Comments
 (0)