Skip to content

Commit cd80d1a

Browse files
authored
Merge pull request #3512 from itowlson/add-respect-target-env-templates
`spin add` should check existing `targets` for templates
2 parents eb69192 + f9cdce7 commit cd80d1a

2 files changed

Lines changed: 79 additions & 13 deletions

File tree

crates/manifest/src/schema/v2.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,16 @@ pub enum TargetEnvironmentRef {
754754
},
755755
}
756756

757+
impl std::fmt::Display for TargetEnvironmentRef {
758+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
759+
match self {
760+
Self::Catalogue(e) => e.fmt(f),
761+
Self::Http { url } => url.fmt(f),
762+
Self::File { path } => path.display().fmt(f),
763+
}
764+
}
765+
}
766+
757767
mod kebab_or_snake_case {
758768
use serde::{Deserialize, Serialize};
759769
pub use spin_serde::{KebabId, SnakeId};

src/commands/new.rs

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl TemplateNewCommandCore {
151151
variant: TemplateVariantInfo,
152152
) -> Result<()> {
153153
let (template_manager, suggested_plugins) =
154-
env_templates_and_plugins(target_environment).await?;
154+
env_templates_and_plugins(target_environment, &variant).await?;
155155

156156
let (name, template_id) = self.resolve_name_template_syntax(&template_manager, &variant)?;
157157

@@ -285,11 +285,25 @@ impl TemplateNewCommandCore {
285285

286286
async fn env_templates_and_plugins(
287287
target_environment: Option<&String>,
288+
variant: &TemplateVariantInfo,
288289
) -> anyhow::Result<(TemplateManager, Vec<String>)> {
289-
Ok(match target_environment {
290-
Some(env) => {
291-
// - resolve the TE
292-
let env_ref = parse_env(env);
290+
let target_env_ref = match variant {
291+
TemplateVariantInfo::NewApplication => target_environment.map(|te| parse_env(te)),
292+
TemplateVariantInfo::AddComponent { manifest_path } => {
293+
match infer_target_env_from_file(manifest_path) {
294+
Ok(t) => t,
295+
Err(_) => {
296+
terminal::warn!(
297+
"Couldn't determine target environment; using your installed templates.\n"
298+
);
299+
None
300+
}
301+
}
302+
}
303+
};
304+
305+
Ok(match target_env_ref {
306+
Some(env_ref) => {
293307
let loaded_env =
294308
spin_environments::load_environment_def(&env_ref, &std::env::current_dir()?)
295309
.await?;
@@ -314,11 +328,28 @@ async fn env_templates_and_plugins(
314328
.await?;
315329
}
316330
if is_empty(&template_manager).await {
317-
anyhow::bail!(
318-
"The {env} environment doesn't list any associated templates. Run `spin new` without `-E` to use generic templates."
319-
);
331+
match variant {
332+
TemplateVariantInfo::NewApplication => {
333+
anyhow::bail!(
334+
"The {env_ref} environment doesn't list any associated templates. Run `spin new` without `-E` to use generic templates."
335+
);
336+
}
337+
TemplateVariantInfo::AddComponent { .. } => {
338+
// `spin add` doesn't have an option for skipping a templateless env (the equivalent of `spin new` without `-E`).
339+
// Fall back to the installed templates.
340+
terminal::warn!(
341+
"The application targets the {env_ref} environment, but that doesn't list any associated templates."
342+
);
343+
eprintln!(
344+
"Templates will instead be taken from the installed template set."
345+
);
346+
eprintln!();
347+
(TemplateManager::try_default()?, vec![])
348+
}
349+
}
350+
} else {
351+
(template_manager, env_def.plugins().to_vec())
320352
}
321-
(template_manager, env_def.plugins().to_vec())
322353
}
323354
None => {
324355
let template_manager = TemplateManager::try_default()
@@ -328,6 +359,25 @@ async fn env_templates_and_plugins(
328359
})
329360
}
330361

362+
fn infer_target_env_from_file(
363+
manifest_path: impl AsRef<Path>,
364+
) -> anyhow::Result<Option<spin_manifest::schema::v2::TargetEnvironmentRef>> {
365+
let manifest = spin_manifest::manifest_from_file(manifest_path)?;
366+
match manifest.application.targets.len() {
367+
0 => Ok(None),
368+
1 => Ok(Some(manifest.application.targets[0].clone())),
369+
_ => {
370+
terminal::warn!("This application targets multiple environments.");
371+
eprintln!(
372+
"Spin doesn't currently support environment-specific templates for multiple environments."
373+
);
374+
eprintln!("Templates will instead be taken from the installed template set.");
375+
eprintln!();
376+
Ok(None)
377+
}
378+
}
379+
}
380+
331381
#[derive(Clone, Debug)]
332382
pub struct ParameterValue {
333383
pub name: String,
@@ -386,10 +436,16 @@ async fn prompt_template(
386436
.collect::<Vec<_>>();
387437

388438
if templates.is_empty() {
389-
if tags.len() == 1 {
390-
bail!("No templates matched '{}'", tags[0]);
391-
} else {
392-
bail!("No templates matched all tags");
439+
match tags.len() {
440+
0 => {
441+
bail!("No suitable templates found");
442+
} // can happen if `spin add` has env, env has templates, but no templates are add-able
443+
1 => {
444+
bail!("No templates matched '{}'", tags[0]);
445+
}
446+
_ => {
447+
bail!("No templates matched all tags");
448+
}
393449
}
394450
}
395451

0 commit comments

Comments
 (0)