mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
[kotlin] Kotlin Build Tools code changes have to pass mandatory review
#KTIJ-33845 GitOrigin-RevId: cb1633213925fbf5f07cdb3509de08b3a3e0e9de
This commit is contained in:
committed by
intellij-monorepo-bot
parent
19fb2ccaf3
commit
a89ebef6c4
@@ -649,7 +649,8 @@
|
||||
This results in better stack traces when generated assertions throw exceptions, but might slow down the compilation."/>
|
||||
<registryKey key="kotlin.commit.message.validation.enabled" defaultValue="true"
|
||||
description="Enables commit messages validation for kotlin plugin"/>
|
||||
|
||||
<registryKey key="kotlin.build.tools.code.ownership.commit.message.enabled" defaultValue="false"
|
||||
description="Enables commit messages validation for Kotlin Build Tools code ownership"/>
|
||||
<codeInsight.declarativeInlayProvider
|
||||
providerId="devkit.threading"
|
||||
bundle="messages.DevKitBundle"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<plugin id="Git4Idea"/>
|
||||
</dependencies>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.KotlinBuildToolsPrePushHandler"/>
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.KotlinPluginPrePushHandler"/>
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.IntelliJPrePushHandler"/>
|
||||
</extensions>
|
||||
|
||||
@@ -8,4 +8,13 @@ push.commit.message.lacks.issue.reference.body=\
|
||||
push.commit.message.lacks.issue.reference.title=Message Lacks YouTrack Issue Reference
|
||||
push.commit.message.lacks.issue.reference.commit=Push As Is
|
||||
push.commit.message.lacks.issue.reference.edit=Edit Message(s)
|
||||
push.commit.handler.idea.name=IDEA Push Handler
|
||||
push.commit.handler.idea.name=IDEA Push Handler
|
||||
|
||||
push.commit.kotlin.build.tools.handler.name=Kotlin Build Tools Code Ownership Push Handler
|
||||
push.commit.kotlin.build.tools.review.title=Kotlin Build Tools Code Ownership Warning
|
||||
push.commit.kotlin.build.tools.message.lacks.issue.reference.body=\
|
||||
<html>Commits listed below change the Kotlin Build Tools code.<br/><br/>\
|
||||
According to the rules of the Kotlin Build Tools team, \
|
||||
all commits to their codebase have to pass mandatory pre-review.\
|
||||
<pre>{0}</pre> \
|
||||
</html>
|
||||
|
||||
@@ -17,15 +17,13 @@ import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.io.path.extension
|
||||
import kotlin.io.path.invariantSeparatorsPathString
|
||||
|
||||
internal abstract class IssueIDPrePushHandler : PrePushHandler {
|
||||
abstract val paths: List<String>
|
||||
internal abstract class AbstractIntelliJProjectPrePushHandler : PrePushHandler {
|
||||
open val paths: List<String> = listOf()
|
||||
open val pathsToIgnore = listOf("/test/", "/testData/")
|
||||
abstract val commitMessageRegex: Regex
|
||||
open val ignorePattern: Regex = Regex("(?!.*)")
|
||||
|
||||
abstract fun isAvailable(): Boolean
|
||||
|
||||
internal fun containSources(files: Collection<VirtualFile>) =
|
||||
fun containSources(files: Collection<VirtualFile>) =
|
||||
files.asSequence()
|
||||
.map { file -> Path.of(file.path) }
|
||||
.any { path ->
|
||||
@@ -35,31 +33,17 @@ internal abstract class IssueIDPrePushHandler : PrePushHandler {
|
||||
&& pathsToIgnore.none { siPath.contains(it) }
|
||||
}
|
||||
|
||||
fun commitMessageIsCorrect(message: String): Boolean = message.matches(commitMessageRegex) || message.matches(ignorePattern)
|
||||
private fun handlerIsApplicable(project: Project): Boolean =
|
||||
isAvailable() && IntelliJProjectUtil.isIntelliJPlatformProject(project)
|
||||
|
||||
companion object {
|
||||
private val fileExtensionsNotToTrack = setOf("iml", "md")
|
||||
|
||||
private fun <T> invokeAndWait(modalityState: ModalityState, computable: () -> T): T {
|
||||
val ref = AtomicReference<T>()
|
||||
ApplicationManager.getApplication().invokeAndWait({ ref.set(computable.invoke()) }, modalityState)
|
||||
return ref.get()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlerIsApplicable(project: Project): Boolean = isAvailable() && IntelliJProjectUtil.isIntelliJPlatformProject(project)
|
||||
|
||||
override fun handle(project: Project, pushDetails: MutableList<PushInfo>, indicator: ProgressIndicator): PrePushHandler.Result {
|
||||
if (!handlerIsApplicable(project)) return PrePushHandler.Result.OK
|
||||
|
||||
return if (pushDetails.any { it.isTargetBranchProtected(project) && it.hasCommitsToEdit(indicator.modalityState) })
|
||||
override fun handle(project: Project, pushDetails: MutableList<PushInfo>, indicator: ProgressIndicator): PrePushHandler.Result =
|
||||
if (handlerIsApplicable(project) && pushDetails.any { isTargetBranchProtected(project, it) && it.complyTheRule(project, indicator.modalityState) }) {
|
||||
PrePushHandler.Result.ABORT_AND_CLOSE
|
||||
else PrePushHandler.Result.OK
|
||||
}
|
||||
} else {
|
||||
PrePushHandler.Result.OK
|
||||
}
|
||||
|
||||
private fun PushInfo.isTargetBranchProtected(project: Project) = GitSharedSettings.getInstance(project).isBranchProtected(pushSpec.target.presentation)
|
||||
|
||||
private fun PushInfo.hasCommitsToEdit(modalityState: ModalityState): Boolean {
|
||||
protected fun PushInfo.complyTheRule(project: Project, modalityState: ModalityState): Boolean {
|
||||
val commitsToWarnAbout = commits.asSequence()
|
||||
.filter(::breaksMessageRules)
|
||||
.map { it.id.toShortString() to it.subject }
|
||||
@@ -67,6 +51,35 @@ internal abstract class IssueIDPrePushHandler : PrePushHandler {
|
||||
|
||||
if (commitsToWarnAbout.isEmpty()) return false
|
||||
|
||||
return doCommitsViolateRule(project, commitsToWarnAbout, modalityState)
|
||||
}
|
||||
|
||||
abstract fun doCommitsViolateRule(project: Project, commitsToWarnAbout: List<Pair<String, String>>, modalityState: ModalityState): Boolean
|
||||
|
||||
protected open fun isTargetBranchProtected(project: Project, pushInfo: PushInfo): Boolean =
|
||||
GitSharedSettings.getInstance(project).isBranchProtected(pushInfo.pushSpec.target.presentation)
|
||||
|
||||
protected open fun breaksMessageRules(commit: VcsFullCommitDetails): Boolean =
|
||||
containSources(commit.changes.mapNotNull { it.virtualFile })
|
||||
|
||||
companion object {
|
||||
internal val fileExtensionsNotToTrack = setOf("iml", "md")
|
||||
|
||||
internal fun <T> invokeAndWait(modalityState: ModalityState, computable: () -> T): T {
|
||||
val ref = AtomicReference<T>()
|
||||
ApplicationManager.getApplication().invokeAndWait({ ref.set(computable.invoke()) }, modalityState)
|
||||
return ref.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class IssueIDPrePushHandler : AbstractIntelliJProjectPrePushHandler() {
|
||||
abstract val commitMessageRegex: Regex
|
||||
open val ignorePattern: Regex = Regex("(?!.*)")
|
||||
|
||||
override val pathsToIgnore = listOf("/test/", "/testData/")
|
||||
|
||||
override fun doCommitsViolateRule(project: Project, commitsToWarnAbout: List<Pair<String, String>>, modalityState: ModalityState): Boolean {
|
||||
val commitsInfo = commitsToWarnAbout.joinToString("<br/>") { hashAndSubject ->
|
||||
"${hashAndSubject.first}: ${hashAndSubject.second}"
|
||||
}
|
||||
@@ -86,6 +99,10 @@ internal abstract class IssueIDPrePushHandler : PrePushHandler {
|
||||
return !commitAsIs
|
||||
}
|
||||
|
||||
private fun breaksMessageRules(commit: VcsFullCommitDetails) =
|
||||
containSources(commit.changes.mapNotNull { it.virtualFile }) && !commitMessageIsCorrect(commit.fullMessage)
|
||||
fun commitMessageIsCorrect(message: String): Boolean =
|
||||
message.matches(commitMessageRegex) || message.matches(ignorePattern)
|
||||
|
||||
override fun breaksMessageRules(commit: VcsFullCommitDetails): Boolean {
|
||||
return super.breaksMessageRules(commit) && !commitMessageIsCorrect(commit.fullMessage)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.dvcs.push.PushInfo
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
@@ -23,4 +27,55 @@ internal class IntelliJPrePushHandler : IssueIDPrePushHandler() {
|
||||
|
||||
override fun isAvailable(): Boolean = Registry.`is`("intellij.commit.message.validation.enabled", true)
|
||||
override fun getPresentableName(): @Nls String = DevKitGitBundle.message("push.commit.handler.idea.name")
|
||||
}
|
||||
|
||||
internal class KotlinBuildToolsPrePushHandler: AbstractIntelliJProjectPrePushHandler() {
|
||||
|
||||
override val pathsToIgnore: List<String> =
|
||||
listOf("community/plugins/kotlin/gradle/gradle-java/k1/test/org/jetbrains/kotlin/idea/scripting/")
|
||||
|
||||
// To be in sync with https://jetbrains.team/p/ij/repositories/ultimate-teamcity-config/files/master/.teamcity/src/idea/cherryPickRobot/branchReviewRules/BranchReviewRules.kt
|
||||
// see approval(ReviewerGroups.kotlinBuildToolsTeam)
|
||||
override val paths: List<String> =
|
||||
listOf(
|
||||
"community/plugins/kotlin/base/facet/",
|
||||
"community/plugins/kotlin/base/jps/",
|
||||
"community/plugins/kotlin/base/external-build-system/",
|
||||
"community/plugins/kotlin/gradle/gradle/",
|
||||
"community/plugins/kotlin/gradle/gradle-tooling/",
|
||||
"community/plugins/kotlin/gradle/gradle-java/",
|
||||
"community/plugins/kotlin/gradle/multiplatform-tests/",
|
||||
"community/plugins/kotlin/gradle/multiplatform-tests-k2/",
|
||||
"community/plugins/kotlin/jps/",
|
||||
"community/plugins/kotlin/maven/"
|
||||
)
|
||||
|
||||
override fun isAvailable(): Boolean =
|
||||
Registry.`is`("kotlin.build.tools.code.ownership.commit.message.enabled", true)
|
||||
|
||||
override fun getPresentableName(): @Nls(capitalization = Nls.Capitalization.Title) String =
|
||||
DevKitGitBundle.message("push.commit.kotlin.build.tools.handler.name")
|
||||
|
||||
override fun isTargetBranchProtected(project: Project, pushInfo: PushInfo): Boolean {
|
||||
return super.isTargetBranchProtected(project, pushInfo) || pushInfo.pushSpec.target.presentation == "kt-master"
|
||||
}
|
||||
|
||||
override fun doCommitsViolateRule(project: Project, commitsToWarnAbout: List<Pair<String, String>>, modalityState: ModalityState): Boolean {
|
||||
val commitsInfo =
|
||||
commitsToWarnAbout
|
||||
.toList().joinToString("<br/>") { hashAndSubject ->
|
||||
"${hashAndSubject.first}: ${hashAndSubject.second}"
|
||||
}
|
||||
|
||||
invokeAndWait(modalityState) {
|
||||
MessageDialogBuilder.okCancel(
|
||||
DevKitGitBundle.message("push.commit.kotlin.build.tools.review.title"),
|
||||
DevKitGitBundle.message("push.commit.kotlin.build.tools.message.lacks.issue.reference.body", commitsInfo)
|
||||
)
|
||||
.asWarning()
|
||||
.ask(project = null)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user