Skip to content

Commit 976bcfa

Browse files
omer-azmonGitHub Enterprise
authored and
GitHub Enterprise
committed
Merge pull request jenkinsci#3 from dev-build/feature-fix-source-detection
Feature fix source detection
2 parents 50dfa31 + 4cb2b1e commit 976bcfa

28 files changed

+1784
-131
lines changed

Jenkinsfile.intuit

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
def docker_url = 'docker.intuit.com/docker-rmt'
2+
def ibpMavenSettingsFileCredential = 'ibp-maven-settings-file'
3+
def assetId = '1298180184892679033'
4+
5+
pipeline {
6+
agent {
7+
kubernetes {
8+
label "coverage-plugin-${UUID.randomUUID().toString()}"
9+
defaultContainer "maven"
10+
yaml """
11+
apiVersion: v1
12+
kind: Pod
13+
spec:
14+
containers:
15+
- name: maven
16+
image: '${docker_url}/maven:3.8.5-openjdk-11'
17+
command:
18+
- cat
19+
tty: true
20+
"""
21+
}
22+
}
23+
environment {
24+
CODE_COV_TOKEN = credentials('ibp-codecov-token')
25+
IBP_MAVEN_SETTINGS_FILE = credentials("${ibpMavenSettingsFileCredential}")
26+
}
27+
options {
28+
buildDiscarder(logRotator(daysToKeepStr: '30', numToKeepStr: '50', artifactNumToKeepStr: '30'))
29+
timestamps()
30+
}
31+
32+
stages {
33+
stage('deploy') {
34+
when {
35+
beforeInput true
36+
allOf {
37+
not { changelog '.*^\\[maven-release-plugin\\].+$' }
38+
not { branch 'master' }
39+
}
40+
}
41+
steps {
42+
container('maven') {
43+
sh '''
44+
export M3_HOME=${MAVEN_HOME}/bin
45+
cd plugin
46+
mvn -s ${IBP_MAVEN_SETTINGS_FILE} clean deploy -B -U
47+
'''
48+
}
49+
}
50+
post {
51+
always {
52+
jacoco exclusionPattern: "**/*Test*", inclusionPattern: "**/*.class,**/*.java"
53+
}
54+
}
55+
}
56+
stage('release') {
57+
when {
58+
beforeInput true
59+
allOf {
60+
not { changelog '.*^\\[maven-release-plugin\\].+$' }
61+
branch 'master'
62+
}
63+
}
64+
environment {
65+
GITHUB_CREDENTIALS = credentials("ibp-dev")
66+
GITHUB_USER = "${env.GITHUB_CREDENTIALS_USR}"
67+
GITHUB_TOKEN = "${env.GITHUB_CREDENTIALS_PSW}"
68+
}
69+
steps {
70+
container('maven') {
71+
sh '''
72+
echo "https://${GITHUB_USER}:${GITHUB_TOKEN}@github.intuit.com" >> /tmp/gitcredfile
73+
git config --global user.name "${GITHUB_USER}"
74+
git config --global user.email "[email protected]"
75+
git config --global credential.helper "store --file=/tmp/gitcredfile"
76+
export M3_HOME=${MAVEN_HOME}/bin
77+
cd plugin
78+
mvn -s ${IBP_MAVEN_SETTINGS_FILE} -Dusername=${GITHUB_USER} -Dpassword=${GITHUB_TOKEN} release:clean release:prepare release:perform -B;
79+
'''
80+
}
81+
}
82+
}
83+
84+
stage('coverage') {
85+
when {
86+
beforeInput true
87+
not { changelog '.*^\\[maven-release-plugin\\].+$' }
88+
}
89+
steps {
90+
container('maven') {
91+
sh '''
92+
curl -s https://codecov.tools.a.intuit.com/bash | bash -s - -t ${CODE_COV_TOKEN}
93+
'''
94+
95+
/* IQ Server */
96+
nexusPolicyEvaluation iqApplication: "${assetId}", iqStage: 'build'
97+
}
98+
}
99+
}
100+
101+
102+
}
103+
}

