Jira custom script validator: check if input textbox exists - textbox

I am totally new to Jira. In fact I don't even know where to start. I went to the jira atlassian website but got nothing solid enough to help me. I would like to validate if the information entered into a textbox already exists. I clicked around jira and ended up on the screen below:
Now I would like to find out the following:
Which programming language should be used for validation ? Is it Java
If the name of the custom field(of type Textbox) is XYZ and I wanna if check if value entered into XYZ already exist, how do I go about doing that ? Can I just write conditional statements in Java ?
I wrote some stuff and nothing worked.

That's a screenshot from the Script Runner add-on.
There are some documentation and examples for custom validators here.
You can also find an example here that shows how to query the JIRA (or an external) database from a groovy script. Ie.:
import com.atlassian.jira.component.ComponentAccessor
import groovy.sql.Sql
import org.ofbiz.core.entity.ConnectionFactory
import org.ofbiz.core.entity.DelegatorInterface
import java.sql.Connection
def delegator = (DelegatorInterface) ComponentAccessor.getComponent(DelegatorInterface)
String helperName = delegator.getGroupHelperName("default");
def sqlStmt = """
SELECT project.pname, COUNT(*) AS kount
FROM project
INNER JOIN jiraissue ON project.ID = jiraissue.PROJECT
GROUP BY project.pname
ORDER BY kount DESC
"""
Connection conn = ConnectionFactory.getConnection(helperName);
Sql sql = new Sql(conn)
try {
StringBuffer sb = new StringBuffer()
sql.eachRow(sqlStmt) {
sb << "${it.pname}\t${it.kount}\n"
}
log.debug sb.toString()
}
finally {
sql.close()
}
For anything that gets a bit complex it's easier to implement your script in a groovy file and make it available to Script Runner via the file system. That also allows you use a vcs like git to easily push/pull your changes. More info about how to go about that, is here.

Related

Need help to read a json file using groovy and Jenkins

I am facing some issues reading a JSON file.
I am using Jenkins Active Choice Parameter to read value from a JSON file via groovy script. This is how my JSON file look.
{
"smoke": "Test1.js",
"default": "Test2.js"
}
I want my groovy script to print out smoke and default. Below is what my groovy code look like.
import groovy.json.JsonSlurper
def inputFile = new File(".\TestSuitesJ.json")
def InputJSON = new JsonSlurper().parseText(inputFile)
InputJson.each
{
return[
key
]
}
Above code is not working for me. Can someone please suggest a better groovy way?
Anyone in similar situation as me trying to import a JSON file at runtime. I used Active Choice parameter to solve my problem. There is an option to write groovy script in Active Choice Parameter plugin of Jenkins. There i have written below code to import a JSON file to achieve desired results.
import groovy.json.JsonSlurper
def inputFile = new File('.//TestSuitesJ.json')
def inputJSON = new JsonSlurper().parse(inputFile)
def keys = inputJSON.keySet() as List
Thanks #sensei to help me learn groovy.
You really should read the groovy dev kit page, and this in particular.
Because in your case parseText() returns a LazyMap instance, the it variable you're getting in your each closure represents a Map.Entry instance. So you could println it.key to get what you want.
A more groovy way would be:
inputJson.each { k, v ->
println k
}
In which case groovy passes your closure the key (k) and the value (v) for every element in the map.

Get input approver user name in Jenkins Workflow plugin

I am trying to get userid who approved an "input" step in workflow jenkins groovy script. Below is the sample script
node('node1'){
stage "test"
input message: 'test'
}
In the workflow UI if a person hits "thumbs up" I want to print his userid in the log. I dont see any option to do it.
def cause = currentBuild.rawBuild.getCause(Cause.UserIdCause)
cause.userId
will print the person who started the build. I have googled this for days but i am not finding anything. Any help here will be greatly appreciated :)
This Jira issue describes how this is likely to work going forward, however it is still open.
In the meantime, the approach of getting the latest ApproverAction via the build actions API was suggested on #Jenkins IRC recently and should work, note it's not sandbox safe.
Something along the lines of the below for getting the most recent approver:
#NonCPS
def getLatestApprover() {
def latest = null
// this returns a CopyOnWriteArrayList, safe for iteration
def acts = currentBuild.rawBuild.getAllActions()
for (act in acts) {
if (act instanceof org.jenkinsci.plugins.workflow.support.steps.input.ApproverAction) {
latest = act.userId
}
}
return latest
}
The JIRA incident referenced u-phoria has been resolved and the fix released.
By setting the submitterParameter to a value, the variable specified by submitterParameter will be populated with the Jenkins user ID that responded to the input field.

Access build parameters in Extended Choice Parameter - in promotion step?

