Skip to content
Open
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## XX.XX.XX
* Added gradle configuration cache support to upload symbols plugin.

## 26.1.2
* Added `CountlyInitProvider` ContentProvider to register activity lifecycle callbacks before `Application.onCreate()`. This ensures the SDK captures the current activity in single-activity frameworks (Flutter, React Native) and apps with deferred initialization.
* Added `CountlyConfig.setInitialActivity(Activity)` as an explicit way for wrapper SDKs to provide the host activity during initialization.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import okhttp3.*
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.StopActionException
import org.gradle.api.tasks.StopExecutionException

import static groovy.io.FileType.FILES

Expand All @@ -20,29 +19,33 @@ class UploadSymbolsPluginExtension {

class UploadSymbolsPlugin implements Plugin<Project> {
void apply(Project project) {
OkHttpClient client = null
Request request = null
def ext = project.extensions.create('countly', UploadSymbolsPluginExtension)
project.tasks.register('uploadJavaSymbols') {
group = "countly"
description = "Upload Java minification mapping file mapping.txt to Countly server"
doFirst {
if (!ext.app_key) {
logger.error("Please specify your app key in countly block.")
throw new StopExecutionException("Please specify your app key in countly block.")
}
if (!ext.server) {
logger.error("Please specify your server in countly block.")
throw new StopExecutionException("Please specify your server in countly block.")
}
String buildVersion = project.android.defaultConfig.versionName
String url = ext.server;
String path = "i/crash_symbols/upload_symbol";

// Resolve project/extension values at configuration time to avoid
// capturing non-serializable Project reference in task actions
def buildVersion = project.android.defaultConfig.versionName
def appKey = ext.app_key
def serverUrl = ext.server
def noteJava = ext.noteJava
def mappingFilePath = "${project.buildDir}/${ext.mappingFile}"

if (!appKey || !serverUrl) {
logger.warn("[Countly] uploadJavaSymbols: 'app_key' or 'server' is empty. " +
"Make sure the countly block is configured before this task is realized. " +
"Disabling task.")
enabled = false
}

doLast {
String url = serverUrl
String path = "i/crash_symbols/upload_symbol"
// Ensure there is exactly one "/" between the base URL and the path
url = url.endsWith("/") ? url + path : url + "/" + path;
def filePath = "$project.buildDir/$ext.mappingFile"
logger.debug("uploadJavaSymbols, Version name:[ {} ], Upload symbol url:[ {} ], Mapping file path:[ {} ]", buildVersion, url, filePath)
File file = new File(filePath)
url = url.endsWith("/") ? url + path : url + "/" + path
logger.debug("uploadJavaSymbols, Version name:[ {} ], Upload symbol url:[ {} ], Mapping file path:[ {} ]", buildVersion, url, mappingFilePath)
File file = new File(mappingFilePath)
if (!file.exists()) {
logger.error("Mapping file not found")
throw new StopActionException("Mapping file not found")
Expand All @@ -52,25 +55,19 @@ class UploadSymbolsPlugin implements Plugin<Project> {
.addFormDataPart("symbols", file.getName(),
RequestBody.create(MediaType.parse("text/plain"), file))
.addFormDataPart("platform", "android")
.addFormDataPart("app_key", ext.app_key)
.addFormDataPart("app_key", appKey)
.addFormDataPart("build", buildVersion)
.addFormDataPart("note", ext.noteJava)
.addFormDataPart("note", noteJava)
.build()
request = new Request.Builder().url(url).post(formBody).build()
}
doLast {
if (request == null) {
logger.error("Request not constructed")
throw new StopActionException("Something happened while constructing the request. Please try again.")
}
Request request = new Request.Builder().url(url).post(formBody).build()

if (request.body() != null) {
logger.debug("uploadJavaSymbols, Generated request: {}", request.body().toString())
} else {
logger.error("uploadJavaSymbols, Request body is null which should not be the case")
}

client = new OkHttpClient()
OkHttpClient client = new OkHttpClient()
Response response = client.newCall(request).execute()

if (response.code() != 200) {
Expand All @@ -88,28 +85,43 @@ class UploadSymbolsPlugin implements Plugin<Project> {
project.tasks.register('uploadNativeSymbols') {
group = "countly"
description = "Upload breakpad symbols folder to Countly server"
doFirst {
String buildVersion = project.android.defaultConfig.versionName
String url = "${ext.server}/i/crash_symbols/upload_symbol"
String breakpadVersion = "$ext.dumpSymsPath/dump_syms --version".execute().getText().trim()

// Resolve project/extension values at configuration time to avoid
// capturing non-serializable Project reference in task actions
def buildVersion = project.android.defaultConfig.versionName
def appKey = ext.app_key
def serverUrl = ext.server
def noteNative = ext.noteNative
def dumpSymsPath = ext.dumpSymsPath
def objectsDirPath = "${project.buildDir}/${ext.nativeObjectFilesDir}"
def countlyDirStr = "${project.buildDir}/intermediates/countly"

if (!appKey || !serverUrl) {
logger.warn("[Countly] uploadNativeSymbols: 'app_key' or 'server' is empty. " +
"Make sure the countly block is configured before this task is realized. " +
"Disabling task.")
enabled = false
}

doLast {
String url = "${serverUrl}/i/crash_symbols/upload_symbol"
String breakpadVersion = "$dumpSymsPath/dump_syms --version".execute().getText().trim()

if (!(breakpadVersion =~ /^\d+\.\d+\+cly$/)) {
breakpadVersion = "0.1+bpd"
}

def objectsDir = new File("$project.buildDir/$ext.nativeObjectFilesDir")
def countlyDirStr = "$project.buildDir/intermediates/countly"
def countlyDir = new File("$countlyDirStr")
def objectsDir = new File(objectsDirPath)
def countlyDir = new File(countlyDirStr)
logger.debug("uploadNativeSymbols, Version name:[ {} ], Upload symbol url:[ {} ], objectsDir:[ {} ], countlyDirStr:[ {} ], countlyDir:[ {} ], breakpadVersion:[ {} ]", buildVersion, url, objectsDir, countlyDirStr, countlyDir, breakpadVersion)

countlyDir.deleteDir()
countlyDir.mkdirs()
// println "objectsDir=$objectsDir"
def filterObjectFiles = ~/.*\.so$/
def i = 0
def processFile = {
i = i + 1
def cmd = "$ext.dumpSymsPath/dump_syms $it"
def cmd = "$dumpSymsPath/dump_syms $it"
println cmd
def proc = cmd.execute()
def outputStream = new StringBuffer()
Expand All @@ -131,23 +143,23 @@ class UploadSymbolsPlugin implements Plugin<Project> {
}
objectsDir.traverse type: FILES, visit: processFile, nameFilter: filterObjectFiles
def tarFileName = "$countlyDirStr/symbols.tar.gz"
project.ant.tar(destfile: tarFileName, basedir: "$countlyDirStr", includes: "symbols/**", compression: "gzip")
// Use standalone AntBuilder instead of project.ant for configuration cache compatibility
new groovy.ant.AntBuilder().tar(destfile: tarFileName, basedir: "$countlyDirStr", includes: "symbols/**", compression: "gzip")
File file = new File(tarFileName)
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("symbols", file.getName(),
RequestBody.create(MediaType.parse("text/plain"), file))
.addFormDataPart("platform", "android_native")
.addFormDataPart("app_key", ext.app_key)
.addFormDataPart("app_key", appKey)
.addFormDataPart("build", buildVersion)
.addFormDataPart("note", ext.noteNative)
.addFormDataPart("note", noteNative)
.addFormDataPart("sym_tool_ver", breakpadVersion)
.build()
request = new Request.Builder().url(url).post(formBody).build()
Request request = new Request.Builder().url(url).post(formBody).build()
logger.debug("uploadNativeSymbols, Generated request: {}", request.body().toString())
}
doLast {
client = new OkHttpClient()

OkHttpClient client = new OkHttpClient()
Response response = client.newCall(request).execute()

if (response.code() != 200) {
Expand Down
Loading