下面列出了怎么用hudson.model.CauseAction的API类实例代码及写法,或者点击链接到github查看源代码。
private static Run getUpstreamBuild(@Nonnull Run build) {
CauseAction causeAction = build.getAction(CauseAction.class);
if (causeAction == null) {
return null;
}
for (Cause cause : causeAction.getCauses()) {
if (cause instanceof Cause.UpstreamCause) {
Cause.UpstreamCause upstreamCause = (Cause.UpstreamCause) cause;
Job upstreamJob =
Jenkins.getInstance().getItemByFullName(upstreamCause.getUpstreamProject(), Job.class);
// We want to ignore rebuilds, rebuilds have the same parent as
// original build, see BuildCache#updateCache().
if (upstreamJob == null || build.getParent() == upstreamJob) {
continue;
}
return upstreamJob.getBuildByNumber(upstreamCause.getUpstreamBuild());
}
}
return null;
}
@Test
public void testPipelineQueue() throws Exception {
FreeStyleProject p1 = j.createFreeStyleProject("pipeline1");
p1.setConcurrentBuild(true);
p1.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("test","test")));
p1.getBuildersList().add(new Shell("echo hello!\nsleep 300"));
p1.scheduleBuild2(0).waitForStart();
p1.scheduleBuild2(0).waitForStart();
Jenkins.getInstance().getQueue().schedule(p1, 0, new ParametersAction(new StringParameterValue("test","test1")), new CauseAction(new Cause.UserIdCause()));
Jenkins.getInstance().getQueue().schedule(p1, 0, new ParametersAction(new StringParameterValue("test","test2")), new CauseAction(new Cause.UserIdCause()));
List queue = request().get("/organizations/jenkins/pipelines/pipeline1/queue").build(List.class);
Assert.assertEquals(2, queue.size());
Assert.assertEquals(4, ((Map) queue.get(0)).get("expectedBuildNumber"));
Assert.assertEquals(3, ((Map) queue.get(1)).get("expectedBuildNumber"));
Assert.assertEquals("Waiting for next available executor", ((Map) queue.get(0)).get("causeOfBlockage"));
Assert.assertEquals("Waiting for next available executor", ((Map) queue.get(1)).get("causeOfBlockage"));
Run r = QueueUtil.getRun(p1, Long.parseLong((String)((Map)queue.get(0)).get("id")));
assertNull(r); //its not moved out of queue yet
}
/**
* Cancel previous builds for specified PR id.
*/
private static boolean cancelQueuedBuildByBranchName(final String branch) {
Queue queue = getJenkinsInstance().getQueue();
for (Queue.Item item : queue.getItems()) {
Optional<Cause> cause = from(item.getAllActions())
.filter(instanceOf(CauseAction.class))
.transformAndConcat(new CausesFromAction())
.filter(instanceOf(GitHubBranchCause.class))
.firstMatch(new CauseHasBranch(branch));
if (cause.isPresent()) {
queue.cancel(item);
return true;
}
}
return false;
}
@Test
public void should_get_cause_from_dbObject() throws Exception {
BasicDBObject cause1DbObject = new BasicDBObject("cause1", "cause1");
DBObject causes = new BasicDBObjectBuilder().add("causes", Arrays.asList(cause1DbObject)).get();
Mapper mapper = Mockito.mock(Mapper.class);
Cause cause1 = new NullBuildCause();
when(mapper.fromDBObject(null, cause1DbObject, null)).thenReturn(cause1);
CauseActionConverter converter = new CauseActionConverter();
converter.setMapper(mapper);
CauseAction action = converter.decode(CauseAction.class, causes, Mockito.mock(MappedField.class));
Assert.assertEquals(1, action.getCauses().size());
Assert.assertEquals(cause1, action.getCauses().get(0));
}
@Test
public void should_convert_cause_action_to_old_format() throws Exception {
Cause cause1 = new NullBuildCause();
Mapper mapper = Mockito.mock(Mapper.class);
when(mapper.toDBObject(cause1)).thenReturn(new BasicDBObject("cause1", "cause1"));
CauseAction causeAction = new CauseAction(cause1);
CauseActionConverter converter = new CauseActionConverter();
converter.setMapper(mapper);
DBObject dbObject = (DBObject) converter.encode(causeAction, null);
Assert.assertEquals(dbObject.get("className"), CauseAction.class.getName());
Assert.assertNotNull(dbObject.get("causes"));
List dbCauses = ((List) dbObject.get("causes"));
Assert.assertEquals(1, dbCauses.size());
Assert.assertEquals("cause1", ((BasicDBObject) dbCauses.get(0)).get("cause1"));
}
/**
* Schedules a build. If build already exists in the queue and the pipeline does not
* support running multiple builds at the same time, return a reference to the existing
* build.
*
* @return Queue item.
*/
@Override
public BlueRun create(StaplerRequest request) {
job.checkPermission(Item.BUILD);
if (job instanceof Queue.Task) {
ScheduleResult scheduleResult;
List<ParameterValue> parameterValues = getParameterValue(request);
int expectedBuildNumber = job.getNextBuildNumber();
if(parameterValues.size() > 0) {
scheduleResult = Jenkins.getInstance()
.getQueue()
.schedule2((Queue.Task) job, 0, new ParametersAction(parameterValues),
new CauseAction(new Cause.UserIdCause()));
}else {
scheduleResult = Jenkins.getInstance()
.getQueue()
.schedule2((Queue.Task) job, 0, new CauseAction(new Cause.UserIdCause()));
}
// Keep FB happy.
// scheduleResult.getItem() will always return non-null if scheduleResult.isAccepted() is true
final Queue.Item item = scheduleResult.getItem();
if(scheduleResult.isAccepted() && item != null) {
return new QueueItemImpl(
pipeline.getOrganization(),
item,
pipeline,
expectedBuildNumber, pipeline.getLink().rel("queue").rel(Long.toString(item.getId())),
pipeline.getLink()
).toRun();
} else {
throw new ServiceException.UnexpectedErrorException("Queue item request was not accepted");
}
} else {
throw new ServiceException.NotImplementedException("This pipeline type does not support being queued.");
}
}
static Collection<BlueCause> getCauses(Run run) {
CauseAction action = run.getAction(CauseAction.class);
if (action == null) {
return null;
}
return getCauses(action.getCauses());
}
@Override
public BlueRun create(StaplerRequest request) {
blueMbPipeline.mbp.checkPermission(Item.BUILD);
Queue.Item queueItem = blueMbPipeline.mbp.scheduleBuild2(0, new CauseAction(new Cause.UserIdCause()));
if(queueItem == null){ // possible mbp.isBuildable() was false due to no sources fetched yet
return null;
}
return new QueueItemImpl(
blueMbPipeline.getOrganization(),
queueItem,
blueMbPipeline,
1
).toRun();
}
@Override
public BlueRun replay() {
if(isReplayable()) {
return new QueueItemImpl(this.pipeline.getOrganization(), pipeline.folder.scheduleBuild2(0,new CauseAction(new hudson.model.Cause.UserIdCause())), pipeline, 1).toRun();
}
return null;
}
@Override
public BlueRun create(StaplerRequest request) {
pipeline.folder.checkPermission(Item.BUILD);
Queue.Item queueItem = pipeline.folder.scheduleBuild2(0, new CauseAction(new Cause.UserIdCause()));
if(queueItem == null){ // possible folder.isBuildable() was false due to no repo fetched yet
return null;
}
return new QueueItemImpl(
pipeline.getOrganization(),
queueItem,
pipeline,
1
).toRun();
}
private void createAndRunPipeline(String jenkinsFileName) throws java.io.IOException, InterruptedException, java.util.concurrent.ExecutionException {
// Create the pipeline and run it
WorkflowJob scriptedSingle = createWorkflowJobWithJenkinsfile(getClass(), jenkinsFileName);
WorkflowRun scriptedSingleRun = scriptedSingle.scheduleBuild2(0, new CauseAction()).waitForStart();
j.waitForCompletion(scriptedSingleRun);
// RunListeners can sometimes be executed after the run is reported as completed. This fixes a race condition.
AnalyticsImpl analytics = (AnalyticsImpl) Analytics.get();
Assert.assertNotNull(analytics);
while (analytics.lastReq == null) {
Thread.sleep(100);
}
}
@VisibleForTesting
static Run<?, ?> getUpstreamRun(AbstractBuild build) {
CauseAction action = build.getAction(hudson.model.CauseAction.class);
if (action != null) {
Cause.UpstreamCause upstreamCause = action.findCause(hudson.model.Cause.UpstreamCause.class);
if (upstreamCause != null) {
return upstreamCause.getUpstreamRun();
}
}
return null;
}
@Test
public void getUpstreamRunIfAvailable() throws Exception {
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, null, true);
FreeStyleBuild upstream = buildWithConduit(getFetchDiffResponse(), null, null, true);
assertNull(PhabricatorBuildWrapper.getUpstreamRun(build));
List<Cause> causes = build.getAction(CauseAction.class).getCauses();
ArrayList<Cause> newCauses = new ArrayList<Cause>(causes);
newCauses.add((new Cause.UpstreamCause(upstream)));
build.replaceAction(new CauseAction(newCauses));
assertEquals(upstream, PhabricatorBuildWrapper.getUpstreamRun(build));
}
public static boolean rebuild(Run<?, ?> run) {
final QueueTaskFuture queueTaskFuture = asParameterizedJobMixIn(run.getParent())
.scheduleBuild2(
0,
run.getAction(ParametersAction.class),
run.getAction(CauseAction.class),
run.getAction(BuildBadgeAction.class)
);
return queueTaskFuture != null;
}
@Nonnull
@Override
protected List<Action> retrieveActions(@Nonnull SCMRevision revision, @CheckForNull SCMHeadEvent event,
@Nonnull TaskListener listener) throws IOException, InterruptedException {
GitHubSCMRevision gitHubSCMRevision = (GitHubSCMRevision) revision;
GitHubCause<?> cause = gitHubSCMRevision.getCause();
if (nonNull(cause)) {
List<ParameterValue> params = new ArrayList<>();
cause.fillParameters(params);
return Arrays.asList(new CauseAction(cause), new GitHubParametersAction(params));
}
return Collections.emptyList();
}
public static QueueTaskFuture schedule(Job<?, ?> job, int number, String param, int queuetPeriod) {
ParameterizedJobMixIn jobMixIn = JobInfoHelpers.asParameterizedJobMixIn(job);
GitHubPRCause cause = newGitHubPRCause().withNumber(number);
ParametersAction parametersAction = new ParametersAction(
Collections.<ParameterValue>singletonList(new StringParameterValue("value", param))
);
return jobMixIn.scheduleBuild2(queuetPeriod, new CauseAction(cause), parametersAction);
}
private void handleMergeRequest(Job<?, ?> job, PushHook hook, boolean ciSkip, BranchFilter branchFilter, GitLabClient client, MergeRequest mergeRequest) {
if (ciSkip && mergeRequest.getDescription() != null && mergeRequest.getDescription().contains("[ci-skip]")) {
LOGGER.log(Level.INFO, "Skipping MR " + mergeRequest.getTitle() + " due to ci-skip.");
return;
}
Boolean workInProgress = mergeRequest.getWorkInProgress();
if (skipWorkInProgressMergeRequest && workInProgress != null && workInProgress) {
LOGGER.log(Level.INFO, "Skip WIP Merge Request #{0} ({1})", toArray(mergeRequest.getIid(), mergeRequest.getTitle()));
return;
}
String sourceBranch = mergeRequest.getSourceBranch();
String targetBranch = mergeRequest.getTargetBranch();
if (targetBranch != null && branchFilter.isBranchAllowed(sourceBranch, targetBranch) && hook.getRef().equals("refs/heads/"+targetBranch) && sourceBranch != null) {
LOGGER.log(Level.INFO, "{0} triggered for push to target branch of open merge request #{1}.",
LoggerUtil.toArray(job.getFullName(), mergeRequest.getId()));
Branch branch = client.getBranch(mergeRequest.getSourceProjectId().toString(), sourceBranch);
Project project = client.getProject(mergeRequest.getSourceProjectId().toString());
String commit = branch.getCommit().getId();
setCommitStatusPendingIfNecessary(job, mergeRequest.getSourceProjectId(), commit, branch.getName());
List<Action> actions = Arrays.<Action>asList(new CauseAction(new GitLabWebHookCause(retrieveCauseData(hook, project, mergeRequest, branch))),
new RevisionParameterAction(commit, retrieveUrIish(hook)));
scheduleBuild(job, actions.toArray(new Action[actions.size()]));
}
}
protected Action[] createActions(Job<?, ?> job, H hook) {
ArrayList<Action> actions = new ArrayList<>();
actions.add(new CauseAction(new GitLabWebHookCause(retrieveCauseData(hook))));
try {
SCMTriggerItem item = SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(job);
GitSCM gitSCM = getGitSCM(item);
actions.add(createRevisionParameter(hook, gitSCM));
} catch (NoRevisionToBuildException e) {
LOGGER.log(Level.WARNING, "unknown handled situation, dont know what revision to build for req {0} for job {1}",
new Object[]{hook, (job != null ? job.getFullName() : null)});
}
return actions.toArray(new Action[actions.size()]);
}
@Override
public CauseAction decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
try (ACLContext _ = ACL.as(Jenkins.ANONYMOUS)) {
if (fromDBObject == null) return null;
final List causes = new ArrayList();
final List rawList = (List) ((DBObject) fromDBObject).get("causes");
for (final Object obj : rawList) {
final DBObject dbObj = (DBObject) obj;
final Object cause = getMapper().fromDBObject(optionalExtraInfo.getSubClass(), dbObj, getMapper().createEntityCache());
causes.add(cause);
}
return new CauseAction(causes);
}
}
@Override
public Object encode(final Object value, final MappedField optionalExtraInfo) {
if (value == null) return null;
final CauseAction action = (CauseAction) value;
final List causes = new BasicDBList();
for (final Object obj : action.getCauses()) {
causes.add(getMapper().toDBObject(obj));
}
return BasicDBObjectBuilder.start("causes", causes).add("className", CauseAction.class.getName()).get();
}
private Class getClass(final DBObject dbObj) {
// see if there is a className value
final String className = (String) dbObj.get(Mapper.CLASS_NAME_FIELDNAME);
if (className != null && className.equals(CauseAction.class.getName())) {
// try to Class.forName(className) as defined in the dbObject first,
// otherwise return the entityClass
try {
return Class.forName(className, true, getClassLoaderForClass(className, dbObj));
} catch (final ClassNotFoundException e) {
//Ignore if notfound
}
}
return null;
}
public void addCause(final Cause manualCause) {
final List<Cause> exisitingCauses = this.getAction(CauseAction.class).getCauses();
final ArrayList<Cause> causes = new ArrayList<>();
causes.add(manualCause);
causes.addAll(exisitingCauses);
this.replaceAction(new CauseAction(causes));
}
public boolean scheduleBuild(final List<? extends Action> actions, final Cause c) {
final List<Action> allActions = new ArrayList<>();
if (actions != null) {
allActions.addAll(actions);
}
allActions.add(new CauseAction(c));
return Jenkins.getInstance().getQueue().schedule(this, getQuietPeriod(), allActions) != null;
}
@Test
public void should_set_building_status_on_queue_enter() throws IOException {
final GHRepository githubRepository = mock(GHRepository.class);
final CommitStatusUpdateQueueListener commitStatusUpdateQueueListener = new CommitStatusUpdateQueueListener() {
@Override
protected GHRepository getGithubRepository(final DynamicProject project) {
return githubRepository;
}
@Override
protected String getJenkinsRootUrl() {
return "jenkins.root.url";
}
};
final BuildCause buildCause = mock(BuildCause.class);
final ArrayList<Action> causeActions = new ArrayList<>();
causeActions.add(new CauseAction(buildCause));
final Queue.WaitingItem queueItem = new Queue.WaitingItem(null, mock(DynamicProject.class), causeActions);
when(buildCause.getSha()).thenReturn("sha");
commitStatusUpdateQueueListener.onEnterWaiting(queueItem);
verify(githubRepository).createCommitStatus("sha", GHCommitState.PENDING, "jenkins.root.url", "Build in queue.", "DotCi/push");
}
@Override
public void isMatch() {
if (getPayload().getObjectAttributes().getNoteableType()
.equals(NoteEvent.NoteableType.MERGE_REQUEST)) {
Integer mergeRequestId = getPayload().getMergeRequest().getIid();
final Pattern mergeRequestJobNamePattern = Pattern
.compile("^MR-" + mergeRequestId + "\\b.*$",
Pattern.CASE_INSENSITIVE);
final String commentBody = getPayload().getObjectAttributes().getNote();
final String commentUrl = getPayload().getObjectAttributes().getUrl();
try (ACLContext ctx = ACL.as(ACL.SYSTEM)) {
boolean jobFound = false;
for (final SCMSourceOwner owner : SCMSourceOwners.all()) {
LOGGER.log(Level.FINEST, String.format("Source Owner: %s", owner.getFullDisplayName()));
// This is a hack to skip owners which are children of a SCMNavigator
if (owner.getFullDisplayName().contains(" » ")) {
continue;
}
for (SCMSource source : owner.getSCMSources()) {
if (!(source instanceof GitLabSCMSource)) {
continue;
}
GitLabSCMSource gitLabSCMSource = (GitLabSCMSource) source;
final GitLabSCMSourceContext sourceContext = new GitLabSCMSourceContext(
null, SCMHeadObserver.none())
.withTraits(gitLabSCMSource.getTraits());
if (!sourceContext.mrCommentTriggerEnabled()) {
continue;
}
if (gitLabSCMSource.getProjectId() == getPayload().getMergeRequest()
.getTargetProjectId() && isTrustedMember(gitLabSCMSource, sourceContext.onlyTrustedMembersCanTrigger())) {
for (Job<?, ?> job : owner.getAllJobs()) {
if (mergeRequestJobNamePattern.matcher(job.getName()).matches()) {
String expectedCommentBody = sourceContext.getCommentBody();
Pattern pattern = Pattern.compile(expectedCommentBody,
Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
if (commentBody == null || pattern.matcher(commentBody)
.matches()) {
ParameterizedJobMixIn.scheduleBuild2(job, 0,
new CauseAction(
new GitLabMergeRequestCommentCause(commentUrl)));
LOGGER.log(Level.INFO,
"Triggered build for {0} due to MR comment on {1}",
new Object[]{
job.getFullName(),
getPayload().getProject().getPathWithNamespace()
}
);
} else {
LOGGER.log(Level.INFO,
"MR comment does not match the trigger build string ({0}) for {1}",
new Object[]{expectedCommentBody, job.getFullName()}
);
}
break;
}
jobFound = true;
}
}
}
}
if (!jobFound) {
LOGGER.log(Level.INFO, "MR comment on {0} did not match any job",
new Object[]{
getPayload().getProject().getPathWithNamespace()
}
);
}
}
}
}
/**
* Handles updates of pull requests.
* @param event only PULL_REQUEST events
* @param payload payload of gh-event. Never blank
*/
@Override
protected void onEvent(GHEvent event, String payload) {
JSONObject json = JSONObject.fromObject(payload);
// Since we receive both pull request and issue comment events in this same code,
// we check first which one it is and set values from different fields
JSONObject pullRequest = json.getJSONObject("pull_request");
final String pullRequestUrl = pullRequest.getString("html_url");
Integer pullRequestId = pullRequest.getInt("number");
// Make sure the action is edited
String action = json.getString("action");
if (!ACTION_EDITED.equals(action)) {
LOGGER.log(Level.FINER, "Pull request action is not edited ({0}) for PR {1}, ignoring",
new Object[] { action, pullRequestUrl }
);
return;
}
// Set some values used below
final Pattern pullRequestJobNamePattern = Pattern.compile("^PR-" + pullRequestId + "\\b.*$",
Pattern.CASE_INSENSITIVE);
// Make sure the repository URL is valid
String repoUrl = json.getJSONObject("repository").getString("html_url");
Matcher matcher = REPOSITORY_NAME_PATTERN.matcher(repoUrl);
if (!matcher.matches()) {
LOGGER.log(Level.WARNING, "Malformed repository URL {0}", repoUrl);
return;
}
final GitHubRepositoryName changedRepository = GitHubRepositoryName.create(repoUrl);
if (changedRepository == null) {
LOGGER.log(Level.WARNING, "Malformed repository URL {0}", repoUrl);
return;
}
LOGGER.log(Level.FINE, "Received update on PR {1} for {2}", new Object[] { pullRequestId, repoUrl });
ACL.impersonate(ACL.SYSTEM, new Runnable() {
@Override
public void run() {
boolean jobFound = false;
for (final SCMSourceOwner owner : SCMSourceOwners.all()) {
for (SCMSource source : owner.getSCMSources()) {
if (!(source instanceof GitHubSCMSource)) {
continue;
}
GitHubSCMSource gitHubSCMSource = (GitHubSCMSource) source;
if (gitHubSCMSource.getRepoOwner().equalsIgnoreCase(changedRepository.getUserName()) &&
gitHubSCMSource.getRepository().equalsIgnoreCase(changedRepository.getRepositoryName())) {
for (Job<?, ?> job : owner.getAllJobs()) {
if (pullRequestJobNamePattern.matcher(job.getName()).matches()) {
if (!(job.getParent() instanceof MultiBranchProject)) {
continue;
}
boolean propFound = false;
for (BranchProperty prop : ((MultiBranchProject) job.getParent()).getProjectFactory().
getBranch(job).getProperties()) {
if (!(prop instanceof TriggerPRUpdateBranchProperty)) {
continue;
}
propFound = true;
ParameterizedJobMixIn.scheduleBuild2(job, 0,
new CauseAction(new GitHubPullRequestUpdateCause(pullRequestUrl)));
break;
}
if (!propFound) {
LOGGER.log(Level.FINE,
"Job {0} for {1}:{2}/{3} does not have a trigger PR update branch property",
new Object[] {
job.getFullName(),
changedRepository.getHost(),
changedRepository.getUserName(),
changedRepository.getRepositoryName()
}
);
}
jobFound = true;
}
}
}
}
}
if (!jobFound) {
LOGGER.log(Level.FINE, "PR update on {0}:{1}/{2} did not match any job",
new Object[] {
changedRepository.getHost(), changedRepository.getUserName(),
changedRepository.getRepositoryName()
}
);
}
}
});
}
/**
* Handles updates of pull requests.
* @param event only PULL_REQUEST_REVIEW events
* @param payload payload of gh-event. Never blank
*/
@Override
protected void onEvent(GHEvent event, String payload) {
JSONObject json = JSONObject.fromObject(payload);
JSONObject pullRequest = json.getJSONObject("pull_request");
final String pullRequestUrl = pullRequest.getString("html_url");
Integer pullRequestId = pullRequest.getInt("number");
// Set some values used below
final Pattern pullRequestJobNamePattern = Pattern.compile("^PR-" + pullRequestId + "\\b.*$",
Pattern.CASE_INSENSITIVE);
// Make sure the repository URL is valid
String repoUrl = json.getJSONObject("repository").getString("html_url");
Matcher matcher = REPOSITORY_NAME_PATTERN.matcher(repoUrl);
if (!matcher.matches()) {
LOGGER.log(Level.WARNING, "Malformed repository URL {0}", repoUrl);
return;
}
final GitHubRepositoryName changedRepository = GitHubRepositoryName.create(repoUrl);
if (changedRepository == null) {
LOGGER.log(Level.WARNING, "Malformed repository URL {0}", repoUrl);
return;
}
LOGGER.log(Level.FINE, "Received review on PR {1} for {2}", new Object[] { pullRequestId, repoUrl });
ACL.impersonate(ACL.SYSTEM, new Runnable() {
@Override
public void run() {
boolean jobFound = false;
for (final SCMSourceOwner owner : SCMSourceOwners.all()) {
for (SCMSource source : owner.getSCMSources()) {
if (!(source instanceof GitHubSCMSource)) {
continue;
}
GitHubSCMSource gitHubSCMSource = (GitHubSCMSource) source;
if (gitHubSCMSource.getRepoOwner().equalsIgnoreCase(changedRepository.getUserName()) &&
gitHubSCMSource.getRepository().equalsIgnoreCase(changedRepository.getRepositoryName())) {
for (Job<?, ?> job : owner.getAllJobs()) {
if (pullRequestJobNamePattern.matcher(job.getName()).matches()) {
if (!(job.getParent() instanceof MultiBranchProject)) {
continue;
}
boolean propFound = false;
for (BranchProperty prop : ((MultiBranchProject) job.getParent()).getProjectFactory().
getBranch(job).getProperties()) {
if (!(prop instanceof TriggerPRReviewBranchProperty)) {
continue;
}
propFound = true;
ParameterizedJobMixIn.scheduleBuild2(job, 0,
new CauseAction(new GitHubPullRequestReviewCause(pullRequestUrl)));
break;
}
if (!propFound) {
LOGGER.log(Level.FINE,
"Job {0} for {1}:{2}/{3} does not have a trigger PR review branch property",
new Object[] {
job.getFullName(),
changedRepository.getHost(),
changedRepository.getUserName(),
changedRepository.getRepositoryName()
}
);
}
jobFound = true;
}
}
}
}
}
if (!jobFound) {
LOGGER.log(Level.FINE, "PR review on {0}:{1}/{2} did not match any job",
new Object[] {
changedRepository.getHost(), changedRepository.getUserName(),
changedRepository.getRepositoryName()
}
);
}
}
});
}
@Test
public void testJobAnalytics() throws Exception {
// Freestyle jobs
j.createFreeStyleProject("freestyle1").save();
j.createFreeStyleProject("freestyle2").save();
// Matrix job
j.createProject(MatrixProject.class, "bob");
// Create single scripted pipeline
WorkflowJob scriptedSingle = createWorkflowJobWithJenkinsfile(getClass(),"JobAnalyticsTest-scripted.jenkinsfile");
WorkflowRun scriptedSingleRun = scriptedSingle.scheduleBuild2(0, new CauseAction()).waitForStart();
j.waitForCompletion(scriptedSingleRun);
// Create single declarative pipeline
WorkflowJob declarativeSingle = createWorkflowJobWithJenkinsfile(getClass(),"JobAnalyticsTest-declarative.jenkinsfile");
WorkflowRun declarativeSingleRun = declarativeSingle.scheduleBuild2(0, new CauseAction()).waitForStart();
j.waitForCompletion(declarativeSingleRun);
// Create Scripted MultiBranch
createMultiBranch(sampleRepo);
// Create Declarative MultiBranch
createMultiBranch(sampleRepo2);
AnalyticsImpl analytics = (AnalyticsImpl)Analytics.get();
Assert.assertNotNull(analytics);
JobAnalytics jobAnalytics = new JobAnalytics();
jobAnalytics.calculateAndSend();
Assert.assertNotNull(analytics.lastReq);
Assert.assertEquals("job_stats", analytics.lastReq.name);
Map<String, Object> properties = analytics.lastReq.properties;
Assert.assertEquals("singlePipelineDeclarative", 1, properties.get("singlePipelineDeclarative"));
Assert.assertEquals("singlePipelineScripted",1, properties.get("singlePipelineScripted"));
Assert.assertEquals("pipelineDeclarative",1, properties.get("pipelineDeclarative"));
Assert.assertEquals("pipelineScripted",1, properties.get("pipelineScripted"));
Assert.assertEquals("freestyle",2, properties.get("freestyle"));
Assert.assertEquals("matrix",1, properties.get("matrix"));
Assert.assertEquals("other",0, properties.get("other"));
}
/**
* The maven-war-app has a dependency on the maven-jar-app
*/
@Test
public void verify_downstream_multi_branch_pipeline_trigger() throws Exception {
System.out.println("gitRepoRule: " + gitRepoRule);
loadMavenJarProjectInGitRepo(this.gitRepoRule);
System.out.println("downstreamArtifactRepoRule: " + downstreamArtifactRepoRule);
loadMavenWarProjectInGitRepo(this.downstreamArtifactRepoRule);
String script = "node('master') {\n" +
" checkout scm\n" +
" withMaven() {\n" +
" sh 'mvn install'\n" +
" }\n" +
"}";
gitRepoRule.write("Jenkinsfile", script);
gitRepoRule.git("add", "Jenkinsfile");
gitRepoRule.git("commit", "--message=jenkinsfile");
downstreamArtifactRepoRule.write("Jenkinsfile", script);
downstreamArtifactRepoRule.git("add", "Jenkinsfile");
downstreamArtifactRepoRule.git("commit", "--message=jenkinsfile");
// TRIGGER maven-jar#1 to record that "build-maven-jar" generates this jar and install this maven jar in the local maven repo
WorkflowMultiBranchProject mavenJarPipeline = jenkinsRule.createProject(WorkflowMultiBranchProject.class, "build-maven-jar");
mavenJarPipeline.addTrigger(new WorkflowJobDependencyTrigger());
mavenJarPipeline.getSourcesList().add(new BranchSource(new GitSCMSource(null, gitRepoRule.toString(), "", "*", "", false)));
System.out.println("trigger maven-jar#1...");
WorkflowJob mavenJarPipelineMasterPipeline = WorkflowMultibranchProjectTestsUtils.scheduleAndFindBranchProject(mavenJarPipeline, "master");
assertEquals(1, mavenJarPipeline.getItems().size());
System.out.println("wait for maven-jar#1...");
jenkinsRule.waitUntilNoActivity();
assertThat(mavenJarPipelineMasterPipeline.getLastBuild().getNumber(), is(1));
// TODO check in DB that the generated artifact is recorded
// TRIGGER maven-war#1 to record that "build-maven-war" has a dependency on "build-maven-jar"
WorkflowMultiBranchProject mavenWarPipeline = jenkinsRule.createProject(WorkflowMultiBranchProject.class, "build-maven-war");
mavenWarPipeline.addTrigger(new WorkflowJobDependencyTrigger());
mavenWarPipeline.getSourcesList().add(new BranchSource(new GitSCMSource(null, downstreamArtifactRepoRule.toString(), "", "*", "", false)));
System.out.println("trigger maven-war#1...");
WorkflowJob mavenWarPipelineMasterPipeline = WorkflowMultibranchProjectTestsUtils.scheduleAndFindBranchProject(mavenWarPipeline, "master");
assertEquals(1, mavenWarPipeline.getItems().size());
System.out.println("wait for maven-war#1...");
jenkinsRule.waitUntilNoActivity();
WorkflowRun mavenWarPipelineFirstRun = mavenWarPipelineMasterPipeline.getLastBuild();
// TODO check in DB that the dependency on the war project is recorded
// TRIGGER maven-jar#2 so that it triggers "maven-war" and creates maven-war#2
System.out.println("trigger maven-jar#2...");
Future<WorkflowRun> mavenJarPipelineMasterPipelineSecondRunFuture = mavenJarPipelineMasterPipeline.scheduleBuild2(0, new CauseAction(new Cause.RemoteCause("127.0.0.1", "junit test")));
System.out.println("wait for maven-jar#2...");
mavenJarPipelineMasterPipelineSecondRunFuture.get();
jenkinsRule.waitUntilNoActivity();
WorkflowRun mavenWarPipelineLastRun = mavenWarPipelineMasterPipeline.getLastBuild();
System.out.println("mavenWarPipelineLastBuild: " + mavenWarPipelineLastRun + " caused by " + mavenWarPipelineLastRun.getCauses());
assertThat(mavenWarPipelineLastRun.getNumber(), is(mavenWarPipelineFirstRun.getNumber() + 1));
Cause.UpstreamCause upstreamCause = mavenWarPipelineLastRun.getCause(Cause.UpstreamCause.class);
assertThat(upstreamCause, notNullValue());
}
/**
* Cancel previous builds for specified PR id.
*/
public int cancelQueuedBuildByPrNumber(final int id) {
int canceled = 0;
SecurityContext old = impersonate(ACL.SYSTEM);
try {
final Queue queue = getJenkinsInstance().getQueue();
final Queue.Item[] items = queue.getItems();
//todo replace with stream?
for (Queue.Item item : items) {
if (!(item.task instanceof Job)) {
LOGGER.debug("Item {} not instanceof job", item);
continue;
}
final Job<?, ?> jobTask = (Job<?, ?>) item.task;
if (!jobTask.getFullName().equals(job.getFullName())) {
LOGGER.debug("{} != {}", jobTask.getFullName(), job.getFullName());
continue;
}
final CauseAction action = item.getAction(CauseAction.class);
if (isNull(action)) {
LOGGER.debug("Cause action is null for {}", jobTask.getFullName());
continue;
}
Optional<Cause> cause = from(action.getCauses())
.filter(instanceOf(GitHubPRCause.class))
.firstMatch(new CauseHasPRNum(id));
if (cause.isPresent()) {
LOGGER.debug("Cancelling {}", item);
queue.cancel(item);
canceled++;
}
}
} finally {
SecurityContextHolder.setContext(old);
}
return canceled;
}