Skip to content

Commit

Permalink
Merge pull request #5 from Liftric/feature/wait-for-deployment
Browse files Browse the repository at this point in the history
 Feature: wait for deployment
  • Loading branch information
benjohnde authored Jun 19, 2020
2 parents fd29586 + 9bbdb90 commit 9def6f0
Show file tree
Hide file tree
Showing 29 changed files with 1,708 additions and 31 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ 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`

`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 All @@ -101,3 +102,35 @@ apiKey.set(provider {
// read from file / vault / etc.
})
```

### task specific configuration
Both the **PromoteReleaseTask** and **UploadPackageTask** provide support for waiting
for any deployment on octopus deploy and will block task finishing until all octopus deploy tasks are finished.

Basically if the upload or progression triggers a release in octopus deploy, the tasks will wait until they are completed.

Configuration is done on the tasks themself:

Property | Description | default value
---|---|---
waitForReleaseDeployments | If the task should wait | false
waitTimeoutSeconds | max time to poll the Ocotopus API | 600
delayBetweenChecksSeconds | how long to delay between polls | 5

Example:
```
import com.liftric.octopusdeploy.task.PromoteReleaseTask
import com.liftric.octopusdeploy.task.UploadPackageTask
[...]
tasks {
val devToDemo by creating(PromoteReleaseTask::class) {
waitForReleaseDeployments.set(true)
projectName.set("example-project")
from.set("dev")
to.set("staging")
}
withType<UploadPackageTask>() {
waitForReleaseDeployments.set(true)
}
}
```
24 changes: 21 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import net.nemerosa.versioning.tasks.VersionDisplayTask
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper

plugins {
kotlin("jvm") version "1.3.61"
`java-gradle-plugin`
id("org.gradle.kotlin.kotlin-dsl") version "1.3.4"
`kotlin-dsl`
`maven-publish`
id("com.gradle.plugin-publish") version "0.11.0"
id("net.nemerosa.versioning") version "2.12.0"
Expand Down Expand Up @@ -36,11 +36,20 @@ repositories {
mavenCentral()
jcenter()
}
val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java).kotlinPluginVersion

dependencies {
implementation(gradleApi())
implementation(kotlin("gradle-plugin"))
implementation(kotlin("stdlib-jdk8"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6")

implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.10.3")
implementation("com.squareup.retrofit2:retrofit:2.6.2")
implementation("com.squareup.retrofit2:converter-jackson:2.6.2")
implementation("com.squareup.retrofit2:converter-scalars:2.6.2")
implementation("com.squareup.okhttp3:logging-interceptor:4.7.2")

testImplementation(gradleTestKit())
testImplementation("junit:junit:4.12")
testImplementation("com.github.stefanbirkner:system-rules:1.19.0")
Expand All @@ -60,6 +69,15 @@ tasks {
}
withType<Test> {
testLogging.showStandardStreams = true
testLogging {
events = setOf(
TestLogEvent.STARTED,
TestLogEvent.PASSED,
TestLogEvent.FAILED,
TestLogEvent.SKIPPED
)
showStandardStreams = true
}
}
withType<VersionDisplayTask> {
doLast {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ data class Item (
val workItems: List<Any?>? = null,

@get:JsonProperty("Commits")@field:JsonProperty("Commits")
val commits: List<Commit>? = null,
val commits: List<CommitCli>? = null,

@get:JsonProperty("IncompleteDataWarning")@field:JsonProperty("IncompleteDataWarning")
val incompleteDataWarning: Any? = null,
Expand Down Expand Up @@ -244,7 +244,7 @@ data class PackageVersionBuildInformation (
val workItems: List<Any?>? = null,

@get:JsonProperty("Commits")@field:JsonProperty("Commits")
val commits: List<Commit>? = null,
val commits: List<CommitCli>? = null,

@get:JsonProperty("IncompleteDataWarning")@field:JsonProperty("IncompleteDataWarning")
val incompleteDataWarning: Any? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.junit.Test
import org.junit.rules.TemporaryFolder
import kotlin.random.Random

class UploadBuildInformationTaskTest {
class UploadBuildInformationTaskIntegrationTest {
@get:Rule
val testProjectDir = TemporaryFolder()

Expand Down Expand Up @@ -86,6 +86,6 @@ octopus {
"""
)
}
testProjectDir.root.setupGitRepo()
testProjectDir.root.setupGitRepoCopy()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import org.junit.Test
import org.junit.rules.TemporaryFolder
import kotlin.random.Random

class UploadPackageTaskTest {
class UploadPackageTaskIntegrationTest {
@get:Rule
val testProjectDir = TemporaryFolder()

Expand Down Expand Up @@ -82,10 +82,11 @@ octopus {
packageName.set(jar.get().archiveBaseName.get().removeSuffix("-"))
version.set(jar.get().archiveVersion.get())
pushPackage.set(jar.get().archiveFile)
}
"""
)
}
testProjectDir.root.setupGitRepo()
testProjectDir.root.setupGitRepoCopy()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.liftric.octopusdeploy.task

import com.liftric.octopusdeploy.apiKey
import com.liftric.octopusdeploy.getPackageResponse
import com.liftric.octopusdeploy.serverUrl
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNotNull
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import kotlin.random.Random

class UploadPackageTaskWithWaitIntegrationTest {
@get:Rule
val testProjectDir = TemporaryFolder()

@Test
fun testExecute() {
val major = Random.Default.nextInt(0, 100)
val minor = Random.Default.nextInt(0, 100)
val micro = Random.Default.nextInt(0, 100)
println(testProjectDir.root.absolutePath)
setupBuild(major, minor, micro)

val result = GradleRunner.create()
.forwardOutput()
.withProjectDir(testProjectDir.root)
.withArguments("build", "uploadPackage")
.withPluginClasspath()
.build()
println(result.output)
assertEquals(TaskOutcome.SUCCESS, result.task(":uploadPackage")?.outcome)

val packageItem = getPackageResponse()
.items
?.filter {
it.version == "$major.$minor.$micro"
}
?.firstOrNull()
assertNotNull(packageItem)
assertEquals(".jar", packageItem?.fileExtension)

val secondResult = GradleRunner.create()
.forwardOutput()
.withProjectDir(testProjectDir.root)
.withArguments("build", "uploadPackage")
.withPluginClasspath()
.buildAndFail()
println(secondResult.output)
// override is not set
assertEquals(TaskOutcome.FAILED, secondResult.task(":uploadPackage")?.outcome)
}

fun setupBuild(major: Int, minor: Int, micro: Int) {
testProjectDir.newFile("build.gradle.kts").apply {
writeText(
"""
import com.liftric.octopusdeploy.task.UploadPackageTask
plugins {
java
id("com.liftric.octopus-deploy-plugin")
}
group = "com.liftric.test"
version = "$major.$minor.$micro"
tasks {
withType<Jar> {
archiveFileName.set(
"${'$'}{archiveBaseName.get()
.removeSuffix("-")}.${'$'}{archiveVersion.get()}.${'$'}{archiveExtension.get()}"
)
}
withType<UploadPackageTask>{
waitForReleaseDeployments.set(true)
waitTimeoutSeconds.set(1L)
delayBetweenChecksSeconds.set(2L)
httpLogLevel.set(okhttp3.logging.HttpLoggingInterceptor.Level.HEADERS)
}
}
octopus {
serverUrl.set("$serverUrl")
apiKey.set("$apiKey")
generateChangelogSinceLastTag = true
val jar by tasks.existing(Jar::class)
packageName.set(jar.get().archiveBaseName.get().removeSuffix("-"))
version.set(jar.get().archiveVersion.get())
pushPackage.set(jar.get().archiveFile)
}
"""
)
}
testProjectDir.root.setupGitRepoCopy()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.liftric.octopusdeploy.task

import junit.framework.TestCase
import junit.framework.TestCase.assertEquals
import java.io.File

/**
* it didn't compile without this, no clue why this happened all of the sudden
*/
fun File.setupGitRepoCopy() {
println("setupGitRepo=${this.absolutePath}")
try {
verboseTestShell("git init .")
verboseTestShell("git add .")
verboseTestShell("git config user.email \"[email protected]\"")
verboseTestShell("git config user.name \"Your Name\"")
verboseTestShell("git commit -m \"initial commit\"")
verboseTestShell("git tag first-one")
verboseTestShell("touch secondfile")
verboseTestShell("git add .")
verboseTestShell("git commit -m \"second commit\"")
verboseTestShell("git tag second-one")
} catch (e: Exception) {
println(e.message)
e.printStackTrace()
val (exitCode, inputText, errorText) = this.shell("ls -lah")
println("exitCode=$exitCode")
println("inputText=$inputText")
println("errorText=$errorText")
throw e
}
}

private fun File.verboseTestShell(cmd: String) {
println("verboseTestShell=$cmd")
val (exitCode, inputText, errorText) = this.shell(cmd)
println("verboseTestShell exitCode=$exitCode")
println("verboseTestShell inputText=$inputText")
println("verboseTestShell errorText=$errorText")
exitCode mustBe 0
}

infix fun Int.mustBe(expected: Int) {
assertEquals(expected, this)
}

internal fun shell(cmd: String): ShellResult = File(".").shell(cmd)

internal fun File.shell(cmd: String): ShellResult {
val process = Runtime.getRuntime().exec(arrayOf("sh", "-c", cmd), emptyArray(), this)
val exitCode = process.waitFor()
val inputText = process.inputStream.bufferedReader().readText().trim()
val errorText = process.errorStream.bufferedReader().readText().trim()
return ShellResult(exitCode, inputText, errorText)
}

data class ShellResult(val exitCode: Int, val inputText: String, val errorText: String)
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.liftric.octopusdeploy

import com.liftric.octopusdeploy.api.BuildInformation
import com.liftric.octopusdeploy.api.BuildInformationCli
import com.liftric.octopusdeploy.api.OverwriteMode
import okhttp3.logging.HttpLoggingInterceptor
import org.gradle.api.Project
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.kotlin.dsl.property
import java.io.File
Expand Down Expand Up @@ -74,7 +76,14 @@ open class OctopusDeployExtension(project: Project) {
/**
* Customize the final octopus build-information before uploading
*/
var buildInformationAddition: BuildInformation.() -> Unit = {}
var buildInformationAddition: BuildInformationCli.() -> Unit = {}

/**
* Configures the http logging of the underlying okhttp client used for octopus api requests
*/
@Input
@Optional
val httpLogLevel: Property<HttpLoggingInterceptor.Level> = 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 @@ -78,12 +78,16 @@ class OctopusDeployPlugin : Plugin<Project> {
octopusUrl.set(extension.serverUrl)
packageFile.set(extension.pushPackage)
overwriteMode = extension.buildInformationOverwriteMode?.name
packageName.set(extension.packageName)
task.version.set(extension.version)
httpLogLevel.set(extension.httpLogLevel)
}
}
project.tasks.withType(PromoteReleaseTask::class.java) {
project.afterEvaluate {
apiKey.set(extension.apiKey ?: error("$extensionName: didn't specify apiKey!"))
octopusUrl.set(extension.serverUrl ?: error("$extensionName: didn't specify serverUrl!"))
httpLogLevel.set(extension.httpLogLevel)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.liftric.octopusdeploy.api

data class BuildInformation(
data class BuildInformationCli(
var Id: String? = null,
var PackageId: String? = null,
var Version: String? = null,
Expand All @@ -14,10 +14,10 @@ data class BuildInformation(
var VcsCommitUrl: String? = null,
var IssueTrackerName: String? = null,
var WorkItems: List<WorkItem>? = null,
var Commits: List<Commit>? = null,
var Commits: List<CommitCli>? = null,
var IncompleteDataWarning: String? = null,
var Created: String? = null,
var LastModifiedOn: String? = null,
var LastModifiedBy: String? = null,
var Links: Links? = null
var Links: LinksCli? = null
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.liftric.octopusdeploy.api

data class Commit(
data class CommitCli(
var Id: String? = null,
var LinkUrl: String? = null,
var Comment: String? = null
Expand Down
Loading

0 comments on commit 9def6f0

Please sign in to comment.