private RedInterval getLastRed(Job job, Run lastUnsuccessfulBuild) { Run repair = lastUnsuccessfulBuild.getNextBuild(); Run initialFailure; Run previousSuccessfulBuild = lastUnsuccessfulBuild.getPreviousSuccessfulBuild(); if (previousSuccessfulBuild == null) { // never succeeded, get the first build initialFailure = lastUnsuccessfulBuild; while (initialFailure.getPreviousBuild() != null) { initialFailure = initialFailure.getPreviousBuild(); } } else { initialFailure = previousSuccessfulBuild.getNextBuild(); } return new RedInterval(job, repair, initialFailure); }
public static List<String> getCollaborators(@Nonnull final Job<?,?> job) { ExtendedGitHubClient client = getGitHubClient(job); RepositoryId repository = getRepositoryId(job); CollaboratorService collaboratorService = new CollaboratorService(client); try { return collaboratorService.getCollaborators(repository) .stream() .map(User::getLogin) .collect(Collectors.toList()); } catch (final IOException e) { LOG.debug("Received an exception while trying to retrieve the collaborators for the repository: {}", repository, e); return Collections.emptyList(); } }
public PullRequestGroovyObject(@Nonnull final CpsScript script) throws Exception { this.script = script; Run<?, ?> build = script.$build(); if (build == null) { throw new IllegalStateException("No associated build"); } Job job = build.getParent(); this.pullRequestHead = GitHubHelper.getPullRequest(job); this.base = GitHubHelper.getRepositoryId(job); this.head = RepositoryId.create(pullRequestHead.getSourceOwner(), pullRequestHead.getSourceRepo()); this.gitHubClient = GitHubHelper.getGitHubClient(job); this.pullRequestService = new ExtendedPullRequestService(gitHubClient); this.issueService = new ExtendedIssueService(gitHubClient); this.commitService = new ExtendedCommitService(gitHubClient); this.pullRequest = pullRequestService.getPullRequest(base, pullRequestHead.getNumber()); }
@Nonnull public static Map<String, String> getPollingEnvVars(@Nonnull Job<?, ?> job, @CheckForNull Node node) throws EnvInjectException { final Run<?, ?> lastBuild = job.getLastBuild(); if (lastBuild != null) { if (EnvInjectPluginHelper.isEnvInjectPluginInstalled()) { return getEnVars(lastBuild); } } if (node == null) { return getFallBackMasterNode(job); } if (node.getRootPath() == null) { return getFallBackMasterNode(job); } return getDefaultEnvVarsJob(job, node); }
@Nonnull private static Map<String, String> gatherEnvVarsMaster(@Nonnull Job<?, ?> job) throws EnvInjectException { final Jenkins jenkins; try { jenkins = Jenkins.getActiveInstance(); } catch(IllegalStateException ex) { throw new EnvInjectException(ex); } EnvVars env = new EnvVars(); env.put("JENKINS_SERVER_COOKIE", Util.getDigestOf("ServerID:" + jenkins.getSecretKey())); env.put("HUDSON_SERVER_COOKIE", Util.getDigestOf("ServerID:" + jenkins.getSecretKey())); // Legacy compatibility env.put("JOB_NAME", job.getFullName()); env.put("JENKINS_HOME", jenkins.getRootDir().getPath()); env.put("HUDSON_HOME", jenkins.getRootDir().getPath()); // legacy compatibility String rootUrl = jenkins.getRootUrl(); if (rootUrl != null) { env.put("JENKINS_URL", rootUrl); env.put("HUDSON_URL", rootUrl); // Legacy compatibility env.put("JOB_URL", rootUrl + job.getUrl()); } return env; }
@Override public void start(@Nonnull final Job<?, ?> job, final boolean newInstance) { super.start(job, newInstance); loadSqsJob(); final DescriptorImpl descriptor = (DescriptorImpl) this.getDescriptor(); descriptor.queue.execute(new Runnable() { @Override public void run() { boolean succeed = SQSTrigger.this.scheduler.register(SQSTrigger.this); log.debug("Register trigger for %s? %s", SQSTrigger.this.job, SQSTrigger.this.getQueueUuid(), succeed); } }); }
@Override public void onChange(Saveable o, XmlFile file) { LOG.fine(">>> MirrorGateSaveableListener onChange starts"); if (o instanceof Job) { Job job = (Job) o; if (!job.isBuildable()) { helper.sendBuildFromJob(job); } } super.onChange(o, file); LOG.fine(">>> MirrorGateSaveableListener onChange ends"); }
/** * Serves the testCoverage badge image. TO DO * @param req * @param rsp * @param job * @return */ @SuppressWarnings("rawtypes") public HttpResponse doTestIcon(StaplerRequest req, StaplerResponse rsp, @QueryParameter String job) { Job<?, ?> project = getProject(job); Integer testPass = null; Integer testTotal = null; if (project.getLastCompletedBuild() != null) { AbstractTestResultAction testAction = project.getLastCompletedBuild().getAction(AbstractTestResultAction.class); if(testAction != null){ int total = testAction.getTotalCount(); int pass = total - testAction.getFailCount() - testAction.getSkipCount(); testTotal = total; testPass = pass; } } return iconResolver.getTestResultImage(testPass, testTotal); }
/** * Serves the Build Description badge image. * @param req * @param rsp * @param job * @return */ public HttpResponse doBuildDescriptionIcon(StaplerRequest req, StaplerResponse rsp, @QueryParameter String job) { Job<?, ?> project = getProject(job); String buildDescription = null; /*if (project.getLastSuccessfulBuild() != null) { buildDescription = project.getLastSuccessfulBuild().getDescription(); }*/ /*if (project.getLastBuild() != null) { buildDescription = project.getLastBuild().getDescription(); }*/ if (project.getLastCompletedBuild() != null) { buildDescription = project.getLastCompletedBuild().getDescription(); } return iconResolver.getBuildDescriptionImage(buildDescription); }
/** * TO DO * @param job * @return */ private Job<?, ?> getProject(String job) { Job<?, ?> p; // as the user might have ViewStatus permission only (e.g. as anonymous) // we get get the project impersonate and // check for permission after getting the project SecurityContext orig = impersonate(SYSTEM); try { p = getInstance().getItemByFullName(job, Job.class); } finally { setContext(orig); } // check if user has permission to view the status if (p == null || !(p.hasPermission(VIEW_STATUS))) { throw notFound(); } return p; }
@Override @CheckForNull public Run<?, ?> getBuild(@Nonnull Job<?, ?> job, @Nonnull RunSelectorContext context) { String resolvedId = context.getEnvVars().expand(id); if (resolvedId.startsWith("$")) { context.logDebug("Unresolved variable {0}", resolvedId); return null; } Permalink p = job.getPermalinks().get(resolvedId); if (p == null) { context.logDebug("No permalink found for {0}", resolvedId); return null; } Run<?, ?> run = p.resolve(job); if (run == null) { context.logDebug("No such build {0} in {1}", id, job.getFullName()); return null; } return run; }
@Override @CheckForNull public Run<?, ?> getBuild(@Nonnull Job<?, ?> job, @Nonnull RunSelectorContext context) throws IOException { String resolvedBuildNumber = context.getEnvVars().expand(buildNumber); if (resolvedBuildNumber.startsWith("$")) { context.logDebug("Unresolved variable {0}", resolvedBuildNumber); return null; } Run<?, ?> run; try { run = job.getBuildByNumber(Integer.parseInt(resolvedBuildNumber)); } catch (NumberFormatException e) { throw new AbortException(Messages.BuildNumberRunSelector_NotANumber(resolvedBuildNumber)); } if (run == null) { context.logDebug("No such build {0} in {1}", buildNumber, job.getFullName()); return null; } return run; }
@Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { for (Cause.UpstreamCause c: Util.filter(build.getCauses(), Cause.UpstreamCause.class)) { Job<?,?> upstreamProject = Jenkins.getInstance().getItemByFullName(c.getUpstreamProject(), Job.class); if (upstreamProject == null) { listener.getLogger().println(String.format("Not Found: %s", c.getUpstreamProject())); continue; } Run<?,?> upstreamBuild = upstreamProject.getBuildByNumber(c.getUpstreamBuild()); if (upstreamBuild == null) { listener.getLogger().println(String.format("Not Found: %s - %d", upstreamProject.getFullName(), c.getUpstreamBuild())); continue; } listener.getLogger().println(String.format("Removed: %s - %s", upstreamProject.getFullName(), upstreamBuild.getFullDisplayName())); upstreamBuild.delete(); } return true; }
@Before public void before() { build = Mockito.mock(Run.class); Job job = Mockito.mock(Job.class); measurementRenderer = new ProjectNameRenderer(CUSTOM_PREFIX); PerfPublisherBuildAction buildAction = Mockito.mock(PerfPublisherBuildAction.class); reports = new ReportContainer(); Mockito.when(build.getNumber()).thenReturn(BUILD_NUMBER); Mockito.when(build.getParent()).thenReturn(job); Mockito.when(job.getName()).thenReturn(JOB_NAME); Mockito.when(build.getAction(PerfPublisherBuildAction.class)).thenReturn(buildAction); Mockito.when(buildAction.getReport()).thenAnswer(new Answer<Report>() { @Override public Report answer(InvocationOnMock invocationOnMock) { return reports.getReports().isEmpty() ? null : reports.getReports().get(0); } }); Mockito.when(buildAction.getReports()).thenReturn(reports); }
@RequirePOST public void doClean(StaplerRequest req, StaplerResponse res) throws IOException, ServletException { // TODO switch to Jenkins.getActiveInstance() once 1.590+ is the baseline Jenkins jenkins = Jenkins.getInstance(); if (jenkins == null) { throw new IllegalStateException("Jenkins has not been started, or was already shut down"); } final Job job = jenkins.getItemByFullName(req.getParameter("job"), Job.class); Timer.get().submit(new Runnable() { @Override public void run() { try { job.logRotate(); } catch (Exception e) { logger.log(Level.WARNING, "logRotate failed", e); } } }); res.forwardToPreviousPage(req); }
private void registerJobs(UsageComputation uc) throws IOException, InterruptedException { Jenkins jenkins = Jenkins.getInstance(); if (jenkins == null) { throw new IllegalStateException("Jenkins has not been started, or was already shut down"); } // Remove useless entries for jobs for (JobDiskItem item : jobsUsages) { if (!item.getPath().exists() || jenkins.getItemByFullName(item.getFullName(), Job.class) == null) { jobsUsages.remove(item); } } // Add or update entries for jobs for (Job job : jenkins.getAllItems(Job.class)) { if (job instanceof TopLevelItem) { uc.addListener(job.getRootDir().toPath(), new JobUsageListener(job)); } } }
/** * Requires @PrepareForTest({GithubProjectProperty.class, GithubUrl.class}) in class usig it. * * @param filePath job's root directory. * @param job mock job. * @param trigger mock trigger that is expected to be returned via job.getTrigger(GitHubPRTrigger.class). */ public static void createForCommonExpectations(String filePath, Job job, GitHubPRTrigger trigger) { GithubUrl githubUrl = PowerMockito.mock(GithubUrl.class); when(githubUrl.toString()).thenReturn("http://blaur"); GithubProjectProperty projectProperty = PowerMockito.mock(GithubProjectProperty.class); File file = new File(filePath); when(job.getRootDir()).thenReturn(file); when(job.getFullName()).thenReturn("jobFullName"); PowerMockito.mockStatic(JobHelper.class); given(ghPRTriggerFromJob(job)) .willReturn(trigger); when(trigger.getJob()).thenReturn(job); when(trigger.getRepoFullName(job)).thenReturn(mock(GitHubRepositoryName.class)); when(job.getProperty(GithubProjectProperty.class)).thenReturn(projectProperty); when(projectProperty.getProjectUrl()).thenReturn(githubUrl); }
public static ConduitCredentials getCredentials(Job owner, String credentialsID) { List<ConduitCredentials> available = availableCredentials(owner); if (available.size() == 0) { return null; } CredentialsMatcher matcher; if (credentialsID != null) { matcher = CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialsID)); } else { matcher = CredentialsMatchers.always(); } return CredentialsMatchers.firstOrDefault( available, matcher, available.get(0) ); }
public static void forEachJob(Callback<Job> callback) { Jenkins jenkins = Jenkins.getInstance(); if (jenkins != null) { List<Item> items = jenkins.getAllItems(); if (items != null) { for (Item item : items) { Collection<? extends Job> jobs = item.getAllJobs(); if (jobs != null) { for (Job job : jobs) { if (job != null) { callback.invoke(job); } } } } } } }
private void observeStage(Map<String, Summary> histogramMap, Job job, Run build, FlowNode stage) { String jobName = job.getName(); String stageName = stage.getDisplayName(); String[] labelNameArray = {"job", "stage"}; String[] labelValueArray = {jobName, stageName}; String key = jobName + "_" + stageName; Summary collector = histogramMap.get(key); if (collector == null) { collector = Summary.build().name(fullname + "_stage_duration_milliseconds_summary"). subsystem(subsystem).namespace(namespace). labelNames(labelNameArray). help("Summary of Jenkins build times by Job and Stage"). create(); histogramMap.put(key, collector); } long duration = FlowNodes.getStageDuration(stage); collector.labels(labelValueArray).observe(duration); }
@Nonnull @Override public Collection<String> getDockerImagesUsedByJob(@Nonnull Job<?,?> job) { if (job instanceof Project) { Project<? extends Project, ? extends Build> project = (Project<?,? extends Build>)job; Set<String> images = new HashSet<String>(); // check DockerHub build step for matching image ID for (Builder b : project.getBuilders()) { if (b instanceof DockerPullImageBuilder) { images.add(((DockerPullImageBuilder)b).getImage()); } } return images; } else { return Collections.emptySet(); } }
/** * support matrix plugin. * * @see JobInfoHelpers#triggerFrom(hudson.model.Job, java.lang.Class) */ @CheckForNull public static <T extends Trigger> T triggerFrom(final Job<?, ?> job, Class<T> tClass) { Job<?, ?> guessJob; if (job instanceof MatrixConfiguration) { guessJob = ((MatrixConfiguration) job).getParent(); } else { guessJob = job; } if (guessJob instanceof AbstractProject<?, ?>) { final AbstractProject<?, ?> abstractProject = (AbstractProject<?, ?>) guessJob; return abstractProject.getTrigger(tClass); } else if (guessJob instanceof ParameterizedJobMixIn.ParameterizedJob) { ParameterizedJobMixIn.ParameterizedJob pJob = (ParameterizedJobMixIn.ParameterizedJob) guessJob; for (Trigger candidate : pJob.getTriggers().values()) { if (tClass.isInstance(candidate)) { return tClass.cast(candidate); } } } return null; }
/** * @see jenkins.model.ParameterizedJobMixIn#getDefaultParametersValues() */ public static List<ParameterValue> getDefaultParametersValues(Job<?, ?> job) { ParametersDefinitionProperty paramDefProp = job.getProperty(ParametersDefinitionProperty.class); List<ParameterValue> defValues = new ArrayList<>(); /* * This check is made ONLY if someone will call this method even if isParametrized() is false. */ if (paramDefProp == null) { return defValues; } /* Scan for all parameter with an associated default values */ for (ParameterDefinition paramDefinition : paramDefProp.getParameterDefinitions()) { ParameterValue defaultValue = paramDefinition.getDefaultParameterValue(); if (defaultValue != null) { defValues.add(defaultValue); } } return defValues; }
@Override public void start(Job<?, ?> job, boolean newInstance) { LOGGER.info("Starting GitHub Pull Request trigger for project {}", job.getFullName()); super.start(job, newInstance); if (newInstance && getRepoProvider().isManageHooks(this) && withHookTriggerMode().apply(job)) { try { getRepoProvider().registerHookFor(this); getErrorsAction().removeErrors(GitHubHookRegistrationError.class); } catch (Throwable error) { getErrorsAction().addOrReplaceError(new GitHubHookRegistrationError( String.format("Failed register hook for %s. <br/> Because %s", job.getFullName(), error.toString()) )); throw error; } } }
public GitHubRepositoryName getRepoFullName(Job<?, ?> job) { if (isNull(repoName)) { checkNotNull(job, "job object is null, race condition?"); GithubProjectProperty ghpp = job.getProperty(GithubProjectProperty.class); checkNotNull(ghpp, "GitHub project property is not defined. Can't setup GitHub trigger for job %s", job.getName()); checkNotNull(ghpp.getProjectUrl(), "A GitHub project url is required"); GitHubRepositoryName repo = GitHubRepositoryName.create(ghpp.getProjectUrl().baseUrl()); checkNotNull(repo, "Invalid GitHub project url: %s", ghpp.getProjectUrl().baseUrl()); setRepoName(repo); } return repoName; }
@Test public void dontFailOnBadJob() throws IOException, ANTLRException { String goodRepo = "https://github.com/KostyaSha-auto/test-repo"; final FreeStyleProject job1 = jRule.createProject(FreeStyleProject.class, "bad job"); job1.addProperty(new GithubProjectProperty("http://bad.url/deep/bad/path/")); job1.addTrigger(new GitHubBranchTrigger("", GitHubPRTriggerMode.HEAVY_HOOKS_CRON, emptyList())); Set<Job> jobs = getBranchTriggerJobs(goodRepo); assertThat(jobs, hasSize(0)); final FreeStyleProject job2 = jRule.createProject(FreeStyleProject.class, "good job"); job2.addProperty(new GithubProjectProperty(goodRepo)); job2.addTrigger(new GitHubBranchTrigger("", GitHubPRTriggerMode.HEAVY_HOOKS_CRON, emptyList())); jobs = getBranchTriggerJobs("KostyaSha-auto/test-repo"); assertThat(jobs, hasSize(1)); assertThat(jobs, hasItems(job2)); }
@Override public void start(Job<?, ?> job, boolean newInstance) { LOG.info("Starting GitHub Branch trigger for project {}", job.getFullName()); super.start(job, newInstance); if (newInstance && getRepoProvider().isManageHooks(this) && withHookTriggerMode().apply(job)) { try { getRepoProvider().registerHookFor(this); getErrorsAction().removeErrors(GitHubHookRegistrationError.class); } catch (Throwable error) { getErrorsAction().addOrReplaceError(new GitHubHookRegistrationError( String.format("Failed register hook for %s. <br/> Because %s", job.getFullName(), error.toString()) )); throw error; } } }
@Test public void dontFailOnBadJob() throws IOException, ANTLRException { String goodRepo = "https://github.com/KostyaSha-auto/test-repo"; final FreeStyleProject job1 = jenkins.createProject(FreeStyleProject.class, "bad job"); job1.addProperty(new GithubProjectProperty("http://bad.url/deep/bad/path/")); job1.addTrigger(new GitHubPRTrigger("", GitHubPRTriggerMode.HEAVY_HOOKS_CRON, emptyList())); Set<Job> jobs = getPRTriggerJobs(goodRepo); MatcherAssert.assertThat(jobs, hasSize(0)); final FreeStyleProject job2 = jenkins.createProject(FreeStyleProject.class, "good job"); job2.addProperty(new GithubProjectProperty(goodRepo)); job2.addTrigger(new GitHubPRTrigger("", GitHubPRTriggerMode.HEAVY_HOOKS_CRON, emptyList())); jobs = getPRTriggerJobs("KostyaSha-auto/test-repo"); MatcherAssert.assertThat(jobs, hasSize(1)); MatcherAssert.assertThat(jobs, hasItems(job2)); }
public static ExtendedGitHubClient getGitHubClient(@Nonnull final Job<?,?> job) { SCMSource scmSource = SCMSource.SourceByItem.findSource(job); if (scmSource instanceof GitHubSCMSource) { GitHubSCMSource gitHubSource = (GitHubSCMSource) scmSource; ExtendedGitHubClient client; if (gitHubSource.getApiUri() == null) { client = new ExtendedGitHubClient(); } else { URI uri = URI.create(gitHubSource.getApiUri()); client = new ExtendedGitHubClient(uri.getHost(), uri.getPort(), uri.getScheme()); } // configure credentials if (gitHubSource.getCredentialsId() != null) { StandardCredentials credentials = Connector.lookupScanCredentials( job, gitHubSource.getApiUri(), gitHubSource.getCredentialsId()); if (credentials instanceof StandardUsernamePasswordCredentials) { StandardUsernamePasswordCredentials c = (StandardUsernamePasswordCredentials) credentials; String userName = c.getUsername(); String password = c.getPassword().getPlainText(); client.setCredentials(userName, password); } } return client; } throw new IllegalArgumentException("Job's SCM is not GitHub."); }
public static RepositoryId getRepositoryId(@Nonnull final Job<?,?> job) { SCMSource src = SCMSource.SourceByItem.findSource(job); if (src instanceof GitHubSCMSource) { GitHubSCMSource source = (GitHubSCMSource) src; if (source.getScanCredentialsId() != null) { return RepositoryId.create(source.getRepoOwner(), source.getRepository()); } } return null; }
public static PullRequestSCMHead getPullRequest(@Nonnull final Job job) throws Exception { PullRequestSCMHead head = (PullRequestSCMHead) SCMHead.HeadByItem.findHead(job); if (head == null) { throw new IllegalStateException("Build is not a pull request"); } return head; }
@Nonnull private static Map<String, String> getFallBackMasterNode(@Nonnull Job<?, ?> job) throws EnvInjectException { final Node masterNode = getMasterNode(); if (masterNode == null) { return gatherEnvVarsMaster(job); } return getDefaultEnvVarsJob(job, masterNode); }
@Nonnull private static Map<String, String> getDefaultEnvVarsJob(@Nonnull Job<?, ?> job, @Nonnull Node node) throws EnvInjectException { // TODO: wat assert node.getRootPath() != null; //--- Same code for master or a slave node Map<String, String> result = gatherEnvVarsMaster(job); result.putAll(gatherEnvVarsNode(job, node)); result.putAll(gatherEnvVarsNodeProperties(node)); return result; }
@Nonnull private static Map<String, String> gatherEnvVarsNode(@Nonnull Job<?, ?> job, @Nonnull Node node) throws EnvInjectException { final FilePath rootPath = node.getRootPath(); if (rootPath == null) { //TODO: better than the original NPE. But maybe it's preferable to have more intelligent handling throw new EnvInjectException("Cannot retrieve Environment variables from the offline node"); } try { Map<String, String> envVars = new EnvVars(rootPath.act(new MasterToSlaveCallable<Map<String, String>, EnvInjectException>() { private static final long serialVersionUID = 1L; @Override public Map<String, String> call() throws EnvInjectException { return EnvVars.masterEnvVars; } })); envVars.put("NODE_NAME", node.getNodeName()); envVars.put("NODE_LABELS", Util.join(node.getAssignedLabels(), " ")); if (job instanceof AbstractProject) { FilePath wFilePath = ((AbstractProject)job).getSomeWorkspace(); if (wFilePath != null) { envVars.put("WORKSPACE", wFilePath.getRemote()); } } return envVars; } catch (IOException | InterruptedException ioe) { throw new EnvInjectException(ioe); } }
@Override public SQSJob createSqsJob(Job job, SQSTrigger sqsTrigger) { SQSJob sqsJob = null; if (job instanceof AbstractProject) { sqsJob = new SQSAbstractProjectJob((AbstractProject) job, sqsTrigger); } else if (job instanceof WorkflowJob) { sqsJob = new SQSWorkflowJob((WorkflowJob) job, sqsTrigger); } return sqsJob; }
public SQSActivityAction(Job job) { this.job = job; this.activityDir = new File(this.job.getRootDir(), ".activity"); if (!this.activityDir.exists() && !this.activityDir.mkdirs()) { log.error("Unable to create trigger activity dir %s", this.activityDir.getPath()); } log.debug("Activity dir %s is writeable? %s", this.activityDir.getPath(), this.activityDir.canWrite()); }
@Test public void sendBuildFromItemResponseOK() { when(service.publishBuildData(any())).thenReturn(responseOk); when(service.sendBuildDataToExtraEndpoints(any(), any())).thenReturn(responseOk); Job[] jobs = new Job[new Random().nextInt(10)]; Arrays.fill(jobs, createMockingJob()); helper.sendBuildFromItem(createMockingItem(jobs)); verify(service, times(jobs.length)).publishBuildData(any()); }
@Test public void sendBuildFromItemResponseError() { when(service.publishBuildData(any())).thenReturn(responseError); when(service.sendBuildDataToExtraEndpoints(any(), any())).thenReturn(responseError); Job[] jobs = new Job[new Random().nextInt(10)]; Arrays.fill(jobs, createMockingJob()); helper.sendBuildFromItem(createMockingItem(jobs)); verify(service, times(jobs.length)).publishBuildData(any()); }
private Job createMockingJob() { Job job = PowerMockito.mock(Job.class); Run build = mock(Run.class); when(job.getLastBuild()).thenReturn(build); PowerMockito.when(job.getAbsoluteUrl()).thenReturn(BUILD_SAMPLE); when(build.getParent()).thenReturn(job); return job; }