Add command to Grails build process - grails

I am using the grails-cdn-asset-pipline plugin. I've gone through the installation and configuration steps on GitHub and I reach the usage section which says
Add this command to your build process (usually before war generation and deployment).
// If all the settings are defined in your Config.groovy
grails asset-cdn-push
// Or
grails asset-cdn-push --provider=S3 --directory=my-bucket --gzip=true --storage-path=some-prefix --expires=365 --region=eu-west-1 --access-key=$MY_S3_ACCESS_KEY --secret-key=$MY_S3_SECRET_KEY
Where in my project do I put this command?
Is it something that I can do within the context of my project, or do I need to keep it separate in another build process and run it in an environment like Jenkins?
In _Events.groovy, I tried to invoke the script in the eventCreateWarStart, but I am having no luck there. (Code taken from this question)
eventCreateWarStart = { warName, stagingDir ->
def pluginManager = PluginManagerHolder.pluginManager
def plugin = pluginManager.getGrailsPlugin("cdn-asset-pipline")
def pluginDir = plugin.descriptor.file.parentFile
Map<String, String> env = System.getenv()
final processBuilder = new ProcessBuilder()
processBuilder.directory(new File("${cdnAssetPipelinePluginDir}/scripts"))
processBuilder.command([env['GRAILS_HOME']+"/bin/grails","cdn-asset-push"])
println processBuilder.directory()
Process proc = processBuilder.start()
proc.consumeProcessOutput(out, err)
proc.waitFor()
}
This link explains the run-script functionality which was merged into Grails 1.3.6. But I ran into the same problem of not knowing where to run it automatically.

Related

find env variables for a all builds for a job on jenkins

I need to monitor what are the changes going with a job on jenkins(update the changes to a file). Need to list the env variables of a job. JOB_NAME,BUILD_NUMBER,BUILD_STATUS,GIT_URL for that build(all the builds of a job). I didn't find out a good example with the groovy. What is the best way to fetch all the info?
build.getEnvironment(listener) should get you what you need
Depending on what you would like to achieve there are at least several approaches to retrieve and save environment variables for:
current build
all past builds
Get environments variables for current build (from slave)
Execute Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
new File(".",'env.txt').withWriter('utf-8') { writer ->
System.getenv().each { key, value ->
writer.writeLine("${key}:${value}")
}
}
Using Groovy Plug-in.
Get environment variables for current build (from master)
Execute system Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
import hudson.FilePath
def path = "env-sys.txt"
def file = null
if (build.workspace.isRemote()) {
file = new FilePath(build.workspace.channel, build.workspace.toString() + "/" + path)
} else {
file = new FilePath(build.workspace.toString() + "/" + path)
}
def output = ""
build.getEnvironment(listener).each { key, value ->
output += "${key}:${value}\n"
}
file.write() << output
Using Groovy Plug-in.
Environment variables returned by Groovy scripts are kept in map. If you don't need all of them, you can access individual values using standard operators/methods.
Get environment variables for all past builds (from master)
This approach expecst that you have installed EnvInject Plug-in and have access to $JENKINS_HOME folder:
$ find . ${JENKINS_HOME}/jobs/[path-to-your-job] -name injectedEnvVars.txt
...
ps. I suspect that one could analyze EnvInject Plug-in API and find a way to extract this information directly from Java/Groovy code.
Using EnvInject Plug-in.
To look for only specific variables you can utilize find, grep and xargs tools .
You can use below script to get the Environment Variables
def thread = Thread.currentThread()
def build = thread.executable
// Get build parameters
def buildVariablesMap = build.buildVariables
// Get all environment variables for the build
def buildEnvVarsMap = build.envVars
String jobName = buildEnvVarsMap?.JOB_NAME // This is for JOB Name env variable.
Hope it helps!

Getting version info and build data from grails war file

