diff --git a/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/TeamCityHelper.kt b/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/TeamCityHelper.kt index c124a78c1c5e..18bebb653213 100644 --- a/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/TeamCityHelper.kt +++ b/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/TeamCityHelper.kt @@ -8,7 +8,6 @@ import java.nio.file.Files import java.nio.file.Path import java.util.function.Supplier -@Suppress("unused") @ApiStatus.Internal object TeamCityHelper { val isUnderTeamCity = System.getenv("TEAMCITY_VERSION") != null diff --git a/platform/build-scripts/intellij.platform.buildScripts.iml b/platform/build-scripts/intellij.platform.buildScripts.iml index 9be64125aa88..9e826307afbb 100644 --- a/platform/build-scripts/intellij.platform.buildScripts.iml +++ b/platform/build-scripts/intellij.platform.buildScripts.iml @@ -166,5 +166,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/ApplicationInfoPropertiesImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/ApplicationInfoPropertiesImpl.kt index 83f0d585f445..7e5a7b17fcde 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/ApplicationInfoPropertiesImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/ApplicationInfoPropertiesImpl.kt @@ -4,6 +4,7 @@ package org.jetbrains.intellij.build import com.intellij.util.xml.dom.readXmlAsModel import org.jetbrains.annotations.VisibleForTesting import org.jetbrains.intellij.build.impl.BuildUtils +import org.jetbrains.intellij.build.impl.logging.reportBuildProblem import org.jetbrains.intellij.build.impl.readSnapshotBuildNumber import org.jetbrains.jps.model.JpsProject import java.nio.file.Files @@ -94,15 +95,11 @@ class ApplicationInfoPropertiesImpl: ApplicationInfoProperties { val expirationDate = buildDate.plus(30, ChronoUnit.DAYS) val now = Instant.ofEpochMilli(System.currentTimeMillis()) if (expirationDate < now) { - val msg = "Supplied build date is $buildDate, " + - "so expiration date is in the past, " + - "distribution won't be able to start" - if (buildOptions.isInDevelopmentMode) { - error(msg) - } - else { - println("##teamcity[buildProblem description='$msg']") - } + reportBuildProblem( + "Supplied build date is $buildDate, " + + "so expiration date is in the past, " + + "distribution won't be able to start" + ) } } majorReleaseDate == null || majorReleaseDate.startsWith("__") -> { diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt index 8af406a2e6f9..6ed1a9eacf26 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt @@ -12,6 +12,10 @@ import com.intellij.util.containers.MultiMap import com.intellij.util.io.Compressor import com.jetbrains.plugin.blockmap.core.BlockMap import com.jetbrains.plugin.blockmap.core.FileHash +import com.jetbrains.plugin.structure.base.plugin.PluginCreationFail +import com.jetbrains.plugin.structure.base.plugin.PluginCreationSuccess +import com.jetbrains.plugin.structure.base.plugin.PluginProblem +import com.jetbrains.plugin.structure.intellij.plugin.IdePluginManager import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.api.common.Attributes import io.opentelemetry.api.trace.Span @@ -25,6 +29,7 @@ import org.jetbrains.intellij.build.* import org.jetbrains.intellij.build.TraceManager.spanBuilder import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot import org.jetbrains.intellij.build.fus.createStatisticsRecorderBundledMetadataProviderTask +import org.jetbrains.intellij.build.impl.logging.reportBuildProblem import org.jetbrains.intellij.build.impl.projectStructureMapping.* import org.jetbrains.intellij.build.io.* import org.jetbrains.intellij.build.tasks.ZipSource @@ -50,6 +55,8 @@ import java.util.* import java.util.concurrent.ConcurrentLinkedQueue import java.util.function.Predicate import java.util.stream.Collectors +import kotlin.io.path.exists +import kotlin.io.path.name /** * Assembles output of modules to platform JARs (in [BuildPaths.distAllDir]/lib directory), @@ -161,6 +168,50 @@ class DistributionJARsBuilder { } } + private fun validatePlugin(path: Path, context: BuildContext) { + spanBuilder("plugin validation").setAttribute("path", "$path").useWithScope { + if (!path.exists()) { + it.addEvent("path doesn't exist, skipped") + return@useWithScope + } + var id: String? = null + val problems = when (val result = IdePluginManager.createManager().createPlugin(path)) { + is PluginCreationSuccess -> { + id = result.plugin.pluginId + result.unacceptableWarnings + } + is PluginCreationFail -> { + result.errorsAndWarnings + } + } + if (problems.isNotEmpty()) { + val msg = problems.joinToString( + prefix = "${id ?: path}: ", + separator = ". ", + transform = PluginProblem::message + ) + when (id) { + // https://youtrack.jetbrains.com/issue/IDEA-308174 + "androidx.compose.plugins.idea", + // https://youtrack.jetbrains.com/issue/IDEA-312410 + "com.intellij.tasks", + // https://youtrack.jetbrains.com/issue/IDEA-312409 + "org.jetbrains.plugins.sass", + // https://youtrack.jetbrains.com/issue/IDEA-312408 + "org.toml.lang", + // https://youtrack.jetbrains.com/issue/IDEA-312407 + "com.intellij.plugins.webcomponents", + // https://youtrack.jetbrains.com/issue/IDEA-312406 + "cucumber-javascript", + // https://youtrack.jetbrains.com/issue/IDEA-312405 + "com.jetbrains.plugins.yeoman" + -> context.messages.warning(msg) + else -> reportBuildProblem(msg, identity = "${id ?: path}") + } + } + } + } + // filter out jars with relative paths in name val productModules: List get() { @@ -361,7 +412,7 @@ class DistributionJARsBuilder { } // buildPlugins pluginBuilt listener is called concurrently - val pluginsToIncludeInCustomRepository = ConcurrentLinkedQueue() + val pluginSpecs = ConcurrentLinkedQueue() val autoPublishPluginChecker = loadPluginAutoPublishList(context) val prepareCustomPluginRepository = context.productProperties.productLayout.prepareCustomPluginRepositoryForPublishedPlugins && !context.isStepSkipped(BuildOptions.ARCHIVE_PLUGINS) @@ -383,10 +434,8 @@ class DistributionJARsBuilder { defaultPluginVersion } val destFile = targetDirectory.resolve("${plugin.directoryName}-$pluginVersion.zip") - if (prepareCustomPluginRepository) { - val pluginXml = moduleOutputPatcher.getPatchedPluginXml(plugin.mainModule) - pluginsToIncludeInCustomRepository.add(PluginRepositorySpec(destFile, pluginXml)) - } + val pluginXml = moduleOutputPatcher.getPatchedPluginXml(plugin.mainModule) + pluginSpecs.add(PluginRepositorySpec(destFile, pluginXml)) dirToJar.add(NonBundledPlugin(pluginDirOrFile, destFile, !plugin.enableSymlinksAndExecutableResources)) } @@ -399,21 +448,24 @@ class DistributionJARsBuilder { targetDir = autoUploadingDir, moduleOutputPatcher = moduleOutputPatcher, context = context) - if (prepareCustomPluginRepository) { - pluginsToIncludeInCustomRepository.add(spec) - } + pluginSpecs.add(spec) } + for (item in buildKeymapPluginsTask.await()) { + pluginSpecs.add(PluginRepositorySpec(pluginZip = item.first, pluginXml = item.second)) + } if (prepareCustomPluginRepository) { - for (item in buildKeymapPluginsTask.await()) { - pluginsToIncludeInCustomRepository.add(PluginRepositorySpec(pluginZip = item.first, pluginXml = item.second)) - } - - val list = pluginsToIncludeInCustomRepository.sortedBy { it.pluginZip } + val list = pluginSpecs.sortedBy { it.pluginZip } generatePluginRepositoryMetaFile(list, nonBundledPluginsArtifacts, context) generatePluginRepositoryMetaFile(list.filter { it.pluginZip.startsWith(autoUploadingDir) }, autoUploadingDir, context) } - + pluginSpecs.forEach { + if (it.pluginZip.startsWith(autoUploadingDir)) { + launch { + validatePlugin(it.pluginZip, context) + } + } + } mappings } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/OsSpecificDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/OsSpecificDistributionBuilder.kt index 22e2b7b6402a..9225431d3fd1 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/OsSpecificDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/OsSpecificDistributionBuilder.kt @@ -13,6 +13,8 @@ import org.jetbrains.intellij.build.BuildContext import org.jetbrains.intellij.build.JvmArchitecture import org.jetbrains.intellij.build.OsFamily import org.jetbrains.intellij.build.TraceManager +import org.jetbrains.intellij.build.dependencies.TeamCityHelper +import org.jetbrains.intellij.build.impl.logging.reportBuildProblem import java.io.BufferedInputStream import java.nio.file.FileSystems import java.nio.file.Files @@ -66,10 +68,13 @@ interface OsSpecificDistributionBuilder { .toSet() if (unmatchedPatterns.isNotEmpty()) { context.messages.warning(matchedFiles.joinToString(prefix = "Matched files ${distribution.name}:\n", separator = "\n")) - val msg = unmatchedPatterns.joinToString(prefix = "Unmatched executable permissions patterns in ${distribution.name}: ") { - patterns.getValue(it) + if (TeamCityHelper.isUnderTeamCity) { + reportBuildProblem( + unmatchedPatterns.joinToString(prefix = "Unmatched executable permissions patterns in ${distribution.name}: ") { + patterns.getValue(it) + } + ) } - println("##teamcity[buildProblem description='$msg']") } } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt index 81fe077374b8..519438a100b6 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt @@ -21,6 +21,7 @@ import org.jetbrains.intellij.build.* import org.jetbrains.intellij.build.CompilationTasks.Companion.create import org.jetbrains.intellij.build.TraceManager.spanBuilder import org.jetbrains.intellij.build.causal.CausalProfilingOptions +import org.jetbrains.intellij.build.impl.logging.reportBuildProblem import org.jetbrains.intellij.build.io.runProcess import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType import org.jetbrains.jps.incremental.ModuleBuildTarget @@ -59,8 +60,8 @@ internal class TestingTasksImpl(private val context: CompilationContext, private } } catch (e: Exception) { - val description = e.message?.lineSequence()?.first()?.replace("'", "\"") - println("##teamcity[buildProblem identity='${name.replace(" ", "_")}' description='$description']") + val description = e.message?.lineSequence()?.firstOrNull() ?: "" + reportBuildProblem(description, identity = name) emptyList() } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/logging/BuildMessagesImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/logging/BuildMessagesImpl.kt index 81e18b215045..66c6340d797b 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/logging/BuildMessagesImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/logging/BuildMessagesImpl.kt @@ -4,8 +4,11 @@ package org.jetbrains.intellij.build.impl.logging import com.intellij.diagnostic.telemetry.useWithScope import com.intellij.openapi.util.ThrowableComputable import com.intellij.util.containers.Stack +import jetbrains.buildServer.messages.serviceMessages.ServiceMessage +import org.jetbrains.annotations.ApiStatus.Internal import org.jetbrains.intellij.build.* import org.jetbrains.intellij.build.TraceManager.spanBuilder +import org.jetbrains.intellij.build.dependencies.TeamCityHelper.isUnderTeamCity import java.io.BufferedWriter import java.io.PrintWriter import java.io.StringWriter @@ -15,6 +18,7 @@ import java.nio.file.StandardCopyOption import java.nio.file.StandardOpenOption import java.util.* import java.util.function.Consumer +import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes.BUILD_PORBLEM as BUILD_PROBLEM class BuildMessagesImpl private constructor(private val logger: BuildMessageLogger, private val debugLogger: DebugLogger) : BuildMessages { @@ -22,8 +26,7 @@ class BuildMessagesImpl private constructor(private val logger: BuildMessageLogg companion object { fun create(): BuildMessagesImpl { - val underTeamCity = System.getenv("TEAMCITY_VERSION") != null - val mainLoggerFactory = if (underTeamCity) TeamCityBuildMessageLogger.FACTORY else ConsoleBuildMessageLogger.FACTORY + val mainLoggerFactory = if (isUnderTeamCity) TeamCityBuildMessageLogger.FACTORY else ConsoleBuildMessageLogger.FACTORY val debugLogger = DebugLogger() return BuildMessagesImpl(logger = CompositeBuildMessageLogger(listOf(mainLoggerFactory(), debugLogger.createLogger())), debugLogger = debugLogger) @@ -206,3 +209,18 @@ private class PrintWriterBuildMessageLogger( disposer.accept(this) } } + +@Internal +fun reportBuildProblem(description: String, identity: String? = null) { + if (isUnderTeamCity) { + val attributes = mutableMapOf("description" to description) + if (identity != null) { + attributes["identity"] = identity + } + println(ServiceMessage.asString(BUILD_PROBLEM, attributes)) + } + else { + error("$identity: $description") + } +} + diff --git a/plugins/github/resources/META-INF/plugin.xml b/plugins/github/resources/META-INF/plugin.xml index 7bcb19781c13..727ba149b919 100644 --- a/plugins/github/resources/META-INF/plugin.xml +++ b/plugins/github/resources/META-INF/plugin.xml @@ -5,7 +5,7 @@ Version Controls GitHub. + Provides integration with GitHub.
  • Specify your GitHub account to access all of your repositories from the IDE.
  • Clone repositories, create and review pull requests, create gists, and much more.
  • diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index f2a7c3c8a4e3..cc081f7af591 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -3,7 +3,7 @@ Mercurial Mercurial version control system. + Allows working with Mercurial version control system. The following features are available:
    • Dedicated page under the Version Control node in the Settings/Preferences dialog.
    • diff --git a/python/pluginCore/resources/META-INF/plugin.xml b/python/pluginCore/resources/META-INF/plugin.xml index 835179b84770..981d5f301f13 100644 --- a/python/pluginCore/resources/META-INF/plugin.xml +++ b/python/pluginCore/resources/META-INF/plugin.xml @@ -9,8 +9,8 @@ The Python plug-in provides smart editing for Python scripts. The feature set of the plugin corresponds to PyCharm IDE Community Edition.
      -PyCharm blog
      -Discussion forum
      +PyCharm blog
      +Discussion forum
      Issue tracker
      ]]>