plugin/pom.xml

+72-14
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,29 @@
99
<relativePath />
1010
</parent>
1111

12+
<!-- START original. Changed for Intuit ONLY
1213
<groupId>io.jenkins.plugins</groupId>
1314
<artifactId>coverage</artifactId>
1415
<version>${revision}${changelist}</version>
1516
<packaging>hpi</packaging>
17+
-->
1618

19+
<groupId>com.intuit.dev.build.ibp.plugins</groupId>
20+
<artifactId>coverage</artifactId>
1721
<name>Coverage Plugin</name>
22+
<version>1.11.16-SNAPSHOT</version>
23+
<packaging>hpi</packaging>
1824
<description>Collects reports of code coverage or mutation coverage tools and visualizes the results. It has support
1925
for the following report formats: JaCoCo, Cobertura, and PIT.</description>
2026
<url>https://github.com/jenkinsci/coverage-plugin</url>
2127

2228
<properties>
2329
<revision>1.11.0</revision>
2430
<changelist>-SNAPSHOT</changelist>
25-
<gitHubRepo>jenkinsci/coverage-plugin</gitHubRepo>
31+
<gitHubRepo>https://github.com/jenkinsci/coverage-plugin</gitHubRepo>
2632

2733
<!-- Library Dependencies Versions -->
28-
<coverage-model.version>0.39.0</coverage-model.version>
34+
<coverage-model.version>0.42.36</coverage-model.version>
2935
<jsoup.version>1.17.2</jsoup.version>
3036

3137
<!-- Jenkins Plug-in Dependencies Versions -->
@@ -55,6 +61,16 @@
5561
</license>
5662
</licenses>
5763

64+
<dependencyManagement>
65+
<dependencies>
66+
<dependency>
67+
<groupId>edu.hm.hafner</groupId>
68+
<artifactId>coverage-model</artifactId>
69+
<version>${coverage-model.version}</version>
70+
</dependency>
71+
</dependencies>
72+
</dependencyManagement>
73+
5874
<dependencies>
5975
<dependency>
6076
<groupId>edu.hm.hafner</groupId>
@@ -310,10 +326,45 @@
310326
</exclusion>
311327
</exclusions>
312328
</dependency>
329+
<dependency>
330+
<groupId>org.jetbrains</groupId>
331+
<artifactId>annotations</artifactId>
332+
<version>17.0.0</version>
333+
<scope>compile</scope>
334+
</dependency>
313335
</dependencies>
314336

315337
<build>
316338
<plugins>
339+
<plugin>
340+
<groupId>org.apache.maven.plugins</groupId>
341+
<artifactId>maven-enforcer-plugin</artifactId>
342+
<configuration>
343+
<rules>
344+
<requireUpperBoundDeps>
345+
<excludes combine.children="append">
346+
<exclude>org.apache.maven.reporting:maven-reporting-api</exclude>
347+
<exclude>org.apache.maven.doxia:doxia-sink-api</exclude>
348+
<exclude>org.apache.maven.doxia:doxia-logging-api</exclude>
349+
<exclude>org.apache.maven:maven-plugin-api</exclude>
350+
<exclude>org.codehaus.plexus:plexus-classworlds</exclude>
351+
</excludes>
352+
</requireUpperBoundDeps>
353+
</rules>
354+
<fail>false</fail>
355+
</configuration>
356+
</plugin>
357+
<plugin>
358+
<groupId>org.apache.maven.plugins</groupId>
359+
<artifactId>maven-surefire-plugin</artifactId>
360+
<configuration>
361+
<useSystemClassLoader>false</useSystemClassLoader>
362+
<!-- Sets the VM argument line used when unit tests are run. -->
363+
<!--suppress UnresolvedMavenProperty -->
364+
<argLine>${surefireArgLine}</argLine>
365+
<!-- Excludes integration tests when unit tests are run. -->
366+
</configuration>
367+
</plugin>
317368
<plugin>
318369
<groupId>org.assertj</groupId>
319370
<artifactId>assertj-assertions-generator-maven-plugin</artifactId>
@@ -413,27 +464,34 @@
413464
</profiles>
414465

