Job DSL script for email notifications for pass/failed Jenkins build? - jobs

I would like to configure email notifications using Job DSL instead of email-ext plugin.

The DSL does not provide the capability of other plugins, it merely exposes their capability to the script. The plugins still need to be installed.
As per the DSL API Docs, DSL has support for the Jenkins mailer plugin (included as standard),
job('example') {
publishers {
mailer('me#example.com', true, true)
}
}
This is not particularly customizable - you can't tell it to email after every passing build.
The email extension plugin is also supported by DSL:
job('example') {
publishers {
extendedEmail {
recipientList('me#halfempty.org')
defaultSubject('Oops')
defaultContent('Something broken')
contentType('text/html')
triggers {
beforeBuild()
stillUnstable {
subject('Subject')
content('Body')
sendTo {
developers()
requester()
culprits()
}
}
}
}
}
}
To email after every build regardless of status, using email-ext, you can use the always trigger (in place of stillUnstable trigger in the above example)
(code samples copied from linked documentation for the sake of surviving downtime.)

I'm using the Pipeline/Workflow DSL and got this working:
mail from: "",
to: "yoyo#example.com",
subject: """Jenkins ${env.JOB_NAME} [${env.BUILD_NUMBER}]""",
mimeType: "text/html",
body: """Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':</p>
<p>Check console output at &QUOT;<a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a>&QUOT;</p>
<pre>${summary}</pre>"""

Related

Jobrunr: How to add custom filters for job?

