From eb6583a9b67ffa780a1adf68f85ddee69a934cf1 Mon Sep 17 00:00:00 2001 From: Geoff Powell Date: Tue, 2 Jan 2024 08:35:11 -0500 Subject: [PATCH] Add version code generation in CI --- .github/workflows/android.yml | 4 +++ .github/workflows/build-number.yml | 39 +++++++++++++++++++++ .github/workflows/check.yml | 5 ++- .github/workflows/desktop-web.yml | 5 ++- .github/workflows/ios.yml | 29 +++++++++------- .run/android.run.xml | 39 --------------------- common/build.gradle.kts | 2 +- composeApp/build.gradle.kts | 6 ++-- gradle.properties | 8 ++++- gradle/libs.versions.toml | 8 ++--- iosApp/iosApp.xcodeproj/project.pbxproj | 12 +++++++ scripts/build-number.sh | 45 +++++++++++++++++++++++++ 12 files changed, 138 insertions(+), 64 deletions(-) create mode 100644 .github/workflows/build-number.yml delete mode 100644 .run/android.run.xml create mode 100755 scripts/build-number.sh diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 818cb7f..eeb1de7 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -11,8 +11,12 @@ concurrency: cancel-in-progress: true jobs: + build-number: + uses: ./.github/workflows/build-number.yml + build-debug: runs-on: ubuntu-latest + steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/build-number.yml b/.github/workflows/build-number.yml new file mode 100644 index 0000000..1023b27 --- /dev/null +++ b/.github/workflows/build-number.yml @@ -0,0 +1,39 @@ +name: Build Number + +on: + workflow_call: + outputs: + build-number: + description: "The build number generated from git tags on current SHA." + value: ${{ jobs.build.outputs.build-number }} + inputs: + token: + description: 'GitHub token or PAT token' + required: false + default: ${{ github.token }} + type: string + +#concurrency: +# group: ${{ github.ref }} +# cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + build_number: ${{ steps.build-number.outputs.BUILD_NUMBER }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Generate build number + id: build-number + env: + INPUT_GITHUB_TOKEN: ${{ inputs.token }} + INPUT_SHA: ${{ github.event.pull_request.head.sha || github.event.workflow_run.head_sha }} + run: | + ./scripts/build-number.sh \ No newline at end of file diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 61453fd..55548e1 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,7 +10,10 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -jobs: +jobs: + build-number: + uses: ./.github/workflows/build-number.yml + check: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/desktop-web.yml b/.github/workflows/desktop-web.yml index 1f8dc58..d2ad8a4 100644 --- a/.github/workflows/desktop-web.yml +++ b/.github/workflows/desktop-web.yml @@ -11,9 +11,12 @@ concurrency: cancel-in-progress: true jobs: + build-number: + uses: ./.github/workflows/build-number.yml + Build-Desktop: runs-on: ubuntu-latest - + needs: build-number steps: - name: Checkout Repo uses: actions/checkout@v4 diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 48b0a1e..5c744b4 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -4,16 +4,20 @@ on: push: branches: - main - - ios-upload-testflight # TODO: this is a temporary branch for testing (REMOVE) + - ci-version-code # TODO: this is a temporary branch for testing (REMOVE) pull_request: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -jobs: - build: +jobs: + build-number: + uses: ./.github/workflows/build-number.yml + + build: runs-on: macos-latest + needs: build-number steps: - name: Check Xcode version run: /usr/bin/xcodebuild -version @@ -61,6 +65,8 @@ jobs: mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles cp $DISTRO_PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles + echo "copied provisioning profiles" + ls ~/Library/MobileDevice/Provisioning\ Profiles - name: set up JDK 17 uses: actions/setup-java@v4 @@ -74,6 +80,12 @@ jobs: with: gradle-home-cache-cleanup: true +# Update build number with the one generated from build-number.yml + - uses: yanamura/ios-bump-version@v1 + with: + build-number: ${{ needs.build-number.outputs.build-number }} + project-path: iosApp + - name: Build Artifact with Xcode run: xcodebuild -project iosApp/iosApp.xcodeproj -scheme iosApp -configuration Debug -destination generic/platform=iOS -archivePath $RUNNER_TEMP/Tidy.xcarchive archive @@ -109,13 +121,4 @@ jobs: mkdir -p ./private_keys echo "$IOS_APPSTORE_PRIVATE_KEY" | sed 's/[^A-Za-z0-9+/=]//g' | base64 --decode -o "./private_keys/AuthKey_$APPSTORE_API_KEY_ID.p8" xcrun altool --validate-app -f ${{ runner.temp }}/Tidy.ipa -t ios --apiKey "$APPSTORE_API_KEY_ID" --apiIssuer ${{ secrets.IOS_APPSTORE_ISSUER_ID }} - xcrun altool --upload-app -f ${{ runner.temp }}/Tidy.ipa -t ios --apiKey "$APPSTORE_API_KEY_ID" --apiIssuer ${{ secrets.IOS_APPSTORE_ISSUER_ID }} - -# - name: Upload app to TestFlight -# if: github.event_name == 'push' -# uses: apple-actions/upload-testflight-build@v1 -# with: -# app-path: $RUNNER_TEMP/Tidy.ipa -# issuer-id: ${{ secrets.IOS_APPSTORE_ISSUER_ID }} -# api-key-id: ${{ secrets.IOS_APPSTORE_API_KEY_ID }} -# api-private-key: $RUNNER_TEMP/appstore_private_key.p8 + xcrun altool --upload-app -f ${{ runner.temp }}/Tidy.ipa -t ios --apiKey "$APPSTORE_API_KEY_ID" --apiIssuer ${{ secrets.IOS_APPSTORE_ISSUER_ID }} \ No newline at end of file diff --git a/.run/android.run.xml b/.run/android.run.xml deleted file mode 100644 index 4c76b02..0000000 --- a/.run/android.run.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 09a408f..d09da0f 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } group = "com.greenmiststudios.tidy" -version = "${libs.versions.version}-SNAPSHOT" +version = "${project.properties["tidy.version_name"]?.toString()}-SNAPSHOT" @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) kotlin { diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 1b251df..eea3714 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -82,8 +82,8 @@ android { applicationId = "com.greenmiststudios.tidy" minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.version.get() + versionCode = project.properties["tidy.version_code"]?.toString()?.toInt() ?: 1 + versionName = project.properties["tidy.version_name"]?.toString() } packaging { resources { @@ -114,7 +114,7 @@ compose.desktop { nativeDistributions { targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) packageName = "com.greenmiststudios.tidy" - packageVersion = libs.versions.version.get() + packageVersion = project.properties["tidy.version_name"]?.toString() } } } diff --git a/gradle.properties b/gradle.properties index 3d8d5b1..69fd7b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,14 @@ +tidy.version_name=1.0.0 +tidy.version_code=1 + kotlin.code.style=official xcodeproj=iosApp kotlin.native.binary.memoryModel=experimental -org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx4096M" +org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dkotlin.daemon.jvm.options\="-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g" org.gradle.configuration-cache=true +# Use this flag carefully, in case some of the plugins are not fully compatible. +org.gradle.configuration-cache.problems=warn org.gradle.configureondemand=true org.gradle.java.installations.fromEnv=JDK_17 org.gradle.daemon=true @@ -15,6 +20,7 @@ java.modularToolchainVersion=17 #Android android.nonTransitiveRClass=true android.useAndroidX=true +android.enableJetifier=false #Compose org.jetbrains.compose.experimental.jscanvas.enabled=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0c03901..f43f0ca 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,8 +10,6 @@ androidx-compose = "1.5.4" android-compileSdk = "34" android-targetSdk = "34" android-minSdk = "24" -version = "1.0.0" -versionCode = "1" [plugins] android-application = { id = "com.android.application", version.ref = "agp" } @@ -24,6 +22,9 @@ sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } spotless = { id = "com.diffplug.spotless", version = "6.23.3" } [libraries] +androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.6.1" } +androidx-core = { module = "androidx.core:core-ktx", version = "1.12.0" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version = "1.8.2" } compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "androidx-compose" } ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-core-wasm = { module = "io.ktor:ktor-client-core-wasm", version.ref = "ktor" } @@ -36,9 +37,6 @@ koin-compose = { module = "io.insert-koin:koin-compose", version = "1.1.2" } koin-androidx-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin" } koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version = "1.7.3" } -androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.6.1" } -androidx-core = { module = "androidx.core:core-ktx", version = "1.12.0" } -androidx-activity-compose = { module = "androidx.activity:activity-compose", version = "1.8.2" } material-compose = { module = "androidx.compose.material3:material3", version = "1.2.0-beta01" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version = "1.3.2" } sqldelight-coroutines-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index 8bf8615..9f72b48 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -33,6 +33,13 @@ path = "Preview Content"; sourceTree = ""; }; + 406824592B3B644800E19DB0 /* New Group */ = { + isa = PBXGroup; + children = ( + ); + path = "New Group"; + sourceTree = ""; + }; 42799AB246E5F90AF97AA0EF /* Frameworks */ = { isa = PBXGroup; children = ( @@ -43,6 +50,7 @@ 7555FF72242A565900829871 = { isa = PBXGroup; children = ( + 406824592B3B644800E19DB0 /* New Group */, AB1DB47929225F7C00F7AF9C /* Configuration */, 7555FF7D242A565900829871 /* iosApp */, 7555FF7C242A565900829871 /* Products */, @@ -303,9 +311,11 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1.0.0; DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = EY47F36LGH; + DYLIB_CURRENT_VERSION = 1.0.0; ENABLE_PREVIEWS = YES; FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; INFOPLIST_FILE = iosApp/Info.plist; @@ -336,9 +346,11 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1.0.0; DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = EY47F36LGH; + DYLIB_CURRENT_VERSION = 1.0.0; ENABLE_PREVIEWS = YES; FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; INFOPLIST_FILE = iosApp/Info.plist; diff --git a/scripts/build-number.sh b/scripts/build-number.sh new file mode 100755 index 0000000..28a0bed --- /dev/null +++ b/scripts/build-number.sh @@ -0,0 +1,45 @@ +#!/bin/bash +set -x + +TAGS=$(git show-ref --tags) + +function getBuildNumberTag { + set +e + echo "$TAGS"| grep "${1:-}" | grep -oE 'build-number-[[:digit:]]+' | grep -oE '[[:digit:]]+' | sort -nr | head -1 + set -e +} + +CURRENT_BUILD_NUMBER=$(getBuildNumberTag "$INPUT_SHA") + +OUT=$(echo "$TAGS" | grep -oE 'build-number-[[:digit:]]+') +echo "$OUT" + +if [[ -z "${CURRENT_BUILD_NUMBER}" ]]; then + echo "No build number found for current SHA $INPUT_SHA." + + # Get the latest build number + LATEST_BUILD_NUMBER=$(getBuildNumberTag) + + if [[ -z "${LATEST_BUILD_NUMBER}" ]]; then + echo "No build number found in tags. Please create a tag with the format 'build-number-1' on main branch." + exit 1 + fi + + CURRENT_BUILD_NUMBER="$((LATEST_BUILD_NUMBER + 1))" + git tag "build-number-$CURRENT_BUILD_NUMBER" + + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + GITHUB_URL_PROTOCOL=$(echo "$GITHUB_SERVER_URL" | sed -e 's,^\(.*://\).*,\1,g') + GITHUB_URL_HOST=$(echo "$GITHUB_SERVER_URL" | sed -e 's,^.*://\(.*\),\1,g') + + echo "Pushing build number tag build-number-$CURRENT_BUILD_NUMBER to Github ($GITHUB_REF)." + + git push "${GITHUB_URL_PROTOCOL}${INPUT_GITHUB_TOKEN}@${GITHUB_URL_HOST}/${GITHUB_REPOSITORY}.git" --tags +else + echo "Found build number $CURRENT_BUILD_NUMBER for current SHA $INPUT_SHA." + echo "Skipping tag creation." +fi + +echo "BUILD_NUMBER=$CURRENT_BUILD_NUMBER" >> "$GITHUB_ENV" \ No newline at end of file