In my application the user has the option to upload a war file to update the software.
I want to get some version information from the war file, before I deploy it to my server. How can I do this?
This information would be useful for me:
def jversion=[
"buildDate": grailsApplication.metadata["build.date"],
"version": grailsApplication.metadata["app.version"],
"branch": grailsApplication.metadata["GIT_BRANCH"],
"buildNumber": grailsApplication.metadata["build.number"],
"gitCommit": grailsApplication.metadata["GIT_COMMIT"]
]
What information can I get from the war file and how?
Best regards,
Peter
For this purpose you can add a script to the grails application that adds this information to a file whenever the user builds the war. Create a new script file under ./scripts in grails app with name _Events.groovy. Here you can hook into different grails events that gets triggered when an app starts or war gets built.
You can use eventCreateWarStart event to log the information whenever war gets built. Below is some sample code that can help you get started. It fetches the current branch name and commit id from local git and stores the data to a file named application.properties.
eventCreateWarStart = { warName, stagingDir ->
addBuildInfo("${stagingDir}/application.properties")
}
private void addBuildInfo(String propertyFile) {
def jVersion = [
"appName" : grailsApp.metadata['app.name'],
"version" : grailsApp.metadata["app.version"],
"buildDate" : new Date(),
"branch" : getBranch().trim(),
"Commit" : getRevision().trim(),
"buildNumber": System.getProperty("build.number", "CUSTOM"),
]
File file = new File(propertyFile)
file.text = ""
jVersion.each {
key, value ->
file.text += "${key}:\t${value}\n"
}
}
def getBranch() {
Process process = "git rev-parse --abbrev-ref HEAD".execute()
process.waitFor()
return process.text ?: 'UNKNOWN'
}
def getRevision() {
Process process = "git log --oneline --no-abbrev-commit -1".execute()
process.waitFor()
return process.text ?: 'UNKNOWN'
}
There is a grails plugin also that claims to fetch build properties from Hudson/Jenkins, if they are being used for building the war.
Grails 3.0.9, in GSP, you can get info from META-INF file. Try these
${grails.util.Metadata.current.getApplicationVersion()}
${grails.util.Metadata.current.getEnvironment()}
${grails.util.Metadata.current.getApplicationName()}
But i don't know how to get build date info.
For grails 3 you can use buildProperties task to add any custom information to war such as build date, verion info, git revision etc.
buildProperties {
inputs.property("info.app.build.date", new Date().format('yyyy-MM-dd HH:mm:ss'))
}
See this article for how to do the same http://nimavat.me/blog/grails3-add-custom-build-info-to-war

How to call external Groovy files from Jenkins Build Flow Plugin script?

A JobDSL script can use a Groovy file in the same directory. For example, Git.groovy with contents like:
class Git extends Closure<Void> {
final String git
def Git(final String git = '/usr/bin/git') {
super(null)
this.git = git
}
def call(ArrayList<String> command, File dir = null) {
final gitCommand = [git, *command].execute(null, dir)
gitCommand.waitFor()
}
}
can be used by a JobDSL script:
final git = new Git()
git(['clone', ...])
But when the same thing is tried in a Build Flow script, it emits something like:
Script1.groovy: 49: unable to resolve class Git
This happens even if the Build Flow script has Flow run needs a workspace set.
How can a Build Flow script re-use common code?

How to write connection script between Grails and Hadoop?

I need to copy the files which are generated within Grails to Hadoop dynamically. How will I write code for this in Grails? Whenever a file is generated it should be copied into Hadoop. If the incoming file already exists, it should get updated in Hadoop.
I used shell script to connect grails and hadoop.
I had all the commands to run hadoop jobs in myjob.sh (Workflow Script)
And i added the code to execute shell script in my controller
def scriptCom="/folderlocation/shellscript.sh"
println "[[Running $scriptCom]]"
def proc = scriptCom.execute()
def oneMinute = 60000
proc.waitForOrKill(oneMinute)
if(proc.exitValue()!=0){
println "[[return code: ${proc.exitValue()}]]"
println "[[stderr: ${proc.err.text}]]"
return null
}else{
println "[[stdout:$revisionid]]"
return proc.in.text.readLines()
}

Jenkins plugin, how to execute system command on remote node?

Our company's Jenkins has master and two slave nodes. I am writing plugin for it. One of the things for plugin to do is to checkout some files from svn. This action cannot be extracted from plugin.
To do this I execute console command "svn checkout" from java code of my plugin. The problem is that files from svn are checked out to master, rather than to slave nodes.
How can I make files be checked out to slave?
First you have these objects, usually received as parameters for perform method:
Launcher launcher;
AbstractBuild<?, ?> build;
BuildListener listener;
Then you have created and added arguments to an argumentListBuilder, maybe something like:
ArgumentListBuilder command = new ArgumentListBuilder();
command.addTokenized("xcopy /?");
Then, do something like:
ProcStarter ps = launcher.new ProcStarter();
ps = ps.cmds(command).stdout(listener);
ps = ps.pwd(build.getWorkspace()).envs(build.getEnvironment(listener));
Proc proc = launcher.launch(ps);
int retcode = proc.join();
ProcStarter will run the command at the node specified by the launcher instance. But please at least glance over the javadocs of all above classes before using, above is not direct copy-paste from working code.
Here is code based on Hyde's answer, suitable for the Groovy script console (at /script)
def static Run(nodeName, runCommand)
{
def output = new java.io.ByteArrayOutputStream();
def listener = new hudson.util.StreamTaskListener(output);
def node = hudson.model.Hudson.instance.getNode(nodeName);
def launcher = node.createLauncher(listener);
def command = new hudson.util.ArgumentListBuilder();
command.addTokenized(runCommand);
def ps = launcher.launch();
ps = ps.cmds(command).stdout(listener);
// ps = ps.pwd(build.getWorkspace()).envs(build.getEnvironment(listener));
def proc = launcher.launch(ps);
int retcode = proc.join();
return [retcode, output.toString()]
}
// for (aSlave in hudson.model.Hudson.instance.slaves) {
(recode, output) = Run("build-slave9", "xcopy /?");
println output;
(Caveats: untested for programs that read stdin. Note the ByteArrayOutputStream, so don't run programs with very long output. Untested for non-ASCII output.)

Resources