@@ -317,7 +317,7 @@ pub struct Component {
317317 ///
318318 /// `environment = { DB_URL = "mysql://spin:spin@localhost/dev" }`
319319 #[ serde( default , skip_serializing_if = "Map::is_empty" ) ]
320- pub environment : Map < String , String > ,
320+ pub ( crate ) environment : Map < String , String > ,
321321 /// The files the component is allowed to read. Each list entry is either:
322322 ///
323323 /// - a glob pattern (e.g. "assets/**/*.jpg"); or
@@ -413,7 +413,7 @@ pub struct Component {
413413 ///
414414 /// Learn more: https://spinframework.dev/writing-apps#using-component-dependencies
415415 #[ serde( default , skip_serializing_if = "ComponentDependencies::is_empty" ) ]
416- pub dependencies : ComponentDependencies ,
416+ pub ( crate ) dependencies : ComponentDependencies ,
417417 /// Override values to use when building or running a named build profile.
418418 ///
419419 /// Example: `profile.debug.build.command = "npm run build-debug"`
@@ -433,6 +433,22 @@ pub struct ComponentProfileOverride {
433433 #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
434434 source : Option < ComponentSource > ,
435435
436+ /// Environment variables for the Wasm module to be overridden in this profile.
437+ /// Environment variables specified in the default profile will still be set
438+ /// if not overridden here.
439+ ///
440+ /// `environment = { DB_URL = "mysql://spin:spin@localhost/dev" }`
441+ #[ serde( default , skip_serializing_if = "Map::is_empty" ) ]
442+ environment : Map < String , String > ,
443+
444+ /// Wasm Component Model imports to be overridden in this profile.
445+ /// Dependencies specified in the default profile will still be composed
446+ /// if not overridden here.
447+ ///
448+ /// Learn more: https://spinframework.dev/writing-apps#using-component-dependencies
449+ #[ serde( default , skip_serializing_if = "ComponentDependencies::is_empty" ) ]
450+ dependencies : ComponentDependencies ,
451+
436452 /// The command or commands for building the component in non-default profiles.
437453 /// If a component has no special build instructions for a profile, the
438454 /// default build command is used.
@@ -502,6 +518,36 @@ impl Component {
502518 None => & self . source ,
503519 }
504520 }
521+
522+ /// The component's environment variables
523+ pub fn environment ( & self , profile : Option < & str > ) -> Map < String , String > {
524+ let mut environment = self . environment . clone ( ) ;
525+
526+ let Some ( overrides) = self . profile ( profile) . map ( |o| o. environment . clone ( ) ) else {
527+ return environment;
528+ } ;
529+
530+ for ( name, value) in overrides {
531+ environment. insert ( name, value) ;
532+ }
533+
534+ environment
535+ }
536+
537+ /// The component's dependencies
538+ pub fn dependencies ( & self , profile : Option < & str > ) -> ComponentDependencies {
539+ let mut dependencies = self . dependencies . clone ( ) ;
540+
541+ let Some ( overrides) = self . profile ( profile) . map ( |o| o. dependencies . clone ( ) ) else {
542+ return dependencies;
543+ } ;
544+
545+ for ( itf, dep) in overrides. inner {
546+ dependencies. inner . insert ( itf, dep) ;
547+ }
548+
549+ dependencies
550+ }
505551}
506552
507553/// Component dependencies
@@ -1225,4 +1271,53 @@ mod tests {
12251271 . commands( ) [ 1 ]
12261272 ) ;
12271273 }
1274+
1275+ #[ test]
1276+ fn profiles_override_env_vars ( ) {
1277+ let manifest = AppManifest :: deserialize ( toml ! {
1278+ spin_manifest_version = 2
1279+ [ application]
1280+ name = "trigger-configs"
1281+ [ [ trigger. fake] ]
1282+ component = "profile-test"
1283+ [ component. profile-test]
1284+ source = "original"
1285+ environment = { DB_URL = "pg://production" }
1286+ [ component. profile-test. profile. fancy]
1287+ environment = { DB_URL = "pg://fancy" , FANCINESS = "1" }
1288+ } )
1289+ . expect ( "manifest should be valid" ) ;
1290+
1291+ let id = KebabId :: try_from ( "profile-test" . to_owned ( ) )
1292+ . expect ( "profile-test should have been kebab" ) ;
1293+ let component = manifest
1294+ . components
1295+ . get ( & id)
1296+ . expect ( "should have compopnent with id profile-test" ) ;
1297+
1298+ assert_eq ! ( 1 , component. environment( None ) . len( ) ) ;
1299+ assert_eq ! (
1300+ "pg://production" ,
1301+ component
1302+ . environment( None )
1303+ . get( "DB_URL" )
1304+ . expect( "DB_URL should have been set" )
1305+ ) ;
1306+
1307+ assert_eq ! ( 2 , component. environment( Some ( "fancy" ) ) . len( ) ) ;
1308+ assert_eq ! (
1309+ "pg://fancy" ,
1310+ component
1311+ . environment( Some ( "fancy" ) )
1312+ . get( "DB_URL" )
1313+ . expect( "DB_URL should have been set" )
1314+ ) ;
1315+ assert_eq ! (
1316+ "1" ,
1317+ component
1318+ . environment( Some ( "fancy" ) )
1319+ . get( "FANCINESS" )
1320+ . expect( "FANCINESS should have been set" )
1321+ ) ;
1322+ }
12281323}
0 commit comments