How can I configure Jenkins using .groovy config file to set up 'Build strategies -> Tags' in my multi-branch pipeline? - jenkins-job-dsl

I want something similar for 'Basic Branch Build Strategies' plugin https://plugins.jenkins.io/basic-branch-build-strategies
I figure out to make it something like this but it's not working:
def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
traits << 'com.cloudbees.jenkins.plugins.bitbucket.TagDiscoveryTrait' {
strategyId(3)
}
traits << 'jenkins.branch.buildstrategies.basic.TagBuildStrategyImpl' {
strategyId(1)
}
Here you can find full config file: https://gist.github.com/sobi3ch/170bfb0abc4b7d91a1f757a9db07decf
The first trait is working fine 'TagDiscoveryTrait' but second (my change) doesn't apply on Jenkins restart, 'TagBuildStrategyImpl'.
How can I configure 'Build strategies -> Tags' in .groovy config for my multibranch pipeline using 'Basic Branch Build Strategies' plugin?
UPDATE: Maybe I don't need to use traits at all. Maybe there is a simpler solution. I'm not expert in Jenkins groovy configuration.
UPDATE 2: This is scan log for my code https://gist.github.com/sobi3ch/74051b3e33967d2dd9dc7853bfb0799d

I am using the following Groovy init script to setup a Jenkins job with a "tag" build strategy.
def job = instance.createProject(WorkflowMultiBranchProject.class, "<job-name>")
PersistedList sources = job.getSourcesList()
// I am using Bitbucket, you need to replace this with your source
def pullRequestSource = new BitbucketSCMSource("<repo-owner>", "<repo-name>")
def source = new BranchSource(pullRequestSource)
source.setBuildStrategies([new TagBuildStrategyImpl(null, null)])
sources.add(source)

If I am recognizing the syntax correctly, the question is about Job DSL plugin.
The problem with the attempted solution is that the TagBuildStrategyImpl is not a Trait (known as Behavior in UI) but a Build Strategy. The error confirms this:
java.lang.ClassCastException: jenkins.branch.buildstrategies.basic.TagBuildStrategyImpl cannot be cast to jenkins.scm.api.trait.SCMSourceTrait
Class cannot be cast because TagBuildStrategyImpl does not extend SCMSourceTrait, it extends BranchBuildStrategy.
The best way to discover the JobDSL syntax applicable for a specific installation of Jenkins is to use the built-in Job DSL API Viewer. It is available under <jenkins-location>/plugin/job-dsl/api-viewer/index.html, e.g. https://ci.jenkins.io/plugin/job-dsl/api-viewer/index.html
On the version I am running what you are try to achieve would look approximately like this:
multibranchPipelineJob('foo') {
branchSources {
branchSource {
source {
bitbucket {
...
traits {
bitbucketTagDiscovery()
}
}
}
buildStrategies {
buildTags { ... }
}
}
}
}

Related

How to load AWS credentials in Jenkins job DSL?

