I have created a gradle closure to generate versionName for an Android Application from git tag. I can run it locally, however I cannot execute in a job of GitHub Actions. The machine is
ubuntu-latest.
Here is the closure and the error.
ext.getVersionName = {
try {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags', '--dirty'
standardOutput = stdout
}
return stdout.toString().trim()
} catch (ignored) {
return null
}
}
Error in Actions
> Process 'command 'git'' finished with non-zero exit value 128
How can I run this block in Github Actions ? Do you have any suggestions ?
Thanks in advance.
Force it to check everything out:
- uses: actions/checkout#v2
with:
fetch-depth: 0
Related
I want to re-create verification-metadata.xml file with single click. I can create verification-metadata.xml with this command ./gradlew --write-verification-metadata sha256. I try to create Gradle Task inside the build.gradle(app) and execute, but it didn't work
task verificationMeta(type: Exec) {
workingDir "${rootDir}"
commandLine './gradlew ', '--write', '-verification', '-metadata', ' sha256'
doLast {
println "Executed!"
}
}
rootDir is root directory of project.
This code gives me error;
Execution failed for task ':verificationMeta'.
> A problem occurred starting process 'command './gradlew ''
How can I make it ?
Are you working on windows machine?
We had the problem that on windows machine you have to call gradlew.bat
Example:
task prodRepackage(type: Exec) {
group = "Build"
if (OperatingSystem.current().isWindows()) {
executable "gradlew.bat"
args "-Pprod", "bootJar"
} else {
executable "./gradlew"
args "-Pprod", "bootJar"
}
}
As a workaround for the issue, I use .bat or .sh scripts to be executed as the following.
task executeCMD(type:Exec) {
workingDir '.'
commandLine 'test.bat'
doLast {
println "Executed!"
}
}
This, for example, will execute the test.bat script, which only has one line
./gradlew --write-verification-metadata sha256
if you're using Linux/macOS, you can replace the .bat with .sh.
I want to run a command line with Gradle that this command has an output.
I run this command in windows powershell:
./mybat.bat myArgs when I hit enter, it will print some digit, like this:
123456
I want to run this command with gradle and save this result(123456)
here is some code that I written in android build.gradle file:
task getSomeOutput(type: Exec) {
workingDir "${buildDir}/output"
commandLine 'powershell', './mybat.bat' , 'foo'//this is myArgs for example
}
this works and prints the value 123456, but I want to save it in a variable, how can I do that?
As you can see in the official doc HERE
This can be achieved with the following task
task executeCMD(type:Exec) {
workingDir '.'
commandLine 'mybat.bat', '>', 'log.txt'
doLast {
println "Executed!"
}
}
This will send the output of mybat.bat execution and set the results into a txt file called log .
the . is the directory where you have the script .
in my case its a project root directory .
the best approach I found is to add '/c' to commandLine arguments and use standardOutput, here some code that might help other people:
task getSomeOutput(type: Exec) {
workingDir "${buildDir}/output"
commandLine 'powershell', '/c', './mybat.bat' , 'foo'//this is myArgs for example
standardOutput = new ByteArrayOutputStream()
doLast {
def result = standardOutput.toString()
println "the result value is: $result"
}
}
I've created a gradle task to check if a program is installed, it works fine but I discovered that it can throw an exception on environments where the command I am executing does not exist. I've tried to catch the exception that is thrown but no luck. How can I gracefully handle the exception and continue the build process if my task fails due to the command not existing?
Error:
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':isGitLFSInstalled'.
A problem occurred starting process 'command 'command''
Code:
task isGitLFSInstalled(type: Exec) {
commandLine 'command', '-v', 'git-lfs' // Fails here on environments that dont have "command"
ignoreExitValue true
standardOutput = new ByteArrayOutputStream()
ext.output = {
return standardOutput.toString()
}
doLast {
if (execResult.exitValue != 0) {
throw new GradleException("Git LFS is not installed, please build project after installing Git LFS.\n" +
"Refer to the following URL to setup Git LFS: https://git-lfs.github.com/")
}
}
}
The problem you're facing is described here. Surrounding commandLine with try/catch doesn't work for a simple reason: commandLine doesn't execute your command, it just sets the command to be executed by the Exec task when it will be run.
One way would be not to use tasks to execute the command. For example, you could use ProcessBuilder wrapped in try/catch in finalizedBy, which will only be run during the execution phase:
task myTask {
finalizedBy {
try {
def proc = new ProcessBuilder("command", "-v", "git-lfs")
proc.start().waitFor()
// Do something with stdout or whatever.
} catch (Exception e) {
println("Couldn't find git-lfs.")
}
}
}
I don't have much time right now, but I hope that helps.
I use bugsnag to monitor crashes in my Android app.
I also use ProGuard when I compile a release version.
I need to upload the mapping.txt file that is generated in build/outputs/mapping/prod/release folder of my project.
When I run this command in (Windows) command line:
curl https://upload.bugsnag.com -F proguard=#C:/mapping.txt -F apiKey=1111111111111111111111 -F versionCode=11111111 -F appId=com.my.package -F versionNumber=1.0.0
The file is uploaded and everything works.
All I need is to add a task to gradle so it uploads the file once its ready.
So once I compile the project for release, the mapping.txt file gets generated and once its ready, upload the file using this curl command (which is taken from bugsnag's web site by the way).
I tried many variations. The current one compiles but I do not think the file is being uploaded... I can't see any indication that it actually happened.
This is the code I currently use:
task uploadPro(type: Exec) {
logger.error("inside upload task")
commandLine 'cmd', '/c', 'curl', 'https://upload.bugsnag.com', '-F','proguard=#build/outputs/mapping/prod/release/mapping.txt', '-F', 'apiKey=1111111111111111111111', '-F', 'versionCode=111111', '-F', 'appId=com.my.package', '-F', 'versionNumber=1.0.0'
standardOutput = new ByteArrayOutputStream()
doLast {
String output = standardOutput.toString()
logger.info(output);
}
}
I also tried using this:
def p = ['cmd', '/c', 'curl', 'https://upload.bugsnag.com', '-F', 'proguard=#build/outputs/mapping/prod/release/mapping.txt', '-F', 'apiKey=11111111111111111111111', '-F', 'versionCode=1111111', '-F', 'appId=com.my.package', '-F', 'versionNumber=1.0.0'].execute()
The way I call this task is by using this command:
tasks.getByName("assembleRelease").finalizedBy(uploadPro)
Im really not sure how to do this. Any help is appreciated!! Thank you!
I found a solution to my own question... mostly. Here is the code I use to run the curl command at the end of the build process:
task uploadPro << {
logger.error("Uploading mapping.txt file to bugsnag")
def myCommand = "cmd /c curl https://upload.bugsnag.com -F proguard=#path\\to\mappingFile\\mapping.txt -F " +
"apiKey=111111111111111111111111 -F versionCode=" + versionCodeId + " -F " +
"appId=com.xxxx.yyy.zzz -F versionNumber=" + versionId
ProcessBuilder builder = new ProcessBuilder(myCommand.split(' '));
Process process = builder.start();
process.waitFor()
println process.err.text
println process.text
}
Then I use this to run it at the end of the build process:
gradle.buildFinished {
tasks.uploadPro.execute()
}
Cant be sure this is best practice but it works.
I would have liked to run the uploadPro task ONLY during a release buildType...but this proves to be difficult as well.
I am trying to write a Gradle task that executes an adb command to clear the app/data cache for a connected android device:
task clearAppDataCache(type: Exec) {
description = "Clears device app data/cache."
group = "Utils"
commandLine "$sdkDir/platform-tools/adb"
args = ["shell", "pm", "clear", "com.my.package"]
}
The above task works if the com.my.package android package is installed on the device. However, if the package is not installed the task prints out a failure and then hangs in the following manner:
Does anyone know why this might be the case? I would expect it to instead failure and finish in a manner similar to how the raw shell command runs.
Edit:
The adding the following configuration clause to the task stops the hang:
doFirst {
if (!packageExists("com.my.package"))
throw new GradleException("com.my.package package is not installed on connected device.")
}
with the following function definition:
/**
* Returns true if the packageName argument exists on the the connected device,
* false otherwise.
*/
def packageExists(String packageName) {
def output = "adb shell pm list packages -f".execute().waitFor().text
if (output.contains("$packageName")) return true
return false
}
However, I am still searching for the reason why it hangs in the first place.
Try this:
task clearAppDataCache(type: Exec) {
description = "Clears device app data/cache."
group = "Utils"
commandLine "./pmclear.sh"
}
pmclear.sh:
#!/bin/bash
[ "`adb shell "pm list packages com.my.package"`" == "" ] || adb shell "pm clear com.my.package