415466
<scm>
416-
<connection>scm:git:https://github.com/${gitHubRepo}.git</connection>
417-
<developerConnection>scm:git:[email protected]:${gitHubRepo}.git</developerConnection>
418-
<url>https://github.com/${gitHubRepo}</url>
419-
<tag>${scmTag}</tag>
467+
<connection>scm:git:https://${env.GIT_USERNAME}:${env.GIT_PASSWORD}@github.intuit.com/dev-build/coverage-plugin.git</connection>
468+
<developerConnection>scm:git:https://${ env.GIT_USERNAME}:${env.GIT_PASSWORD}@github.intuit.com/dev-build/coverage-plugin.git</developerConnection>
469+
<tag>HEAD</tag>
420470
</scm>
421471

422472
<repositories>
423473
<repository>
424-
<id>repo.jenkins-ci.org</id>
425-
<url>https://repo.jenkins-ci.org/public/</url>
426-
</repository>
427-
<repository>
428-
<id>incrementals.jenkins-ci.org</id>
429-
<url>https://repo.jenkins-ci.org/incrementals/</url>
474+
<id>central-mirror</id>
475+
<url>https://artifact.intuit.com/artifactory/maven-proxy</url>
430476
</repository>
431477
</repositories>
478+
432479
<pluginRepositories>
433480
<pluginRepository>
434-
<id>repo.jenkins-ci.org</id>
435-
<url>https://repo.jenkins-ci.org/public/</url>
481+
<id>central-mirror</id>
482+
<url>https://artifact.intuit.com/artifactory/maven-proxy</url>
436483
</pluginRepository>
437484
</pluginRepositories>
438485

