Can't get Gradle to use System.in - gradle

This question explains how to use System.in when running a task to run a specific class in a project.
But for me currently it's not working: although I have included the application plugin and the following lines in build.gradle:
mainClassName = "misc.StreamsExp"
run{
standardInput = System.in
}
task stream( type: JavaExec, dependsOn: assemble ){
classpath sourceSets.main.runtimeClasspath
main = "misc.StreamsExp"
}
the line with readLine in the app code below should be blocking but it's not:
BufferedReader br = new BufferedReader(new InputStreamReader( System.in ));
String enteredLine = "";
while( enteredLine == null || ! enteredLine.equals( "q" )){
System.out.println( "spuds");
enteredLine = br.readLine();
}
... instead the thing just spins on forever:
spuds
spuds
spuds
...
NB I am on a Windows 10 OS, with Java 8.91. I have tried both the Windows DOS console and Cygwin.
NB2 The same thing occurs when I run this stream task inside Eclipse (Gradle STS Eclipse plugin)... but not when I do Run as --> Java application: then the blocking occurs as expected.

Hah... one of those sits where you think you're gonna be stumped forever and you find the solution 2 mins after posting to SO! I'll leave it here for anyone else...
The answer is to put the line standardInput = in the task you're running, like so:
task stream( type: JavaExec, dependsOn: assemble ){
standardInput = System.in
classpath sourceSets.main.runtimeClasspath
main = "misc.StreamsExp"
}
Strangely, the prompt "spuds" is followed in the Windows DOS terminal by
> Building 88% > :stream
... which is a known "bug" referred to in the question I referenced. In Cygwin this bug does not happen.
CAVEAT: this works in the Windows DOS terminal and the Cygwin terminal... it does NOT solve the problem when running the bespoke stream task in Eclipse!

Related

Gradle sync in IntelliJ triggers tasks defined in build.gradle - why, and how to prevent that? [duplicate]

So I am sure this is something very dumb mistake, but I need your help since I am not a gradle expert.
TASK:
read versionCode from file add +1 to it and save it back.
task executeOrderSixtySix {
def versionPropsFile = file('versionCodes.properties')
if (versionPropsFile.canRead()) {
def Properties versionProps = new Properties()
versionProps.load(new FileInputStream(versionPropsFile))
def versionNumber = versionProps['DEV_VERSION'].toInteger() + 1
versionProps['DEV_VERSION'] = versionNumber.toString()
versionProps.store(versionPropsFile.newWriter(), null)
// 'assembleDebug'
} else {
throw new GradleException("Nyeeeh on versionCodes.properties!")
}}
So when I have to do an internal drop I would like to run this task first, increase the devVersion number by 1 and then run the 'assemble' task to build all artifacts.
PROBLEM:
This task executes itself, even if I just sync the cradle file causing increased versionCode all the time.
I don't want to increase the versionCode during sync, development build only just for QAdrop, when I also have to assemble every APK.
Could you please help me out and tell me why is this task getting called/executed and who can I prevent it?
You need a doLast block inside of your task block. build.gradle file is a configuration script so it reads as declare the task when on configuration and declare the action on the execution.
Anything done in the task either before or after the doLast block would be run during configuration time. The code in the doLast block itself runs at execution time.
task executeOrderSixtySix {
doLast {
def versionPropsFile = file('versionCodes.properties')
if (versionPropsFile.canRead()) {
def Properties versionProps = new Properties()
versionProps.load(new FileInputStream(versionPropsFile))
def versionNumber = versionProps['DEV_VERSION'].toInteger() + 1
versionProps['DEV_VERSION'] = versionNumber.toString()
versionProps.store(versionPropsFile.newWriter(), null)
// 'assembleDebug'
} else {
throw new GradleException("Nyeeeh on versionCodes.properties!")
}
}
}
Ref: https://www.oreilly.com/learning/write-your-own-custom-tasks-in-gradle

Add password to package in gradle

I packed a zip containing a list of webapps with gradle.
At the end, I would like to add a password to the zip.
I tried to user commandLine passing the linuz command "zipcloak", then the psw in required twice and I'm not able to send it to the command line:
commandLine ("zipcloak", zip_name + ".zip")
setStandardInput ("psw")
setStandardInput ("psw")
Maybe there is a better solution to do this...
Thanks
EDIT:
I progressed by adding this lines:
commandLine "zipcloak", "zipname.zip"
ByteArrayOutputStream bytes = new ByteArrayOutputStream()
PrintWriter out = new PrintWriter(bytes)
out.println("psw")
out.println("psw")
out.flush()
ByteArrayInputStream input = new ByteArrayInputStream(bytes.toByteArray())
standardInput = input
Now the command is executed and I see on the console the request of the password, but I'm not still able to send a string to this request directly from the script, I have to add it manually on the console...
EDIT - SOLUTION FOUND:
I found the solution: instead of adding a password to an existing zip, I packed the zip WITH password
task encodeZip(type: Exec) {
workingDir path_target_workspace
commandLine "zip", "-P", "password", "-r", "zipname.zip", "file1", "file2", "fil3" .....
}
Hope it helps