I have the following DSL structure:
freeStyleJob {
wrappers {
credentialsBinding {
[
$class:"AmazonWebServicesCredentialsBinding",
accessKeyVariable: "AWS_ACCESS_KEY_ID",
credentialsId: "your-credential-id",
secretKeyVariable: "AWS_SECRET_ACCESS_KEY"
]
}
}
steps {
// ACCESS AWS ENVIRONMENT VARIABLES HERE!
}
}
However, this does not work. What is the correct syntax to do so? For Jenkins pipelines, you can do:
withCredentials([[
$class: "AmazonWebServicesCredentialsBinding",
accessKeyVariable: "AWS_ACCESS_KEY_ID",
credentialsId: "your-credential-id",
secretKeyVariable: "AWS_SECRET_ACCESS_KEY"]]) {
// ACCESS AWS ENVIRONMENT VARIABLES HERE!
}
but this syntax does not work in normal DSL job groovy.
tl;dr how can I export AWS credentials defined by the AmazonWebServicesCredentialsBinding plugin into environment variables in Groovy job DSL? (NOT PIPELINE PLUGIN SYNTAX!)
I found a solution to solve this problem:
wrappers {
credentialsBinding {
amazonWebServicesCredentialsBinding {
accessKeyVariable("AWS_ACCESS_KEY_ID")
secretKeyVariable("AWS_SECRET_ACCESS_KEY")
credentialsId("your-credentials-id")
}
}
}
This will lead to the desired outcome.
I'm not able to re-use Miguel's solution (even with installed aws-credentials plugin), so here is another approach with DSL configure block
configure { project ->
def bindings = project / 'buildWrappers' / 'org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper' / 'bindings'
bindings << 'com.cloudbees.jenkins.plugins.awscredentials.AmazonWebServicesCredentialsBinding' {
accessKeyVariable("AWS_ACCESS_KEY_ID")
secretKeyVariable("AWS_SECRET_ACCESS_KEY")
credentialsId("credentials-id")
}
}
This is the full detailed answer that #bitbrain did with possible fix for issue reported by #Viacheslav
freeStyleJob {
wrappers {
credentialsBinding {
amazonWebServicesCredentialsBinding {
accessKeyVariable("AWS_ACCESS_KEY_ID")
secretKeyVariable("AWS_SECRET_ACCESS_KEY")
credentialsId("your-credentials-id")
}
}
}
}
Ensure this is on the classpath for compilation:
compile "org.jenkins-ci.plugins:aws-credentials:1.23"
If you have tests running you might also need to add the plugin to the classpath:
testPlugins "org.jenkins-ci.plugins:aws-credentials:1.23"
I believe this is why there are reports of people needing to manually modify the XML to get this to work. Hint: if you can pass the compile stage (or compile in IDE) but not able to compile tests then this is the issue.

Dataflow - how to create a PCollectionView to use with DoFnTester?

This question is about Google Dataflow. I would like to test a do function with side inputs. The Google manuals list that you need code like this:
static class MyDoFn extends DoFn<String, Integer> { ... }
MyDoFn myDoFn = ...;
DoFnTester<String, Integer> fnTester = DoFnTester.of(myDoFn);
PCollectionView<List<Integer>> sideInput = ...;
Iterable<Integer> value = ...;
fnTester.setSideInputInGlobalWindow(sideInput, value);
I wonder how the code to create the PCollectionView instance looks like. When using DoFnTester you do not have a pipeline, and I do not see how to create PCollectionView instances without a pipeline. Can you tell me how to create a PCollectionView instance for use with DoFnTester?
Thanks for your time.
With kind regards,
Martijn Dirkse
I found the answer myself. You can just create a TestPipeline instance and use it to build the PCollectionView you need. It is no problem that the TestPipeline does not have any other purpose in your code.
Dataflow 2.1 sdk sample here . There is no setSideInputInGlobalWindow in 2.X use setSideInput instead.

In Jenkins "Job DSL Plugin", how to specify alternate location of pom.xml in 'mavenJob'?

I was looking at the instructions here and cannot figure out how to set a alternate pom.xml location of the Root POM, other than default.
https://jenkinsci.github.io/job-dsl-plugin/#path/mavenJob
Does anyone out there know how to set that?
You can use the rootPOM DSL method.
mavenJob('example') {
rootPOM('sub-module/pom.xml')
}
Try using the following code:
mavenJob('JobXXX') {
scm {
github('Repository/Project', 'master')
}
goals('clean compile build')
rootPOM('projectname/pom.xml')
}

How can I create a JSON webservice to store and retrieve data from a simple properties file?

