net.nemerosa.ontrack.it.AbstractDSLTestSupport.kt Maven / Gradle / Ivy
package net.nemerosa.ontrack.it
import net.nemerosa.ontrack.common.Document
import net.nemerosa.ontrack.model.buildfilter.BuildFilterProviderData
import net.nemerosa.ontrack.model.buildfilter.BuildFilterService
import net.nemerosa.ontrack.model.buildfilter.StandardFilterProviderDataBuilder
import net.nemerosa.ontrack.model.exceptions.BuildNotFoundException
import net.nemerosa.ontrack.model.labels.*
import net.nemerosa.ontrack.model.security.GlobalFunction
import net.nemerosa.ontrack.model.security.ValidationRunCreate
import net.nemerosa.ontrack.model.security.ValidationRunStatusChange
import net.nemerosa.ontrack.model.settings.CachedSettingsService
import net.nemerosa.ontrack.model.settings.PredefinedPromotionLevelService
import net.nemerosa.ontrack.model.settings.PredefinedValidationStampService
import net.nemerosa.ontrack.model.structure.*
import net.nemerosa.ontrack.model.support.OntrackConfigProperties
import net.nemerosa.ontrack.test.TestUtils
import net.nemerosa.ontrack.test.TestUtils.uid
import org.springframework.beans.factory.annotation.Autowired
import java.time.LocalDateTime
import kotlin.reflect.KClass
import kotlin.test.assertEquals
abstract class AbstractDSLTestSupport : AbstractServiceTestSupport() {
@Autowired
protected lateinit var ontrackConfigProperties: OntrackConfigProperties
@Autowired
protected lateinit var labelManagementService: LabelManagementService
@Autowired
protected lateinit var projectLabelManagementService: ProjectLabelManagementService
@Autowired
protected lateinit var buildFilterService: BuildFilterService
@Autowired
protected lateinit var settingsService: CachedSettingsService
@Autowired
protected lateinit var predefinedPromotionLevelService: PredefinedPromotionLevelService
@Autowired
protected lateinit var predefinedValidationStampService: PredefinedValidationStampService
/**
* Kotlin friendly
*/
protected final inline fun asUserWith(noinline code: () -> Unit): Unit = asUserWith(code)
protected final inline fun asUserWith(noinline code: () -> R): R =
asUser().with(T::class.java).call(code)
/**
* Kotlin friendly
*/
fun asUserWithView(vararg entities: ProjectEntity, code: () -> Unit) {
asUserWithView(*entities).execute(code)
}
fun ProjectEntity.asUserWithView(code: () -> T): T = asUserWithView(this).call(code)
/**
* Kotlin friendly anonymous execution
*/
fun asAnonymous(code: () -> T): T = asAnonymous().call(code)
/**
* Kotlin friendly admin execution
*/
fun asAdmin(code: () -> T): T = asAdmin().call(code)
/**
* Kotlin friendly user execution
*/
fun asUser(code: () -> T): T = asUser().call(code)
/**
* Kotlin friendly account role execution
*/
fun ProjectEntity.asAccountWithProjectRole(role: String, code: () -> T): T {
val account = doCreateAccountWithProjectRole(project, role)
return asFixedAccount(account).call(code)
}
/**
* Kotlin friendly account role execution
*/
fun asAccountWithGlobalRole(role: String, code: () -> T): T {
val account = doCreateAccountWithGlobalRole(role)
return asFixedAccount(account).call(code)
}
fun withDisabledConfigurationTest(code: () -> T): T {
val configurationTest = ontrackConfigProperties.configurationTest
ontrackConfigProperties.configurationTest = false
return try {
code()
} finally {
ontrackConfigProperties.configurationTest = configurationTest
}
}
fun project(name: NameDescription = nameDescription(), init: Project.() -> Unit = {}): Project {
val project = doCreateProject(name)
securityService.asAdmin {
project.init()
}
return project
}
fun project(init: Project.() -> T): T {
val project = doCreateProject()
return asAdmin().call {
project.init()
}
}
fun Project.branch(name: String = uid("B"), init: Branch.() -> Unit = {}): Branch {
val branch = doCreateBranch(this, NameDescription.nd(name, ""))
branch.init()
return branch
}
fun Project.branch(name: String = uid("B"), init: Branch.() -> T): T {
val branch = doCreateBranch(this, NameDescription.nd(name, ""))
return branch.init()
}
/**
* Deletes a branch
*/
fun Branch.delete() {
asAdmin {
structureService.deleteBranch(id)
}
}
fun Branch.promotionLevel(name: String = uid("P"), description: String = "", init: PromotionLevel.() -> Unit = {}): PromotionLevel =
doCreatePromotionLevel(this, NameDescription.nd(name, description)).apply {
init()
}
/**
* Creates and returns a validation stamp
*
* @receiver Branch to create a validation stamp for
* @param name Name of the validation stamp to create
* @return Created validation stamp
*/
fun Branch.validationStamp(
name: String = uid("VS"),
validationDataTypeConfig: ValidationDataTypeConfig<*>? = null,
description: String = "",
): ValidationStamp =
doCreateValidationStamp(this, NameDescription.nd(name, description), validationDataTypeConfig)
/**
* Deletes a validation stamp
*/
fun ValidationStamp.delete() {
asAdmin {
structureService.deleteValidationStamp(id)
}
}
fun Branch.build(name: String = uid("B"), init: (Build.() -> Unit)? = {}): Build {
val build = doCreateBuild(this, NameDescription.nd(name, ""))
if (init != null) {
build.init()
}
return build
}
fun Branch.build(name: String, init: Build.() -> T): T {
val build = doCreateBuild(this, NameDescription.nd(name, ""))
return build.init()
}
/**
* Updating the signature of a [Branch].
*/
fun Branch.updateBranchSignature(
user: String? = null,
time: LocalDateTime? = null
) {
structureService.saveBranch(
withSignature(
Signature(time ?: signature.time, user?.let { User(user) } ?: signature.user)
)
)
}
/**
* Updating the signature of a [Build].
*/
fun Build.updateBuildSignature(
user: String? = null,
time: LocalDateTime? = null
) {
structureService.saveBuild(
withSignature(
Signature(time ?: signature.time, user?.let { User(user) } ?: signature.user)
)
)
}
protected fun > ProjectEntity.property(type: KClass, value: T?) {
if (value != null) {
propertyService.editProperty(
this,
type.java,
value
)
} else {
propertyService.deleteProperty(
this,
type.java
)
}
}
protected fun > ProjectEntity.property(type: KClass): T? =
propertyService.getProperty(this, type.java).value
fun Build.promote(promotionLevel: PromotionLevel, description: String = "", signature: Signature = Signature.of("test")) {
doPromote(this, promotionLevel, description, signature)
}
/**
* Creates a validation run on a build.
*
* @receiver Build to validate
* @param validationStamp Stamp to apply
* @param validationRunStatusID Status to apply
*/
fun Build.validate(
validationStamp: ValidationStamp,
validationRunStatusID: ValidationRunStatusID = ValidationRunStatusID.STATUS_PASSED,
description: String? = null,
code: ValidationRun.() -> Unit = {}
): ValidationRun {
return this.validateWithData(
validationStampName = validationStamp.name,
validationRunStatusID = validationRunStatusID,
description = description
).apply {
code()
}
}
/**
* Creates a validation run on a build, possibly with some data and a status.
*/
fun Build.validateWithData(
validationStamp: ValidationStamp,
validationRunStatusID: ValidationRunStatusID? = null,
validationDataTypeId: String? = null,
validationRunData: T? = null,
description: String? = null
) = validateWithData(
validationStampName = validationStamp.name,
validationRunStatusID = validationRunStatusID,
validationDataTypeId = validationDataTypeId,
validationRunData = validationRunData,
description = description
)
/**
* Creates a validation run on a build, possibly with some data and a status.
*/
fun Build.validateWithData(
validationStampName: String,
validationRunStatusID: ValidationRunStatusID? = null,
validationDataTypeId: String? = null,
validationRunData: T? = null,
description: String? = null
): ValidationRun {
return asUser().withView(this).with(this, ValidationRunCreate::class.java).call {
structureService.newValidationRun(
this,
ValidationRunRequest(
validationStampName = validationStampName,
dataTypeId = validationDataTypeId,
data = validationRunData,
validationRunStatusId = validationRunStatusID,
description = description
)
)
}
}
/**
* Deletes a build
*/
fun Build.delete() {
asAdmin {
structureService.deleteBuild(id)
}
}
fun Build.linkTo(project: Project, buildName: String) {
val build = structureService.buildSearch(
project.id,
BuildSearchForm(
buildExactMatch = true,
buildName = buildName,
)
).firstOrNull() ?: throw BuildNotFoundException(project.name, buildName)
linkTo(build)
}
infix fun Build.linkTo(build: Build) {
structureService.addBuildLink(
this,
build
)
}
fun Build.unlinkTo(build: Build) {
structureService.deleteBuildLink(
this,
build
)
}
/**
* Change of status for a validation run
*/
fun ValidationRun.validationStatus(status: ValidationRunStatusID, description: String): ValidationRun {
return asUser().with(this, ValidationRunStatusChange::class.java).call {
structureService.newValidationRunStatus(
this,
ValidationRunStatus(
ID.NONE,
Signature.of("test"),
status,
description
)
)
}
}
/**
* Change of status for a validation run
*/
fun ValidationRun.validationStatusWithCurrentUser(status: ValidationRunStatusID, description: String): ValidationRun {
return structureService.newValidationRunStatus(
this,
ValidationRunStatus(
ID.NONE,
securityService.currentSignature,
status,
description
)
)
}
/**
* Creates a label
*/
fun label(category: String? = uid("C"), name: String = uid("N"), checkForExisting: Boolean = true): Label {
return asUser().with(LabelManagement::class.java).call {
if (checkForExisting) {
val labels = labelManagementService.findLabels(category, name)
val existingLabel = labels.firstOrNull()
existingLabel ?: labelManagementService.newLabel(
LabelForm(
category = category,
name = name,
description = null,
color = "#FF0000"
)
)
} else {
labelManagementService.newLabel(
LabelForm(
category = category,
name = name,
description = null,
color = "#FF0000"
)
)
}
}
}
/**
* Sets some labels to a project
*/
var Project.labels: List