Jenkins delete builds older than latest 20 builds for all jobs

I am in the process of cleaning up Jenkins (it was setup incorrectly) and I need to delete builds that are older than the latest 20 builds for every job.
Is there any way to automate this using a script or something?
I found many solutions to delete certain builds for specific jobs, but I can't seem to find anything for all jobs at once.
Any help is much appreciated.
You can use the Jenkins Script Console to iterate through all jobs, get a list of the N most recent and perform some action on the others.
import jenkins.model.Jenkins
import hudson.model.Job
MAX_BUILDS = 20
for (job in Jenkins.instance.items) {
println job.name
def recent = job.builds.limit(MAX_BUILDS)
for (build in job.builds) {
if (!recent.contains(build)) {
println "Preparing to delete: " + build
// build.delete()
}
}
}
The Jenkins Script Console is a great tool for administrative maintenance like this and there's often an existing script that does something similar to what you want.
I got an issue No such property: builds for class: com.cloudbees.hudson.plugins.folder.Folder on Folders Plugin 6.6 while running #Dave Bacher's script
Alter it to use functional api
import jenkins.model.Jenkins
import hudson.model.Job
MAX_BUILDS = 5
Jenkins.instance.getAllItems(Job.class).each { job ->
println job.name
def recent = job.builds.limit(MAX_BUILDS)
for (build in job.builds) {
if (!recent.contains(build)) {
println "Preparing to delete: " + build
build.delete()
}
}
}
There are lots of ways to do this
Personally I would use the 'discard old builds' in the job config
If you have lots of jobs you could use the CLI to step through all the jobs to add it
Alternatively there is the configuration slicing plugin which will also do this for you on a large scale
For Multibranch Pipelines, I modified the script by Dave Bacher a bit. Use this to delete builds older than the latest 20 build of "master" branches:
MAX_BUILDS = 20
for (job in Jenkins.instance.items) {
if(job instanceof jenkins.branch.MultiBranchProject) {
job = job.getJob("master")
def recent = job.builds.limit(MAX_BUILDS)
for (build in job.builds) {
if (!recent.contains(build)) {
println "Preparing to delete: " + build
// build.delete()
}
}
}
}
This can be done in many ways. You can try the following
get all your job names in a textfile by going to the jobs location in jenkins and run the following
ls >jobs.txt
Now you can write a shell script with a for loop
#!/bin/bash
##read the jobs.txt
for i in 'cat <pathtojobs.txt>'
do
curl -X POST http://jenkins-host.tld:8080/jenkins/job/$i/[1-9]*/doDeleteAll
done
the above deletes all the jobs
you can also refer here for more answers
I had issues running the suggestions on my Jenkins instance. It could be because it is dockerized. In any case, removing the folder beforehand using the underlying bash interpreter fixes the issue. I also modified the script to keep 180 days of build logs and keep a minimum of 7 build logs:
import jenkins.model.Jenkins
import hudson.model.Job
MIN_BUILD_LOGS = 7
def sixMonthsAgo = new Date() - 180
Jenkins.instance.getAllItems(Job.class).each { job ->
println job.getFullDisplayName()
def recent = job.builds.limit(MIN_BUILD_LOGS)
def buildsToDelete = job.builds.findAll {
!recent.contains(it) && ! (it.getTime() > sixMonthsAgo)
}
if (!buildsToDelete) {
println "nothing to do"
}
for (build in buildsToDelete) {
println "Preparing to delete: " + build + build.getTime()
["bash", "-c", "rm -r " + build.getRootDir()].execute()
build.delete()
}
}
"done"

In Gradle, is there a better way to get Environment Variables?

In several Tasks, I reference jars in my home folder.
Is there a better way to get Environment Variables than
ENV = System.getenv()
HOME = ENV['HOME']
task copyToServer(dependsOn: 'jar', type: Copy) {
from 'build/libs/'
into HOME + "/something/plugins/"
}
This sets $HOME but I was hoping that I missed some magic from the documentation.
Well; this works as well:
home = "$System.env.HOME"
It's not clear what you're aiming for.
I couldn't get the form suggested by #thoredge to work in Gradle 1.11, but this works for me:
home = System.getenv('HOME')
It helps to keep in mind that anything that works in pure Java will work in Gradle too.
In android gradle 0.4.0 you can just do:
println System.env.HOME
classpath com.android.tools.build:gradle-experimental:0.4.0
This is for Kotlin DSL (build.gradle.kts):
val myVariable = System.getenv("MY_VARIABLE_NAME") ?: "my default value"
OR
val myVariable = System.getenv("MY_VARIABLE_NAME") ?: error("Env variable not found")
OR
val environment = System.getenv()
val myVariable = environment["MY_VARIABLE_NAME"] ?: "my default value"
// OR val myVariable = environment["MY_VARIABLE_NAME"] ?: error("Env variable not found")

