Move Maven default CI spec provider to a separate plugin and improve it

to detect Java versions
This commit is contained in:
Robin Shen 2019-06-08 18:05:28 +08:00
parent e595f0904c
commit 2971df6a5d
17 changed files with 209 additions and 100 deletions

View File

@ -345,6 +345,11 @@
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>

View File

@ -80,14 +80,14 @@ import io.onedev.server.cache.DefaultCodeCommentRelationInfoManager;
import io.onedev.server.cache.DefaultCommitInfoManager;
import io.onedev.server.cache.DefaultUserInfoManager;
import io.onedev.server.cache.UserInfoManager;
import io.onedev.server.ci.detector.CISpecDetector;
import io.onedev.server.ci.DefaultCISpecProvider;
import io.onedev.server.ci.job.DefaultJobManager;
import io.onedev.server.ci.job.DependencyPopulator;
import io.onedev.server.ci.job.JobManager;
import io.onedev.server.ci.job.log.DefaultLogManager;
import io.onedev.server.ci.job.log.LogManager;
import io.onedev.server.ci.job.log.LogNormalizer;
import io.onedev.server.ci.job.log.instruction.LogInstruction;
import io.onedev.server.ci.job.log.normalizer.LogNormalizer;
import io.onedev.server.entitymanager.BuildDependenceManager;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.BuildParamManager;
@ -386,7 +386,7 @@ public class CoreModule extends AbstractPluginModule {
});
contributeFromPackage(Authenticator.class, Authenticator.class);
contributeFromPackage(CISpecDetector.class, CISpecDetector.class);
contributeFromPackage(DefaultCISpecProvider.class, DefaultCISpecProvider.class);
contributeFromPackage(LogNormalizer.class, LogNormalizer.class);
bind(IndexManager.class).to(DefaultIndexManager.class);

View File

@ -0,0 +1,27 @@
package io.onedev.server.ci;
import javax.annotation.Nullable;
import org.eclipse.jgit.lib.ObjectId;
import io.onedev.commons.launcher.loader.ExtensionPoint;
import io.onedev.server.model.Project;
@ExtensionPoint
public interface DefaultCISpecProvider {
int DEFAULT_PRIORITY = 100;
/**
* Get default CI spec for specified project and commit
* @param project
* @param commitId
* @return
* default CI spec, or <tt>null</tt> if no default CI spec can be provided
*/
@Nullable
CISpec getDefaultCISpec(Project project, ObjectId commitId);
int getPriority();
}

View File

@ -1,21 +0,0 @@
package io.onedev.server.ci.detector;
import javax.annotation.Nullable;
import org.eclipse.jgit.lib.ObjectId;
import io.onedev.commons.launcher.loader.ExtensionPoint;
import io.onedev.server.ci.CISpec;
import io.onedev.server.model.Project;
@ExtensionPoint
public interface CISpecDetector {
int DEFAULT_PRIORITY = 100;
@Nullable
CISpec detect(Project project, ObjectId commitId);
int getPriority();
}

View File

@ -1,54 +0,0 @@
package io.onedev.server.ci.detector;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import io.onedev.server.ci.CISpec;
import io.onedev.server.ci.job.Job;
import io.onedev.server.ci.job.cache.JobCache;
import io.onedev.server.ci.job.trigger.BranchUpdateTrigger;
import io.onedev.server.git.Blob;
import io.onedev.server.git.BlobIdent;
import io.onedev.server.model.Project;
public class MavenDetector implements CISpecDetector {
@Override
public CISpec detect(Project project, ObjectId commitId) {
Blob blob = project.getBlob(new BlobIdent(commitId.name(), "pom.xml", FileMode.TYPE_FILE), false);
if (blob != null) {
CISpec ciSpec = new CISpec();
Job job = new Job();
job.setName("ci");
job.setEnvironment("maven:3.6.1-jdk-8");
job.setCommands(""
+ "buildVersion=$(mvn org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate -Dexpression=project.version -q -DforceStdout)\n"
+ "echo \"##onedev[SetBuildVersion '$buildVersion']\"\n"
+ "echo\n"
+ "mvn clean test");
BranchUpdateTrigger trigger = new BranchUpdateTrigger();
job.getTriggers().add(trigger);
JobCache cache = new JobCache();
cache.setKey("maven-local-repository");
cache.setPath("/root/.m2");
job.getCaches().add(cache);
ciSpec.getJobs().add(job);
return ciSpec;
} else {
return null;
}
}
@Override
public int getPriority() {
return DEFAULT_PRIORITY;
}
}

View File

@ -44,7 +44,6 @@ import io.onedev.server.OneDev;
import io.onedev.server.ci.job.log.instruction.LogInstruction;
import io.onedev.server.ci.job.log.instruction.LogInstructionParser.InstructionContext;
import io.onedev.server.ci.job.log.instruction.LogInstructionParser.ParamContext;
import io.onedev.server.ci.job.log.normalizer.LogNormalizer;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.event.build.BuildFinished;
import io.onedev.server.model.Build;

