Browse Source

Merge pull request #508 from nightscout/auto-vesion-action

Add Actions Workflow to Auto-Increase version on dev Pushes (formerly #503)
Sam King 1 year ago
parent
commit
7f9523afad

+ 1 - 1
.github/workflows/add_to_project.yml

@@ -1,4 +1,4 @@
-name: 8. DONT RUN Add bugs to bugs project
+name: zzz [DO NOT RUN] Add Bugs to Project 'Bugs'
 
 
 on:
 on:
   issues:
   issues:

+ 100 - 0
.github/workflows/auto_version_dev.yml

@@ -0,0 +1,100 @@
+# -----------------------------------------------------------------------------
+# Workflow: `auto_version_dev.yml`
+#
+# Description:
+# This GitHub Actions workflow automatically manages and increments the
+# `APP_DEV_VERSION` defined in `Config.xcconfig` on every push to `dev` branch.
+# This version is used for internal tracking and diagnostics (e.g. in
+# Crashlytics) and follows a 4-digit semantic versioning format:
+# `MAJOR.MINOR.PATCH.FEATURE`.
+#
+# Versioning Logic:
+# - Reads the base version from `APP_VERSION = x.y.z`
+# - Reads the last internal dev version from `APP_DEV_VERSION`
+#
+# Behavior:
+# - If `APP_DEV_VERSION` matches `APP_VERSION` (e.g. both are `0.5.0`),
+#   it assumes the first dev push after a release and sets `APP_DEV_VERSION`
+#   to `APP_VERSION.1` (e.g. `0.5.0.1`)
+# - If `APP_DEV_VERSION` is already in 4-digit form (e.g. `0.5.0.3`),
+#   it increments the fourth digit (e.g. → `0.5.0.4`)
+#
+# Example Progression:
+# - Release sets `APP_VERSION = 0.5.0`, `APP_DEV_VERSION = 0.5.0`
+# - First push to `dev`:      → `APP_DEV_VERSION = 0.5.0.1`
+# - Second push to `dev`:     → `APP_DEV_VERSION = 0.5.0.2`
+# - ...
+#
+# The updated value is committed and pushed back to the `dev` branch.
+#
+# Prerequisites:
+# - `APP_VERSION` must be present in `Config.xcconfig` in the form `x.y.z`
+# - `APP_DEV_VERSION` must either match `APP_VERSION` or be `x.y.z.w`
+# - GitHub Actions must have write permission to push to `dev`
+# - This workflow only runs when the repository owner is `nightscout`
+# -----------------------------------------------------------------------------
+
+name: zzz [DO NOT RUN] Bump APP_DEV_VERSION on dev push
+
+on:
+  push:
+    branches:
+      - dev
+
+jobs:
+  bump-dev-version:
+    if: github.repository_owner == 'nightscout'
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout repo
+        uses: actions/checkout@v4
+
+      - name: Set up Git
+        run: |
+          git config --global user.name "github-actions[bot]"
+          git config --global user.email "github-actions[bot]@users.noreply.github.com"
+
+      - name: Bump APP_DEV_VERSION
+        run: |
+          FILE=Config.xcconfig
+
+          # Read current APP_VERSION
+          BASE_VERSION=$(grep '^APP_VERSION' "$FILE" | cut -d '=' -f2 | xargs)
+
+          # Read existing APP_DEV_VERSION, if any
+          DEV_LINE=$(grep '^APP_DEV_VERSION' "$FILE" || echo "")
+          if [ -z "$DEV_LINE" ]; then
+            CURRENT_DEV_VERSION="$BASE_VERSION"
+          else
+            CURRENT_DEV_VERSION=$(echo "$DEV_LINE" | cut -d '=' -f2 | xargs)
+          fi
+
+          echo "APP_VERSION       = $BASE_VERSION"
+          echo "APP_DEV_VERSION   = $CURRENT_DEV_VERSION"
+
+          # Decide next dev version
+          if [ "$CURRENT_DEV_VERSION" = "$BASE_VERSION" ]; then
+            # First post-release commit to dev → bump to .1
+            NEW_DEV_VERSION="${BASE_VERSION}.1"
+            if [ -z "$DEV_LINE" ]; then
+              echo "APP_DEV_VERSION = $NEW_DEV_VERSION" >> "$FILE"
+            else
+              sed -i -E "s|^APP_DEV_VERSION *= *.*|APP_DEV_VERSION = $NEW_DEV_VERSION|" "$FILE"
+            fi
+          else
+            # Already in .X form → bump last digit
+            IFS='.' read -r MAJOR MINOR PATCH FEATURE <<< "$CURRENT_DEV_VERSION"
+            FEATURE=$((FEATURE + 1))
+            NEW_DEV_VERSION="$MAJOR.$MINOR.$PATCH.$FEATURE"
+            sed -i -E "s|^APP_DEV_VERSION *= *.*|APP_DEV_VERSION = $NEW_DEV_VERSION|" "$FILE"
+          fi
+
+          echo "NEW APP_DEV_VERSION = $NEW_DEV_VERSION"
+          echo "NEW_DEV_VERSION=$NEW_DEV_VERSION" >> $GITHUB_ENV
+
+      - name: Commit and push updated dev version
+        run: |
+          git add Config.xcconfig
+          git commit -m "CI: Bump APP_DEV_VERSION to $NEW_DEV_VERSION"
+          git push

+ 1 - 1
.github/workflows/stale_issues.yml

@@ -1,4 +1,4 @@
-name: 8. DONT RUN close inactive issues
+name: zzz [DO NOT RUN] Close Inactive Issues
 on:
 on:
   schedule:
   schedule:
     - cron: "30 1 * * *"
     - cron: "30 1 * * *"

+ 1 - 0
Config.xcconfig

@@ -1,5 +1,6 @@
 APP_DISPLAY_NAME = Trio
 APP_DISPLAY_NAME = Trio
 APP_VERSION = 0.4.1
 APP_VERSION = 0.4.1
+APP_DEV_VERSION = 0.4.1
 APP_BUILD_NUMBER = 1
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 COPYRIGHT_NOTICE =
 DEVELOPER_TEAM = ##TEAM_ID##
 DEVELOPER_TEAM = ##TEAM_ID##

+ 2 - 0
Trio/Resources/Info.plist

@@ -4,6 +4,8 @@
 <dict>
 <dict>
 	<key>AppGroupID</key>
 	<key>AppGroupID</key>
 	<string>$(APP_GROUP_ID)</string>
 	<string>$(APP_GROUP_ID)</string>
+	<key>AppDevVersion</key>
+	<string>$(APP_DEV_VERSION)</string>
 	<key>BGTaskSchedulerPermittedIdentifiers</key>
 	<key>BGTaskSchedulerPermittedIdentifiers</key>
 	<array>
 	<array>
 		<string>$(PRODUCT_BUNDLE_IDENTIFIER).background-task.critical-event-log</string>
 		<string>$(PRODUCT_BUNDLE_IDENTIFIER).background-task.critical-event-log</string>

+ 1 - 0
Trio/Sources/Application/AppDelegate.swift

@@ -18,6 +18,7 @@ class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject, UNUserNoti
         // the next app boot, but this is fine since the app will need
         // the next app boot, but this is fine since the app will need
         // to boot after a crash
         // to boot after a crash
         Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(crashReportingEnabled)
         Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(crashReportingEnabled)
+        Crashlytics.crashlytics().setCustomValue(Bundle.main.appDevVersion ?? "unknown", forKey: "app_dev_version")
 
 
         return true
         return true
     }
     }

