IJI-184 publication of nightly versions of Intellij modules as a Maven artifacts

GitOrigin-RevId: abc65f37dcc8993651fdd8cf4d89b4dbcad89366
This commit is contained in:
Dmitriy.Panov
2019-08-06 13:03:24 +03:00
committed by intellij-monorepo-bot
parent 3e431c162c
commit 3fbb8c21bb
2 changed files with 150 additions and 18 deletions
@@ -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}.
*
* <p>
* Note: Requires installed `mvn`.
* </p>
*/
@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<String> modulesToPublish, File modulesOutputDir) {
def modules = new HashSet<JpsModule>()
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<JpsModule> 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 << """<settings xmlns="https://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>$repositoryId</id>
<username>${require('repository.user')}</username>
<password>${require('repository.password')}</password>
</server>
</servers>
</settings>
""".stripIndent()
it.deleteOnExit()
it
}
}
}
@@ -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<JpsModule, MavenArtifactData> results, Set<JpsModule> nonMavenizableModules,
Set<JpsModule> 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<MavenArtifactDependency> dependencies = []
static Map<JpsDependencyElement, DependencyScope> scopedDependencies(JpsModule module) {
Map<JpsDependencyElement, DependencyScope> 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<JpsModule, MavenArtifactData> results, Set<JpsModule> nonMavenizableModules,
Set<JpsModule> 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<MavenArtifactDependency> 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<MavenArtifactDependency> dependencies
}
private enum DependencyScope { COMPILE, RUNTIME }
@Immutable
private static class MavenArtifactDependency {
MavenCoordinates coordinates