Skip to content

Commit

Permalink
Android TLC: 2023 edition (with 2024 goodies) (#65)
Browse files Browse the repository at this point in the history
* Target SDK 33

* Update dependency versions

* First pass at M3 update

* add app launch todo

* Remainder of M3 upgrade

* Dependency updates

* Cleanup M3 upgrade todos

* Use android-build-box 1.25 for Java 17 support

* Update detekt config to remove deprecated rules

* Update detekt plugin version

* Update comment

* Style fixes

* Use Java 17

* Update dependencies and finish M3 upgrade

* Fix ruby lock file?

* In-app update cleanup, update Hilt version, move from kapt to ksp

* Final fixes

* Remove unnecessary themes.xml files

* Remove unused dependencies

* change plugin repo order to optimize builds

* Add back material dependency

* Add CodeQL analysis for Ruby

* Move Ruby analysis to separate workflow

* Rename job for clarity

* Remove redundant comment from Ruby CodeQL workflow

* Trim trailing whitespace in README

* Remove fade transitions from app navigations

* Update release instructions

* Refactor repeated update state code

* Fix bug where optional update bottom sheet background didn't match dark theme

* Fix copy spacing

* Add debug buttons in settings to test update screens

* revert version code change

---------

Co-authored-by: Evan Strat <[email protected]>
Co-authored-by: Kristaps Berzinch <[email protected]>
  • Loading branch information
3 people authored Jul 18, 2024
1 parent b4c6912 commit 2060ef7
Show file tree
Hide file tree
Showing 50 changed files with 1,073 additions and 747 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '11'
java-version: '17'
distribution: 'corretto'
cache: gradle

Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
GOOGLE_PLAY_PRIVATE_KEY: ${{ secrets.GOOGLE_PLAY_PRIVATE_KEY }}
IS_CI: true

- name: Perform CodeQL Analysis
- name: Perform CodeQL Analysis for Java/Kotlin
uses: github/codeql-action/analyze@v3
with:
category: "/language:java-kotlin"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/internal-test-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '11'
java-version: '17'
distribution: 'corretto'
cache: gradle

Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/ruby-codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CodeQL Analysis

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
ruby:

runs-on: ubuntu-latest

permissions:
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ruby
build-mode: none

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:ruby"
66 changes: 20 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ NFC functionality uses the NXP MIFARE TapLinx Android SDK. You must provide a l
license key from the TapLinx Developer Center on https://www.mifare.net/en/products/tools/taplinx/.

Additionally, important licensing information about the TapLinx library is included in the [`libs`](libs)
directory, including the [license](libs/LA_OPT_NXP_Software_License.txt)
directory, including the [license](libs/LA_OPT_NXP_Software_License.txt)
and [Software Content Register](libs/Taplinx_Android_SDK_SCR.txt).

**Note:** For RoboJackets developers, reach out in #apiary-mobile in Slack to obtain our keys.
Expand All @@ -31,7 +31,7 @@ sentryDsn=SENTRY_DSN_HERE
There are 5 modules encompassing features and utilities.

- **app** - The main application module

Note: To avoid circular dependencies, the below modules **must not** have the **app** module as a
dependency. Place such code in the `base` (or a new) module.

Expand All @@ -42,12 +42,12 @@ dependency. Place such code in the `base` (or a new) module.

#### Dependency management

Dependency versions are managed centrally in
Dependency versions are managed centrally in
[Dependencies.kt](buildSrc/src/main/java/Dependencies.kt) in the `buildSrc` module. If you change
a version in `Dependencies.kt`, make sure to manually sync Gradle because Android Studio might not
recognize that the change requires a Gradle sync.

After adding a dependency in `Dependencies.kt`, you must also add it to the appropriate Gradle
After adding a dependency in `Dependencies.kt`, you must also add it to the appropriate Gradle
Script (take a look at a `build.gradle.kts` file for one of the modules for examples).

### Environment configuration
Expand All @@ -73,12 +73,6 @@ is a helpful resource.

Detekt is used for linting Kotlin code. The recommended command to run it is

_(Windows)_
```bash
./gradlew detektAll -PdetektAutoFix=true
```

_(*nix)_
```bash
./gradlew detektAll -PdetektAutoFix=true
```
Expand All @@ -87,7 +81,7 @@ The detektAutoFix parameter will automatically fix simple issues.

### Fastlane

We use Fastlane to automate steps of the Android release process, in combination with Concourse CI.
We use Fastlane to automate steps of the Android release process, in combination with Github Actions.

To install Fastlane, you'll need Ruby with the development kit installed. On Windows, install
the latest 64-bit version of Ruby+Devkit from https://rubyinstaller.org/downloads/.
Expand Down Expand Up @@ -115,44 +109,24 @@ App releases don't have to perfectly coincide with PRs being merged, especially
merged in close proximity. Our Concourse pipeline has jobs to automatically handle building,
signing, and uploading production releases of the app.

1. After you've merged all PRs to be included in the release, ensure the `.update-priority`
file is set correctly according to the table below. Use priority 2 as the default. If you want to
use priority 4 or 5, post in #apiary-mobile first.
1. Update priority affects if and how often users receive in-app update prompts to update the
app to the latest version.

| Update priority | Description | Examples | Update timeline for users |
| --- | --- |--- | --- |
| 0/1/2 | Very low or low priority | UI touchups that don't impact functionality, releases with options to opt-in to beta features | No prompt initially. Optional prompt starting 14 days after release. Immediate update 21 days after release. |
| 3 | Medium priority | Medium-priority bug fixes, performance improvements, non-time-sensitive feature launches | No prompts for the first 3 days. Optional starting 4 days after release. Immediate update 21 days after release. |
| 4 | High priority or time-sensitive | High priority bug fixes, time-sensitive feature launches | Optional for the first 24 hours, then immediate. |
| 5 | Critical bug fixes | Crashes/bugs impacting major features, urgent vulnerabilities | Immediate update required. |

2. Create a new release on `main` using a tag with a name like `v1.0.0`. Use semantic versioning
to determine how to increment the version number.
1. Go to https://github.com/RoboJackets/apiary-mobile/releases
2. Press the **Draft a new release** button.
3. Decide on the new version tag; it **must** start with `v`. In general, you should increment
the previous release's version using [semantic versioning](https://semver.org/) guidelines (most
releases will be a 0.1.0 (minor) or 0.0.1 (patch) increment). Press **Choose a tag**, then enter the
new tag name to create it on publish.
4. Leave **Release title** blank. Instead, press **Generate release notes**. The release title
and description should automatically fill in with the changes since the last release.
1. In general, you shouldn't need to manually set the value of the `Previous tag` field,
unless the release notes seem incorrect.
3. When you publish the release (which creates a new tag), a Concourse job to create a draft Google
Play internal test release will begin shortly.
1. If it doesn't start, a common reason is that it wasn't alphabetically the latest tag, so the
[`tagged-release`](https://concourse.sandbox.aws.robojackets.net/teams/information-technology/pipelines/apiary-mobile/resources/tagged-release)
resource didn't trigger a new build. We can disable old versions of the resource to trigger a new
build.
4. If the Concourse [build-release job](https://concourse.sandbox.aws.robojackets.net/teams/information-technology/pipelines/apiary-mobile/jobs/build-release)
finishes successfully, you'll find a new draft release on the Internal Test track in Google Play.
1. After you've merged all PRs to be included in the release, open the [Release to Internal Test](https://github.com/RoboJackets/apiary-mobile/actions/workflows/internal-test-release.yml)
Github Actions pipeline.
2. Find the `Run workflow` button. Use the table below to enter a value for the `update_priority`.
Update priority is an integer passed to Google Play, and it determines update nag behavior
(frequency/intensity) in the app.

| Update priority | Description | Examples |
|-----------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
| 1 | Optional update with prompts when the update is first available, then every 8 days. | UI touchups that don't impact functionality, releases with options to opt-in to beta features |
| 3 | Optional update with prompts when the update is first available, then every 4 days. | Medium-priority bug fixes, performance improvements, new features |
| 5 | Required update with immediate prompt and no option to decline. | Crashes/bugs impacting major features, urgent vulnerabilities |

3. If the build runs successfully, you'll find a new draft release on the Internal Test track in Google Play.
At this point, you should do some small QA efforts to verify the new build. Post in #apiary-mobile
to have some people help you test. Note that access to the internal test track must be granted via
the Google Play Console.
1. Internal testers may need to uninstall the app to see the update if it was recently published.
6. If no issues are found, it's time to release! Promote the build to the Production track in
4. If no issues are found, it's time to release! Promote the build to the Production track in
Google Play, add release notes, and save the release.
7. Google Play typically spends a day or two reviewing the release, then makes it available. In
5. Google Play typically spends a day or two reviewing the release, then makes it available. In
general, expect it to take at least ~24 hours for a production release to be available to users.
28 changes: 16 additions & 12 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ plugins {
id("com.android.application")
kotlin("android")
id("kotlin-android")
kotlin("kapt")
id("com.google.devtools.ksp")
id("dagger.hilt.android.plugin")
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
id("com.google.android.gms.oss-licenses-plugin")
Expand Down Expand Up @@ -31,30 +31,33 @@ dependencies {

implementation(AuthDependencies.appauth)

implementation(ComposeDependencies.accompanist_nav_material)
implementation(ComposeDependencies.compose_material_navigation)
implementation(ComposeDependencies.compose_ui)
implementation(ComposeDependencies.lifecycle_viewmodel_compose)
implementation(ComposeDependencies.compose_ui_tooling)
implementation(ComposeDependencies.compose_foundation)
implementation(ComposeDependencies.compose_material)
implementation(ComposeDependencies.compose_material3)
implementation(ComposeDependencies.compose_material_icons_core)
implementation(ComposeDependencies.compose_material_icons_extended)
implementation(ComposeDependencies.compose_settings)


implementation(HiltDependencies.hilt)
kapt(HiltDependencies.hilt_android_compiler)
ksp(HiltDependencies.hilt_android_compiler)
implementation(HiltDependencies.hilt_navigation_compose)

implementation(MaterialDependencies.material_android)

implementation(NetworkDependencies.moshi_converter_factory)
implementation(NetworkDependencies.okhttp)
implementation(platform(NetworkDependencies.okhttp_bom))
implementation(NetworkDependencies.okhttp_logging_interceptor)
implementation(NetworkDependencies.retrofit)
implementation(NetworkDependencies.sandwich) // yum yum
implementation(NetworkDependencies.sandwich_retrofit)
implementation(NetworkDependencies.sandwich_retrofit_serialization)

implementation(platform(NfcDependencies.nfc_firebase_bom))
implementation(NfcDependencies.nfc_firebase_core) // Firebase BoM and Core are required when including TapLinx (line below) manually
implementation(NfcDependencies.nfc_firebase_analytics) // Firebase BoM and Analytics (f/k/a Core) are required when including TapLinx (line below) manually
implementation(files(NfcDependencies.nxp_nfc_android_aar_path))

// Test dependencies
Expand All @@ -71,11 +74,11 @@ android {
create("release") {
}
}
compileSdk = 32
compileSdk = 35
defaultConfig {
applicationId = "org.robojackets.apiary"
minSdk = 21
targetSdk = 32
targetSdk = 35
versionCode = 12
versionName = "1.0.0"
vectorDrawables {
Expand All @@ -90,17 +93,18 @@ android {
}
buildFeatures {
compose = true
buildConfig = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
isCoreLibraryDesugaringEnabled = true
}
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = "17"
}
composeOptions {
kotlinCompilerExtensionVersion = "1.2.0-beta03"
kotlinCompilerExtensionVersion = "1.5.1"
}
namespace = "org.robojackets.apiary"
hilt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import io.sentry.android.timber.SentryTimberIntegration
import timber.log.Timber

// Note: this class has to be in the same module as the @AndroidEntryPoint annotated class, which
// is MainActivity. In other words, you can't move this class to another module to solve
// dependency issues (use dependency injection instead!).
// is MainActivity. In other words, you can't move this class to another module to solve dependency
// issues (use dependency injection instead!).
@HiltAndroidApp
class ApiaryMobileApplication : Application() {
override fun onCreate() {
Expand Down
Loading

0 comments on commit 2060ef7

Please sign in to comment.