From 3fbb8c21bb5684853902a08fff302ad61faeb73d Mon Sep 17 00:00:00 2001 From: "Dmitriy.Panov" Date: Tue, 6 Aug 2019 12:44:34 +0300 Subject: [PATCH] IJI-184 publication of nightly versions of Intellij modules as a Maven artifacts GitOrigin-RevId: abc65f37dcc8993651fdd8cf4d89b4dbcad89366 --- .../build/impl/IntellijModulesPreview.groovy | 124 ++++++++++++++++++ .../build/impl/MavenArtifactsBuilder.groovy | 44 ++++--- 2 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/IntellijModulesPreview.groovy diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/IntellijModulesPreview.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/IntellijModulesPreview.groovy new file mode 100644 index 000000000000..9f51681c6f8b --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/IntellijModulesPreview.groovy @@ -0,0 +1,124 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.intellij.build.impl + + +import groovy.transform.CompileStatic +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.jps.model.module.JpsModule +import org.jetbrains.jps.model.module.JpsModuleDependency + +/** + * Publishes specified nightly versions of Intellij modules as a Maven artifacts using the output of {@link org.jetbrains.intellij.build.impl.MavenArtifactsBuilder}. + * + *

+ * Note: Requires installed `mvn`. + *

+ */ +@CompileStatic +@SuppressWarnings("unused") +class IntellijModulesPreview { + private final BuildContext buildContext + private final int uploadRetryCount = 3 + private final String repositoryId + private final String repositoryUrl + private final File mavenSettings + + IntellijModulesPreview(BuildContext context) { + buildContext = context + repositoryId = require('repository.id') + repositoryUrl = "${require('repository.publicationUrl')}/;publish=1;" + mavenSettings = settingsXml() + } + + private String require(String property) { + System.getProperty(property) ?: buildContext.messages.error("$property is not specifed") + } + + /** + * @param modulesOutputDir output of {@link org.jetbrains.intellij.build.impl.MavenArtifactsBuilder} + */ + void publish(List modulesToPublish, File modulesOutputDir) { + def modules = new HashSet() + modulesToPublish.each { + def module = buildContext.findRequiredModule(it) + modules << module + transitiveModuleDependencies(module, modules) + } + modules.each { + def coordinates = MavenArtifactsBuilder.generateMavenCoordinates( + it.name, buildContext.messages, buildContext.buildNumber + ) + def dir = new File(modulesOutputDir, coordinates.directoryPath) + def pom = new File(dir, coordinates.getFileName('', 'pom')) + def jar = new File(dir, coordinates.getFileName('', 'jar')) + def sources = new File(dir, coordinates.getFileName('sources', 'jar')) + deployJar(jar, pom) + if (sources.exists()) { + deploySources(sources, coordinates) + } + } + } + + private def transitiveModuleDependencies(JpsModule module, Collection result) { + MavenArtifactsBuilder.scopedDependencies(module) + .findAll { it.key instanceof JpsModuleDependency } + .each { + def dependencyModule = (it.key as JpsModuleDependency).module + if (!result.contains(dependencyModule)) { + result << dependencyModule + transitiveModuleDependencies(dependencyModule, result) + } + } + } + + private def deployJar(File jar, File pom) { + deployFile(jar, ["-DpomFile=$pom.absolutePath"]) + } + + private def deploySources(File sources, MavenArtifactsBuilder.MavenCoordinates coordinates) { + deployFile(sources, [ + "-DgroupId=$coordinates.groupId", + "-DartifactId=$coordinates.artifactId", + "-Dversion=$coordinates.version", + '-Dpackaging=java-source', + '-DgeneratePom=false' + ]) + } + + private def deployFile(File file, Collection args) { + buildContext.messages.info("Upload of $file.name") + def process = ([ + 'mvn', '--settings', mavenSettings.absolutePath, + 'deploy:deploy-file', + "-Dfile=$file.absolutePath", + "-DrepositoryId=$repositoryId", + "-Durl=$repositoryUrl", + "-DretryFailedDeploymentCount=$uploadRetryCount" + ] + args).execute() + def output = process.text + def exitCode = process.waitFor() + if (exitCode != 0) { + buildContext.messages.error("Upload of $file.name failed with exit code $exitCode: $output") + } + } + + private File settingsXml() { + File.createTempFile('settings', '.xml').with { + it << """ + + + $repositoryId + ${require('repository.user')} + ${require('repository.password')} + + + + """.stripIndent() + it.deleteOnExit() + it + } + } +} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MavenArtifactsBuilder.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MavenArtifactsBuilder.groovy index 711a72282b09..d4869dfb1ccf 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MavenArtifactsBuilder.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MavenArtifactsBuilder.groovy @@ -19,6 +19,7 @@ import org.jetbrains.jps.model.java.JpsJavaExtensionService import org.jetbrains.jps.model.library.JpsLibrary import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor import org.jetbrains.jps.model.library.JpsRepositoryLibraryType +import org.jetbrains.jps.model.module.JpsDependencyElement import org.jetbrains.jps.model.module.JpsLibraryDependency import org.jetbrains.jps.model.module.JpsModule import org.jetbrains.jps.model.module.JpsModuleDependency @@ -176,23 +177,10 @@ class MavenArtifactsBuilder { return results } - private MavenArtifactData generateMavenArtifactData(JpsModule module, Map results, Set nonMavenizableModules, - Set computationInProgress) { - if (results.containsKey(module)) return results[module] - if (nonMavenizableModules.contains(module)) return null - if (!module.name.startsWith("intellij.")) { - buildContext.messages.debug(" module '$module.name' doesn't belong to IntelliJ project so it cannot be published") - return null - } - def scrambleTool = buildContext.proprietaryBuildTools.scrambleTool - if (scrambleTool != null && scrambleTool.namesOfModulesRequiredToBeScrambled.contains(module.name)) { - buildContext.messages.debug(" module '$module.name' must be scrambled so it cannot be published") - return null - } + enum DependencyScope { COMPILE, RUNTIME } - boolean mavenizable = true - computationInProgress << module - List dependencies = [] + static Map scopedDependencies(JpsModule module) { + Map result = [:] module.dependenciesList.dependencies.each { dependency -> def extension = JpsJavaExtensionService.getInstance().getDependencyExtension(dependency) if (extension == null) return @@ -213,7 +201,29 @@ class MavenArtifactsBuilder { default: return } + result[dependency] = scope + } + return result + } + private MavenArtifactData generateMavenArtifactData(JpsModule module, Map results, Set nonMavenizableModules, + Set computationInProgress) { + if (results.containsKey(module)) return results[module] + if (nonMavenizableModules.contains(module)) return null + if (!module.name.startsWith("intellij.")) { + buildContext.messages.debug(" module '$module.name' doesn't belong to IntelliJ project so it cannot be published") + return null + } + def scrambleTool = buildContext.proprietaryBuildTools.scrambleTool + if (scrambleTool != null && scrambleTool.namesOfModulesRequiredToBeScrambled.contains(module.name)) { + buildContext.messages.debug(" module '$module.name' must be scrambled so it cannot be published") + return null + } + + boolean mavenizable = true + computationInProgress << module + List dependencies = [] + scopedDependencies(module).each { dependency, scope -> if (dependency instanceof JpsModuleDependency) { def depModule = (dependency as JpsModuleDependency).module if (computationInProgress.contains(depModule)) { @@ -281,8 +291,6 @@ class MavenArtifactsBuilder { List dependencies } - private enum DependencyScope { COMPILE, RUNTIME } - @Immutable private static class MavenArtifactDependency { MavenCoordinates coordinates