I am trying to integrate jobrunr 5.1.6 to my micronaut application. I am unable to get the filter implementing ApplyStateFilter triggered when the job is processed. Please see below:
class JobCompletionFilter : ApplyStateFilter {
override fun onStateApplied(job: Job?, oldState: JobState?, newState: JobState?) {
if (newState != null) {
if (isFailed(newState) && maxAmountOfRetriesReached(job)) {
// Failed after retry. Add logs and handle strategy logic
} else if (newState is SucceededState) {
// Job succeeded. Add job completion logic
}
}
}
How do I inject this filter for all of my jobs? Below is how I am enqueueing the jobs
#Inject
lateinit var jobScheduler: JobScheduler
jobScheduler.enqueue {jobProcessor.execute(job)}
In the free version, you will have to manually configure JobRunr via the Fluent Java API instead of using the Spring integration. There, you have the possibility to pass the filter. An example:
JobRunr
.configure()
.withJobFilter(...) // pass your job filters here
For more info, see the fluent API.
In the Pro version, any Job Filter which is a Spring Bean (e.g. an #Component or #Service) will automatically be executed without any additional configuration. For more info, see the docs.

Test Suite in kotest

I don't know if I am missing something but I could not find anything that says how to do a test suite like in JUnit. Can someone help me? I saw that documentation offers grouping tests, but when I run from Gradle, the logs are really large, and not very useful
You can group your tests using Tags, see https://kotest.io/docs/framework/tags.html.
For example, to group tests by operating system you could define the following tags:
object Linux : Tag()
object Windows: Tag()
Test cases can then be marked with tags using the config function:
import io.kotest.specs.StringSpec
class MyTest : StringSpec() {
init {
"should run on Windows".config(tags = setOf(Windows)) {
// ...
}
"should run on Linux".config(tags = setOf(Linux)) {
// ...
}
"should run on Windows and Linux".config(tags = setOf(Windows, Linux)) {
// ...
}
}
}
Then you can tell Gradle to run only tests with specific Tags, see https://kotest.io/docs/framework/tags.html#running-with-tags
Example: To run only test tagged with Linux, but not tagged with Database, you would invoke Gradle like this:
gradle test -Dkotest.tags="Linux & !Database"
Tags can also be included/excluded in runtime (for example, if you're running a project configuration instead of properties) through the RuntimeTagExtension:
RuntimeTagExpressionExtension.expression = "Linux & !Database"

Why do I need to reference a custom gradle config with square brackets?

I created a gradle build config just to download some dependencies. The documentation has been sparse, so I've piece together this working snippet based on random snippets and guesses.
configurations {
create("downloadDeps")
}
dependencies {
// JSON
configurations["downloadDeps"]("com.fasterxml.jackson.core:jackson-databind:2.13.3")
configurations["downloadDeps"]("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3")
}
repositories {
// internal repository
maven {
url = uri("...")
credentials {
username = System.getenv("ARTIFACTORY_USER") ?: System.getProperty("ARTIFACTORY_USER") as String
password = System.getenv("ARTIFACTORY_TOKEN") ?: System.getProperty("ARTIFACTORY_TOKEN") as String
}
}
}
tasks.register<Copy> ("downloadDeps") {
from(configurations["downloadDeps"])
into("lib/")
}
If I reference the "downloadDeps" dependency like configuration.downloadDeps or downloadDeps("com.fasterxml.jackson.core:jackson-databind:2.13.3"). I get an error about an unresolved reference to "downloadDeps".
Why does implementation("...") or configuration.implementation.get() work?
The documentation #Slaw provided helped me understand why I can do something like this:
implementation("group:artifact:1.0.0")
but not
myCustomConfig("group:artifact:1.0.0")
implementation being declared that way is supported because it comes from a plugin (the Kotlin/Java plugins)
The simplest way to associate a dependency with myCustomConfig would be to do this (see these docs):
"myCustomConfig"("group:artifact:1.0.0")

Ktor - post unhanldled error with coroutines

I a new to Kotlin and Ktor in particular, so I have tried to do simple post request. As you can see below, there is nothing special.
routing {
post("/articles/add"){
val post = call.receive<ArticleRequest>()
println(post)
}
Error shown in logs is below and I don't understand why I should use here coroutines.
ERROR Application - Unhandled: POST - /articles/add
java.lang.IllegalStateException: Using blocking primitives on this dispatcher is not allowed. Consider using async channel instead or use blocking primitives in withContext(Dispatchers.IO) instead.
I am using 1.4.2 version. I would appreciate any help.
If you are using Jackson this is a bug and there is a suggested workaround:
routing {
post("/articles/add") {
with(Dispatchers.IO) {
val post = call.receive<ArticleRequest>()
println(post)
}
}
}
Or you can rollback to 1.4.1 until the bug is solved.
I've experienced the same issue after upgrading to ktor 1.4.2 and Kotlin 1.4.20, and I used both Moshi and Gson on this specific project but I don't believe they are causing this issue.
If you have a 'gradle.properties' file, add these ( or whatever version you wish to use ) :
ktor_version=1.3.2
kotlin_version=1.3.70.
Otherwise, in your 'build.gradle' file, create variables for different version :
buildscript {
ext.kotlin_version = '1.3.70'
ext.ktor_version = '1.3.2'
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Then sync your gradle, run project.. all should be good.
However if you still experience some gradle-related issue, try this :
go to gradle (folder) -> wrapper -> open gradle_wrapper.properties and make sure the url has version 6.x.x or 5.x.x.
Mine looks like this currently:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Swagger for Kotlin

Has anyone used a swagger tool with Kotlin?
In our organization, we have create most of our REST services using Java and SpringMVC (#RestController classes). We have used springfox to generate the Swagger API documentation. The swagger JSON representation is also used to automatically feed a searchable service catalog, so the swagger format for service metadata is important to us.
Some dev teams are now beginning to use Kotlin. We're looking for recommendations or comments related to using springfox or other swagger lib with Kotlin.
Here is sample spring boot app with swagger:
#RestController
class MyController {
#ApiOperation(value = "doc header...", notes = "detailed doc...")
#RequestMapping(value = "/double", method = arrayOf(RequestMethod.GET))
fun doubleValue(number: Int) = 2 * number
}
#Configuration
#EnableSwagger2
class SwaggerConfig {
#Bean
fun api(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
}
}
dependencies are
compile("io.springfox:springfox-swagger2:2.7.0")
compile("io.springfox:springfox-swagger-ui:2.7.0")
If you browse http://localhost:8080/swagger-ui.html it is all there...
I recently had a similar requirement. As a result I created a template project that integrates Kotlin, Webflux, and Swagger. It provides interactive API doc and automatic request validation.
See here -> https://github.com/cdimascio/kotlin-swagger-spring-functional-template
Validation is functional. It's used as such:
validate.request(req) {
// Do stuff e.g. return a list of names
ok().body(Mono.just(listOf("carmine", "alex", "eliana")))
}
with body
validate.request(req).withBody(User::class.java) { body ->
// Note that body is deserialized as User!
// Now you can do stuff.
// For example, lets echo the request as the response
ok().body(Mono.just(body))
}
It utilizes openapi 2 and 3 validation provided by atlassian.