Prepare App Store 1.0 build 4
This commit is contained in:
@@ -35,6 +35,8 @@ struct App {
|
||||
support_url: String,
|
||||
marketing_url: String,
|
||||
age_rating: String,
|
||||
copyright: String,
|
||||
review_notes: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -42,6 +44,7 @@ struct Release {
|
||||
version: String,
|
||||
build: String,
|
||||
minimum_ios: String,
|
||||
minimum_watchos: String,
|
||||
notes: String,
|
||||
}
|
||||
|
||||
@@ -113,9 +116,12 @@ fn verify(root: &Path) -> Result<(), Box<dyn Error>> {
|
||||
if metadata.app.bundle_identifier != BUNDLE_ID {
|
||||
return Err(format!("main bundle identifier must be {BUNDLE_ID}").into());
|
||||
}
|
||||
if metadata.app.age_rating != "4+" || metadata.release.minimum_ios != "17.0" {
|
||||
if metadata.app.age_rating != "4+"
|
||||
|| metadata.release.minimum_ios != "17.0"
|
||||
|| metadata.release.minimum_watchos != "26.0"
|
||||
{
|
||||
return Err(
|
||||
"release metadata must retain the reviewed 4+ rating and iOS 17.0 minimum".into(),
|
||||
"release metadata must retain the reviewed 4+ rating, iOS 17.0 minimum, and watchOS 26.0 minimum".into(),
|
||||
);
|
||||
}
|
||||
if metadata.release.build.parse::<u64>()? == 0 {
|
||||
@@ -135,6 +141,8 @@ fn verify(root: &Path) -> Result<(), Box<dyn Error>> {
|
||||
("keywords", metadata.app.keywords.as_str()),
|
||||
("category", metadata.app.category.as_str()),
|
||||
("release notes", metadata.release.notes.as_str()),
|
||||
("copyright", metadata.app.copyright.as_str()),
|
||||
("review notes", metadata.app.review_notes.as_str()),
|
||||
] {
|
||||
if value.trim().is_empty() {
|
||||
return Err(format!("{name} must not be empty").into());
|
||||
@@ -156,20 +164,20 @@ fn verify(root: &Path) -> Result<(), Box<dyn Error>> {
|
||||
let workspace_version = workspace["workspace"]["package"]["version"]
|
||||
.as_str()
|
||||
.ok_or("workspace version is missing")?;
|
||||
if metadata.release.version != workspace_version {
|
||||
if normalized_version(&metadata.release.version)? != normalized_version(workspace_version)? {
|
||||
return Err("App Store version must match the Rust workspace version".into());
|
||||
}
|
||||
|
||||
let project = fs::read_to_string(root.join("apple/project.yml"))?;
|
||||
for required in [
|
||||
"PRODUCT_BUNDLE_IDENTIFIER: de.rfc1437.ironstorage\n",
|
||||
"PRODUCT_BUNDLE_IDENTIFIER: de.rfc1437.ironstorage.autofill\n",
|
||||
"PRODUCT_BUNDLE_IDENTIFIER: de.rfc1437.ironstorage.watch\n",
|
||||
"DEVELOPMENT_TEAM: MU22FMRGK8\n",
|
||||
"ITSAppUsesNonExemptEncryption: false\n",
|
||||
"NSFaceIDUsageDescription:",
|
||||
"NSCameraUsageDescription:",
|
||||
"- target: IronStorageAutoFill\n embed: true",
|
||||
"deploymentTarget: \"26.0\"\n",
|
||||
"\"ARCHS[sdk=watchos*]\": \"arm64 arm64_32\"\n",
|
||||
"- target: IronStorageWatch\n embed: true",
|
||||
] {
|
||||
if !project.contains(required) {
|
||||
@@ -203,6 +211,25 @@ fn verify(root: &Path) -> Result<(), Box<dyn Error>> {
|
||||
if metadata.screenshots.len() != 6 {
|
||||
return Err("exactly six reviewed iPhone screenshots are required".into());
|
||||
}
|
||||
let iphone_size = (
|
||||
metadata.screenshots[0].width,
|
||||
metadata.screenshots[0].height,
|
||||
);
|
||||
if ![
|
||||
(1242, 2688),
|
||||
(1284, 2778),
|
||||
(1260, 2736),
|
||||
(1290, 2796),
|
||||
(1320, 2868),
|
||||
]
|
||||
.contains(&iphone_size)
|
||||
|| metadata
|
||||
.screenshots
|
||||
.iter()
|
||||
.any(|screenshot| (screenshot.width, screenshot.height) != iphone_size)
|
||||
{
|
||||
return Err("iPhone screenshots must use one required 6.5-inch or 6.9-inch size".into());
|
||||
}
|
||||
if metadata.watch_screenshots.len() != 2 {
|
||||
return Err("exactly the reviewed Watch list and detail screenshots are required".into());
|
||||
}
|
||||
@@ -357,6 +384,17 @@ fn require_https(name: &str, value: &str) -> Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn normalized_version(value: &str) -> Result<Vec<u64>, Box<dyn Error>> {
|
||||
let mut parts = value
|
||||
.split('.')
|
||||
.map(str::parse)
|
||||
.collect::<Result<Vec<u64>, _>>()?;
|
||||
while parts.last() == Some(&0) {
|
||||
parts.pop();
|
||||
}
|
||||
Ok(parts)
|
||||
}
|
||||
|
||||
fn png_size(path: &Path) -> Result<(u32, u32), Box<dyn Error>> {
|
||||
let bytes = fs::read(path)?;
|
||||
if bytes.len() < 24 || &bytes[..8] != b"\x89PNG\r\n\x1a\n" || &bytes[12..16] != b"IHDR" {
|
||||
@@ -383,6 +421,12 @@ mod tests {
|
||||
assert!(metadata.release.notes.contains("Apple Watch"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_store_and_rust_versions_ignore_trailing_zeroes() {
|
||||
assert_eq!(normalized_version("1.0").unwrap(), vec![1]);
|
||||
assert_eq!(normalized_version("1.0.0").unwrap(), vec![1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repository_release_metadata_is_consistent() {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
|
||||
Reference in New Issue
Block a user