I am running a Jenkins pipeline script. I keep get the error that org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Required context class hudson.FilePath is missing Perhaps you forgot to surround the code with a step that provides this, such as: node in the stack trace. The actual credentials in my script on Jenkins are there but for the sake of this example they were given symbols.
Here is my script that I am running:
try {
node {
stage('Preparation') {
git credentialsId: 'validCredentials', url: 'repo', branch: 'branch'
}
stage('Clean Build') {
dir("directory-to-where-my gradle-wrapper-is-located") {
sh "pwd"
sh 'ls -al'
sh './gradlew clean build'
}
}
}
}catch (caughtError) {
err = caughtError
currentBuild.result = "FAILURE"
} finally {
if(currentBuild.result == "FAILURE"){
sh "echo 'Build FAILURE'"
}else{
sh "echo 'Build SUCCESSFUL'"
}
}
any ideas?
Related
I'm trying to get an argument from the command line using a Gradle task:
class myApk extends DefaultTask {
#Option(option="apkName", description="apkName for your file")
String apkName
#TaskAction
void uploadApk() {
def arg = "curl -F \"demo${apkName}.apk=" +
"#${project.projectDir}\\app\\build\\outputs\\apk\\debug\\app-debug.apk\" " +
"https://URL"
project.exec {
commandLine("cmd", "/c", arg)
}
}
}
task uploadApk(type: myApk) { }
But after typing gradle uploadApk --apkName=foo in the terminal I get this kind of exception:
Problem configuring task :app:uploadApk from command line.
> Unknown command-line option '--apkName'.
P.S. I've read this topic(How to pass arguments from command line to gradle), but it doesn't seem helpful for this problem;(
Thanks to the comment above, I used -P to work it out
I'm trying to upload a debug apk file to the server by Gradle. I'm using a special name for it, smth like "demo-testing.apk" or "demo-first.apk".
class Apk extends DefaultTask {
String apkName
#TaskAction
void uploadApk() {
exec {
commandLine(
"cmd",
"-c",
"curl -F \"demo${apkName}.apk=" +
"#${DEFAULT_BUILD_DIR_NAME}/outputs/apk/debug/app-debug.apk\" " +
"https://URL"
)
}
}
}
tasks.register("first", Apk) {
group = 'apkUploads'
description = 'Uploads first apk'
apkName = '-first'
}
But it doesn't execute(with proper URL in the command line arguments) due to this exception:
Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method exec() for arguments [Apk$_uploadApk_closure1#58ed1
b0a] on task ':first' of type Apk.
Can someone please tell me what I'm doing wrong?
So thanks to the comment above I should have invoke project.exec instead of exec and it worked
I am very beginning to Jenkins. I followed this tutorial for automated publish app to play store. https://medium.com/mindorks/automating-android-app-play-store-publishing-via-jenkins-a6c30dbc59dd
I got this error message very beginning.
groovy.lang.MissingPropertyException: No such property: HOME for
class: groovy.lang.Binding
def home = sh(script: "echo $HOME",returnStdout: true).trim()
def SDKPath = "$home/Android/SDK"
stage("Preparing SDK"){
// Check SDK Downloaded
def isSDKDownloaded = sh(script: "test -e sdk-tools-linux-4333796.zip && echo true || echo false",returnStdout: true).trim()
if(isSDKDownloaded == "false"){
// Download SDK
sh "wget 'https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip'"
}
// Check if SDK is Extracted
def isExtracted = sh(script: "test -e $SDKPath/tools && echo true || echo false",returnStdout: true).trim()
if(isExtracted == "false"){
sh "mkdir -p $SDKPath"
//Unzip SDK
sh "unzip sdk-tools-linux-4333796.zip -d $SDKPath"
}
// Install SDK Tools
sh "yes | $SDKPath/tools/bin/sdkmanager 'build-tools;28.0.3' 'platform-tools' 'platforms;android-27'"
sh "ls $SDKPath/licenses"
// See installed And Available SDK
sh "$SDKPath/tools/bin/sdkmanager --list"
// Accept All SDK Licences
sh "yes | $SDKPath/tools/bin/sdkmanager --licenses"
}
def selectedBranch = SELECTED_RELEASE_BRANCH
stage('Checkout') {
git branch: selectedBranch, url: 'git#gitlab.com:...'
// Remove Existing local properties
sh 'rm local.properties ||:'
// Write sdk.dir Path into local properties file
sh "echo 'sdk.dir=$SDKPath' >> local.properties"
}
stage('Setup Tools') {
withCredentials([file(credentialsId: 'android_keystore', variable: 'KEYFILE')]) {
sh "cp \$KEYFILE app/key.jks"
}
}
stage('Build Release APK') {
sh "./gradlew clean assembleRelease"
}
stage('Upload to Play Store') {
androidApkUpload googleCredentialsId: 'P12 KEY added to here', apkFilesPattern: '**/*-release.apk', trackName: 'alpha'
}
stage('Cleanup Credential') {
sh "rm app/key.jks"
}
Change path name ANDROID_HOME instead of HOME
I am trying to write a task in build.gradle that executes shell commands on all connected devices. However, when I run my task, I get the notorious 'multiple devices connected' error.
task(myTask, type: Exec) {
doFirst {
println 'myTask'
commandLine 'adb', 'shell', 'my command'
}
}
This is understandable, because I did not specify which device to run on with -s. However, I noticed that the installDebug task will execute its commands on all connected devices (install debug .apk on all devices).
Is there an API in the android plugin that returns a collection of devices IDs that I can iterate over?
Yes.You can check the Android Gradle Plugin source here, where you will find the following:
import com.android.ddmlib.AndroidDebugBridge
import com.android.ddmlib.IDevice
// ...
AndroidDebugBridge.initIfNeeded(false /*clientSupport*/)
AndroidDebugBridge bridge = AndroidDebugBridge.createBridge(android.getAdbExe().absolutePath,
false /*forceNewBridge*/)
long timeOut = 30000 // 30 sec
int sleepTime = 1000
while (!bridge.hasInitialDeviceList() && timeOut > 0) {
sleep(sleepTime)
timeOut -= sleepTime
}
if (timeOut <= 0 && !bridge.hasInitialDeviceList()) {
throw new RuntimeException("Timeout getting device list.", null)
}
IDevice[] devices = bridge.devices
if (devices.length == 0) {
throw new RuntimeException("No connected devices!", null)
}
File destination = project.file("$project.buildDir/outputs/screenshots")
delete destination
for (IDevice device : devices) {
// iterate over your devices here ;)
}
Also you will notice that there is a getter for adb as well that you can use in the loop from above:
project.exec {
executable = android.getAdbExe()
args '-s'
args "$device.serialNumber"
}
Old thread, but maybe it helps someone at some point.
As David Medenjak already mentioned the android.ddmlib is the solution.
You can use it like the following:
In yourscript.gradle:
import com.android.ddmlib.AndroidDebugBridge
import com.android.ddmlib.IDevice
import com.android.ddmlib.NullOutputReceiver
task pressPower {
description = "Press the power button of a device using the adb."
AndroidDebugBridge.initIfNeeded(false)
def bridge = AndroidDebugBridge.createBridge(android.adbExecutable.path, false)
doLast {
bridge.devices.each {
it.executeShellCommand("input keyevent 26", NullOutputReceiver.receiver)
}
}
}
In which "input keyevent 26" corresponds to the shell command ./adb shell input keyevent 26.
If you want to work with the output of the shell you can use the CollectingOutputReceiver like below:
import com.android.ddmlib.AndroidDebugBridge
import com.android.ddmlib.IDevice
import com.android.ddmlib.CollectingOutputReceiver
task getAnimationValue {
description = "Get the Value for the window animation scale."
AndroidDebugBridge.initIfNeeded(false)
def bridge = AndroidDebugBridge.createBridge(android.adbExecutable.path, false)
def receiver = CollectingOutputReceiver.newInstance()
doLast{
bridge.devices.each {
it.executeShellCommand("settings get global window_animation_scale", receiver)
println "Value: ${receiver.getOutput()}"
}
}
}
The task prints the value for the window animation scale gathered by receiver.getOutput().
I run Appium server:
➜ ~ appium
info: Welcome to Appium v1.3.5 (REV a124a15677e26b33db16e81c4b3b34d9c6b8cac9)
info: Appium REST http interface listener started on 0.0.0.0:4723
info: Console LogLevel: debug
info: --> POST /wd/hub/session {"desiredCapabilities":{"appPackage":"com.grindrapp.android","appActivity":".activity.SplashActivity","platformVersion":"4.4.2","browserName":"","platformName":"Android","deviceName":"10.0.0.9:5555"}}
info: Client User-Agent string: Apache-HttpClient/4.3.4 (java 1.5)
info: [debug] Didn't get app but did get Android package, will attempt to launch it on the device
info: [debug] Creating new appium session 090abe0c-36d9-4f9b-987a-f3b665045928
info: Starting android appium
info: [debug] Getting Java version
info: [debug] Cleaning up android objects
info: [debug] Cleaning up appium session
error: Failed to start an Appium session, err was: Error: Could not get the Java version. Is Java installed?
info: [debug] Error: Could not get the Java version. Is Java installed?
at /usr/local/lib/node_modules/appium/lib/devices/android/android-common.js:1040:17
at ChildProcess.exithandler (child_process.js:735:7)
at ChildProcess.emit (events.js:110:17)
at maybeClose (child_process.js:1008:16)
at Socket.<anonymous> (child_process.js:1176:11)
at Socket.emit (events.js:107:17)
at Pipe.close (net.js:476:12)
info: [debug] Responding to client with error: {"status":33,"value":{"message":"A new session could not be created. (Original error: Could not get the Java version. Is Java installed?)","origValue":"Could not get the Java version. Is Java installed?"},"sessionId":null}
info: <-- POST /wd/hub/session 500 316.738 ms - 222
^C
➜ ~ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home
I try to run this code to post to Appium server:
public class AndroidTest {
private AppiumDriver driver;
#Before
public void setUp() throws Exception {
// File classpathRoot = new File(System.getProperty("user.dir"));
// File appDir = new File(classpathRoot, "../../../data/app/");
// File app = new File(appDir, "Facebook.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
capabilities.setCapability("deviceName","10.0.0.9:5555");
capabilities.setCapability("platformVersion", "4.4.2");
capabilities.setCapability("platformName","Android");
//capabilities.setCapability("app", app.getCanonicalPath());
capabilities.setCapability("appPackage", "com.grindrapp.android");
capabilities.setCapability("appActivity", ".activity.SplashActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
but as you can see I get this error:
info: [debug] Error: Could not get the Java version. Is Java installed?
how can I fix this?
I'm trying to automatically open an app which i downloaded from the google play and I don't have its apk.
I think this is the final solution for your problem.
As always, make a backup copy of the file before editing.
Edit the file /usr/local/lib/node_modules/appium/lib/devices/android/android-common.js
In the else if(stderr) branch around line 1034:
else if (stderr) {
var firstLine = stderr.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}
}
replace the code to read:
else if (stderr){
if(new RegExp("java version").test(stderr)){
var regex = "java version \"[0-9]+\.[0-9]+\.[0-9]+";
var stderrstring = '' + stderr + '';
var regmatch = stderrstring.match(regex);
javaVersion = '' + regmatch + '' //convert object to string
javaVersion.replace(/"/g,'');
}
}
The code should work with a regular java version response message plus the one that you are receiving.
The file is located here:
/usr/local/lib/node_modules/appium/lib/devices/android/android-common.js
The code we are concerned with starting at line 1029 is:
androidCommon.getJavaVersion = function (cb) {
exec("java -version", function (err, stdout, stderr) {
var javaVersion = null;
if (err) {
return cb(new Error("'java -version' failed. " + err));
} else if (stderr) {
var firstLine = stderr.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}
}
if (javaVersion === null) {
return cb(new Error("Could not get the Java version. Is Java installed?"));
}
return cb(null, javaVersion);
});
};
I am unable to test this on my system, but I think that a successful execution of java -version would return its response on stdout and not stderr. I would change the code to provide more information as to what is happening and help debug it.
You are getting the JavaVersion = null message at the end of the listing which means that there is nothing returned in err and parsing of stderr is not setting JavaVersion. It does not tell you if there is anything in stderr nor does it even look at stdout.
Here is a revised code listing. If the output is indeed returned on stderr, the code will now at least print it out so you can see what is returned. I added the same code branch for stdout as it was not checked at all.
androidCommon.getJavaVersion = function (cb) {
exec("java -version", function (err, stdout, stderr) {
var javaVersion = null;
var firstLine = null;
if (err) {
return cb(new Error("'java -version' failed. " + err));
} else if (stderr) {
firstLine = stderr.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}else{
return cb(new Error("Java version stderr string parse error: " + stderr));
}
} else if(stdout){
firstLine = stdout.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}else{
return cb(new Error("Java version stdout string parse error: " + stdout));
}
}
if (javaVersion === null) {
return cb(new Error("Could not get the Java version. Is Java installed?"));
}
return cb(null, javaVersion);
});
}
So:
make a backup copy of android-commons.js
make the code change and give it a try.
This might work as written or the error messages will tell you what is being returned.
The code in android-common.js is looking for the java version number on the first line.
I had the similar issue, but my java -version returns result as
[~]$ java -version
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
So I simply changed the code in android-common.js to split second line instead of first line
firstLine = stderr.split("\n")[0]; -> firstLine = stderr.split("\n")[1]