problem in imagemagick and grails

i have a new problem in image magick that look strange ..
i'm using mac osx snow leopard and i've installed image magick on it and it's working fine on command ..
but when i call it from the grails class like the following snippet it gives me
"Cannot run program "convert": error=2, No such file or directory"
the code is :-
public static boolean resizeImage(String srcPath, String destPath,String size) {
ArrayList<String> command = new ArrayList<String>(10);
command.add("convert");
command.add("-geometry");
command.add(size);
command.add("-quality");
command.add("100" );
command.add(srcPath);
command.add(destPath);
System.out.println(command);
return exec((String[])command.toArray(new String[1]));
}
private static boolean exec(String[] command) {
Process proc;
try {
//System.out.println("Trying to execute command " + Arrays.asList(command));
proc = Runtime.getRuntime().exec(command);
} catch (IOException e) {
System.out.println("IOException while trying to execute " );
for(int i =0 ; i<command.length; i++) {
System.out.println(command[i]);
}
return false;
}
//System.out.println("Got process object, waiting to return.");
int exitStatus;
while (true) {
try {
exitStatus = proc.waitFor();
break;
} catch (java.lang.InterruptedException e) {
System.out.println("Interrupted: Ignoring and waiting");
}
}
if (exitStatus != 0) {
System.out.println("Error executing command: " + exitStatus);
}
return (exitStatus == 0);
}
i've tried normal command like ls and it's ok so the problem is that grails can't find convert command itself.. is it a os problem or something?
(see lower for the answer)
I have run into the same problem. The issue appears to be something with Mac OS X specifically, as we have several Linux instances running without error. The error looks similar to the following:
java.io.IOException: Cannot run program "/usr/bin/ImageMagick-6.7.3/bin/convert /a/temp/in/tmpPic3143119797006817740.png /a/temp/out/100000726.png": error=2, No such file or directory
All the files are there, and in chmod 777 directories - and as you pointed out, running the exact command from the shell works fine.
My theory at this point is that imagemgick can not load some sort of library itself, and the "no such file" is in reference to an dylib or something along those lines.
I have tried setting LD_LIBRARY_PATH and a few others to no avail.
I finally got this working. Here is how I have it setup. I hope this helps.
The crux of the fix, for me, was I wrapped the 'convert' into a shell script, set a bunch of environment variables, and then call that shell script instead of convert directly:
(convertWrapper.sh)
export MAGICK_HOME=/usr/local/ImageMagick-6.7.5
export MAGICK_CONFIGURE_PATH=${MAGICK_HOME}/etc/ImageMagick:${MAGICK_HOME}/share/doc/ImageMagick/www/source
export PATH=${PATH}:${MAGICK_HOME}/bin
export LD_LIBRARY_PATH=${MAGICK_HOME}/lib:${LD_LIBRARY_PATH}
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:${MAGICK_HOME}/lib
export MAGICK_TMPDIR=/private/tmp
echo "$#" >> /private/tmp/m.log 2>&1
/usr/local/ImageMagick-6.7.5/bin/convert -verbose "$#" >> /private/tmp/m.log 2>&1
(convertWrapper.sh)
Additionally, the convert call was doing some rather complicated stuff, so I added the parameter '-respect-parenthesis' (which may or may not have had an effect).
I am not sure how much of the environment variable setting is needed as I was stabbing in the dark for a while, but since this is only for my development box...
You need to work out what your PATH is set to when you run a command from Java. It must be different to the one you have when running from the terminal.
Are you running Grails (via Tomcat?) as a different user? It might have a different path to your normal user.
you might want to try one of the Image Plugins that are part of the grails ecosystem
http://www.grails.org/ImageTools+plugin
the grails path when the app is running in the server is probably different from running java from the command line
I do so:
Put "convert" file to /usr/bin
Then add to Config.groovy:
gk {
imageMagickPath = "/usr/bin/convert"
}
Then in my ImageService.groovy:
import org.springframework.web.context.request.RequestContextHolder as RCH
[..]
def grailsApplication = RCH.requestAttributes.servletContext.grailsApplication
def imPath = grailsApplication.config.gk.imageMagickPath
def command = imPath + " some_properties"
def proc = Runtime.getRuntime().exec(command)
So this way you get command like: /usr/bin/convert some_properties
And it works, but don't forget to put file "convert" to you location and use it with this location.

Resources