Merge pull request #106 from ouchadam/release-candidate
[Auto] Release Candidate
This commit is contained in:
commit
c580bcbdab
|
@ -24,4 +24,6 @@ jobs:
|
|||
- uses: gradle/gradle-build-action@v2
|
||||
|
||||
- name: Assemble debug variant
|
||||
run: ./gradlew assembleDebug --no-daemon
|
||||
run: |
|
||||
./gradlew assembleDebug --no-daemon
|
||||
./gradlew assembleDebug -Pfoss --no-daemon
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
name: Nightly
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 19 * * *'
|
||||
|
||||
jobs:
|
||||
check-develop-beta-changes:
|
||||
name: Check if develop is ahead of beta release
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version:
|
||||
16
|
||||
- run: npm ci
|
||||
working-directory: ./tools/beta-release/
|
||||
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const { startReleaseProcess } = await import('${{ github.workspace }}/tools/beta-release/app.js')
|
||||
await startReleaseProcess({github, context, core})
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
name: Generate and publish Release Candidate
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'release'
|
||||
|
||||
jobs:
|
||||
publish-release-candidate:
|
||||
name: Publish release candidate
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version:
|
||||
16
|
||||
- run: npm ci
|
||||
working-directory: ./tools/beta-release/
|
||||
|
||||
- name: Write secrets
|
||||
run: |
|
||||
mkdir .secrets
|
||||
touch .secrets/upload-key.jks
|
||||
touch .secrets/service-account.json
|
||||
echo -n '${{ secrets.UPLOAD_KEY }}' | base64 --decode >> .secrets/upload-key.jks
|
||||
echo -n '${{ secrets.SERVICE_ACCOUNT }}' | base64 --decode >> .secrets/service-account.json
|
||||
|
||||
- name: Assemble release variant
|
||||
run: ./tools/generate-release.sh ${{ secrets.STORE_PASS }}
|
||||
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const { publishRelease } = await import('${{ github.workspace }}/tools/beta-release/app.js')
|
||||
const artifacts = {
|
||||
bundle: '${{ github.workspace }}/app/build/outputs/bundle/release/app-release.aab',
|
||||
mapping: '${{ github.workspace }}/app/build/outputs/mapping/release/mapping.txt',
|
||||
}
|
||||
await publishRelease(github, artifacts)
|
||||
|
|
@ -10,4 +10,6 @@
|
|||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
/benchmark-out
|
||||
/benchmark-out
|
||||
**/node_modules
|
||||
.secrets
|
35
README.md
35
README.md
|
@ -16,8 +16,6 @@
|
|||
- Focused on reliability and stability.
|
||||
- Bare-bones feature set.
|
||||
|
||||
##### _*Google play only with automatic crash reporting enabled_
|
||||
|
||||
---
|
||||
|
||||
### Feature list
|
||||
|
@ -28,7 +26,8 @@
|
|||
- Message bubbles, supporting text, replies and edits
|
||||
- Push notifications (DMs always notify, Rooms notify once)
|
||||
- Importing of E2E room keys from Element clients
|
||||
- [UnifiedPush](https://unifiedpush.org/)
|
||||
- [UnifiedPush](https://unifiedpush.org/)
|
||||
- FOSS variant
|
||||
|
||||
### Planned
|
||||
|
||||
|
@ -57,4 +56,34 @@
|
|||
|
||||
---
|
||||
|
||||
|
||||
### Building
|
||||
|
||||
|
||||
##### Debug `.apk`
|
||||
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
|
||||
##### Release (signed with debug key) `.apk`
|
||||
|
||||
```bash
|
||||
./gradlew assembleRelease
|
||||
```
|
||||
|
||||
##### Unsigned release `.apk`
|
||||
|
||||
```bash
|
||||
./gradlew assembleRelease -Punsigned
|
||||
```
|
||||
|
||||
##### Unsigned release (FOSS) `.apk`
|
||||
|
||||
```bash
|
||||
./gradlew assembleRelease -Punsigned -Pfoss
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Join the conversation @ https://matrix.to/#/#small-talk:iswell.cool
|
||||
|
|
|
@ -24,6 +24,10 @@ android {
|
|||
} else {
|
||||
resConfigs "en"
|
||||
}
|
||||
|
||||
if (isFoss()) {
|
||||
archivesBaseName = "$archivesBaseName-foss"
|
||||
}
|
||||
}
|
||||
|
||||
bundle {
|
||||
|
@ -46,8 +50,11 @@ android {
|
|||
"proguard/serializationx.pro",
|
||||
"proguard/olm.pro"
|
||||
|
||||
// actual releases are signed with a different config
|
||||
signingConfig = buildTypes.debug.signingConfig
|
||||
if (project.hasProperty("unsigned")) {
|
||||
// releases are signed externally
|
||||
} else {
|
||||
signingConfig = buildTypes.debug.signingConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +89,8 @@ dependencies {
|
|||
implementation project(":domains:android:imageloader")
|
||||
implementation project(":domains:olm")
|
||||
|
||||
firebase(it, "messaging")
|
||||
|
||||
implementation project(":matrix:matrix")
|
||||
implementation project(":matrix:matrix-http-ktor")
|
||||
implementation project(":matrix:services:auth")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package app.dapk.st
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import app.dapk.st.core.CoreAndroidModule
|
||||
import app.dapk.st.core.ModuleProvider
|
||||
|
@ -11,13 +10,13 @@ import app.dapk.st.core.extensions.ResettableUnsafeLazy
|
|||
import app.dapk.st.core.extensions.Scope
|
||||
import app.dapk.st.directory.DirectoryModule
|
||||
import app.dapk.st.domain.StoreModule
|
||||
import app.dapk.st.firebase.messaging.MessagingModule
|
||||
import app.dapk.st.graph.AppModule
|
||||
import app.dapk.st.home.HomeModule
|
||||
import app.dapk.st.login.LoginModule
|
||||
import app.dapk.st.messenger.MessengerModule
|
||||
import app.dapk.st.notifications.NotificationsModule
|
||||
import app.dapk.st.profile.ProfileModule
|
||||
import app.dapk.st.push.firebase.FirebasePushService
|
||||
import app.dapk.st.push.PushModule
|
||||
import app.dapk.st.settings.SettingsModule
|
||||
import app.dapk.st.share.ShareEntryModule
|
||||
|
@ -75,6 +74,7 @@ class SmallTalkApplication : Application(), ModuleProvider {
|
|||
ProfileModule::class -> featureModules.profileModule
|
||||
NotificationsModule::class -> featureModules.notificationsModule
|
||||
PushModule::class -> featureModules.pushModule
|
||||
MessagingModule::class -> featureModules.messagingModule
|
||||
MessengerModule::class -> featureModules.messengerModule
|
||||
TaskRunnerModule::class -> appModule.domainModules.taskRunnerModule
|
||||
CoreAndroidModule::class -> appModule.coreAndroidModule
|
||||
|
|
|
@ -16,6 +16,7 @@ import app.dapk.st.core.extensions.ErrorTracker
|
|||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
import app.dapk.st.directory.DirectoryModule
|
||||
import app.dapk.st.domain.StoreModule
|
||||
import app.dapk.st.firebase.messaging.MessagingModule
|
||||
import app.dapk.st.home.HomeModule
|
||||
import app.dapk.st.home.MainActivity
|
||||
import app.dapk.st.imageloader.ImageLoaderModule
|
||||
|
@ -55,6 +56,7 @@ import app.dapk.st.olm.OlmPersistenceWrapper
|
|||
import app.dapk.st.olm.OlmWrapper
|
||||
import app.dapk.st.profile.ProfileModule
|
||||
import app.dapk.st.push.PushModule
|
||||
import app.dapk.st.push.messaging.MessagingServiceAdapter
|
||||
import app.dapk.st.settings.SettingsModule
|
||||
import app.dapk.st.share.ShareEntryModule
|
||||
import app.dapk.st.tracking.TrackingModule
|
||||
|
@ -208,6 +210,10 @@ internal class FeatureModules internal constructor(
|
|||
domainModules.pushModule
|
||||
}
|
||||
|
||||
val messagingModule by unsafeLazy {
|
||||
domainModules.messaging
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class MatrixModules(
|
||||
|
@ -428,23 +434,30 @@ internal class DomainModules(
|
|||
private val dispatchers: CoroutineDispatchers,
|
||||
) {
|
||||
|
||||
val pushModule by unsafeLazy {
|
||||
val pushHandler by unsafeLazy {
|
||||
val store = storeModule.value
|
||||
val pushHandler = MatrixPushHandler(
|
||||
MatrixPushHandler(
|
||||
workScheduler = workModule.workScheduler(),
|
||||
credentialsStore = store.credentialsStore(),
|
||||
matrixModules.sync,
|
||||
store.roomStore(),
|
||||
)
|
||||
}
|
||||
|
||||
val messaging by unsafeLazy { MessagingModule(MessagingServiceAdapter(pushHandler), context) }
|
||||
|
||||
val pushModule by unsafeLazy {
|
||||
PushModule(
|
||||
errorTracker,
|
||||
pushHandler,
|
||||
context,
|
||||
dispatchers,
|
||||
SharedPreferencesDelegate(context.applicationContext, fileName = "dapk-user-preferences", dispatchers)
|
||||
SharedPreferencesDelegate(context.applicationContext, fileName = "dapk-user-preferences", dispatchers),
|
||||
messaging.messaging,
|
||||
)
|
||||
}
|
||||
val taskRunnerModule by unsafeLazy { TaskRunnerModule(TaskRunnerAdapter(matrixModules.matrix::run, AppTaskRunner(matrixModules.push))) }
|
||||
|
||||
}
|
||||
|
||||
internal class AndroidImageContentReader(private val contentResolver: ContentResolver) : ImageContentReader {
|
||||
|
|
17
build.gradle
17
build.gradle
|
@ -118,7 +118,7 @@ ext.applyAndroidLibraryModule = { project ->
|
|||
}
|
||||
|
||||
ext.applyCrashlyticsIfRelease = { project ->
|
||||
if (isReleaseBuild) {
|
||||
if (isReleaseBuild && !isFoss()) {
|
||||
project.apply plugin: 'com.google.firebase.crashlytics'
|
||||
project.afterEvaluate {
|
||||
project.tasks.withType(com.google.firebase.crashlytics.buildtools.gradle.tasks.UploadMappingFileTask).configureEach {
|
||||
|
@ -151,6 +151,19 @@ ext.androidImportFixturesWorkaround = { project, fixtures ->
|
|||
project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}.jar")
|
||||
}
|
||||
|
||||
ext.isFoss = {
|
||||
return rootProject.hasProperty("foss")
|
||||
}
|
||||
|
||||
ext.firebase = { dependencies, name ->
|
||||
if (isFoss()) {
|
||||
dependencies.implementation(project(":domains:firebase:$name-noop"))
|
||||
} else {
|
||||
dependencies.implementation(project(":domains:firebase:$name"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (launchTask.contains("codeCoverageReport".toLowerCase())) {
|
||||
apply from: 'tools/coverage.gradle'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,9 @@ dependencies {
|
|||
implementation project(':domains:android:core')
|
||||
implementation project(':domains:store')
|
||||
implementation project(':matrix:services:push')
|
||||
implementation platform('com.google.firebase:firebase-bom:29.0.3')
|
||||
implementation 'com.google.firebase:firebase-messaging'
|
||||
|
||||
firebase(it, "messaging")
|
||||
|
||||
implementation Dependencies.mavenCentral.kotlinSerializationJson
|
||||
implementation Dependencies.jitPack.unifiedPush
|
||||
}
|
||||
|
|
|
@ -2,15 +2,6 @@
|
|||
<manifest package="app.dapk.st.push" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
|
||||
<service
|
||||
android:name=".firebase.FirebasePushService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver android:exported="true" android:enabled="true" android:name=".unifiedpush.UnifiedPushMessageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
|
||||
|
|
|
@ -7,7 +7,8 @@ import app.dapk.st.core.extensions.ErrorTracker
|
|||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
import app.dapk.st.domain.Preferences
|
||||
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
||||
import app.dapk.st.push.firebase.FirebasePushTokenRegistrar
|
||||
import app.dapk.st.firebase.messaging.Messaging
|
||||
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
||||
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
||||
|
||||
class PushModule(
|
||||
|
@ -16,15 +17,16 @@ class PushModule(
|
|||
private val context: Context,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val preferences: Preferences,
|
||||
private val messaging: Messaging,
|
||||
) : ProvidableModule {
|
||||
|
||||
private val registrars by unsafeLazy {
|
||||
PushTokenRegistrars(
|
||||
context,
|
||||
FirebasePushTokenRegistrar(
|
||||
MessagingPushTokenRegistrar(
|
||||
errorTracker,
|
||||
context,
|
||||
pushHandler,
|
||||
messaging,
|
||||
),
|
||||
UnifiedPushRegistrar(context),
|
||||
PushTokenRegistrarPreferences(preferences)
|
||||
|
|
|
@ -2,7 +2,7 @@ package app.dapk.st.push
|
|||
|
||||
import android.content.Context
|
||||
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
|
||||
import app.dapk.st.push.firebase.FirebasePushTokenRegistrar
|
||||
import app.dapk.st.push.messaging.MessagingPushTokenRegistrar
|
||||
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
|
||||
|
@ -11,7 +11,7 @@ private val NONE = Registrar("None")
|
|||
|
||||
class PushTokenRegistrars(
|
||||
private val context: Context,
|
||||
private val firebasePushTokenRegistrar: FirebasePushTokenRegistrar,
|
||||
private val messagingPushTokenRegistrar: MessagingPushTokenRegistrar,
|
||||
private val unifiedPushRegistrar: UnifiedPushRegistrar,
|
||||
private val pushTokenStore: PushTokenRegistrarPreferences,
|
||||
) : PushTokenRegistrar {
|
||||
|
@ -19,27 +19,36 @@ class PushTokenRegistrars(
|
|||
private var selection: Registrar? = null
|
||||
|
||||
fun options(): List<Registrar> {
|
||||
return listOf(NONE, FIREBASE_OPTION) + UnifiedPush.getDistributors(context).map { Registrar(it) }
|
||||
val messagingOption = when (messagingPushTokenRegistrar.isAvailable()) {
|
||||
true -> FIREBASE_OPTION
|
||||
else -> null
|
||||
}
|
||||
return listOfNotNull(NONE, messagingOption) + UnifiedPush.getDistributors(context).map { Registrar(it) }
|
||||
}
|
||||
|
||||
suspend fun currentSelection() = selection ?: (pushTokenStore.currentSelection()?.let { Registrar(it) } ?: FIREBASE_OPTION).also { selection = it }
|
||||
suspend fun currentSelection() = selection ?: (pushTokenStore.currentSelection()?.let { Registrar(it) } ?: defaultSelection()).also { selection = it }
|
||||
|
||||
private fun defaultSelection() = when (messagingPushTokenRegistrar.isAvailable()) {
|
||||
true -> FIREBASE_OPTION
|
||||
else -> NONE
|
||||
}
|
||||
|
||||
suspend fun makeSelection(option: Registrar) {
|
||||
selection = option
|
||||
pushTokenStore.store(option.id)
|
||||
when (option) {
|
||||
NONE -> {
|
||||
firebasePushTokenRegistrar.unregister()
|
||||
messagingPushTokenRegistrar.unregister()
|
||||
unifiedPushRegistrar.unregister()
|
||||
}
|
||||
|
||||
FIREBASE_OPTION -> {
|
||||
unifiedPushRegistrar.unregister()
|
||||
firebasePushTokenRegistrar.registerCurrentToken()
|
||||
messagingPushTokenRegistrar.registerCurrentToken()
|
||||
}
|
||||
|
||||
else -> {
|
||||
firebasePushTokenRegistrar.unregister()
|
||||
messagingPushTokenRegistrar.unregister()
|
||||
unifiedPushRegistrar.registerSelection(option)
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +56,7 @@ class PushTokenRegistrars(
|
|||
|
||||
override suspend fun registerCurrentToken() {
|
||||
when (selection) {
|
||||
FIREBASE_OPTION -> firebasePushTokenRegistrar.registerCurrentToken()
|
||||
FIREBASE_OPTION -> messagingPushTokenRegistrar.registerCurrentToken()
|
||||
NONE -> {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -58,10 +67,10 @@ class PushTokenRegistrars(
|
|||
|
||||
override fun unregister() {
|
||||
when (selection) {
|
||||
FIREBASE_OPTION -> firebasePushTokenRegistrar.unregister()
|
||||
FIREBASE_OPTION -> messagingPushTokenRegistrar.unregister()
|
||||
NONE -> {
|
||||
runCatching {
|
||||
firebasePushTokenRegistrar.unregister()
|
||||
messagingPushTokenRegistrar.unregister()
|
||||
unifiedPushRegistrar.unregister()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package app.dapk.st.push.firebase
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
suspend fun FirebaseMessaging.token() = suspendCoroutine<String> { continuation ->
|
||||
this.token.addOnCompleteListener { task ->
|
||||
when {
|
||||
task.isSuccessful -> continuation.resume(task.result!!)
|
||||
task.isCanceled -> continuation.resumeWith(Result.failure(CancelledTokenFetchingException()))
|
||||
else -> continuation.resumeWith(Result.failure(task.exception ?: UnknownTokenFetchingFailedException()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CancelledTokenFetchingException : Throwable()
|
||||
private class UnknownTokenFetchingFailedException : Throwable()
|
|
@ -1,37 +1,28 @@
|
|||
package app.dapk.st.push.firebase
|
||||
package app.dapk.st.push.messaging
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import app.dapk.st.core.AppLogTag
|
||||
import app.dapk.st.core.extensions.CrashScope
|
||||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import app.dapk.st.core.log
|
||||
import app.dapk.st.firebase.messaging.Messaging
|
||||
import app.dapk.st.push.PushHandler
|
||||
import app.dapk.st.push.PushTokenPayload
|
||||
import app.dapk.st.push.PushTokenRegistrar
|
||||
import app.dapk.st.push.unifiedpush.UnifiedPushMessageReceiver
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
|
||||
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
|
||||
|
||||
class FirebasePushTokenRegistrar(
|
||||
class MessagingPushTokenRegistrar(
|
||||
override val errorTracker: ErrorTracker,
|
||||
private val context: Context,
|
||||
private val pushHandler: PushHandler,
|
||||
private val messaging: Messaging,
|
||||
) : PushTokenRegistrar, CrashScope {
|
||||
|
||||
override suspend fun registerCurrentToken() {
|
||||
log(AppLogTag.PUSH, "FCM - register current token")
|
||||
context.packageManager.setComponentEnabledSetting(
|
||||
ComponentName(context, FirebasePushService::class.java),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
)
|
||||
messaging.enable()
|
||||
|
||||
kotlin.runCatching {
|
||||
FirebaseMessaging.getInstance().token().also {
|
||||
messaging.token().also {
|
||||
pushHandler.onNewToken(
|
||||
PushTokenPayload(
|
||||
token = it,
|
||||
|
@ -48,14 +39,10 @@ class FirebasePushTokenRegistrar(
|
|||
|
||||
override fun unregister() {
|
||||
log(AppLogTag.PUSH, "FCM - unregister")
|
||||
FirebaseMessaging.getInstance().deleteToken()
|
||||
context.stopService(Intent(context, FirebasePushService::class.java))
|
||||
|
||||
context.packageManager.setComponentEnabledSetting(
|
||||
ComponentName(context, FirebasePushService::class.java),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
)
|
||||
messaging.deleteToken()
|
||||
messaging.disable()
|
||||
}
|
||||
|
||||
fun isAvailable() = messaging.isAvailable()
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package app.dapk.st.push.messaging
|
||||
|
||||
import app.dapk.st.core.AppLogTag
|
||||
import app.dapk.st.core.log
|
||||
import app.dapk.st.firebase.messaging.ServiceDelegate
|
||||
import app.dapk.st.matrix.common.EventId
|
||||
import app.dapk.st.matrix.common.RoomId
|
||||
import app.dapk.st.push.PushHandler
|
||||
import app.dapk.st.push.PushTokenPayload
|
||||
|
||||
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
|
||||
|
||||
class MessagingServiceAdapter(
|
||||
private val handler: PushHandler,
|
||||
) : ServiceDelegate {
|
||||
|
||||
override fun onNewToken(token: String) {
|
||||
log(AppLogTag.PUSH, "FCM onNewToken")
|
||||
handler.onNewToken(
|
||||
PushTokenPayload(
|
||||
token = token,
|
||||
gatewayUrl = SYGNAL_GATEWAY,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onMessageReceived(eventId: EventId?, roomId: RoomId?) {
|
||||
log(AppLogTag.PUSH, "FCM onMessage")
|
||||
handler.onMessageReceived(eventId, roomId)
|
||||
}
|
||||
}
|
|
@ -2,9 +2,5 @@ applyAndroidLibraryModule(project)
|
|||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
implementation platform('com.google.firebase:firebase-bom:29.0.3')
|
||||
implementation 'com.google.firebase:firebase-crashlytics'
|
||||
|
||||
// is it worth the 400kb size increase?
|
||||
// implementation 'com.google.firebase:firebase-analytics'
|
||||
firebase(it, "crashlytics")
|
||||
}
|
||||
|
|
|
@ -4,16 +4,12 @@ import android.util.Log
|
|||
import app.dapk.st.core.AppLogTag
|
||||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import app.dapk.st.core.log
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
||||
class CrashlyticsCrashTracker(
|
||||
private val firebaseCrashlytics: FirebaseCrashlytics,
|
||||
) : ErrorTracker {
|
||||
class CrashTrackerLogger : ErrorTracker {
|
||||
|
||||
override fun track(throwable: Throwable, extra: String) {
|
||||
Log.e("ST", throwable.message, throwable)
|
||||
log(AppLogTag.ERROR_NON_FATAL, "${throwable.message ?: "N/A"} extra=$extra")
|
||||
firebaseCrashlytics.recordException(throwable)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
package app.dapk.st.tracking
|
||||
|
||||
import android.util.Log
|
||||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import app.dapk.st.firebase.crashlytics.CrashlyticsModule
|
||||
|
||||
class TrackingModule(
|
||||
private val isCrashTrackingEnabled: Boolean,
|
||||
|
@ -11,13 +10,18 @@ class TrackingModule(
|
|||
|
||||
val errorTracker: ErrorTracker by unsafeLazy {
|
||||
when (isCrashTrackingEnabled) {
|
||||
true -> CrashlyticsCrashTracker(FirebaseCrashlytics.getInstance())
|
||||
false -> object : ErrorTracker {
|
||||
override fun track(throwable: Throwable, extra: String) {
|
||||
Log.e("error", throwable.message, throwable)
|
||||
}
|
||||
}
|
||||
true -> compositeTracker(
|
||||
CrashTrackerLogger(),
|
||||
CrashlyticsModule().errorTracker,
|
||||
)
|
||||
false -> CrashTrackerLogger()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun compositeTracker(vararg loggers: ErrorTracker) = object : ErrorTracker {
|
||||
override fun track(throwable: Throwable, extra: String) {
|
||||
loggers.forEach { it.track(throwable, extra) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
plugins { id 'kotlin' }
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package app.dapk.st.firebase.crashlytics
|
||||
|
||||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
|
||||
class CrashlyticsModule {
|
||||
|
||||
val errorTracker: ErrorTracker by unsafeLazy {
|
||||
object : ErrorTracker {
|
||||
override fun track(throwable: Throwable, extra: String) {
|
||||
// no op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
applyAndroidLibraryModule(project)
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
implementation platform('com.google.firebase:firebase-bom:29.0.3')
|
||||
implementation 'com.google.firebase:firebase-crashlytics'
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="app.dapk.st.firebase.crashlytics"/>
|
|
@ -0,0 +1,14 @@
|
|||
package app.dapk.st.firebase.crashlytics
|
||||
|
||||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
||||
class CrashlyticsCrashTracker(
|
||||
private val firebaseCrashlytics: FirebaseCrashlytics,
|
||||
) : ErrorTracker {
|
||||
|
||||
override fun track(throwable: Throwable, extra: String) {
|
||||
firebaseCrashlytics.recordException(throwable)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package app.dapk.st.firebase.crashlytics
|
||||
|
||||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
||||
class CrashlyticsModule {
|
||||
|
||||
val errorTracker: ErrorTracker by unsafeLazy {
|
||||
CrashlyticsCrashTracker(FirebaseCrashlytics.getInstance())
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
applyAndroidLibraryModule(project)
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
implementation project(':matrix:common')
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="app.dapk.st.firebase.messaging"/>
|
|
@ -0,0 +1,23 @@
|
|||
package app.dapk.st.firebase.messaging
|
||||
|
||||
class Messaging {
|
||||
|
||||
fun isAvailable() = false
|
||||
|
||||
fun enable() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fun disable() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fun deleteToken() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
suspend fun token(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package app.dapk.st.firebase.messaging
|
||||
|
||||
import android.content.Context
|
||||
import app.dapk.st.core.ProvidableModule
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
|
||||
@Suppress("UNUSED")
|
||||
class MessagingModule(
|
||||
val serviceDelegate: ServiceDelegate,
|
||||
val context: Context,
|
||||
) : ProvidableModule {
|
||||
|
||||
val messaging by unsafeLazy {
|
||||
Messaging()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package app.dapk.st.firebase.messaging
|
||||
|
||||
import app.dapk.st.matrix.common.EventId
|
||||
import app.dapk.st.matrix.common.RoomId
|
||||
|
||||
interface ServiceDelegate {
|
||||
fun onNewToken(token: String)
|
||||
fun onMessageReceived(eventId: EventId?, roomId: RoomId?)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
applyAndroidLibraryModule(project)
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
implementation project(':domains:android:core')
|
||||
implementation project(':matrix:common')
|
||||
implementation platform('com.google.firebase:firebase-bom:29.0.3')
|
||||
implementation 'com.google.firebase:firebase-messaging'
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="app.dapk.st.firebase.messaging" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
|
||||
<service
|
||||
android:name=".FirebasePushServiceDelegate"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -1,4 +1,4 @@
|
|||
package app.dapk.st.push.firebase
|
||||
package app.dapk.st.firebase.messaging
|
||||
|
||||
import app.dapk.st.core.AppLogTag
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
|
@ -6,31 +6,21 @@ import app.dapk.st.core.log
|
|||
import app.dapk.st.core.module
|
||||
import app.dapk.st.matrix.common.EventId
|
||||
import app.dapk.st.matrix.common.RoomId
|
||||
import app.dapk.st.push.PushModule
|
||||
import app.dapk.st.push.PushTokenPayload
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
|
||||
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
|
||||
class FirebasePushServiceDelegate : FirebaseMessagingService() {
|
||||
|
||||
class FirebasePushService : FirebaseMessagingService() {
|
||||
|
||||
private val handler by unsafeLazy { module<PushModule>().pushHandler() }
|
||||
private val delegate by unsafeLazy { module<MessagingModule>().serviceDelegate }
|
||||
|
||||
override fun onNewToken(token: String) {
|
||||
log(AppLogTag.PUSH, "FCM onNewToken")
|
||||
handler.onNewToken(
|
||||
PushTokenPayload(
|
||||
token = token,
|
||||
gatewayUrl = SYGNAL_GATEWAY,
|
||||
)
|
||||
)
|
||||
delegate.onNewToken(token)
|
||||
}
|
||||
|
||||
override fun onMessageReceived(message: RemoteMessage) {
|
||||
log(AppLogTag.PUSH, "FCM onMessage")
|
||||
val eventId = message.data["event_id"]?.let { EventId(it) }
|
||||
val roomId = message.data["room_id"]?.let { RoomId(it) }
|
||||
handler.onMessageReceived(eventId, roomId)
|
||||
delegate.onMessageReceived(eventId, roomId)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package app.dapk.st.firebase.messaging
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import com.google.android.gms.common.ConnectionResult
|
||||
import com.google.android.gms.common.GoogleApiAvailabilityLight
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class Messaging(
|
||||
private val instance: FirebaseMessaging,
|
||||
private val context: Context,
|
||||
) {
|
||||
|
||||
fun isAvailable() = GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS
|
||||
|
||||
fun enable() {
|
||||
context.packageManager.setComponentEnabledSetting(
|
||||
ComponentName(context, FirebasePushServiceDelegate::class.java),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
)
|
||||
}
|
||||
|
||||
fun disable() {
|
||||
context.stopService(Intent(context, FirebasePushServiceDelegate::class.java))
|
||||
context.packageManager.setComponentEnabledSetting(
|
||||
ComponentName(context, FirebasePushServiceDelegate::class.java),
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fun deleteToken() {
|
||||
instance.deleteToken()
|
||||
}
|
||||
|
||||
suspend fun token() = suspendCoroutine { continuation ->
|
||||
instance.token.addOnCompleteListener { task ->
|
||||
when {
|
||||
task.isSuccessful -> continuation.resume(task.result!!)
|
||||
task.isCanceled -> continuation.resumeWith(Result.failure(CancelledTokenFetchingException()))
|
||||
else -> continuation.resumeWith(Result.failure(task.exception ?: UnknownTokenFetchingFailedException()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CancelledTokenFetchingException : Throwable()
|
||||
private class UnknownTokenFetchingFailedException : Throwable()
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package app.dapk.st.firebase.messaging
|
||||
|
||||
import android.content.Context
|
||||
import app.dapk.st.core.ProvidableModule
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
|
||||
class MessagingModule(
|
||||
val serviceDelegate: ServiceDelegate,
|
||||
val context: Context,
|
||||
) : ProvidableModule {
|
||||
|
||||
val messaging by unsafeLazy {
|
||||
Messaging(FirebaseMessaging.getInstance(), context)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package app.dapk.st.firebase.messaging
|
||||
|
||||
import app.dapk.st.matrix.common.EventId
|
||||
import app.dapk.st.matrix.common.RoomId
|
||||
|
||||
interface ServiceDelegate {
|
||||
fun onNewToken(token: String)
|
||||
fun onMessageReceived(eventId: EventId?, roomId: RoomId?)
|
||||
}
|
|
@ -34,6 +34,11 @@ include ':domains:store'
|
|||
include ':domains:olm-stub'
|
||||
include ':domains:olm'
|
||||
|
||||
include ':domains:firebase:crashlytics'
|
||||
include ':domains:firebase:crashlytics-noop'
|
||||
include ':domains:firebase:messaging'
|
||||
include ':domains:firebase:messaging-noop'
|
||||
|
||||
include ':matrix:matrix'
|
||||
include ':matrix:common'
|
||||
include ':matrix:matrix-http'
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
import { release } from './release.js'
|
||||
|
||||
const config = {
|
||||
owner: "ouchadam",
|
||||
repo: "small-talk",
|
||||
pathToVersionFile: "version.json",
|
||||
rcBranchesFrom: "main",
|
||||
rcMergesTo: "release",
|
||||
packageName: "app.dapk.st"
|
||||
}
|
||||
|
||||
const rcBranchName = "release-candidate"
|
||||
|
||||
export const startReleaseProcess = async ({ github, context, core }) => {
|
||||
console.log("script start")
|
||||
if (await doesNotHaveInProgressRelease(github) && await isWorkingBranchAhead(github)) {
|
||||
await startRelease(github)
|
||||
} else {
|
||||
console.log(`Release skipped due to being behind`)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
export const publishRelease = async (github, artifacts) => {
|
||||
const versionFile = await readVersionFile(github, "release")
|
||||
await release(
|
||||
github,
|
||||
versionFile.content,
|
||||
config.packageName,
|
||||
artifacts,
|
||||
config,
|
||||
).catch((error) => console.log(error))
|
||||
}
|
||||
|
||||
const isWorkingBranchAhead = async (github) => {
|
||||
const result = await github.rest.repos.compareCommitsWithBasehead({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
basehead: `${config.rcMergesTo}...${config.rcBranchesFrom}`,
|
||||
per_page: 1,
|
||||
page: 1,
|
||||
})
|
||||
return result.data.status === "ahead"
|
||||
}
|
||||
|
||||
const doesNotHaveInProgressRelease = async (github) => {
|
||||
const releasePrs = await github.rest.pulls.list({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
state: "open",
|
||||
base: config.rcMergesTo
|
||||
})
|
||||
|
||||
const syncPrs = await github.rest.pulls.list({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
state: "open",
|
||||
base: config.rcBranchesFrom,
|
||||
head: `${config.owner}:${config.rcMergesTo}`
|
||||
})
|
||||
|
||||
return releasePrs.data.length === 0 && syncPrs.data.length === 0
|
||||
}
|
||||
|
||||
const startRelease = async (github) => {
|
||||
console.log(`creating release candidate from head of ${config.rcBranchesFrom}`)
|
||||
|
||||
await createBranch(github, "release-candidate", config.rcBranchesFrom)
|
||||
await incrementVersionFile(github, rcBranchName)
|
||||
|
||||
const createdPr = await github.rest.pulls.create({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
title: "[Auto] Release Candidate",
|
||||
head: rcBranchName,
|
||||
base: config.rcMergesTo,
|
||||
body: "todo",
|
||||
})
|
||||
|
||||
github.graphql(
|
||||
`
|
||||
mutation ($pullRequestId: ID!, $mergeMethod: PullRequestMergeMethod!) {
|
||||
enablePullRequestAutoMerge(input: {
|
||||
pullRequestId: $pullRequestId,
|
||||
mergeMethod: $mergeMethod
|
||||
}) {
|
||||
pullRequest {
|
||||
autoMergeRequest {
|
||||
enabledAt
|
||||
enabledBy {
|
||||
login
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
pullRequestId: createdPr.data.node_id,
|
||||
mergeMethod: "MERGE"
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const createBranch = async (github, branchName, fromBranch) => {
|
||||
const mainRef = await github.rest.git.getRef({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
ref: `heads/${fromBranch}`,
|
||||
})
|
||||
|
||||
await github.rest.git.createRef({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
ref: `refs/heads/${branchName}`,
|
||||
sha: mainRef.data.object.sha,
|
||||
})
|
||||
}
|
||||
|
||||
const incrementVersionFile = async (github, branchName) => {
|
||||
const versionFile = await readVersionFile(github, branchName)
|
||||
|
||||
const updatedVersionFile = {
|
||||
...versionFile.content,
|
||||
code: versionFile.content.code + 1,
|
||||
}
|
||||
const encodedContentUpdate = Buffer.from(JSON.stringify(updatedVersionFile, null, 2)).toString('base64')
|
||||
await github.rest.repos.createOrUpdateFileContents({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
content: encodedContentUpdate,
|
||||
path: config.pathToVersionFile,
|
||||
sha: versionFile.sha,
|
||||
branch: branchName,
|
||||
message: "updating version for release",
|
||||
})
|
||||
}
|
||||
|
||||
const readVersionFile = async (github, branch) => {
|
||||
const result = await github.rest.repos.getContent({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
path: config.pathToVersionFile,
|
||||
ref: branch,
|
||||
})
|
||||
|
||||
const content = Buffer.from(result.data.content, result.data.encoding).toString()
|
||||
return {
|
||||
content: JSON.parse(content),
|
||||
sha: result.data.sha,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,767 @@
|
|||
{
|
||||
"name": "beta-release",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "beta-release",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@googleapis/androidpublisher": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@googleapis/androidpublisher": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@googleapis/androidpublisher/-/androidpublisher-3.0.0.tgz",
|
||||
"integrity": "sha512-r4JfmLlcu/VI4hObZuQ8RW5OeWRFtOxqE9xU8C2GAp3GTu2ZcemEICu69xy/rchpzMNQY4lrr8WiqUG1LE1L5Q==",
|
||||
"dependencies": {
|
||||
"googleapis-common": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/abort-controller": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||
"dependencies": {
|
||||
"event-target-shim": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.5"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/bignumber.js": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz",
|
||||
"integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1",
|
||||
"get-intrinsic": "^1.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"node_modules/fast-text-encoding": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz",
|
||||
"integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ=="
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"node_modules/gaxios": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz",
|
||||
"integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==",
|
||||
"dependencies": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"extend": "^3.0.2",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"node-fetch": "^2.6.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/gcp-metadata": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz",
|
||||
"integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==",
|
||||
"dependencies": {
|
||||
"gaxios": "^4.0.0",
|
||||
"json-bigint": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
|
||||
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/google-auth-library": {
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz",
|
||||
"integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==",
|
||||
"dependencies": {
|
||||
"arrify": "^2.0.0",
|
||||
"base64-js": "^1.3.0",
|
||||
"ecdsa-sig-formatter": "^1.0.11",
|
||||
"fast-text-encoding": "^1.0.0",
|
||||
"gaxios": "^4.0.0",
|
||||
"gcp-metadata": "^4.2.0",
|
||||
"gtoken": "^5.0.4",
|
||||
"jws": "^4.0.0",
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/google-p12-pem": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz",
|
||||
"integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==",
|
||||
"dependencies": {
|
||||
"node-forge": "^1.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"gp12-pem": "build/src/bin/gp12-pem.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/googleapis-common": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-5.1.0.tgz",
|
||||
"integrity": "sha512-RXrif+Gzhq1QAzfjxulbGvAY3FPj8zq/CYcvgjzDbaBNCD6bUl+86I7mUs4DKWHGruuK26ijjR/eDpWIDgNROA==",
|
||||
"dependencies": {
|
||||
"extend": "^3.0.2",
|
||||
"gaxios": "^4.0.0",
|
||||
"google-auth-library": "^7.14.0",
|
||||
"qs": "^6.7.0",
|
||||
"url-template": "^2.0.8",
|
||||
"uuid": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gtoken": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz",
|
||||
"integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==",
|
||||
"dependencies": {
|
||||
"gaxios": "^4.0.0",
|
||||
"google-p12-pem": "^3.1.3",
|
||||
"jws": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/json-bigint": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
|
||||
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
|
||||
"dependencies": {
|
||||
"bignumber.js": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jwa": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
|
||||
"integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
|
||||
"dependencies": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jws": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||
"dependencies": {
|
||||
"jwa": "^2.0.0",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
|
||||
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.0",
|
||||
"get-intrinsic": "^1.0.2",
|
||||
"object-inspect": "^1.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/url-template": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
|
||||
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@googleapis/androidpublisher": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@googleapis/androidpublisher/-/androidpublisher-3.0.0.tgz",
|
||||
"integrity": "sha512-r4JfmLlcu/VI4hObZuQ8RW5OeWRFtOxqE9xU8C2GAp3GTu2ZcemEICu69xy/rchpzMNQY4lrr8WiqUG1LE1L5Q==",
|
||||
"requires": {
|
||||
"googleapis-common": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"abort-controller": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||
"requires": {
|
||||
"event-target-shim": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"requires": {
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz",
|
||||
"integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A=="
|
||||
},
|
||||
"buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
|
||||
},
|
||||
"call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1",
|
||||
"get-intrinsic": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"fast-text-encoding": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz",
|
||||
"integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ=="
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"gaxios": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz",
|
||||
"integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==",
|
||||
"requires": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"extend": "^3.0.2",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"node-fetch": "^2.6.7"
|
||||
}
|
||||
},
|
||||
"gcp-metadata": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz",
|
||||
"integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==",
|
||||
"requires": {
|
||||
"gaxios": "^4.0.0",
|
||||
"json-bigint": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
|
||||
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"google-auth-library": {
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz",
|
||||
"integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==",
|
||||
"requires": {
|
||||
"arrify": "^2.0.0",
|
||||
"base64-js": "^1.3.0",
|
||||
"ecdsa-sig-formatter": "^1.0.11",
|
||||
"fast-text-encoding": "^1.0.0",
|
||||
"gaxios": "^4.0.0",
|
||||
"gcp-metadata": "^4.2.0",
|
||||
"gtoken": "^5.0.4",
|
||||
"jws": "^4.0.0",
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"google-p12-pem": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz",
|
||||
"integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==",
|
||||
"requires": {
|
||||
"node-forge": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"googleapis-common": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-5.1.0.tgz",
|
||||
"integrity": "sha512-RXrif+Gzhq1QAzfjxulbGvAY3FPj8zq/CYcvgjzDbaBNCD6bUl+86I7mUs4DKWHGruuK26ijjR/eDpWIDgNROA==",
|
||||
"requires": {
|
||||
"extend": "^3.0.2",
|
||||
"gaxios": "^4.0.0",
|
||||
"google-auth-library": "^7.14.0",
|
||||
"qs": "^6.7.0",
|
||||
"url-template": "^2.0.8",
|
||||
"uuid": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"gtoken": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz",
|
||||
"integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==",
|
||||
"requires": {
|
||||
"gaxios": "^4.0.0",
|
||||
"google-p12-pem": "^3.1.3",
|
||||
"jws": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"requires": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
|
||||
},
|
||||
"json-bigint": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
|
||||
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
|
||||
"requires": {
|
||||
"bignumber.js": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"jwa": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
|
||||
"integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
|
||||
"requires": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"jws": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||
"requires": {
|
||||
"jwa": "^2.0.0",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA=="
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
|
||||
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"requires": {
|
||||
"side-channel": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||
"requires": {
|
||||
"call-bind": "^1.0.0",
|
||||
"get-intrinsic": "^1.0.2",
|
||||
"object-inspect": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"url-template": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
|
||||
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "beta-release",
|
||||
"version": "1.0.0",
|
||||
"main": "app.js",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@googleapis/androidpublisher": "^3.0.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
import * as google from '@googleapis/androidpublisher';
|
||||
import * as fs from "fs";
|
||||
import * as http from 'https';
|
||||
import * as url from 'url';
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
const auth = new google.auth.GoogleAuth({
|
||||
keyFile: '.secrets/service-account.json',
|
||||
scopes: ['https://www.googleapis.com/auth/androidpublisher'],
|
||||
})
|
||||
|
||||
const androidPublisher = google.androidpublisher({
|
||||
version: 'v3',
|
||||
auth: auth,
|
||||
})
|
||||
|
||||
const universalApkPath = `${__dirname}/universal.apk`
|
||||
|
||||
export const release = async (github, version, applicationId, artifacts, config) => {
|
||||
const appEditId = await startPlayRelease(applicationId)
|
||||
|
||||
console.log("Uploading bundle...")
|
||||
await uploadBundle(appEditId, applicationId, artifacts.bundle)
|
||||
|
||||
console.log("Uploading mapping...")
|
||||
await uploadMappingFile(appEditId, version.code, applicationId, artifacts.mapping)
|
||||
|
||||
console.log("Assign artifacts to beta release...")
|
||||
await addReleaseToTrack(appEditId, version, applicationId)
|
||||
|
||||
console.log("Commiting draft release...")
|
||||
await androidPublisher.edits.commit({
|
||||
editId: appEditId,
|
||||
packageName: applicationId,
|
||||
}).catch((error) => Promise.reject(error.response.data))
|
||||
|
||||
console.log("Downloading generated universal apk...")
|
||||
await dowloadSignedUniversalApk(
|
||||
version,
|
||||
applicationId,
|
||||
await auth.getAccessToken(),
|
||||
universalApkPath
|
||||
)
|
||||
|
||||
const releaseResult = await github.rest.repos.createRelease({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
tag_name: version.name,
|
||||
prerelease: true,
|
||||
generate_release_notes: true,
|
||||
})
|
||||
|
||||
console.log(releaseResult.data.id)
|
||||
|
||||
await github.rest.repos.uploadReleaseAsset({
|
||||
owner: config.owner,
|
||||
repo: config.repo,
|
||||
release_id: releaseResult.data.id,
|
||||
name: `universal-${version.name}.apk`,
|
||||
data: fs.readFileSync(universalApkPath)
|
||||
})
|
||||
|
||||
console.log("Promoting beta draft release to live...")
|
||||
await promoteDraftToLive(applicationId)
|
||||
}
|
||||
|
||||
const startPlayRelease = async (applicationId) => {
|
||||
const result = await androidPublisher.edits.insert({
|
||||
packageName: applicationId
|
||||
}).catch((error) => Promise.reject(error.response.data))
|
||||
return result.data.id
|
||||
}
|
||||
|
||||
const uploadBundle = async (appEditId, applicationId, bundleReleaseFile) => {
|
||||
const res = await androidPublisher.edits.bundles.upload({
|
||||
packageName: applicationId,
|
||||
editId: appEditId,
|
||||
media: {
|
||||
mimeType: 'application/octet-stream',
|
||||
body: fs.createReadStream(bundleReleaseFile)
|
||||
}
|
||||
}).catch((error) => Promise.reject(error.response.data))
|
||||
|
||||
return res.data
|
||||
}
|
||||
|
||||
const uploadMappingFile = async (appEditId, versionCode, applicationId, mappingFilePath) => {
|
||||
await androidPublisher.edits.deobfuscationfiles.upload({
|
||||
packageName: applicationId,
|
||||
editId: appEditId,
|
||||
apkVersionCode: versionCode,
|
||||
deobfuscationFileType: 'proguard',
|
||||
media: {
|
||||
mimeType: 'application/octet-stream',
|
||||
body: fs.createReadStream(mappingFilePath)
|
||||
}
|
||||
}).catch((error) => Promise.reject(error.response.data))
|
||||
}
|
||||
|
||||
const addReleaseToTrack = async (appEditId, version, applicationId) => {
|
||||
const result = await androidPublisher.edits.tracks
|
||||
.update({
|
||||
editId: appEditId,
|
||||
packageName: applicationId,
|
||||
track: "beta",
|
||||
requestBody: {
|
||||
track: "beta",
|
||||
releases: [
|
||||
{
|
||||
name: version.name,
|
||||
status: "draft",
|
||||
releaseNotes: {
|
||||
language: "en-GB",
|
||||
text: "Bug fixes and improvments - See https://github.com/ouchadam/small-talk/releases for more details",
|
||||
},
|
||||
versionCodes: [version.code]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
.catch((error) => Promise.reject(error.response.data))
|
||||
return result.data;
|
||||
}
|
||||
|
||||
|
||||
const dowloadSignedUniversalApk = async (version, applicationId, authToken, outputFile) => {
|
||||
console.log("fetching universal apk")
|
||||
|
||||
const apkRes = await androidPublisher.generatedapks.list({
|
||||
packageName: applicationId,
|
||||
versionCode: version.code,
|
||||
})
|
||||
|
||||
const apks = apkRes.data.generatedApks
|
||||
|
||||
console.log(`found ${apks.length} apks`)
|
||||
apks.forEach((apk) => {
|
||||
console.log(apk)
|
||||
})
|
||||
|
||||
const id = apks[0].generatedUniversalApk.downloadId
|
||||
|
||||
console.log(`downloading: ${id}`)
|
||||
|
||||
const downloadUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${applicationId}/generatedApks/${version.code}/downloads/${id}:download?alt=media`
|
||||
const options = {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${authToken}`
|
||||
}
|
||||
}
|
||||
|
||||
await downloadToFile(downloadUrl, options, outputFile)
|
||||
}
|
||||
|
||||
const downloadToFile = async (url, options, outputFile) => {
|
||||
return new Promise((resolve, error) => {
|
||||
http.get(url, options, (response) => {
|
||||
const file = fs.createWriteStream(outputFile)
|
||||
response.pipe(file)
|
||||
|
||||
file.on("finish", () => {
|
||||
file.close()
|
||||
resolve()
|
||||
})
|
||||
|
||||
file.on("error", (cause) => {
|
||||
error(cause)
|
||||
})
|
||||
}).on("error", (cause) => {
|
||||
error(cause)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const promoteDraftToLive = async () => {
|
||||
const fappEditId = await startPlayRelease(applicationId)
|
||||
|
||||
await androidPublisher.edits.tracks
|
||||
.update({
|
||||
editId: fappEditId,
|
||||
packageName: applicationId,
|
||||
track: "beta",
|
||||
requestBody: {
|
||||
track: "beta",
|
||||
releases: [
|
||||
{
|
||||
status: "completed",
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
.catch((error) => Promise.reject(error.response.data))
|
||||
|
||||
|
||||
await androidPublisher.edits.commit({
|
||||
editId: fappEditId,
|
||||
packageName: applicationId,
|
||||
}).catch((error) => Promise.reject(error.response.data))
|
||||
}
|
||||
|
|
@ -67,30 +67,10 @@ def collectProjects(predicate) {
|
|||
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
|
||||
}
|
||||
|
||||
//task unitCodeCoverageReport(type: JacocoReport) {
|
||||
// outputs.upToDateWhen { false }
|
||||
// rootProject.apply plugin: 'jacoco'
|
||||
// def excludedProjects = [
|
||||
// 'olm-stub',
|
||||
// 'test-harness'
|
||||
// ]
|
||||
// def projects = collectProjects { !excludedProjects.contains(it.name) }
|
||||
// dependsOn { ["app:assembleDebug"] + projects*.test }
|
||||
// initializeReport(it, projects, excludes)
|
||||
//}
|
||||
//
|
||||
//task harnessCodeCoverageReport(type: JacocoReport) {
|
||||
// outputs.upToDateWhen { false }
|
||||
// rootProject.apply plugin: 'jacoco'
|
||||
// def projects = collectProjects { true }
|
||||
// dependsOn { ["app:assembleDebug", project(":test-harness").test] }
|
||||
// initializeReport(it, projects, excludes)
|
||||
//}
|
||||
|
||||
task allCodeCoverageReport(type: JacocoReport) {
|
||||
outputs.upToDateWhen { false }
|
||||
rootProject.apply plugin: 'jacoco'
|
||||
def projects = collectProjects { !it.name.contains("stub") }
|
||||
def projects = collectProjects { !it.name.contains("stub") && !it.name.contains("-noop") }
|
||||
dependsOn { ["app:assembleDebug"] + projects*.test }
|
||||
initializeReport(it, projects, excludes)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/bash
|
||||
|
||||
./gradlew clean bundleRelease -Punsigned --no-daemon --no-configuration-cache --no-build-cache
|
||||
|
||||
WORKING_DIR=app/build/outputs/bundle/release
|
||||
RELEASE_AAB=$WORKING_DIR/app-release.aab
|
||||
|
||||
cp $RELEASE_AAB $WORKING_DIR/app-release-unsigned.aab
|
||||
|
||||
echo "signing $RELEASE_AAB"
|
||||
jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
|
||||
-keystore .secrets/upload-key.jks \
|
||||
-storepass $1 \
|
||||
$RELEASE_AAB \
|
||||
key0
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"name": "0.0.1-alpha03",
|
||||
"code": 5
|
||||
"name": "0.0.1-alpha04",
|
||||
"code": 7
|
||||
}
|
Loading…
Reference in New Issue