Skip to content

Commit

Permalink
Sentry gradle script refactoring, compatibility with Gradle 5.0 recov…
Browse files Browse the repository at this point in the history
…ered (#532)

* Sentry gradle script refactoring, compatibility with Gradle 5.0 recovered

* Merged/rebase with latest version of master
  • Loading branch information
Oleksandr authored and HazAT committed Jan 29, 2019
1 parent 6365d3d commit e98f2c0
Showing 1 changed file with 162 additions and 129 deletions.
291 changes: 162 additions & 129 deletions sentry.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,20 @@ import java.util.regex.Pattern
def config = project.hasProperty("sentryCli") ? project.sentryCli : [];

gradle.projectsEvaluated {
def releases = [:];
android.applicationVariants.each { variant ->
def releaseName = "${variant.getApplicationId()}-${variant.getVersionName()}";
variant.outputs.each { output ->
def versionCode = output.getVersionCode();
def variantName = variant.getName();
def outputName = output.getName();
if (releases[variantName] == null) {
releases[variantName] = [:];
}
releases[variantName][outputName] = [outputName, releaseName, versionCode];
}
}
def releases = extractReleasesInfo()

// separately we then hook into the bundle task of react native to inject
// sourcemap generation parameters. In case for whatever reason no release
// was found for the asset folder we just bail.
def bundleTasks = tasks.findAll { task ->
task.name.startsWith("bundle") && task.name.endsWith("JsAndAssets")
}
def bundleTasks = tasks.findAll { task -> task.name.startsWith("bundle") && task.name.endsWith("JsAndAssets") }
bundleTasks.each { bundleTask ->
def props = bundleTask.getProperties();
def cmd = props.get("commandLine") as List<String>;
def cmdArgs = props.get("args") as List<String>;
def bundleOutput = null;
def sourcemapOutput = null;
def reactRoot = props.get("workingDir");
def shouldCleanUp = false;

cmdArgs.eachWithIndex{ String arg, int i ->
if (arg == "--bundle-output") {
bundleOutput = cmdArgs[i + 1];
} else if (arg == "--sourcemap-output") {
sourcemapOutput = cmdArgs[i + 1];
}
}

if (sourcemapOutput == null) {
sourcemapOutput = bundleOutput + ".map";
cmd.push("--sourcemap-output");
cmd.push(sourcemapOutput);
cmdArgs.push("--sourcemap-output");
cmdArgs.push(sourcemapOutput);
def shouldCleanUp
def sourcemapOutput
def bundleOutput
def props = bundleTask.getProperties()
def reactRoot = props.get("workingDir")

shouldCleanUp = true
}

bundleTask.setProperty("commandLine", cmd);
bundleTask.setProperty("args", cmdArgs);
(shouldCleanUp, bundleOutput, sourcemapOutput) = forceSourceMapOutputFromBundleTask(bundleTask)

if (config.flavorAware) {
println "**********************************"
Expand All @@ -68,121 +34,188 @@ gradle.projectsEvaluated {
// .findAll{!['class', 'active'].contains(it.key)}
// .join('\n')

def currentRelease = "";
def pattern = Pattern.compile("bundle([A-Z][A-Za-z0-9]+)JsAndAssets")
Matcher matcher = pattern.matcher(bundleTask.name)
if (matcher.find()) {
def match = matcher.group(1);
currentRelease = match.substring(0, 1).toLowerCase() + match.substring(1);
}
def currentVariants = extractCurrentVariants(bundleTask, releases)
if (currentVariants == null) return

def currentVariants = null;
releases.each { key, release ->
if (key.equalsIgnoreCase(currentRelease)) {
currentVariants = release;
}
}

if (currentVariants == null) return;

def variant = null;
def releaseName = null;
def versionCodes = new ArrayList<Integer>(currentVariants.size());
def variant = null
def releaseName = null
def versionCodes = new ArrayList<Integer>(currentVariants.size())

currentVariants.each { key, currentVariant ->
variant = currentVariant[0];
releaseName = currentVariant[1];
versionCodes.push(currentVariant[2]);
variant = currentVariant[0]
releaseName = currentVariant[1]
versionCodes.push(currentVariant[2])
}

def cliTask = tasks.create(
name: bundleTask.getName() + variant + "SentryUpload",
type: Exec) {
def nameCliTask = "${bundleTask.name}_SentryUpload"
def nameCleanup = "${bundleTask.name}_SentryUploadCleanUp"

/** Upload source map file to the sentry server via CLI call. */
def cliTask = tasks.create(name: nameCliTask, type: Exec) {
description = "upload debug symbols to sentry"
group = 'sentry.io'

def propertiesFile = "$reactRoot/android/sentry.properties";
workingDir reactRoot

def propertiesFile = "$reactRoot/android/sentry.properties"
if (config.flavorAware) {
propertiesFile = "$reactRoot/android/sentry-$variant"+".properties"
println "For $variant using: $propertiesFile"
propertiesFile = "$reactRoot/android/sentry-${variant}.properties"
project.logger.info("For $variant using: $propertiesFile")
} else {
environment("SENTRY_PROPERTIES", propertiesFile)
}
Properties sentryProps = new Properties();

Properties sentryProps = new Properties()
try {
sentryProps.load(new FileInputStream(propertiesFile));
sentryProps.load(new FileInputStream(propertiesFile))
} catch (FileNotFoundException e) {
println "File not found: $propertiesFile"
project.logger.info("file not found '$propertiesFile' for '$variant'")
}
def cliExecutable = sentryProps.get("cli.executable", "$reactRoot/node_modules/@sentry/cli/bin/sentry-cli");
def cliExecutable = sentryProps.get("cli.executable", "$reactRoot/node_modules/@sentry/cli/bin/sentry-cli")

workingDir reactRoot

// fix path separator for Windows
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
cliExecutable = cliExecutable.replaceAll("/","\\\\");
cliExecutable = cliExecutable.replaceAll("/", "\\\\")
}

def args = [
cliExecutable
];
if (config.logLevel) {
args.push("--log-level");
args.push(config.logLevel);
}
//
// based on:
// https://github.com/getsentry/sentry-cli/blob/master/src/commands/react_native_gradle.rs
//
def args = [cliExecutable]

args.addAll( !config.logLevel ? [] : [
"--log-level", config.logLevel // control verbosity of the output
])
args.addAll(!config.flavorAware ? [] : [
"--url", sentryProps.get("defaults.url"),
"--auth-token", sentryProps.get("auth.token")
])
args.addAll(["react-native", "gradle",
"--bundle", bundleOutput, // The path to a bundle that should be uploaded.
"--sourcemap", sourcemapOutput, // The path to a sourcemap that should be uploaded.
"--release", releaseName // The name of the release to publish.
])
args.addAll(!config.flavorAware ? [] : [
"--org", sentryProps.get("defaults.org"),
"--project", sentryProps.get("defaults.project")
])

// The names of the distributions to publish. Can be supplied multiple times.
versionCodes.each { versionCode -> args.addAll(["--dist", versionCode]) }

project.logger.info("Sentry-CLI arguments: ${args}")

def osCompatibility = Os.isFamily(Os.FAMILY_WINDOWS) ? ['cmd', '/c', 'node'] : []
commandLine(*osCompatibility, *args)

if (config.flavorAware) {
args.push("--url");
args.push(sentryProps.get("defaults.url"));
args.push("--auth-token");
args.push(sentryProps.get("auth.token"));
}
enabled true
}

args.push("react-native");
args.push("gradle");
args.push("--bundle");
args.push(bundleOutput);
args.push("--sourcemap");
args.push(sourcemapOutput);
args.push("--release");
args.push(releaseName);
/** Delete sourcemap files */
def cliCleanUpTask = tasks.create(name: nameCleanup, type: Delete) {
description = "clean up extra sourcemap"
group = 'sentry.io'

if (config.flavorAware) {
args.push("--org");
args.push(sentryProps.get("defaults.org"));
args.push("--project");
args.push(sentryProps.get("defaults.project"));
}
delete sourcemapOutput
}

versionCodes.each { versionCode ->
args.add("--dist");
args.add(versionCode);
}
// dependsOn, mustRunAfter, shouldRunAfter, doFirst, doLast, finalizedBy
// bundleTask --> cliTask
bundleTask.finalizedBy cliTask

if (config.logLevel) {
println args
}
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine("cmd", "/c", "node", *args)
} else {
commandLine(*args)
// register clean task extension
cliCleanUpTask.onlyIf { shouldCleanUp }
project.tasks.clean.dependsOn cliCleanUpTask
}
}

/** Compose lookup map of build variants - to - outputs. */
def extractReleasesInfo() {
def releases = [:]

android.applicationVariants.each { variant ->
def releaseName = "${variant.getApplicationId()}-${variant.getVersionName()}"

variant.outputs.each { output ->
def versionCode = output.getVersionCode()
def variantName = variant.getName()
def outputName = output.getName()
if (releases[variantName] == null) {
releases[variantName] = [:]
}
enabled true
releases[variantName][outputName] = [outputName, releaseName, versionCode]
}
}

def cliCleanUpTask = tasks.create(
name: bundleTask.getName() + variant + "SentryUploadCleanUp",
type: Delete) {
description = "clean up extra sourcemap"
return releases
}

delete sourcemapOutput
};
/** Extract from arguments collection bundle and sourcemap files output names. */
static extractBundleTaskArguments(cmdArgs){
def bundleOutput = null
def sourcemapOutput = null

bundleTask.doLast {
cliTask.execute();
if (shouldCleanUp) {
cliCleanUpTask.execute();
}
cmdArgs.eachWithIndex { String arg, int i ->
if (arg == "--bundle-output") {
bundleOutput = cmdArgs[i + 1]
} else if (arg == "--sourcemap-output") {
sourcemapOutput = cmdArgs[i + 1]
}
}

return [ bundleOutput, sourcemapOutput ]
}

/** Force Bundle task to produce sourcemap files if they are not pre-configured by user yet. */
def forceSourceMapOutputFromBundleTask(bundleTask){
def props = bundleTask.getProperties()
def cmd = props.get("commandLine") as List<String>
def cmdArgs = props.get("args") as List<String>
def shouldCleanUp = false
def bundleOutput = null
def sourcemapOutput = null

(bundleOutput, sourcemapOutput) = extractBundleTaskArguments(cmdArgs)

if (sourcemapOutput == null) {
sourcemapOutput = bundleOutput + ".map"

cmd.addAll(["--sourcemap-output", sourcemapOutput])
cmdArgs.addAll(["--sourcemap-output", sourcemapOutput])

cliTask.dependsOn(bundleTask)
shouldCleanUp = true

bundleTask.setProperty("commandLine", cmd)
bundleTask.setProperty("args", cmdArgs)

project.logger.info("forced sourcemap file output for `${bundleTask.name}` task")
} else {
project.logger.info("Info: used pre-configured source map files: ${sourcemapOutput}")
}

return [shouldCleanUp, bundleOutput, sourcemapOutput]
}

/** compose array with one item - current build flavor name */
static extractCurrentVariants(bundleTask, releases) {
// examples: bundleLocalReleaseJsAndAssets, bundleYellowDebugJsAndAssets
def pattern = Pattern.compile("bundle([A-Z][A-Za-z0-9_]+)JsAndAssets")

def currentRelease = ""

Matcher matcher = pattern.matcher(bundleTask.name)
if (matcher.find()) {
def match = matcher.group(1)
currentRelease = match.substring(0, 1).toLowerCase() + match.substring(1)
}

def currentVariants = null
releases.each { key, release ->
if (key.equalsIgnoreCase(currentRelease)) {
currentVariants = release
}
}

return currentVariants
}

0 comments on commit e98f2c0

Please sign in to comment.