+ 21 - 1
Trio/Sources/Application/TrioApp.swift

@@ -115,9 +115,23 @@ extension Notification.Name {
             "\(key): \(value.branch) \(value.commitSHA)"
             "\(key): \(value.branch) \(value.commitSHA)"
         }.joined(separator: ", ")
         }.joined(separator: ", ")
 
 
+        /// The current development version of the app.
+        ///
+        /// Follows a semantic pattern where release versions are like `0.5.0`, and
+        /// development versions increment with a fourth component (e.g., `0.5.0.1`, `0.5.0.2`)
+        /// after the base release. For example:
+        /// - After release `0.5.0` → `0.5.0`
+        /// - First dev push → `0.5.0.1`
+        /// - Next dev push → `0.5.0.2`
+        /// - Next release `0.6.0` → `0.6.0`
+        /// - Next dev push → `0.6.0.1`
+        ///
+        /// If the dev version is unavailable, `"unknown"` is returned.
+        let devVersion = Bundle.main.appDevVersion ?? "unknown"
+
         debug(
         debug(
             .default,
             .default,
-            "Trio Started: v\(Bundle.main.releaseVersionNumber ?? "")(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.shared.buildDate()))] [buildExpires: \(String(describing: BuildDetails.shared.calculateExpirationDate()))] [Branch: \(BuildDetails.shared.branchAndSha)] [submodules: \(submodulesInfo)]"
+            "Trio Started: v\(devVersion)(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.shared.buildDate()))] [buildExpires: \(String(describing: BuildDetails.shared.calculateExpirationDate()))] [Branch: \(BuildDetails.shared.branchAndSha)] [submodules: \(submodulesInfo)]"
         )
         )
         // Fix bug in iOS 18 related to the translucent tab bar
         // Fix bug in iOS 18 related to the translucent tab bar
         configureTabBarAppearance()
         configureTabBarAppearance()