View File

@ -1,9 +1,8 @@
package io.onedev.server.ci.job.log.normalizer;
package io.onedev.server.ci.job.log;
import javax.annotation.Nullable;
import io.onedev.commons.launcher.loader.ExtensionPoint;
import io.onedev.server.ci.job.log.LogLevel;
@ExtensionPoint
public interface LogNormalizer {

View File

@ -77,7 +77,7 @@ import io.onedev.commons.utils.stringmatch.Matcher;
import io.onedev.server.OneDev;
import io.onedev.server.cache.CommitInfoManager;
import io.onedev.server.ci.CISpec;
import io.onedev.server.ci.detector.CISpecDetector;
import io.onedev.server.ci.DefaultCISpecProvider;
import io.onedev.server.ci.job.Job;
import io.onedev.server.ci.job.param.JobParam;
import io.onedev.server.ci.job.trigger.BranchUpdateTrigger;
@ -717,11 +717,11 @@ public class Project extends AbstractEntity implements Validatable {
if (blob != null) {
ciSpecOpt = Optional.fromNullable(CISpec.parse(blob.getBytes()));
} else {
List<CISpecDetector> detectors = new ArrayList<>(OneDev.getExtensions(CISpecDetector.class));
detectors.sort(Comparator.comparing(CISpecDetector::getPriority));
List<DefaultCISpecProvider> providers = new ArrayList<>(OneDev.getExtensions(DefaultCISpecProvider.class));
providers.sort(Comparator.comparing(DefaultCISpecProvider::getPriority));
CISpec ciSpec = null;
for (CISpecDetector detector: detectors) {
ciSpec = detector.detect(this, commitId);
for (DefaultCISpecProvider provider: providers) {
ciSpec = provider.getDefaultCISpec(this, commitId);
if (ciSpec != null)
break;
}

View File

@ -23,7 +23,7 @@
<a wicket:id="link"><span wicket:id="label"></span></a>
</wicket:fragment>
<wicket:fragment wicket:id="statusFrag">
<span wicket:id="icon"></span> <span wicket:id="label"></span>
<span wicket:id="icon"></span> <a wicket:id="link"><span wicket:id="label"></span></a>
</wicket:fragment>
<wicket:fragment wicket:id="commitFrag">
<a wicket:id="hashLink" class="hash"><span wicket:id="hash"></span></a>

View File

@ -147,6 +147,12 @@ public abstract class BuildListPanel extends Panel {
return null;
}
private QueryPosition getQueryPosition(Item<ICellPopulator<Build>> cellItem) {
OddEvenItem<?> row = cellItem.findParent(OddEvenItem.class);
return new QueryPosition(parsedQueryModel.getObject().toString(), (int)buildsTable.getItemCount(),
(int)buildsTable.getCurrentPage() * WebConstants.PAGE_SIZE + row.getIndex());
}
@Override
protected void onInitialize() {
super.onInitialize();
@ -298,11 +304,8 @@ public abstract class BuildListPanel extends Panel {
Build build = rowModel.getObject();
Long buildId = build.getId();
OddEvenItem<?> row = cellItem.findParent(OddEvenItem.class);
QueryPosition position = new QueryPosition(parsedQueryModel.getObject().toString(), (int)buildsTable.getItemCount(),
(int)buildsTable.getCurrentPage() * WebConstants.PAGE_SIZE + row.getIndex());
Link<Void> link = new BookmarkablePageLink<Void>("link", BuildLogPage.class, BuildLogPage.paramsOf(build, position));
Link<Void> link = new BookmarkablePageLink<Void>("link", BuildLogPage.class,
BuildLogPage.paramsOf(build, getQueryPosition(cellItem)));
link.add(new Label("label", new AbstractReadOnlyModel<String>() {
@Override
@ -338,7 +341,8 @@ public abstract class BuildListPanel extends Panel {
@Override
public void populateItem(Item<ICellPopulator<Build>> cellItem, String componentId, IModel<Build> rowModel) {
Long buildId = rowModel.getObject().getId();
Build build = rowModel.getObject();
Long buildId = build.getId();
Fragment fragment = new Fragment(componentId, "statusFrag", BuildListPanel.this);
fragment.add(new BuildStatusIcon("icon", new LoadableDetachableModel<Status>() {
@ -357,7 +361,10 @@ public abstract class BuildListPanel extends Panel {
});
fragment.add(new Label("label", new AbstractReadOnlyModel<String>() {
Link<Void> link = new BookmarkablePageLink<Void>("link", BuildLogPage.class,
BuildLogPage.paramsOf(build, getQueryPosition(cellItem)));
link.add(new Label("label", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
@ -374,6 +381,7 @@ public abstract class BuildListPanel extends Panel {
}
});
fragment.add(link);
cellItem.add(fragment);
}
});

View File

@ -19,5 +19,6 @@
<module>server-plugin-archetype</module>
<module>server-plugin-artifact</module>
<module>server-plugin-htmlreport</module>
</modules>
<module>server-plugin-maven</module>
</modules>
</project>

View File

@ -0,0 +1,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>server-plugin-maven</artifactId>
<parent>
<groupId>io.onedev</groupId>
<artifactId>server-plugin</artifactId>
<version>3.0.0</version>
</parent>
<properties>
<moduleClass>io.onedev.server.plugin.maven.MavenModule</moduleClass>
</properties>
</project>

View File

@ -0,0 +1,106 @@
package io.onedev.server.plugin.maven;
import java.io.StringReader;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.onedev.server.ci.CISpec;
import io.onedev.server.ci.DefaultCISpecProvider;
import io.onedev.server.ci.job.Job;
import io.onedev.server.ci.job.cache.JobCache;
import io.onedev.server.ci.job.trigger.BranchUpdateTrigger;
import io.onedev.server.git.Blob;
import io.onedev.server.git.BlobIdent;
import io.onedev.server.model.Project;
public class DefaultMavenCISpecProvider implements DefaultCISpecProvider {
private static final Logger logger = LoggerFactory.getLogger(DefaultMavenCISpecProvider.class);
@Override
public CISpec getDefaultCISpec(Project project, ObjectId commitId) {
Blob blob = project.getBlob(new BlobIdent(commitId.name(), "pom.xml", FileMode.TYPE_FILE), false);
if (blob != null) {
Document document;
try {
document = new SAXReader().read(new StringReader(blob.getText().getContent()));
} catch (DocumentException e) {
logger.debug("Error parsing pom.xml (project: {}, commit: {})",
project.getName(), commitId.getName(), e);
return null;
}
String javaVersion = "1.8";
// Use XPath with localname as POM project element may contain xmlns definition
Node node = document.selectSingleNode("//*[local-name()='maven.compiler.source']");
if (node != null) {
javaVersion = node.getText().trim();
} else {
node = document.selectSingleNode("//*[local-name()='artifactId' and text()='maven-compiler-plugin']");
if (node != null)
node = node.getParent().selectSingleNode(".//*[local-name()='source']");
if (node != null) {
javaVersion = node.getText().trim();
} else {
// detect java version from Spring initializer generated projects
node = document.selectSingleNode("//*[local-name()='java.version']");
if (node != null)
javaVersion = node.getText().trim();
}
}
CISpec ciSpec = new CISpec();
Job job = new Job();
job.setName("ci");
switch (javaVersion) {
case "13":
job.setEnvironment("maven:3.6.1-jdk-13");
break;
case "12":
job.setEnvironment("maven:3.6.1-jdk-12");
break;
case "11":
job.setEnvironment("maven:3.6.1-jdk-11");
break;
default:
job.setEnvironment("maven:3.6.1-jdk-8");
}
job.setCommands(""
+ "buildVersion=$(mvn org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate -Dexpression=project.version -q -DforceStdout)\n"
+ "echo \"##onedev[SetBuildVersion '$buildVersion']\"\n"
+ "echo\n"
+ "mvn clean test");
BranchUpdateTrigger trigger = new BranchUpdateTrigger();
job.getTriggers().add(trigger);
JobCache cache = new JobCache();
cache.setKey("maven-local-repository");
cache.setPath("/root/.m2");
job.getCaches().add(cache);
ciSpec.getJobs().add(job);
return ciSpec;
} else {
return null;
}
}
@Override
public int getPriority() {
return DEFAULT_PRIORITY;
}
}

View File

@ -1,11 +1,12 @@
package io.onedev.server.ci.job.log.normalizer;
package io.onedev.server.plugin.maven;
import javax.inject.Singleton;
import io.onedev.server.ci.job.log.LogLevel;
import io.onedev.server.ci.job.log.LogNormalizer;
@Singleton
public class MavenNormalizer implements LogNormalizer {
public class MavenLogNormalizer implements LogNormalizer {
@Override
public Result normalize(String message) {

View File

@ -0,0 +1,22 @@
package io.onedev.server.plugin.maven;
import io.onedev.commons.launcher.loader.AbstractPluginModule;
import io.onedev.server.ci.DefaultCISpecProvider;
import io.onedev.server.ci.job.log.LogNormalizer;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
*
*/
public class MavenModule extends AbstractPluginModule {
@Override
protected void configure() {
super.configure();
// put your guice bindings here
contribute(DefaultCISpecProvider.class, DefaultMavenCISpecProvider.class);
contribute(LogNormalizer.class, MavenLogNormalizer.class);
}
}

View File

@ -23,6 +23,11 @@
<artifactId>server-plugin-htmlreport</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.onedev</groupId>
<artifactId>server-plugin-maven</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<properties>
<executables>bin/*.sh, boot/wrapper-*</executables>

View File

@ -1,11 +1,9 @@
package io.onedev.server.product;
import java.io.IOException;
public class Test {
@org.junit.Test
public void test() throws IOException {
public void test() {
}
}