一、前言
这段时间参与的
Devops
平台需要对接Jenkins
平台,以java
方式调用Jenkins API
达到对Jenkins
平台上面的若干任务进行管理,官方Jenkins-client
下面只提供了FreeStyle
风格(也就是普通任务类型)和Maven
风格的任务API
,并未提供多配置类型的任务的API
,所以就对比源码和API
文档,仿照写了一份,也能够拿到任务的构建历史,任务配置信息,还有构建归档的文件等等。所以在此记录一下
二、API
1、AllMatrixBuilds
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/15 11:42
*/
public class AllMatrixBuilds extends BaseModel {
private List<MatrixBuild> allBuilds;
public AllMatrixBuilds() {
}
public List<MatrixBuild> getAllBuilds() {
return this.allBuilds;
}
}
2、HealthReport
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/15 15:03
*/
public class HealthReport {
private String description;
private String iconClassName;
private String iconUrl;
private Integer score;
public void setDescription(String description) {
this.description = description;
}
public void setIconClassName(String iconClassName) {
this.iconClassName = iconClassName;
}
public void setIconUrl(String iconUrl) {
this.iconUrl = iconUrl;
}
public void setScore(Integer score) {
this.score = score;
}
@Override
public String toString() {
return "HealthReport{" + "\n" +
"description='" + description + '\'' + "\n" +
"iconClassName='" + iconClassName + '\'' + "\n" +
"iconUrl='" + iconUrl + '\'' + "\n" +
"score=" + score + "\n" +
'}';
}
}
3、MatrixBuild
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/14 20:51
*/
public class MatrixBuild extends Build {
public static final MatrixBuild BUILD_HAS_NEVER_RUN = new MatrixBuild(-1, -1, "UNKNOWN");
public MatrixBuild() {
}
public MatrixBuild(Build from) {
super(from);
}
public MatrixBuild(int number, String url) {
super(number, url);
}
public MatrixBuild(int number, int queueId, String url) {
this.setNumber(number);
this.setQueueId(queueId);
this.setUrl(url);
}
@Override
public MatrixBuildWithDetails details() throws IOException {
MatrixBuildWithDetails detail = this.client.get(this.getUrl(), MatrixBuildWithDetails.class);
detail.setClient(this.client);
return detail;
}
@Override
public String toString() {
return "MatrixBuild{" + "\n" +
"number=" + super.getNumber() + "\n" +
"queueId='" + super.getQueueId() + '\'' + "\n" +
"url='" + super.getUrl() + '\'' + "\n" +
'}';
}
}
4、MatrixBuildWithDetails
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/19 17:16
*/
public class MatrixBuildWithDetails extends BuildWithDetails {
private List<Build> runs;
public List<Build> getRuns() {
for (Build build : this.runs) {
build.setClient(this.client);
}
return runs;
}
}
5、MatrixConfiguration
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/15 11:14
*/
public class MatrixConfiguration extends Job {
private String name;
private String url;
private String color;
public void setName(String name) {
this.name = name;
}
public void setUrl(String url) {
this.url = url;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String getName() {
return name;
}
@Override
public String getUrl() {
return url;
}
public String getColor() {
return color;
}
@Override
public String toString() {
return "MatrixConfiguration{" + "\n" +
"name='" + name + '\'' + "\n" +
"url='" + url + '\'' + "\n" +
"color='" + color + '\'' + "\n" +
'}';
}
}
6、MatrixJob
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/14 20:40
*/
public class MatrixJob extends Job {
public MatrixJob() {
}
public MatrixJob(String name, String url) {
super(name, url);
}
public MatrixJob(String name, String url, String fullName) {
super(name, url, fullName);
}
public MatrixJobWithDetail matrixJobDetail() throws IOException {
return this.client.get(this.getUrl(), MatrixJobWithDetail.class);
}
}
7、MatrixJobWithDetail
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/14 20:40
*/
public class MatrixJobWithDetail extends MatrixJob {
private String description;
private String displayName;
private String fullDisplayName;
private String fullName;
private String name;
private String url;
private boolean buildable;
private List<MatrixBuild> builds;
private String color;
private MatrixBuild firstBuild;
private List<HealthReport> healthReport;
private boolean inQueue;
private boolean keepDependencies;
private MatrixBuild lastBuild;
private MatrixBuild lastCompletedBuild;
private MatrixBuild lastFailedBuild;
private MatrixBuild lastStableBuild;
private MatrixBuild lastSuccessfulBuild;
private MatrixBuild lastUnstableBuild;
private MatrixBuild lastUnsuccessfulBuild;
private Integer nextBuildNumber;
private QueueItem queueItem;
private boolean concurrentBuild;
private boolean disabled;
private List<Job> downstreamProjects;
private LabelWithDetails labelExpression;
private List<Job> upstreamProjects;
private List<MatrixConfiguration> activeConfigurations;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getFullDisplayName() {
return fullDisplayName;
}
public void setFullDisplayName(String fullDisplayName) {
this.fullDisplayName = fullDisplayName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public void setName(String name) {
this.name = name;
}
public void setUrl(String url) {
this.url = url;
}
public void setBuildable(boolean buildable) {
this.buildable = buildable;
}
public void setBuilds(List<MatrixBuild> builds) {
this.builds = builds;
}
public void setColor(String color) {
this.color = color;
}
public void setFirstBuild(MatrixBuild firstBuild) {
this.firstBuild = firstBuild;
}
public void setHealthReport(List<HealthReport> healthReport) {
this.healthReport = healthReport;
}
public void setInQueue(boolean inQueue) {
this.inQueue = inQueue;
}
public void setKeepDependencies(boolean keepDependencies) {
this.keepDependencies = keepDependencies;
}
public void setLastBuild(MatrixBuild lastBuild) {
this.lastBuild = lastBuild;
}
public void setLastCompletedBuild(MatrixBuild lastCompletedBuild) {
this.lastCompletedBuild = lastCompletedBuild;
}
public void setLastFailedBuild(MatrixBuild lastFailedBuild) {
this.lastFailedBuild = lastFailedBuild;
}
public void setLastStableBuild(MatrixBuild lastStableBuild) {
this.lastStableBuild = lastStableBuild;
}
public void setLastSuccessfulBuild(MatrixBuild lastSuccessfulBuild) {
this.lastSuccessfulBuild = lastSuccessfulBuild;
}
public void setLastUnstableBuild(MatrixBuild lastUnstableBuild) {
this.lastUnstableBuild = lastUnstableBuild;
}
public void setLastUnsuccessfulBuild(MatrixBuild lastUnsuccessfulBuild) {
this.lastUnsuccessfulBuild = lastUnsuccessfulBuild;
}
public void setNextBuildNumber(Integer nextBuildNumber) {
this.nextBuildNumber = nextBuildNumber;
}
public void setQueueItem(QueueItem queueItem) {
this.queueItem = queueItem;
}
public void setConcurrentBuild(boolean concurrentBuild) {
this.concurrentBuild = concurrentBuild;
}
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
public void setDownstreamProjects(List<Job> downstreamProjects) {
this.downstreamProjects = downstreamProjects;
}
public void setLabelExpression(LabelWithDetails labelExpression) {
this.labelExpression = labelExpression;
}
public void setUpstreamProjects(List<Job> upstreamProjects) {
this.upstreamProjects = upstreamProjects;
}
public void setActiveConfigurations(List<MatrixConfiguration> activeConfigurations) {
this.activeConfigurations = activeConfigurations;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public String getName() {
return name;
}
@Override
public String getUrl() {
return url;
}
public boolean isBuildable() {
return buildable;
}
public String getColor() {
return color;
}
public List<HealthReport> getHealthReport() {
return healthReport;
}
public boolean isInQueue() {
return inQueue;
}
public boolean isKeepDependencies() {
return keepDependencies;
}
public Integer getNextBuildNumber() {
return nextBuildNumber;
}
public QueueItem getQueueItem() {
return queueItem;
}
public boolean isConcurrentBuild() {
return concurrentBuild;
}
public boolean isDisabled() {
return disabled;
}
public LabelWithDetails getLabelExpression() {
return labelExpression;
}
public List<MatrixConfiguration> getActiveConfigurations() {
return activeConfigurations;
}
public List<MatrixBuild> getBuilds() {
return this.builds == null ? Collections.emptyList() : this.builds.stream().map(MatrixJobWithDetail.this::buildWithClient).collect(Collectors.toList());
}
public List<MatrixBuild> getAllBuilds() throws IOException {
String path = "/";
try {
List<MatrixBuild> builds = this.client.get(path + "job/" + EncodingUtils.encode(this.getName()) + "?tree=allBuilds[number[*],url[*],queueId[*]]", AllMatrixBuilds.class).getAllBuilds();
return builds == null ? Collections.emptyList() : builds.stream().map(MatrixJobWithDetail.this::buildWithClient).collect(Collectors.toList());
} catch (HttpResponseException var3) {
if (var3.getStatusCode() == 404) {
return null;
} else {
throw var3;
}
}
}
public List<MatrixBuild> getAllBuilds(Range range) throws IOException {
String path = "/job/" + EncodingUtils.encode(this.getName()) + "?tree=allBuilds[number[*],url[*],queueId[*]]";
try {
List<MatrixBuild> builds = this.client.get(path + range.getRangeString(), AllMatrixBuilds.class).getAllBuilds();
return builds == null ? Collections.emptyList() : builds.stream().map(MatrixJobWithDetail.this::buildWithClient).collect(Collectors.toList());
} catch (HttpResponseException var4) {
if (var4.getStatusCode() == 404) {
return null;
} else {
throw var4;
}
}
}
public MatrixBuild getFirstBuild() {
return this.firstBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.firstBuild);
}
public MatrixBuild getLastStableBuild() {
return this.lastStableBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastStableBuild);
}
public MatrixBuild getLastBuild() {
return this.lastBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastBuild);
}
public MatrixBuild getLastCompletedBuild() {
return this.lastCompletedBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastCompletedBuild);
}
public MatrixBuild getLastFailedBuild() {
return this.lastFailedBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastFailedBuild);
}
public MatrixBuild getLastSuccessfulBuild() {
return this.lastSuccessfulBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastSuccessfulBuild);
}
public MatrixBuild getLastUnstableBuild() {
return this.lastUnstableBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastUnstableBuild);
}
public MatrixBuild getLastUnsuccessfulBuild() {
return this.lastUnsuccessfulBuild == null ? MatrixBuild.BUILD_HAS_NEVER_RUN : this.buildWithClient(this.lastUnsuccessfulBuild);
}
private MatrixBuild buildWithClient(MatrixBuild from) {
MatrixBuild ret = new MatrixBuild(from);
ret.setClient(this.client);
return ret;
}
public List<Job> getDownstreamProjects() {
return this.downstreamProjects == null ? Collections.emptyList() : Lists.transform(this.downstreamProjects, new MatrixJobWithDetail.MatrixJobWithClient());
}
public List<Job> getUpstreamProjects() {
return this.upstreamProjects == null ? Collections.emptyList() : Lists.transform(this.upstreamProjects, new MatrixJobWithDetail.MatrixJobWithClient());
}
@Override
public String toString() {
return "MatrixJobWithDetail{" + "\n" +
"description='" + description + '\'' + "\n" +
"displayName='" + displayName + '\'' + "\n" +
"fullDisplayName='" + fullDisplayName + '\'' + "\n" +
"fullName='" + fullName + '\'' + "\n" +
"fullName='" + fullName + '\'' + "\n" +
"name='" + name + '\'' + "\n" +
"url='" + url + '\'' + "\n" +
"buildable=" + buildable + "\n" +
"builds=" + builds + "\n" +
"color='" + color + '\'' + "\n" +
"firstBuild=" + firstBuild + "\n" +
"healthReport=" + healthReport + "\n" +
"inQueue=" + inQueue + "\n" +
"keepDependencies=" + keepDependencies + "\n" +
"lastBuild=" + lastBuild + "\n" +
"lastCompletedBuild=" + lastCompletedBuild + "\n" +
"lastFailedBuild=" + lastFailedBuild + "\n" +
"lastStableBuild=" + lastStableBuild + "\n" +
"lastSuccessfulBuild=" + lastSuccessfulBuild + "\n" +
"lastUnstableBuild=" + lastUnstableBuild + "\n" +
"lastUnsuccessfulBuild=" + lastUnsuccessfulBuild + "\n" +
"nextBuildNumber=" + nextBuildNumber + "\n" +
"queueItem=" + queueItem + "\n" +
"concurrentBuild=" + concurrentBuild + "\n" +
"disabled=" + disabled + "\n" +
"downstreamProjects=" + downstreamProjects + "\n" +
"labelExpression=" + labelExpression + "\n" +
"upstreamProjects=" + upstreamProjects + "\n" +
"activeConfigurations=" + activeConfigurations + "\n" +
'}';
}
private class MatrixJobWithClient implements Function<Job, Job> {
private MatrixJobWithClient() {
}
@Override
public Job apply(Job job) {
assert job != null;
job.setClient(MatrixJobWithDetail.this.client);
return job;
}
}
}
8、MatrixJobJenkinsServer
/**
* @author PengHuAnZhi
* @ProjectName Jenkins API Demo
* @Description TODO
* @time 2021/10/14 21:05
*/
public class MatrixJobJenkinsServer extends JenkinsServer {
private final Logger MATRIX_LOGGER;
private final JenkinsHttpConnection MATRIX_CLIENT;
public MatrixJobJenkinsServer(URI serverUri) {
this(new JenkinsHttpClient(serverUri));
}
public MatrixJobJenkinsServer(URI serverUri, String username, String passwordOrToken) {
this(new JenkinsHttpClient(serverUri, username, passwordOrToken));
}
public MatrixJobJenkinsServer(JenkinsHttpConnection client) {
super(client);
this.MATRIX_LOGGER = LoggerFactory.getLogger(this.getClass());
this.MATRIX_CLIENT = client;
}
/**
* @param jobName 任务名称
* @return MatrixJobWithDetail
* @description 获取MatrixJob
* @author PengHuAnZhi
* @date 2021/10/14 21:08
*/
public MatrixJobWithDetail getMatrixJob(String jobName) throws IOException {
return this.getMatrixJob((FolderJob) null, UrlUtils.toFullJobPath(jobName));
}
private MatrixJobWithDetail getMatrixJob(FolderJob folder, String jobName) throws IOException {
try {
MatrixJobWithDetail job = this.MATRIX_CLIENT.get(UrlUtils.toJobBaseUrl(folder, jobName), MatrixJobWithDetail.class);
job.setClient(this.MATRIX_CLIENT);
return job;
} catch (HttpResponseException var4) {
this.MATRIX_LOGGER.debug("getMatrixJob(jobName={}) status={}", jobName, var4.getStatusCode());
if (var4.getStatusCode() == 404) {
return null;
} else {
throw var4;
}
}
}
}
三、测试
其他的直接调用测就可以了,主要是测了拿取归档文件
/**
* @param jobName 任务名称
* @param buildNumber 构建序号
* @description 获取多配置任务产出文件
* @author PengHuAnZhi
* @date 2021/10/14 21:01
*/
private void getMatrixJobBuildArtifact(String jobName, int buildNumber) {
try {
MatrixJobWithDetail matrixJobWithDetail = matrixJobServer.getMatrixJob(jobName);
List<MatrixBuild> matrixBuilds = matrixJobWithDetail.getAllBuilds().stream().filter(build -> build.getNumber() == buildNumber).collect(Collectors.toList());
if (matrixBuilds.size() != 1) {
throw new Exception("获取构建失败");
}
MatrixBuildWithDetails matrixBuild = matrixBuilds.get(0).details();
List<Build> runs = matrixBuild.getRuns();
BuildWithDetails details = runs.get(0).details();
List<Artifact> artifacts = details.getArtifacts();
for (Artifact artifact : artifacts) {
String urlBuilder = details.getUrl() + "artifact/" +
artifact.getFileName();
URI uri = new URI(urlBuilder);
InputStream inputStream = client.getFile(uri);
File file = new File("C:\\Users\\Administrator\\Desktop\\" + artifact.getFileName());
FileOutputStream outputStream = new FileOutputStream(file, true);
byte[] bytes = new byte[inputStream.available()];
int ch;
while ((ch = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, ch);
}
inputStream.close();
outputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}