@@ -447,3 +461,9 @@ extension Notification.Name {
         }
         }
     }
     }
 }
 }
+
+public extension Bundle {
+    var appDevVersion: String? {
+        object(forInfoDictionaryKey: "AppDevVersion") as? String
+    }
+}

+ 15 - 2
Trio/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -78,7 +78,20 @@ extension Settings {
                     Section(
                     Section(
                         header: Text("BRANCH: \(buildDetails.branchAndSha)").textCase(nil),
                         header: Text("BRANCH: \(buildDetails.branchAndSha)").textCase(nil),
                         content: {
                         content: {
-                            let versionNumber = Bundle.main.releaseVersionNumber ?? String(localized: "Unknown")
+                            /// The current development version of the app.
+                            ///
+                            /// Follows a semantic pattern where release versions are like `0.5.0`, and
+                            /// development versions increment with a fourth component (e.g., `0.5.0.1`, `0.5.0.2`)
+                            /// after the base release. For example:
+                            /// - After release `0.5.0` → `0.5.0`
+                            /// - First dev push → `0.5.0.1`
+                            /// - Next dev push → `0.5.0.2`
+                            /// - Next release `0.6.0` → `0.6.0`
+                            /// - Next dev push → `0.6.0.1`
+                            ///
+                            /// If the dev version is unavailable, `"unknown"` is returned.
+                            let devVersion = Bundle.main.appDevVersion ?? "unknown"
+
                             let buildNumber = Bundle.main.buildVersionNumber ?? String(localized: "Unknown")
                             let buildNumber = Bundle.main.buildVersionNumber ?? String(localized: "Unknown")
 
 
                             NavigationLink(destination: SubmodulesView(buildDetails: buildDetails)) {
                             NavigationLink(destination: SubmodulesView(buildDetails: buildDetails)) {
@@ -90,7 +103,7 @@ extension Settings {
                                         .cornerRadius(10)
                                         .cornerRadius(10)
                                         .padding(.trailing, 10)
                                         .padding(.trailing, 10)
                                     VStack(alignment: .leading, spacing: 4) {
                                     VStack(alignment: .leading, spacing: 4) {
-                                        Text("Trio v\(versionNumber) (\(buildNumber))")
+                                        Text("Trio v\(devVersion) (\(buildNumber))")
                                             .font(.headline)
                                             .font(.headline)
                                         if let expirationDate = buildDetails.calculateExpirationDate() {
                                         if let expirationDate = buildDetails.calculateExpirationDate() {
                                             let formattedDate = DateFormatter.localizedString(
                                             let formattedDate = DateFormatter.localizedString(