Fix iOS App Store upload validation
This commit is contained in:
parent
fd9ea84ea5
commit
0924e40463
7 changed files with 115 additions and 8 deletions
|
|
@ -9,6 +9,14 @@ import subprocess
|
|||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PROFILE_REQUIRED_KEYS = {
|
||||
"application-identifier",
|
||||
"beta-reports-active",
|
||||
"com.apple.developer.team-identifier",
|
||||
"com.apple.developer.default-data-protection",
|
||||
"keychain-access-groups",
|
||||
}
|
||||
|
||||
|
||||
def decode_profile(path: Path) -> dict:
|
||||
commands = [
|
||||
|
|
@ -33,10 +41,66 @@ def decode_profile(path: Path) -> dict:
|
|||
raise RuntimeError(f"unable to decode provisioning profile {path}: {'; '.join(errors)}")
|
||||
|
||||
|
||||
def load_entitlements_template(path: Path) -> dict:
|
||||
value = plistlib.loads(path.read_bytes())
|
||||
if not isinstance(value, dict):
|
||||
raise RuntimeError(f"entitlements template is not a dictionary: {path}")
|
||||
return value
|
||||
|
||||
|
||||
def _has_build_setting(value: object) -> bool:
|
||||
if isinstance(value, str):
|
||||
return "$(" in value
|
||||
if isinstance(value, list):
|
||||
return any(_has_build_setting(item) for item in value)
|
||||
if isinstance(value, dict):
|
||||
return any(_has_build_setting(item) for item in value.values())
|
||||
return False
|
||||
|
||||
|
||||
def _filter_list(template_value: list, profile_value: object) -> list:
|
||||
if not isinstance(profile_value, list):
|
||||
return template_value
|
||||
profile_set = set(profile_value)
|
||||
filtered = [item for item in template_value if item in profile_set]
|
||||
return filtered
|
||||
|
||||
|
||||
def filter_entitlements(profile_entitlements: dict, template_entitlements: dict) -> dict:
|
||||
filtered = {
|
||||
key: profile_entitlements[key]
|
||||
for key in PROFILE_REQUIRED_KEYS
|
||||
if key in profile_entitlements
|
||||
}
|
||||
|
||||
for key, template_value in template_entitlements.items():
|
||||
if key not in profile_entitlements:
|
||||
print(
|
||||
f"warning: entitlement {key} requested by template but absent from provisioning profile; omitting",
|
||||
file=sys.stderr,
|
||||
)
|
||||
continue
|
||||
|
||||
profile_value = profile_entitlements[key]
|
||||
if _has_build_setting(template_value):
|
||||
filtered[key] = profile_value
|
||||
elif isinstance(template_value, list):
|
||||
filtered[key] = _filter_list(template_value, profile_value)
|
||||
else:
|
||||
filtered[key] = template_value
|
||||
|
||||
return dict(sorted(filtered.items()))
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("profile", type=Path)
|
||||
parser.add_argument("--output", "-o", type=Path, required=True)
|
||||
parser.add_argument(
|
||||
"--template",
|
||||
type=Path,
|
||||
help="Optional entitlements template used to filter profile entitlements for a target.",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
profile = decode_profile(args.profile)
|
||||
|
|
@ -44,6 +108,9 @@ def main(argv: list[str]) -> int:
|
|||
if not isinstance(entitlements, dict):
|
||||
raise RuntimeError(f"profile has no Entitlements dictionary: {args.profile}")
|
||||
|
||||
if args.template:
|
||||
entitlements = filter_entitlements(entitlements, load_entitlements_template(args.template))
|
||||
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.output.write_bytes(plistlib.dumps(entitlements, fmt=plistlib.FMT_XML))
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -66,7 +66,12 @@ require_tool() {
|
|||
extract_profile_entitlements() {
|
||||
local profile="$1"
|
||||
local output="$2"
|
||||
Scripts/apple/profile-entitlements.py "$profile" --output "$output"
|
||||
local template="${3:-}"
|
||||
local args=("$profile" --output "$output")
|
||||
if [[ -n "$template" ]]; then
|
||||
args+=(--template "$template")
|
||||
fi
|
||||
Scripts/apple/profile-entitlements.py "${args[@]}"
|
||||
}
|
||||
|
||||
sign_bundle() {
|
||||
|
|
@ -128,8 +133,8 @@ sign_ios() {
|
|||
cp "$ext_profile" "${ext}/embedded.mobileprovision"
|
||||
app_entitlements="${work_dir}/app-entitlements.plist"
|
||||
ext_entitlements="${work_dir}/extension-entitlements.plist"
|
||||
extract_profile_entitlements "$app_profile" "$app_entitlements"
|
||||
extract_profile_entitlements "$ext_profile" "$ext_entitlements"
|
||||
extract_profile_entitlements "$app_profile" "$app_entitlements" Apple/App/App-iOS.entitlements
|
||||
extract_profile_entitlements "$ext_profile" "$ext_entitlements" Apple/NetworkExtension/NetworkExtension-iOS.entitlements
|
||||
|
||||
rm -rf "${app}/_CodeSignature" "${ext}/_CodeSignature"
|
||||
sign_bundle ios "$ext" "$ext_entitlements"
|
||||
|
|
|
|||
|
|
@ -71,7 +71,12 @@ profile_for() {
|
|||
generate_entitlements_from_profile() {
|
||||
local profile="$1"
|
||||
local output="$2"
|
||||
Scripts/apple/profile-entitlements.py "$profile" --output "$output"
|
||||
local template="${3:-}"
|
||||
local args=("$profile" --output "$output")
|
||||
if [[ -n "$template" ]]; then
|
||||
args+=(--template "$template")
|
||||
fi
|
||||
Scripts/apple/profile-entitlements.py "${args[@]}"
|
||||
}
|
||||
|
||||
apple_signing_available() {
|
||||
|
|
@ -331,8 +336,8 @@ build_ios_kms_release() {
|
|||
|
||||
app_entitlements="${apple_root}/ios-kms/app-entitlements.plist"
|
||||
ext_entitlements="${apple_root}/ios-kms/extension-entitlements.plist"
|
||||
generate_entitlements_from_profile "$app_profile" "$app_entitlements"
|
||||
generate_entitlements_from_profile "$ext_profile" "$ext_entitlements"
|
||||
generate_entitlements_from_profile "$app_profile" "$app_entitlements" Apple/App/App-iOS.entitlements
|
||||
generate_entitlements_from_profile "$ext_profile" "$ext_entitlements" Apple/NetworkExtension/NetworkExtension-iOS.entitlements
|
||||
|
||||
rm -rf "${app}/_CodeSignature" "${ext}/_CodeSignature"
|
||||
kms_sign_bundle ios "$ext" "$ext_entitlements"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue