Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Android CI/CD #38

Merged
merged 3 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/dev-build-upload-android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Android Build & Deploy

on:
workflow_dispatch:
# push:
# branches: ["dev"]

jobs:
deploy:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x]
ruby-version: [3.3]

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- name: "Set login password for downloading mapbox SDK"
uses: extractions/netrc@v2
with:
machine: api.mapbox.com
username: mapbox
password: ${{ secrets.MAPBOX_SDK_REGISTRY_TOKEN }}
- run: npm ci
- name: Install Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true
working-directory: android

- name: Run tests
run: bundle exec fastlane android test

- name: Decode Service Account Key JSON File
uses: timheuer/base64-to-file@v1
id: service_account_json_file
with:
fileName: "serviceAccount.json"
encodedString: ${{ secrets.GPLAY_SERVICE_ACCOUNT_KEY_JSON }}

- name: Decode Keystore File
uses: timheuer/base64-to-file@v1
id: android_keystore
with:
fileName: "android_keystore.keystore"
encodedString: ${{ secrets.KEYSTORE_FILE }}

- name: Build & deploy Android release
run: bundle exec fastlane android deploy
env:
KEYSTORE_FILE: ${{ steps.android_keystore.outputs.filePath }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS}}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ANDROID_JSON_KEY_FILE: ${{ steps.service_account_json_file.outputs.filePath }}

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: assets
path: |
${{ github.workspace }}/android/app/build/outputs/bundle/release
2 changes: 1 addition & 1 deletion .github/workflows/dev-build-upload-ios.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# See https://www.runway.team/blog/how-to-set-up-a-ci-cd-pipeline-for-your-ios-app-fastlane-github-actions

name: Build iOS and upload to Testflight
name: iOS Build and Deploy

on:
push:
Expand Down
8 changes: 8 additions & 0 deletions android/Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
source "https://rubygems.org"

gem "fastlane"
gem "screengrab"

# To Resolve warnings about libraries removed in Ruby 3.4.0
gem "mutex_m"
gem "abbrev"

plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)
9 changes: 9 additions & 0 deletions android/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ GEM
base64
nkf
rexml
abbrev (0.1.2)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.17)
Expand Down Expand Up @@ -109,6 +110,7 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-plugin-increment_version_code (0.4.3)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
Expand Down Expand Up @@ -158,6 +160,7 @@ GEM
mini_mime (1.1.5)
multi_json (1.15.0)
multipart-post (2.4.0)
mutex_m (0.2.0)
nanaimo (0.3.0)
naturally (2.2.1)
nkf (0.2.0)
Expand All @@ -175,6 +178,8 @@ GEM
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
screengrab (1.0.0)
fastlane (>= 2.0.0, < 3.0.0)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
Expand Down Expand Up @@ -212,7 +217,11 @@ PLATFORMS
ruby

DEPENDENCIES
abbrev
fastlane
fastlane-plugin-increment_version_code
mutex_m
screengrab

BUNDLED WITH
2.5.4
34 changes: 28 additions & 6 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,19 @@ android {
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion

namespace "com.oneboulder"
buildFeatures {
buildConfig true
}

namespace "one.oneboulder.one"
defaultConfig {
applicationId "com.oneboulder"
applicationId "one.oneboulder.one"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
versionCode 7
versionName "1.0.4"
missingDimensionStrategy 'react-native-camera', 'general'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
signingConfigs {
debug {
Expand All @@ -90,17 +95,25 @@ android {
keyAlias 'androiddebugkey'
keyPassword 'android'
}
release {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
applicationIdSuffix ".debug"
debuggable true
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
}
Expand All @@ -115,6 +128,15 @@ dependencies {
} else {
implementation jscFlavor
}

testImplementation 'junit:junit:4.13.2'

androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test:rules:1.5.0'

androidTestImplementation 'tools.fastlane:screengrab:2.1.1'
androidTestImplementation 'com.jraska:falcon:2.2.0'
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
54 changes: 53 additions & 1 deletion android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,10 +1,62 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# in /usr/local/opt/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-dontwarn okio.**
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions


# OkHttp rules

# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**

# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*

# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.internal.platform.ConscryptPlatform


# Retrofit rules

# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response

# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
61 changes: 61 additions & 0 deletions android/app/src/androidTest/ExampleInstrumentedTest
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package one.oneboulder.one

import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*
import org.junit.Rule
import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy
import tools.fastlane.screengrab.locale.LocaleTestRule

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {

// JVMField needed!
@Rule
@JvmField
val localeTestRule = LocaleTestRule()

@get:Rule
var activityRule = ActivityTestRule(MainActivity::class.java, false, false)

@Test
fun testTakeScreenshot() {
activityRule.launchActivity(null)
//prepares to take a screenshot of the app
Screengrab.setDefaultScreenshotStrategy(UiAutomatorScreenshotStrategy())

Espresso.onView(ViewMatchers.withId(R.id.generateButton))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
//Takes screenshot of the first screen
Screengrab.screenshot("myAvatar_before_click")

//Trigger the generate button onClick function
Espresso.onView(ViewMatchers.withId(R.id.genrateButton))
.perform(ViewActions.click())

//Takes another screenshot
Screengrab.screenshot("myAvatar_after_click")
}

@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("one.oneboulder.one", appContext.packageName)
}
}
14 changes: 14 additions & 0 deletions android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<!-- Allows unlocking your device and activating its screen so UI tests can succeed -->
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- Allows for storing and retrieving screenshots -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<!-- Allows changing locales -->
<uses-permission
android:name="android.permission.CHANGE_CONFIGURATION"
tools:ignore="ProtectedPermissions" />

<application
android:usesCleartextTraffic="true"
tools:targetApi="28"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.oneboulder
package one.oneboulder.one

import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.oneboulder
package one.oneboulder.one

import android.app.Application
import com.facebook.react.PackageList
Expand Down
Loading
Loading