How can I create a Java or Javascript JSON webservice to retrieve data from a simple properties file? My intention is to uses this as a global property storage for a Jenkins instance that runs many Unit tests. The master property file also needs to be capable of being manually edited and stored in source control.
I am just wondering what method people would recommend that would be the easiest for a junior level programmer like me. I need read capability at miniumum but, and if its not too hard, write capability also. Therefore, that means it is not required to be REST.
If something like this already exists in Java or Groovy, a link to that resource would be appreciated. I am a SoapUI expert but I am unsure if a mock service could do this sort of thing.
I found something like this in Ruby but I could not get it to work as I am not a Ruby programmer at all.
There are a multitude of Java REST frameworks, but I'm most familiar with Jersey so here's a Groovy script that gives a simple read capability to a properties file.
#Grapes([
#Grab(group='org.glassfish.jersey.containers', module='jersey-container-grizzly2-http', version='2.0'),
#Grab(group='org.glassfish.jersey.core', module='jersey-server', version='2.0'),
#Grab(group='org.glassfish.jersey.media', module='jersey-media-json-jackson', version='2.0')
])
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory
import org.glassfish.jersey.jackson.JacksonFeature
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
#Path("properties")
class PropertiesResource {
#GET
#Produces("application/json")
Properties get() {
new File("test.properties").withReader { Reader reader ->
Properties p = new Properties()
p.load(reader)
return p
}
}
}
def rc = new org.glassfish.jersey.server.ResourceConfig(PropertiesResource, JacksonFeature);
GrizzlyHttpServerFactory.createHttpServer('http://localhost:8080/'.toURI(), rc).start()
System.console().readLine("Press any key to exit...")
Unfortunately, since Jersey uses the 3.1 version of the asm library, there are conflicts with Groovy's 4.0 version of asm unless you run the script using the groovy-all embeddable jar (it won't work by just calling groovy on the command-line and passing the script). I also had to supply an Apache Ivy dependency. (Hopefully the Groovy team will resolve these in the next release--the asm one in particular has caused me grief in the past.) So you can call it like this (supply the full paths to the classpath jars):
java -cp ivy-2.2.0.jar:groovy-all-2.1.6.jar groovy.lang.GroovyShell restProperties.groovy
All you have to do is create a properties file named test.properties, then copy the above script into a file named restProperties.groovy, then run via the above command line. Then you can run the following in Unix to try it out.
curl http://localhost:8080/properties
And it will return a JSON map of your properties file.

TFS: Query for builds containing a specific changeset

I have a number of build definitions that get executed based upon a single branch in TFS (eg Main).
I'd like to (somehow) query TFS to find all builds containing a specific changeset number that I supply, and return a list of string of the names of the builds that TFS contains. Any kind of app (VS extension, CLI app, winforms, whatever) will do.
Note: this isn't a 'plz give me the code' request; I'm willing to hoof it and do serious work on this. Any pointers to documentation on how to query the database or SDK, or an example of how to query builds; just some place to start looking would be extremely helpful. Thanks.
The following snippet will crawl all Build Definitions of all Team Project of a Collection, and will check each and every build for an Association to the input changeset number:
using System;
using System.Linq;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace FindChangesetInBuild
{
class Program
{
static void Main(string[] args)
{
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/collectionName"));
var versionControl = teamProjectCollection.GetService<VersionControlServer>();
var buildService = (IBuildServer)teamProjectCollection.GetService(typeof(IBuildServer));
var teamProjects = versionControl.GetAllTeamProjects(true);
foreach (var teamProject in teamProjects)
{
var buildDefinitions = buildService.QueryBuildDefinitions(teamProject.Name);
foreach (var buildDefinition in buildDefinitions)
{
var builds = buildService.QueryBuilds(buildDefinition);
foreach (var buildDetail in builds)
{
var changesets = InformationNodeConverters.GetAssociatedChangesets(buildDetail);
if (changesets.Any(changesetSummary => changesetSummary.ChangesetId == Convert.ToInt32(args[0])))
{
Console.WriteLine("Changeset was build in "+buildDetail.BuildNumber);
}
}
}
}
}
}
}
Needless to say, this is a brute force attack.You can further refine the code if you narrow down the list of buildDefinition, make focus on specific teamProjects etc. In any case I can hardly imagine the above to be useful as-is!Apart from (obviously) MSDN, a great resource for TFS-SDK is Shai Raiten's blog.For Build-Speficic examples, check also here & here for some possibly interesting SO posts.
You can use this little DB Query in TFS 2010 and just substitute 90264 with your changeset id.
USE Tfs_Warehouse
go
SELECT BuildName
FROM DimBuild
INNER JOIN FactBuildChangeset
ON DimBuild.BuildSK = FactBuildChangeset.BuildSK
WHERE FactBuildChangeset.ChangesetSK = 90264