From 99b5955ec5e0ae7fa4d45d17141558ad01101123 Mon Sep 17 00:00:00 2001 From: LucaGerlich Date: Tue, 18 Aug 2026 20:26:44 +0200 Subject: [PATCH] release: 1.0.1 with version guards in the pipeline Bumps MARKETING_VERSION to 1.0.1 and CURRENT_PROJECT_VERSION to 2, and makes the project file the single source of truth for both. release.sh previously passed MARKETING_VERSION on the command line, which left CURRENT_PROJECT_VERSION untouched. Sparkle compares build numbers, so a 1.0.1 built that way would have advertised the same build as 1.0.0 and would never have been offered as an update. The script now verifies that the project's MARKETING_VERSION matches the requested version, and refuses to build when the build number is not greater than the one the published appcast advertises. --- InputPilot.xcodeproj/project.pbxproj | 24 ++++++++++++------------ Scripts/release.sh | 27 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/InputPilot.xcodeproj/project.pbxproj b/InputPilot.xcodeproj/project.pbxproj index 279dfef..3d520bf 100644 --- a/InputPilot.xcodeproj/project.pbxproj +++ b/InputPilot.xcodeproj/project.pbxproj @@ -405,7 +405,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = T5M4XW2T24; ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; @@ -420,7 +420,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.lucagerlich.InputPilot; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; @@ -440,7 +440,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = T5M4XW2T24; ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; @@ -455,7 +455,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.lucagerlich.InputPilot; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; @@ -473,11 +473,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = T5M4XW2T24; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.lucagerlich.InputPilotTests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -494,11 +494,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = T5M4XW2T24; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.lucagerlich.InputPilotTests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -514,10 +514,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = T5M4XW2T24; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.lucagerlich.InputPilotUITests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -533,10 +533,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = T5M4XW2T24; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.lucagerlich.InputPilotUITests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; diff --git a/Scripts/release.sh b/Scripts/release.sh index b97063d..e524773 100755 --- a/Scripts/release.sh +++ b/Scripts/release.sh @@ -49,6 +49,32 @@ if ! grep -q "SUPublicEDKey" Config/AppInfo.plist || grep -A1 "SUPublicEDKey" Co echo "Sparkle updates will not validate until you run generate_keys and fill it in." >&2 fi +# The project file is the single source of truth for versions. Overriding +# MARKETING_VERSION here instead would leave CURRENT_PROJECT_VERSION stale, and +# Sparkle compares the build number - a release with an unchanged build number +# is never offered as an update. +echo "==> Checking versions" +BUILD_SETTINGS="$(xcodebuild -project InputPilot.xcodeproj -target InputPilot -configuration Release -showBuildSettings 2>/dev/null)" +PROJECT_VERSION="$(echo "$BUILD_SETTINGS" | awk -F' = ' '/ MARKETING_VERSION =/ {print $2; exit}' | tr -d ' ')" +BUILD_NUMBER="$(echo "$BUILD_SETTINGS" | awk -F' = ' '/ CURRENT_PROJECT_VERSION =/ {print $2; exit}' | tr -d ' ')" + +if [[ "$PROJECT_VERSION" != "$VERSION" ]]; then + echo "ERROR: MARKETING_VERSION in the project is '$PROJECT_VERSION' but you asked to release '$VERSION'." >&2 + echo "Update MARKETING_VERSION (and CURRENT_PROJECT_VERSION) in the project, commit, then re-run." >&2 + exit 1 +fi + +if [[ -f appcast.xml ]]; then + PUBLISHED_BUILD="$(grep -o '[0-9]*' appcast.xml | grep -o '[0-9]*' | sort -n | tail -1)" + if [[ -n "$PUBLISHED_BUILD" && "$BUILD_NUMBER" -le "$PUBLISHED_BUILD" ]]; then + echo "ERROR: CURRENT_PROJECT_VERSION is $BUILD_NUMBER but the published appcast already advertises build $PUBLISHED_BUILD." >&2 + echo "Sparkle compares build numbers, so this release would never be offered as an update. Bump CURRENT_PROJECT_VERSION." >&2 + exit 1 + fi +fi + +echo "Releasing $VERSION (build $BUILD_NUMBER)" + rm -rf "$DIST" mkdir -p "$DIST" @@ -58,7 +84,6 @@ xcodebuild -project InputPilot.xcodeproj \ -configuration Release \ -destination 'generic/platform=macOS' \ -archivePath "$ARCHIVE" \ - MARKETING_VERSION="$VERSION" \ archive echo "==> Exporting with Developer ID"