Skip to content

Commit

Permalink
feat: support Jira issue parsing in commits from changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
Ingwersaft committed Jul 23, 2020
1 parent 9def6f0 commit 14966c7
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 2 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,17 @@ generateChangelogSinceLastTag | Enable to calculate the commits for the changelo
commitLinkBaseUrl | Prefix / Baseurl for the build-information commit urls | http://git.example.com/repo/commits/
outputDir | Output folder for files generated by the plugin | build/octopus
gitRoot | Directory to run the git helpers in. By default the projects root dir | project.rootDir
pushPackage | Target file (package) which will be uploaded to octopus |
pushPackage | Target file (package) which will be uploaded to octopus | -
version | Package version (lazy gradle property)| -
packageName | Package name (lazy gradle property)| -
buildInformationOverwriteMode | octo build-information OverwriteMode | -
pushOverwriteMode | octo push OverwriteMode | -
buildInformationAddition | Customize the final octopus build-information before uploading | {}
gitlab() | Default `buildInformationAddition` implementation adding context from the CI environment for Gitlab CI. Also sets `commitLinkBaseUrl`. | not applied
httpLogLevel | configures the http logging while using the Octopus API | `HttpLoggingInterceptor.Level.NONE`
issueTrackerName | When parsing issues the target issue tracker name is needed. Currently only `Jira` supported | **optional/none**
parseCommitsForJiraIssues | Enable Jira Issue parsing. This needs the changelog generation enabled to parse the commits there. | **optional/none**
jiraBaseBrowseUrl | For proper Jira URLs we need the base URL, something like `https://testric.atlassian.net/browse/`. | **optional/none**

