Skip to content

Commit bdb8c4b

Browse files
authored
Merge pull request #2530 from itowlson/moar-manifest-validations
Validate variable keys as part of schema
2 parents c14a222 + d4a67d3 commit bdb8c4b

File tree

11 files changed

+29
-19
lines changed

11 files changed

+29
-19
lines changed

crates/doctor/tests/ui/maximal_v1.cured

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ global_option = true
1111

1212
[variables]
1313
var_one = { default = "Default" }
14-
var_TWO = { required = true, secret = true }
14+
var_two = { required = true, secret = true }
1515

1616
[[trigger.fake]]
1717
id = "trigger-minimal-component"

crates/doctor/tests/ui/maximal_v1.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ global_option = true
1111

1212
[variables]
1313
var_one = { default = "Default" }
14-
var_TWO = { required = true, secret = true }
14+
var_two = { required = true, secret = true }
1515

1616
[[component]]
1717
id = "minimal-component"

crates/manifest/src/compat.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ fn component_id_from_string(id: String) -> Result<v2::KebabId, Error> {
144144
.map_err(|err: String| Error::InvalidID { id, reason: err })
145145
}
146146

147-
fn id_from_string<const DELIM: char>(id: String) -> Result<spin_serde::id::Id<DELIM>, Error> {
147+
fn id_from_string<const DELIM: char, const LOWER: bool>(
148+
id: String,
149+
) -> Result<spin_serde::id::Id<DELIM, LOWER>, Error> {
148150
id.clone()
149151
.try_into()
150152
.map_err(|err: String| Error::InvalidID { id, reason: err })

crates/manifest/src/schema/v2.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use serde::{Deserialize, Serialize};
2-
use spin_serde::FixedVersion;
2+
use spin_serde::{FixedVersion, LowerSnakeId};
33
pub use spin_serde::{KebabId, SnakeId};
44

55
pub use super::common::{ComponentBuildConfig, ComponentSource, Variable, WasiFilesMount};
@@ -16,7 +16,7 @@ pub struct AppManifest {
1616
pub application: AppDetails,
1717
/// `[variables]`
1818
#[serde(default, skip_serializing_if = "Map::is_empty")]
19-
pub variables: Map<SnakeId, Variable>,
19+
pub variables: Map<LowerSnakeId, Variable>,
2020
/// `[[trigger.<type>]]`
2121
#[serde(rename = "trigger")]
2222
pub triggers: Map<String, Vec<Trigger>>,
@@ -106,7 +106,7 @@ pub struct Component {
106106
pub description: String,
107107
/// `variables = { name = "{{ app_var }}"}`
108108
#[serde(default, skip_serializing_if = "Map::is_empty")]
109-
pub variables: Map<SnakeId, String>,
109+
pub variables: Map<LowerSnakeId, String>,
110110
/// `environment = { VAR = "value" }`
111111
#[serde(default, skip_serializing_if = "Map::is_empty")]
112112
pub environment: Map<String, String>,

crates/manifest/tests/ui/maximal.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"var_one": {
2424
"default": "Default"
2525
},
26-
"var_TWO": {
26+
"var_two": {
2727
"required": true,
2828
"secret": true
2929
}

crates/manifest/tests/ui/maximal.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ lint_level = "savage"
1414

1515
[variables]
1616
var_one = { default = "Default" }
17-
var_TWO = { required = true, secret = true }
17+
var_two = { required = true, secret = true }
1818

1919
[[trigger.fake]]
2020
component = "minimal-component"

crates/manifest/tests/ui/v1/maximal.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"var_one": {
1919
"default": "Default"
2020
},
21-
"var_TWO": {
21+
"var_two": {
2222
"required": true,
2323
"secret": true
2424
}

crates/manifest/tests/ui/v1/maximal.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ global_option = true
1111

1212
[variables]
1313
var_one = { default = "Default" }
14-
var_TWO = { required = true, secret = true }
14+
var_two = { required = true, secret = true }
1515

1616
[[component]]
1717
id = "minimal-component"

crates/manifest/tests/ui/v1/maximal.toml.v2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ global_option = true
1212
[variables.var_one]
1313
default = "Default"
1414

15-
[variables.var_TWO]
15+
[variables.var_two]
1616
required = true
1717
secret = true
1818

crates/serde/src/id.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,27 @@ use serde::{Deserialize, Serialize};
66
/// `word`s separated by a delimiter char.
77
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
88
#[serde(into = "String", try_from = "String")]
9-
pub struct Id<const DELIM: char>(String);
9+
pub struct Id<const DELIM: char, const LOWER: bool>(String);
1010

11-
impl<const DELIM: char> std::fmt::Display for Id<DELIM> {
11+
impl<const DELIM: char, const LOWER: bool> std::fmt::Display for Id<DELIM, LOWER> {
1212
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1313
write!(f, "{}", self.0)
1414
}
1515
}
1616

17-
impl<const DELIM: char> AsRef<str> for Id<DELIM> {
17+
impl<const DELIM: char, const LOWER: bool> AsRef<str> for Id<DELIM, LOWER> {
1818
fn as_ref(&self) -> &str {
1919
&self.0
2020
}
2121
}
2222

23-
impl<const DELIM: char> From<Id<DELIM>> for String {
24-
fn from(value: Id<DELIM>) -> Self {
23+
impl<const DELIM: char, const LOWER: bool> From<Id<DELIM, LOWER>> for String {
24+
fn from(value: Id<DELIM, LOWER>) -> Self {
2525
value.0
2626
}
2727
}
2828

29-
impl<const DELIM: char> TryFrom<String> for Id<DELIM> {
29+
impl<const DELIM: char, const LOWER: bool> TryFrom<String> for Id<DELIM, LOWER> {
3030
type Error = String;
3131

3232
fn try_from(id: String) -> Result<Self, Self::Error> {
@@ -63,6 +63,11 @@ impl<const DELIM: char> TryFrom<String> for Id<DELIM> {
6363
return Err(format!("{DELIM:?}-separated words must be all lowercase or all UPPERCASE; got {word:?}"));
6464
}
6565
}
66+
if LOWER && word_is_uppercase {
67+
return Err(format!(
68+
"Lower-case identifiers must be all lowercase; got {id:?}"
69+
));
70+
}
6671
}
6772
Ok(Self(id))
6873
}

0 commit comments

Comments
 (0)