When promoting a build, I want to expose some choices of how/what to promote. To do this properly, I need some info about the build which I am promoting, and I'd really like to use the Extended Choice Parameter to do this.
How can I access a build's parameters in an Extended Choice Parameter block in a build promotion step? For example, say the build I want to promote was built with a parameter myvar="1,2,5", and I want to let the build promoter select 1, 2, 5, or some combination. How can I access that particular build's myvar value, in an extended choice parameter, in a promotion process?
I can auto-populate these with available Git branches for a certain repo, with global environment variables, but I haven't seen the groovy magic I need to access info about the build I'm (about to) promote.
This was not obvious to me, but I found that environment variables such as PROMOTED_URL, PROMOTED_JOB_NAME, etc, were not available until the promotion steps were in progress. I need this information exposed when the promotion parameters are being populated via Extended Choice Parameter's Groovy Script fields. I accomplished it by peeking into the thread name:
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
def jenkins = Jenkins.instance
def thread = Thread.currentThread().toString()
def (jobName,buildNumber) = thread.replaceAll(/.*GET \/job\/(.*)\/promotion\/.*/, '$1').split('/')
def job = jenkins.getJob(jobName)
def build = job.getBuild(buildNumber)
return build.getBuildVariables()["SOME_BUILD_PARAM"]
What do I use this for? Say I can select certain targets to build but not others, when building. I want to be able to promote only some subset of those that were actually built, so the parameter can't just hold a default value. Pretty narrow edge-case, I'll grant, but sometimes it seems like my entire life, as far as Jenkins is concerned, is dealing with some edge-case or another. If there is a more elegant way, I am all ears!
building on the #courtlandj solution (with the latest hudson API):
import hudson.model.*
def paramToLookup = "SOME_BUILD_VARIABLE_NAME"
// you can of course parse the jobName from the currentThread
// but that is a case-by-case basis depending on how you name them
// build numbers are strictly numeric - and more predictable to parse with regex
def jobName = "some-jenkins-full-job-name"
int buildNumber = 0
// Similar approach to courtlandj to get THIS build number (of page being viewed):
def thisPromotionInfo = Thread.currentThread().toString()
// groovy regex that gets the promotion digits (\d)
def buildRegex = /.*\/(\d+)\/promotion\/.*/
def matcher = ( thisPromotionInfo =~ buildRegex )
if (matcher.matches()) {
buildNumber = matcher[0][1].toInteger()
} else {
return "unable to identify buildNumber in Extended Choice Parameter (see Jenkins Config)"
}
// borrowed slightly from here: https://wiki.jenkins-ci.org/display/JENKINS/Display+job+parameters
try {
def job = Hudson.instance.getItemByFullName(jobName)
def build = job.getBuildByNumber(buildNumber)
return build.getProperties()["buildVariableResolver"].resolve(paramToLookup).toString()
} catch(Exception ex) {
return ex.toString()
}
relevant links I borrowed from:
https://groups.google.com/forum/#!topic/jenkinsci-users/cHClVbjuSN4
http://groovy.jmiguel.eu/groovy.codehaus.org/Tutorial+5+-+Capturing+regex+groups.html
http://hudson-ci.org/javadoc/hudson/model/Hudson.html

Quickly testing Jelly templates in email-ext of Jenkins

The Email-ext of Jenkins allows you to write a Jelly email template. How do you write and test one without triggering a build every time? Basically, I'm looking for a 1 second iteration where I can modify a Jelly script, hit refresh on a browser, and it will automatically render the template based upon a hard-code project and build result.
Open Jenkins script console at _http://server/script/ (Stackoverflow is having issues saving an edit when this is an actual URL).
Enter the following code and replace your-project-name with the name of your project and me#me.com with your email address:
import hudson.model.StreamBuildListener
import hudson.plugins.emailext.ExtendedEmailPublisher
import java.io.ByteArrayOutputStream
def projectName = "your-project-name"
def project = Jenkins.instance.getItem(projectName)
try
{
def testing = Jenkins.instance.copy(project, "$projectName-Testing")
def build = project.lastUnsuccessfulBuild
// see the javadoc for the Job class for other ways to get builds
def baos = new ByteArrayOutputStream()
def listener = new StreamBuildListener(baos)
testing.publishersList.each() { p ->
println(p)
if(p instanceof ExtendedEmailPublisher) {
// modify the properties as necessary here
p.recipientList = 'me#me.com' // set the recipient list while testing
// run the publisher
p.perform((AbstractBuild<?,?>)build, null, listener)
// print out the build log from ExtendedEmailPublisher
println(new String( baos.toByteArray(), "UTF-8" ))
}
}
}
finally
{
if (testing != null)
{
testing.delete()
}
}
SOURCE: https://earl-of-code.com/2013/02/prototyping-and-testing-groovy-email-templates/
There is also an issue that tracks making this easier:
JENKINS-9594 - Should be able to send test e-mail based on previous build
There is now an option to test templates against builds in the more recent versions of the plugin. When you are on a job's screen, there should be a link on the left side that says Email Template Testing. It will let you select a build to test again and it will render the template right there.