486+
<distributionManagement>
487+
<repository>
488+
<id>scm.int.rel.repo</id>
489+
<url>https://nexus.intuit.com/nexus/content/repositories/IBP.Intuit-Releases</url>
490+
</repository>
491+
<snapshotRepository>
492+
<id>scm.dev.snap.repo</id>
493+
<url>https://nexus.intuit.com/nexus/content/repositories/IBP.Intuit-Snapshots</url>
494+
</snapshotRepository>
495+
</distributionManagement>
496+
439497
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package io.jenkins.plugins.coverage.metrics.steps;
2+
3+
import edu.hm.hafner.util.FilteredLog;
4+
import hudson.FilePath;
5+
import hudson.remoting.VirtualChannel;
6+
import io.jenkins.plugins.prism.SourceDirectoryFilter;
7+
import io.jenkins.plugins.util.RemoteResultWrapper;
8+
import jenkins.MasterToSlaveFileCallable;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.io.Serializable;
14+
import java.util.ArrayList;
15+
import java.util.Objects;
16+
import java.util.Set;
17+
import java.util.Stack;
18+
19+
public class AgentSourceFilesFetcher {
20+
private final FilePath workspace;
21+
private final FilteredLog log;
22+
23+
public AgentSourceFilesFetcher(FilePath workspace, FilteredLog log) {
24+
this.workspace = workspace;
25+
this.log = log;
26+
}
27+
28+
public AgentSourceFilesList fetch(Set<String> permittedSourceDirectories, Set<String> requestedSourceDirectories)
29+
throws IOException, InterruptedException {
30+
RemoteResultWrapper<AgentSourceFilesList> actResult = workspace.act(
31+
new AgentSourceFileListCallable(permittedSourceDirectories, requestedSourceDirectories)
32+
);
33+
log.merge(actResult);
34+
log.logInfo("Successfully fetched all source paths provided");
35+
return actResult.getResult();
36+
}
37+
/**
38+
* Callable to fetch file list from Agent (slave)
39+
*/
40+
// package-protected for testing
41+
static class AgentSourceFileListCallable extends MasterToSlaveFileCallable<RemoteResultWrapper<AgentSourceFilesList>> {
42+
private final Set<String> permittedSourceDirectories;
43+
private final Set<String> requestedSourceDirectories;
44+
45+
/**
46+
* @param requestedSourceDirectories the requested relative and absolute source directories (in the step configuration)
47+
* @param permittedSourceDirectories the directories that may be searched
48+
*/
49+
public AgentSourceFileListCallable(Set<String> permittedSourceDirectories, Set<String> requestedSourceDirectories) {
50+
super();
51+
this.permittedSourceDirectories = permittedSourceDirectories;
52+
this.requestedSourceDirectories = requestedSourceDirectories;
53+
}
54+
55+
@Override
56+
public RemoteResultWrapper<AgentSourceFilesList> invoke(File workspaceFile, VirtualChannel channel) {
57+
FilteredLog log = new FilteredLog("Errors while resolving source files on agent:");
58+
59+
Set<String> sourceDirectories = new SourceDirectoryFilter().getPermittedSourceDirectories(workspaceFile.getAbsolutePath(),
60+
permittedSourceDirectories, requestedSourceDirectories, log);
61+
if (sourceDirectories.isEmpty()) {
62+
log.logInfo("Searching for source code files in root of workspace '%s'", workspaceFile);
63+
} else if (sourceDirectories.size() > 1) {
64+
log.logInfo("Searching for source code files in '%s'", formatDirectoryList(sourceDirectories));
65+
} else {
66+
log.logInfo("Searching for source code files in workspace: '%s' ", workspaceFile);
67+
}
68+
69+
// Ensure our "List" class type supports serializable
70+
AgentSourceFilesList agentSourceFilesList = buildSourceFilesList(workspaceFile.getAbsolutePath(), sourceDirectories);
71+
72+
var result = new RemoteResultWrapper<>(agentSourceFilesList, "Errors during source files listing:");
73+
74+
result.merge(log);
75+
76+
return result;
77+
}
78+
79+
@NotNull
80+
private static String formatDirectoryList(Set<String> sourceDirectories) {
81+
final StringBuilder sb;
82+
sb = new StringBuilder("[");
83+
sourceDirectories.forEach(d -> {
84+
sb.append("\n");
85+
sb.append(d);
86+
});
87+
sb.append("\n]");
88+
return sb.toString();
89+
}
90+
91+
private AgentSourceFilesList buildSourceFilesList(String workspacePath, Set<String> sourceDirectories) {
92+
// Populate search directory stack with source directories
93+
final Stack<File> directoryStack = new Stack<>();
94+
sourceDirectories.stream()
95+
.map(File::new)
96+
.filter(f -> f.exists() && f.isDirectory())
97+
.forEach(directoryStack::push);
98+
99+
// If no source directories are found in the workspace, use workspace root as search starting point
100+
if (directoryStack.isEmpty()) {
101+
directoryStack.push(new File(workspacePath));
102+
}
103+
104+
// Walk all directories and subdirectories and create a mapping for each file found
105+
ArrayList<String> sourceFilesList = new ArrayList<>();
106+
while (!directoryStack.empty() && directoryStack.peek() != null) {
107+
File f = directoryStack.pop();
108+
File[] fileList = f.listFiles();
109+
if (fileList == null) continue;
110+
for (File child : fileList) {
111+
if (child.isDirectory()) {
112+
directoryStack.push(child);
113+
} else { // child.isFile()
114+
sourceFilesList.add(child.getAbsolutePath());
115+
}
116+
}
117+
}
118+
return new AgentSourceFilesList(workspacePath, sourceFilesList);
119+
}
120+
}
121+
122+
public static class AgentSourceFilesList implements Serializable {
123+
private final String workspacePath;
124+
private final ArrayList<String> sourceFilesList;
125+
126+
public AgentSourceFilesList(String workspacePath, ArrayList<String> sourceFilesList) {
127+
this.workspacePath = workspacePath;
128+
this.sourceFilesList = sourceFilesList;
129+
}
130+
131+
public String getWorkspacePath() {
132+
return workspacePath;
133+
}
134+
135+
public ArrayList<String> getSourceFilesList() {
136+
return sourceFilesList;
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)