`generateChangelogSinceLastTag` extracts all commits between the HEAD and the last tag.
If no tag is found, the first commit in the history tree is used instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,27 @@ open class OctopusDeployExtension(project: Project) {
@Optional
val httpLogLevel: Property<HttpLoggingInterceptor.Level> = project.objects.property()

/**
* When parsing issues the target issue tracker name is needed. Currently only `Jira` supported
*/
@Input
@Optional
val issueTrackerName: Property<String> = project.objects.property()

/**
* Enable Jira Issue parsing. This needs the changelog generation enabled to parse the commits there.
*/
@Input
@Optional
val parseCommitsForJiraIssues: Property<Boolean> = project.objects.property()

/**
* For proper Jira URLs we need the base URL, something like `https://testric.atlassian.net/browse/`.
*/
@Input
@Optional
val jiraBaseBrowseUrl: Property<String> = project.objects.property()

/**
* Default `buildInformationAddition` implementation adding context from the CI environment for Gitlab CI. Also sets `commitLinkBaseUrl`.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class OctopusDeployPlugin : Plugin<Project> {
commits = emptyList()
outputDir = extension.outputDir
packageName.set(extension.packageName)
issueTrackerName.set(extension.issueTrackerName)
parseCommitsForJiraIssues.set(extension.parseCommitsForJiraIssues)
jiraBaseBrowseUrl.set(extension.jiraBaseBrowseUrl)
task.version.set(extension.version)
}
doFirst {
Expand Down Expand Up @@ -77,7 +80,7 @@ class OctopusDeployPlugin : Plugin<Project> {
apiKey.set(extension.apiKey)
octopusUrl.set(extension.serverUrl)
packageFile.set(extension.pushPackage)
overwriteMode = extension.buildInformationOverwriteMode?.name
overwriteMode = extension.pushOverwriteMode?.name
packageName.set(extension.packageName)
task.version.set(extension.version)
httpLogLevel.set(extension.httpLogLevel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategy
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.liftric.octopusdeploy.api.BuildInformationCli
import com.liftric.octopusdeploy.api.CommitCli
import com.liftric.octopusdeploy.api.WorkItem
import org.gradle.api.DefaultTask
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
Expand Down Expand Up @@ -37,8 +38,25 @@ open class CreateBuildInformationTask : DefaultTask() {
@Optional
var outputFile: File? = null

@Input
@Optional
val issueTrackerName: Property<String> = project.objects.property()

@Input
@Optional
val parseCommitsForJiraIssues: Property<Boolean> = project.objects.property()

@Input
@Optional
val jiraBaseBrowseUrl: Property<String> = project.objects.property()

@TaskAction
fun execute() {
val workItems: List<WorkItem>? = if (parseCommitsForJiraIssues.getOrElse(false)) {
parseCommitsForJira(commits, jiraBaseBrowseUrl.getOrElse(""))
} else {
null
}
outputFile = File(outputDir, "build-information.json").apply {
writeText(
jacksonObjectMapper().apply {
Expand All @@ -50,8 +68,32 @@ open class CreateBuildInformationTask : DefaultTask() {
VcsType = "Git"
Commits = commits
buildInformationAddition()
issueTrackerName.orNull.let { IssueTrackerName = it }
workItems?.let { WorkItems = it }
}).also { println(it) }
)
}
}

private fun parseCommitsForJira(
commits: List<CommitCli>,
jiraBaseBrowseUrl: String
): List<WorkItem> {
val jiraIssues = commits
.mapNotNull { it.Comment }
.map { jiraKeyRegex.findAll(it).map { it.groupValues[1] }.toList() }
.flatten()
.toSet()
println("parseCommitsForJira: found $jiraIssues")
return jiraIssues.map {
WorkItem(
Id = it,
LinkUrl = "${jiraBaseBrowseUrl.removeSuffix("/")}/$it",
Description = "some placeholder text"
)
}
}
}

// from https://confluence.atlassian.com/stashkb/integrating-with-custom-jira-issue-key-313460921.html
private val jiraKeyRegex = Regex("((?<!([A-Z]{1,10})-?)[A-Z]+-\\d+)")
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.liftric.octopusdeploy.task

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.liftric.octopusdeploy.api.BuildInformationCli
import com.liftric.octopusdeploy.api.CommitCli
import com.liftric.octopusdeploy.api.WorkItem
import junit.framework.TestCase.*
import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder

class CreateBuildInformationTaskTest {
@get:Rule
val outputDir = TemporaryFolder()

@Test
fun testParseJira() {
val project: Project = ProjectBuilder.builder().build()
project.pluginManager.apply("com.liftric.octopus-deploy-plugin")

assertTrue(project.tasks.getByName("createBuildInformation") is CreateBuildInformationTask)

val task = project.tasks.getByName("createBuildInformation") as CreateBuildInformationTask
val baseJiraUrl = "https://testric.atlassian.net/browser/"
task.apply {
packageName.set("test-package")
version.set("2.1.4")
commits = createTestCommits()
outputDir = this@CreateBuildInformationTaskTest.outputDir.root
issueTrackerName.set("Jira")
parseCommitsForJiraIssues.set(true)
jiraBaseBrowseUrl.set(baseJiraUrl)
}
task.execute()
assertTrue(task.outputFile?.exists() == true)
val jsonText = task.outputFile!!.readText()
val taskResult = jacksonObjectMapper().readValue<BuildInformationCli>(jsonText)
assertNotNull(taskResult.WorkItems)
taskResult.WorkItems?.let { workItems ->
assertEquals(2, workItems.size)
workItems.verify("LIF-71", baseJiraUrl)
workItems.verify("LIF-72", baseJiraUrl)
}
}

private fun createTestCommits(): List<CommitCli> {
return listOf(
testCommit1,
testCommit2,
testCommit3,
testCommit4,
testCommit5
)
}

companion object {
val testCommit1 = CommitCli(
"7119e5a28ef691cf95ec98cbf8b2e6bc4b1d84fc",
"null/commit/7119e5a28ef691cf95ec98cbf8b2e6bc4b1d84fc",
"[Gradle Release Plugin] - pre tag commit: '0.1.44'. "
)
val testCommit2 = CommitCli(
"c6dc72fa67b5eb8fb134153ab240b169dea0d565",
"null/commit/c6dc72fa67b5eb8fb134153ab240b169dea0d565",
"Merge branch 'feature/test-octopus-integration' into 'master' "
)
val testCommit3 = CommitCli(
"cb230f92c95ee1118d1348a9e96d6d45e7c611c9",
"null/commit/cb230f92c95ee1118d1348a9e96d6d45e7c611c9",
"feat(build): dummy commit for octopus - LIF-71 "
)
val testCommit4 = CommitCli(
"cb230f92c95ee1118d1348a9e96d6d35e7c611c9",
"null/commit/cb230f92c95ee1218d1348a9e96d6d45e7c611c9",
"feat(build): dummy commit 2 for octopus - LIF-72"
)
val testCommit5 = CommitCli(
"0f1352918b05338eba2275cbab8d33601a810251",
"null/commit/0f1352918b05338eba2275cbab8d33601a810251",
"[Gradle Release Plugin] [ci skip] - new version commit: '0.1.44-SNAPSHOT'"
)
}
}

private fun List<WorkItem>.verify(
key: String,
baseJiraUrl: String
) {
assertEquals(1, count { it.Id == key })
first { it.Id == key }.let { workItem ->
assertEquals(workItem.Id, key)
assertEquals(workItem.LinkUrl, "${baseJiraUrl}${key}")
}
}

0 comments on commit 14966c7

Please sign in to comment.