how to create log files in Gradle - gradle

I am using Gradle-2.11 and I am unable to find a way to create log files that logs debug level information. I don't want to do it through command line by redirecting the logs to the log file. I want Gradle code just like Apache Ant's 'record' task so that I can put that code in my build.gradle file wherever I want to create logs.
For ex: If I want to convert this ant task to gradle, then what would be the code:
<record name="${BuildLogPath}/${BuildLogFile}" append="no" loglevel="verbose" action="start"/>

Gradle integrates really nicely with Ant (https://docs.gradle.org/2.11/userguide/ant.html)
It doesn't automatically record each step. I didn't realize that is what you were asking. The updated below will produce the output and you can manually log.
ant.record(name: "${BuildLogPath}/${BuildLogFile}", append:false, loglevel: "verbose", action: "start")
ant.echo("start logging")
//... do stuff here
ant.echo(message: "end logging")
ant.record(name: "${BuildLogPath}/${BuildLogFile}", append:false, loglevel: "verbose", action: "stop")
This may do more of what you are asking. Note: This is something I adapted slightly from this excellent example:
http://themrsion.blogspot.com/2013/10/gradle-logging-writing-to-log-to-file.html
import org.gradle.logging.internal.*
String currentDate = new Date().format('yyyy-MMM-dd_HH-mm-ss-S')
String loggingDirectory = "${rootDir}/build/logs"
mkdir("${loggingDirectory}")
File gradleBuildLog = new File("${loggingDirectory}/${currentDate}_gradleBuild.log")
gradle.services.get(LoggingOutputInternal).addStandardOutputListener (new StandardOutputListener () {
void onOutput(CharSequence output) {
gradleBuildLog << output
}
})
gradle.services.get(LoggingOutputInternal).addStandardErrorListener (new StandardOutputListener () {
void onOutput(CharSequence output) {
gradleBuildLog << output
}
})

Related

Looking for a way to excute a command line from cypress

I need to create a file and copy it somewhere by some code from cypress .
the first step is done by using cy.writeFile and now myfile.txt is created
Now i need to copy it somewhere like c:/lib/Sth
i used this command cy.exec('cp myfile.txt c:/lib/sth')
it shows this error message :
CypressError: cy.exec('cp myfile.txt c:/lib/sth') failed because the command exited with a non-zero code. Pass {failOnNonZeroExit: false}` to ignore exit code failures.
Information about the failure:
Code: 127
I add {failOnNonZeroExit: false} to my code to ignore error , it works , but my file is not copied.
is there any other solution to copy my file from cypress ??
A work-around you could do is set up a custom cypress task to execute a command.
Something like
// cypress/plugins/index.ts
const { exec } = require('child_process');
/**
* #type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on('task', {
async execute(command: string) {
return new Promise((resolve, reject) => {
try {
resolve(exec(command));
} catch (e) {
reject(e);
}
});
},
});
};
Then execute like so
cy.task('execute', 'cp myfile.txt c:/lib/sth');
This was a potential solution I came up with when cy.exec() didn't work for me either when trying to execute a relatively complex node script.
Another thing you could try is to create a really simple script that copies the file, and try executing that script.
Best of luck!

systematic failure when trying to execute a system command with Cypress

I'm new to Cypress and Javascript
I'm trying to send system commands through Cypress. I've been through several examples but even the simplest does not work.
it always fails with the following message
Information about the failure:
Code: 127
Stderr:
/c/Program: Files\Git\usr\bin\bash.exe: No such file or directory`
I'm trying cy.exec('pwd') or 'ls' to see where it is launched from but it does not work.
Is there a particular include I am missing ? some particular configuration ?
EDIT :
indeed, I'm not clear about the context I'm trying to use the command in. However, I don't set any path explicitely.
I send requests on a linux server but I also would like to send system commands.
My cypress project is in /c/Cypress/test_integration/cypress
I work with a .feature file located in /c/Cypress/test_integration/cypress/features/System and my scenario calls a function in a file system.js located in /c/Cypress/test_integration/cypress/step_definitions/generic.
System_operations.features:
Scenario: [0004] - Restore HBox configuration
Given I am logging with "Administrator" account from API
And I store the actual configuration
...
Then I my .js file, I want to send a system command
system.js:
Given('I store the actual configuration', () => {
let nb_elem = 0
cy.exec('ls -l')
...
})
I did no particular path configuration in VS Code for the use of bash command (I just configured the terminal in bash instead of powershell)
Finally, with some help, I managed to call system functions by using tasks.
In my function I call :
cy.task('send_system_cmd', 'pwd').then((output) => {
console.log("output = ", output)
})
with a task created as follows:
on('task', {
send_system_cmd(cmd) {
console.log("task test command system")
const execSync = require('child_process').execSync;
const output = execSync(cmd, { encoding: 'utf-8' });
return output
}
})
this works at least for simple commands, I haven't tried much further for the moment.
UPDATE for LINUX system commands as the previous method works for WINDOWS
(sorry, I can't remember where I found this method, it's not my credit. though it fulfills my needs)
This case requires node-ssh
Still using tasks, the function call is done like this
cy.task('send_system_cmd', {cmd:"<my_command>", endpoint:<address>,user:<ssh_login>, pwd:<ssh_password>}).then((output) => {
<process output.stdout or output.stderr>
})
with the task being build like this:
// send system command - remote
on('task', {
send_system_cmd({cmd, endpoint, user, pwd}) {
return new Promise((resolve, reject) => {
const { NodeSSH } = require('node-ssh')
const ssh = new NodeSSH()
let ssh_output = {}
ssh.connect({
host: endpoint,
username: user,
password: pwd
})
.then(() => {
if(!ssh.isConnected())
reject("ssh connection not set")
//console.log("ssh connection OK, send command")
ssh.execCommand(cmd).then(function (result) {
ssh_output["stderr"] = result.stderr
ssh_output["stdout"] = result.stdout
resolve(ssh_output)
});
})
.catch((err)=>{
console.log(err)
reject(err)
})
})
}
})

How to configure jenkins pipeline with logstash plugin?

Usecase: I want to send jenkins job console log to elasticsearch, from there to kibana so that i can visualise the data.
I am using logstash plugin to achieve this. For freestyle job logstash plugin configuration is working fine but for jenkins pipeline jobs I am getting all required data like build number, job name, build duration and all but it is not showing the build result i.e., success or failure it is not showing.
I tried in two ways:
1.
stage('send to ES') {
logstashSend failBuild: true, maxLines: -1
}
2.
timestamps {
logstash {
node() {
sh'''
echo 'Hello, World!'
'''
try {
stage('GitSCM')
{
git url: 'github repo.git'
}
stage('Initialize')
{
jdk = tool name: 'jdk'
env.JAVA_HOME = "${jdk}"
echo "jdk installation path is: ${jdk}"
sh "${jdk}/bin/java -version"
sh '$JAVA_HOME/bin/java -version'
def mvnHome = tool 'mvn'
}
stage('Build Stage')
{
def mvnHome = tool 'mvn'
sh "${mvnHome}/bin/mvn -B verify"
}
currentBuild.result = 'SUCCESS'
} catch (Exception err) {
currentBuild.result = 'FAILURE'
}
}
}
}
But in both ways I am not getting build result i.e., success or failure in my elasticsearch or kibana.
Can someone help.
I didn't find a clear way to do that, my solution was add those lines at the end of the Jenkinsfile:
echo "Current result: ${currentBuild.currentResult}"
logstashSend failBuild: true, maxLines: 3
In my case, I dont need it to send all console logs, only one log with the result per job.

How it is possible to passthrough file in logstash?

I want to passthrough a file in logstash for debugging purposes. Is it possible somehow?
If i use following config to stdout stdin input, it works fine:
input { stdin { } }
output { stdout { } }
But when i want to do the same for file, it does not work:
input {
file {
path => ["/home/logstash/xunit.json"]
}
}
output {
stdout { }
}
I only see following warning, and nothing more:
Using milestone 2 input plugin 'file'. This plugin should be stable, but if you see strange behavior, please let us know! For more information on plugin milestones, see http://logstash.net/docs/1.4.2/plugin-milestones {:level=>:warn}
What i am doing wrong?
P.S. If using verbose mode, i see following lines, then everything hangs:
Registering file input {:path=>["/home/logstash/xunit.json"], :level=>:info}
Pipeline started {:level=>:info}
P.P.S. User has access to file.

How to define and call custom methods in build.gradle?

As part of my project, I need to read files from a directory and do some operations all these in build script. For each file, the operation is the same(reading some SQL queries and execute it). I think its a repetitive task and better to write inside a method. Since I'm new to Gradle, I don't know how it should be. Please help.
One approach given below:
ext.myMethod = { param1, param2 ->
// Method body here
}
Note that this gets created for the project scope, ie. globally available for the project, which can be invoked as follows anywhere in the build script using myMethod(p1, p2) which is equivalent to project.myMethod(p1, p2)
The method can be defined under different scopes as well, such as within tasks:
task myTask {
ext.myMethod = { param1, param2 ->
// Method body here
}
doLast {
myMethod(p1, p2) // This will resolve 'myMethod' defined in task
}
}
If you have defined any methods in any other file *.gradle - ext.method() makes it accessible project wide. For example here is a
versioning.gradle
// ext makes method callable project wide
ext.getVersionName = { ->
try {
def branchout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
standardOutput = branchout
}
def branch = branchout.toString().trim()
if (branch.equals("master")) {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = stdout
}
return stdout.toString().trim()
} else {
return branch;
}
}
catch (ignored) {
return null;
}
}
build.gradle
task showVersion << {
// Use inherited method
println 'VersionName: ' + getVersionName()
}
Without ext.method() format , the method will only be available within the *.gradle file it is declared. This is the same with properties.
You can define methods in the following way:
// Define an extra property
ext.srcDirName = 'src/java'
// Define a method
def getSrcDir(project) {
return project.file(srcDirName)
}
You can find more details in gradle documentation Chapter 62. Organizing Build Logic
An example with a root object containing methods.
hg.gradle file:
ext.hg = [
cloneOrPull: { source, dest, branch ->
if (!dest.isDirectory())
hg.clone(source, dest, branch)
else
hg.pull(dest)
hg.update(dest, branch)
},
clone: { source, dest, branch ->
dest.mkdirs()
exec {
commandLine 'hg', 'clone', '--noupdate', source, dest.absolutePath
}
},
pull: { dest ->
exec {
workingDir dest.absolutePath
commandLine 'hg', 'pull'
}
},
]
build.gradle file
apply from: 'hg.gradle'
hg.clone('path/to/repo')
Somehow, maybe because it's five years since the OP, but none of the
ext.someMethod = { foo ->
methodBody
}
approaches are working for me. Instead, a simple function definition seems to be getting the job done in my gradle file:
def retrieveEnvvar(String envvar_name) {
if ( System.getenv(envvar_name) == "" ) {
throw new InvalidUserDataException("\n\n\nPlease specify environment variable ${envvar_name}\n")
} else {
return System.getenv(envvar_name)
}
}
And I call it elsewhere in my script with no prefix, ie retrieveEnvvar("APP_PASSWORD")
This is 2020 so I'm using Gradle 6.1.1.
#ether_joe the top-voted answer by #InvisibleArrow above does work however you must define the method you call before you call it - i.e. earlier in the build.gradle file.
You can see an example here. I have used this approach with Gradle 6.5 and it works.
With Kotlin DSL (build.gradle.kts) you can define regular functions and use them.
It doesn't matter whether you define your function before the call site or after it.
println(generateString())
fun generateString(): String {
return "Black Forest"
}
tasks.create("MyTask") {
println(generateString())
}
If you want to import and use a function from another script, see this answer and this answer.
In my react-native in build.gradle
def func_abc(y){return "abc"+y;}
then
def x = func_abc("y");
If you want to check:
throw new GradleException("x="+x);
or
println "x="+x;

Resources