grails: guidance on writing scripts, esp for calling existing database-migration scripts

My requirement is to invoke some processing from a Jenkins build server, to determine whether the domain model has changed since the last build. I've come to the conclusion that the way forward is to write a script that will invoke a sequence of existing scripts from the db-migration plugin. Then I can invoke it in the step that calls test-app and war.
I've looked in the Grails doc, and at some of the db-migration scripts, and I find I'm stuck - have no idea where to start trying things. I'd be really grateful if someone could point me at any suitable sources. BTW, I'm a bit rusty in Grails. Started to teach myself two years ago via proof of concept project, which lasted 6 months. Then it was back to Eclipse rich client work. That might be part of my problem, though I never go involved in scripts.
One thing I need in the Jenkins evt is to get hold of the current SVN revision number being used for the build. Suggestions welcome.
Regards, John
Create a new script by running grails create-script scriptname. The database-migration plugins scripts are configured to be easily reused. There are is a lot of shared code in _DatabaseMigrationCommon.groovy and each script defines one target with a unique name. So you can import either the shared script or any standalone script (or multiple scripts) and call the targets like they're methods.
By default the script generated by create-script "imports" the _GrailsInit script via includeTargets << grailsScript("_GrailsInit") and you can do the same, taking advantage of the magic variables that point at installed plugins' directories:
includeTargets << new File("$databaseMigrationPluginDir/scripts/DbmGenerateChangelog.groovy")
If you do this you can remove the include of _GrailsInit since it's already included, but if you don't that's fine since Grails only includes files once.
Then you can define your target and call any of the plugin's targets. The targets cannot accept parameters, but you can add data to the argsMap (this is a map Grails creates from the parsed commandline arguments) to simulate user-specified args. Note that any args passed to your script will be seen by the database-migration plugin's scripts since they use the same argsMap.
Here's an example script that just does the same thing as dbm-generate-changelog but adds a before and after message:
includeTargets << new File("$databaseMigrationPluginDir/scripts/DbmGenerateChangelog.groovy")
target(foo: "Just calls dbmGenerateChangelog") {
println 'before'
dbmGenerateChangelog()
println 'after'
}
setDefaultTarget foo
Note that I renamed the target from main to foo so it's unique, in case you want to call this from another script.
As an example of working with args, here's a modified version that specifies a default changelog name if none is provided:
println 'before'
if (!argsMap.params) {
argsMap.params = ['foo2.groovy']
}
dbmGenerateChangelog()
println 'after'
Edit: Here's a fuller example that captures the output of dbm-gorm-diff to a string:
includeTargets << new File("$databaseMigrationPluginDir/scripts/_DatabaseMigrationCommon.groovy")
target(foo: "foo") {
depends dbmInit
def configuredSchema = config.grails.plugin.databasemigration.schema
String argSchema = argsMap.schema
String effectiveSchema = argSchema ?: configuredSchema ?: defaultSchema
def realDatabase
boolean add = false // booleanArg('add')
String filename = null // argsList[0]
try {
printMessage "Starting $hyphenatedScriptName"
ByteArrayOutputStream baos = new ByteArrayOutputStream()
def baosOut = new PrintStream(baos)
ScriptUtils.executeAndWrite filename, add, dsName, { PrintStream out ->
MigrationUtils.executeInSession(dsName) {
realDatabase = MigrationUtils.getDatabase(effectiveSchema, dsName)
def gormDatabase = ScriptUtils.createGormDatabase(dataSourceSuffix, config, appCtx, realDatabase, effectiveSchema)
ScriptUtils.createAndPrintFixedDiff(gormDatabase, realDatabase, realDatabase, appCtx, diffTypes, baosOut)
}
}
String xml = new String(baos.toString('UTF-8'))
def ChangelogXml2Groovy = classLoader.loadClass('grails.plugin.databasemigration.ChangelogXml2Groovy')
String groovy = ChangelogXml2Groovy.convert(xml)
// do something with the groovy or xml here
printMessage "Finished $hyphenatedScriptName"
}
catch (e) {
ScriptUtils.printStackTrace e
exit 1
}
finally {
ScriptUtils.closeConnection realDatabase
}
}
setDefaultTarget foo

Resources