Make iOS release signing deterministic
This commit is contained in:
@@ -9,6 +9,9 @@ APPLE_TEAM_ID=
|
|||||||
#
|
#
|
||||||
# If export fails with "profile doesn't include signing certificate", regenerate App Store
|
# If export fails with "profile doesn't include signing certificate", regenerate App Store
|
||||||
# profiles at developer.apple.com for com.beenvoice.app and com.beenvoice.app.ExpoWidgetsTarget,
|
# profiles at developer.apple.com for com.beenvoice.app and com.beenvoice.app.ExpoWidgetsTarget,
|
||||||
|
# Optional overrides when those App Store profile names differ from the bundle IDs:
|
||||||
|
# IOS_MAIN_APPSTORE_PROFILE_NAME=com.beenvoice.app
|
||||||
|
# IOS_WIDGET_APPSTORE_PROFILE_NAME=com.beenvoice.app.ExpoWidgetsTarget
|
||||||
# then re-run the full release (not --export-only).
|
# then re-run the full release (not --export-only).
|
||||||
|
|
||||||
# Production API baked into the JS bundle (App Store / TestFlight)
|
# Production API baked into the JS bundle (App Store / TestFlight)
|
||||||
|
|||||||
@@ -2,41 +2,63 @@
|
|||||||
const { withXcodeProject } = require("@expo/config-plugins");
|
const { withXcodeProject } = require("@expo/config-plugins");
|
||||||
|
|
||||||
const RELEASE_SIGN_KEY = '"CODE_SIGN_IDENTITY[sdk=iphoneos*]"';
|
const RELEASE_SIGN_KEY = '"CODE_SIGN_IDENTITY[sdk=iphoneos*]"';
|
||||||
|
const MAIN_BUNDLE_ID = "com.beenvoice.app";
|
||||||
|
const WIDGET_BUNDLE_ID = "com.beenvoice.app.ExpoWidgetsTarget";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RN / Expo sets Release CODE_SIGN_IDENTITY to "iPhone Developer", which forces
|
* Keep App Store archives on distribution signing. Automatic signing can select
|
||||||
* development-signed archives. Remove it so automatic signing picks Distribution
|
* an Apple Development identity for the widget target when archiving from the CLI,
|
||||||
* for App Store archives.
|
* so both release targets use their explicit App Store profiles instead.
|
||||||
*/
|
*/
|
||||||
|
function configureReleaseSigning(project) {
|
||||||
|
const configurations = project.pbxXCBuildConfigurationSection();
|
||||||
|
|
||||||
|
for (const key of Object.keys(configurations)) {
|
||||||
|
const buildConfig = configurations[key];
|
||||||
|
if (
|
||||||
|
!buildConfig ||
|
||||||
|
typeof buildConfig !== "object" ||
|
||||||
|
!buildConfig.buildSettings
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildConfig.name !== "Release") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bundleId = String(
|
||||||
|
buildConfig.buildSettings.PRODUCT_BUNDLE_IDENTIFIER ?? "",
|
||||||
|
).replaceAll('"', "");
|
||||||
|
if (bundleId !== MAIN_BUNDLE_ID && bundleId !== WIDGET_BUNDLE_ID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const profileName =
|
||||||
|
bundleId === WIDGET_BUNDLE_ID
|
||||||
|
? (process.env.IOS_WIDGET_APPSTORE_PROFILE_NAME ?? WIDGET_BUNDLE_ID)
|
||||||
|
: (process.env.IOS_MAIN_APPSTORE_PROFILE_NAME ?? MAIN_BUNDLE_ID);
|
||||||
|
|
||||||
|
buildConfig.buildSettings[RELEASE_SIGN_KEY] = '"Apple Distribution"';
|
||||||
|
buildConfig.buildSettings.CODE_SIGN_STYLE = "Manual";
|
||||||
|
buildConfig.buildSettings.PROVISIONING_PROFILE_SPECIFIER = `"${profileName}"`;
|
||||||
|
|
||||||
|
if (process.env.APPLE_TEAM_ID) {
|
||||||
|
buildConfig.buildSettings.DEVELOPMENT_TEAM = process.env.APPLE_TEAM_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {import('@expo/config-plugins').ConfigPlugin} */
|
/** @type {import('@expo/config-plugins').ConfigPlugin} */
|
||||||
function withAppStoreSigning(config) {
|
function withAppStoreSigning(config) {
|
||||||
return withXcodeProject(config, (config) => {
|
return withXcodeProject(config, (config) => {
|
||||||
const project = config.modResults;
|
configureReleaseSigning(config.modResults);
|
||||||
const configurations = project.pbxXCBuildConfigurationSection();
|
|
||||||
|
|
||||||
for (const key of Object.keys(configurations)) {
|
|
||||||
const buildConfig = configurations[key];
|
|
||||||
if (!buildConfig || typeof buildConfig !== "object" || !buildConfig.buildSettings) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildConfig.name !== "Release") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const identity = buildConfig.buildSettings[RELEASE_SIGN_KEY];
|
|
||||||
if (
|
|
||||||
identity === "iPhone Developer" ||
|
|
||||||
identity === '"iPhone Developer"' ||
|
|
||||||
identity === "Apple Distribution" ||
|
|
||||||
identity === '"Apple Distribution"'
|
|
||||||
) {
|
|
||||||
delete buildConfig.buildSettings[RELEASE_SIGN_KEY];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = withAppStoreSigning;
|
module.exports = withAppStoreSigning;
|
||||||
|
module.exports.configureReleaseSigning = configureReleaseSigning;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// @ts-check
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const xcode = require("xcode");
|
||||||
|
const { configureReleaseSigning } = require("../plugins/withAppStoreSigning");
|
||||||
|
|
||||||
|
const projectPath = process.argv[2];
|
||||||
|
if (!projectPath) {
|
||||||
|
throw new Error(
|
||||||
|
"Usage: node scripts/configure-ios-signing.js <project.pbxproj>",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedPath = path.resolve(projectPath);
|
||||||
|
const project = xcode.project(resolvedPath);
|
||||||
|
project.parseSync();
|
||||||
|
configureReleaseSigning(project);
|
||||||
|
fs.writeFileSync(resolvedPath, project.writeSync());
|
||||||
|
|
||||||
|
console.log("Configured manual App Store signing for iOS release targets.");
|
||||||
@@ -185,6 +185,10 @@ prepare_native_project() {
|
|||||||
fi
|
fi
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if [[ -f "$ROOT/$PROJECT/project.pbxproj" ]]; then
|
||||||
|
node "$ROOT/scripts/configure-ios-signing.js" "$ROOT/$PROJECT/project.pbxproj"
|
||||||
|
fi
|
||||||
|
|
||||||
resolve_xcode_workspace
|
resolve_xcode_workspace
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +245,6 @@ archive_app() {
|
|||||||
-archivePath "$ARCHIVE_PATH" \
|
-archivePath "$ARCHIVE_PATH" \
|
||||||
-destination "generic/platform=iOS" \
|
-destination "generic/platform=iOS" \
|
||||||
-allowProvisioningUpdates \
|
-allowProvisioningUpdates \
|
||||||
CODE_SIGN_STYLE=Automatic \
|
|
||||||
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
|
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
|
||||||
"${API_AUTH_ARGS[@]}" \
|
"${API_AUTH_ARGS[@]}" \
|
||||||
archive
|
archive
|
||||||
|
|||||||
Reference in New Issue
Block a user