@Override public CauseOfBlockage canRun(Queue.Item item) { // Skip locking for multiple configuration projects, // only the child jobs will actually lock resources. if (item.task instanceof MatrixProject) return null; AbstractProject<?, ?> project = Utils.getProject(item); if (project == null) return null; LockableResourcesStruct resources = Utils.requiredResources(project); if (resources == null || (resources.required.isEmpty() && resources.label.isEmpty())) { return null; } int resourceNumber; try { resourceNumber = Integer.parseInt(resources.requiredNumber); } catch (NumberFormatException e) { resourceNumber = 0; } LOGGER.finest(project.getName() + " trying to get resources with these details: " + resources); if (resourceNumber > 0 || !resources.label.isEmpty()) { Map<String, Object> params = new HashMap<String, Object>(); if (item.task instanceof MatrixConfiguration) { MatrixConfiguration matrix = (MatrixConfiguration) item.task; params.putAll(matrix.getCombination()); } List<LockableResource> selected = LockableResourcesManager.get() .queue(resources, item.id, project.getFullName(), resourceNumber, params, LOGGER); if (selected != null) { LOGGER.finest(project.getName() + " reserved resources " + selected); return null; } else { LOGGER.finest(project.getName() + " waiting for resources"); return new BecauseResourcesLocked(resources); } } else { if (LockableResourcesManager.get().queue(resources.required, item.id)) { LOGGER.finest(project.getName() + " reserved resources " + resources.required); return null; } else { LOGGER.finest(project.getName() + " waiting for resources " + resources.required); return new BecauseResourcesLocked(resources); } } }
public TestResultAction(String jobs, boolean includeFailedBuilds, AbstractBuild<?, ?> owner) { super(owner); this.includeFailedBuilds = includeFailedBuilds; if (jobs == null) { // resolve null as the transitive downstream jobs StringBuilder buf = new StringBuilder(); for (AbstractProject p : getProject().getTransitiveDownstreamProjects()) { if (buf.length() > 0) buf.append(','); buf.append(p.getFullName()); } jobs = buf.toString(); } this.jobs = jobs; }
private void configureGit(GitHubRepositoryName gitHubRepoName, PullRequestBuildTrigger trigger) throws IOException { if (project.getScm() instanceof GitSCM) { GitSCM git = (GitSCM) project.getScm(); List<UserRemoteConfig> userRemoteConfigs = new ArrayList<UserRemoteConfig>(); if (git.getUserRemoteConfigs().isEmpty() || (git.getUserRemoteConfigs().size() == 1 && StringUtils.isBlank(git.getUserRemoteConfigs().get(0).getUrl()))) { LOGGER.info( MessageFormat.format( "Git is selected as SCM of project {0} but not yet configured, configuring it", project.getFullName())); String url = MessageFormat.format( "https://{0}/{1}/{2}.git", gitHubRepoName.getHost(), gitHubRepoName.getUserName(), gitHubRepoName.getRepositoryName()); userRemoteConfigs.add( new UserRemoteConfig(url, "origin", "+refs/pull/*:refs/remotes/origin/pr/*", null)); List<BranchSpec> branches = new ArrayList<BranchSpec>(); branches.add(new BranchSpec("${PR_COMMIT}")); GitSCM updatedGit = new GitSCM( userRemoteConfigs, branches, git.isDoGenerateSubmoduleConfigurations(), git.getSubmoduleCfg(), git.getBrowser(), git.getGitTool(), git.getExtensions()); project.setScm(updatedGit); LOGGER.info( MessageFormat.format( "Git is configured to work with {0}", trigger.getDescriptor().getDisplayName())); } } }
@SuppressWarnings("rawtypes") @Override public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) { // As DependecyDeclarer was renamed to DependencyDeclarer in Jenkins 1.501, // codes referring DependecyDeclarer may not work depending on which version of // Jenkins core used. // Instead, I use DescribableList#buildDependencyGraph, which is a part of // Jenkins core and always work. // See JENKINS-25017 for details. for (BuildStep publisher : getPublisherList()) { if (publisher instanceof Publisher) { DescribableList<Publisher, Descriptor<Publisher>> lst = new DescribableList<Publisher, Descriptor<Publisher>>( new Saveable() { @Override public void save() throws IOException {} }, Arrays.asList((Publisher) publisher)); lst.buildDependencyGraph( owner, new ConditionalDependencyGraphWrapper(graph, condition, runner)); } else if (publisher instanceof Builder) { // Case used with Any Build Step plugin // (https://wiki.jenkins-ci.org/display/JENKINS/Any+Build+Step+Plugin). DescribableList<Builder, Descriptor<Builder>> lst = new DescribableList<Builder, Descriptor<Builder>>( new Saveable() { @Override public void save() throws IOException {} }, Arrays.asList((Builder) publisher)); lst.buildDependencyGraph( owner, new ConditionalDependencyGraphWrapper(graph, condition, runner)); } else if (publisher instanceof DependecyDeclarer) { ((DependecyDeclarer) publisher) .buildDependencyGraph( owner, new ConditionalDependencyGraphWrapper(graph, condition, runner)); } else { LOGGER.log( Level.WARNING, "May failed to build dependency for {0} in {1}", new Object[] {publisher.getClass(), owner.getFullName()}); } } }
private void updateGeneratedJobMap( AbstractProject<?, ?> seedJob, Set<GeneratedJob> createdOrUpdatedJobs, Set<GeneratedJob> removedJobs) throws IOException { DescriptorImpl descriptor = Jenkins.getInstance().getDescriptorByType(DescriptorImpl.class); boolean descriptorMutated = false; Map<String, SeedReference> generatedJobMap = descriptor.getGeneratedJobMap(); for (GeneratedJob generatedJob : createdOrUpdatedJobs) { Item item = getLookupStrategy().getItem(seedJob, generatedJob.getJobName(), Item.class); if (item != null) { SeedReference newSeedReference = new SeedReference(seedJob.getFullName()); if (generatedJob.getTemplateName() != null) { Item template = getLookupStrategy().getItem(seedJob, generatedJob.getTemplateName(), Item.class); newSeedReference.setTemplateJobName(template.getFullName()); } newSeedReference.setDigest(Util.getDigestOf(Items.getConfigFile(item).getFile())); SeedReference oldSeedReference = generatedJobMap.get(item.getFullName()); if (!newSeedReference.equals(oldSeedReference)) { generatedJobMap.put(item.getFullName(), newSeedReference); descriptorMutated = true; } } } for (GeneratedJob removedJob : removedJobs) { Item removedItem = getLookupStrategy().getItem(seedJob, removedJob.getJobName(), Item.class); if (removedItem != null) { generatedJobMap.remove(removedItem.getFullName()); descriptorMutated = true; } } if (descriptorMutated) { descriptor.save(); } }
public PullRequestBuildHandler(AbstractProject<?, ?> project, boolean newTrigger) throws IOException { this.project = project; final GithubProjectProperty property = project.getProperty(GithubProjectProperty.class); if (property == null || property.getProjectUrl() == null || StringUtils.isBlank(property.getProjectUrl().baseUrl())) { throw new IOException( MessageFormat.format( "GitHub project URL must be specified for project {0}", project.getFullName())); } String gitHubProjectUrl = property.getProjectUrl().baseUrl().trim(); GitHubRepositoryName gitHubRepoName = GitHubRepositoryName.create(gitHubProjectUrl); if (gitHubRepoName == null) { throw new IOException( MessageFormat.format("Invalid GitHub project URL specified: {0}", gitHubProjectUrl)); } GHRepository repo = gitHubRepoName.resolveOne(); if (repo == null) { LOGGER.severe( MessageFormat.format( "Cannot connect to {0}. Please check your registered GitHub credentials", gitHubRepoName)); gitHubRepositoryUrl = gitHubProjectUrl; } else { gitHubRepositoryUrl = repo.getHtmlUrl().toString(); } if (!gitHubRepositoryUrl.endsWith("/")) { gitHubRepositoryUrl += '/'; } PullRequestBuildTrigger trigger = project.getTrigger(PullRequestBuildTrigger.class); triggerPhrasePattern = Pattern.compile(trigger.getTriggerPhrase(), Pattern.CASE_INSENSITIVE); if (StringUtils.isNotBlank(trigger.getWhitelist())) { Set<String> entries = new HashSet<String>(); for (String entry : trigger.getWhitelist().split(",")) { if (StringUtils.isNotBlank(entry)) { entries.add(entry); } } if (!entries.isEmpty()) { whitelist = entries; } } if (newTrigger) { configureGit(gitHubRepoName, trigger); // The construction of webhook URL requires Jenkins root URL which might be null if it is not // manually // configured and it is retrieved in a separate thread without request context. So the webhook // URL is first // retrieved here. PullRequestBuildTrigger.DescriptorImpl descriptor = (PullRequestBuildTrigger.DescriptorImpl) Jenkins.getInstance().getDescriptor(PullRequestBuildTrigger.class); final String webhookUrl = StringUtils.isBlank(descriptor.getWebHookExternalUrl()) ? descriptor.getWebHookUrl() : descriptor.getWebHookExternalUrl(); if (webhookUrl == null) { LOGGER.warning( MessageFormat.format( "Cannot add webhook to GitHub repository {0}. " + "Please configure Jenkins URL or Webhook External URL for {1}", gitHubRepositoryUrl, descriptor.getDisplayName())); } else { LOGGER.info( MessageFormat.format( "Adding webhook {0} to GitHub repository {1}", webhookUrl, gitHubRepositoryUrl)); sequentialExecutionQueue.execute( new Runnable() { public void run() { try { createWebHook(webhookUrl); } catch (Throwable ex) { LOGGER.log( Level.SEVERE, MessageFormat.format( "Error adding webhook to GitHub repository {0}", gitHubRepositoryUrl), ex); } } }); } } }
void handle(GHEventPayload.IssueComment issueComment, GitHub gitHub) throws IOException { // check the trigger phrase PullRequestBuildTrigger trigger = project.getTrigger(PullRequestBuildTrigger.class); if (StringUtils.isBlank(trigger.getTriggerPhrase())) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("No trigger phrase configured for project: " + project.getDisplayName()); } return; } String issueUrl = issueComment.getIssue().getHtmlUrl().toString(); if (!issueUrl.startsWith(gitHubRepositoryUrl)) { LOGGER.finest( MessageFormat.format( "GitHub issue {0} is not related to project {1}. " + "GitHub project URL configured for project {1}: {2}", issueUrl, project.getFullName(), gitHubRepositoryUrl)); return; } String commentBody = issueComment.getComment().getBody(); if (!triggerPhrasePattern.matcher(commentBody).find()) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("No trigger phrase matching on comment: " + commentBody); } return; } GHUser buildRequester = issueComment.getComment().getUser(); if (!isWhitelisted(buildRequester, gitHub)) { LOGGER.info( MessageFormat.format( "GitHub user {0} is not in the whitelist of project {1}", buildRequester.getLogin(), project.getFullName())); return; } final int prNumber = issueComment.getIssue().getNumber(); GHPullRequest pullRequest = issueComment.getRepository().getPullRequest(prNumber); // Updating PR to force the cache (if present) to refresh: pullRequest.setTitle(pullRequest.getTitle()); pullRequest = issueComment.getRepository().getPullRequest(prNumber); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("ghPullRequest = " + getPullRequestAsString(pullRequest)); } if (pullRequest.getState() == GHIssueState.OPEN) { PullRequestData pullRequestData = PullRequestManager.getInstance().addPullRequestData(pullRequest, project); cancelBuilds(pullRequestData); build(pullRequest, buildRequester, new TriggerCause(pullRequest, buildRequester)); } else if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine( MessageFormat.format( "Pull request {0} is not opened, no build is triggered", pullRequest.getHtmlUrl().toString())); } }
void handle(GHEventPayload.PullRequest prEventPayload, GitHub gitHub) throws IOException { GHPullRequest pullRequest = prEventPayload.getPullRequest(); String pullRequestUrl = pullRequest.getHtmlUrl().toString(); if (!pullRequestUrl.startsWith(gitHubRepositoryUrl)) { LOGGER.config( MessageFormat.format( "Pull request {0} is not related to project {1}. " + "GitHub project URL configured for project {1}: {2}", pullRequestUrl, project.getFullName(), gitHubRepositoryUrl)); return; } LOGGER.info( MessageFormat.format( "Handling event ''{0}'' of pull request {1} for project {2}", prEventPayload.getAction(), pullRequestUrl, project.getFullName())); PullRequestManager pullRequestManager = PullRequestManager.getInstance(); PullRequestData pullRequestData = pullRequestManager.getPullRequestData(pullRequestUrl, project); if (PullRequestManager.PullRequestAction.CLOSED.equals(prEventPayload.getAction())) { if (pullRequestData != null) { cancelBuilds(pullRequestData); deleteInstances(pullRequest); } else { LOGGER.warning( "No previous data available for received Pull Request 'close' event: " + pullRequestUrl); } return; } if (!isWhitelisted(pullRequest.getUser(), gitHub)) { LOGGER.info( MessageFormat.format( "GitHub user {0} is not in the whitelist of project {1}", pullRequest.getUser().getLogin(), project.getFullName())); return; } boolean startBuild = false; if (pullRequestData == null) { if (PullRequestManager.PullRequestAction.SYNCHRONIZE.equals(prEventPayload.getAction())) { LOGGER.info( MessageFormat.format( "Updated pull request {0} was not built previously", pullRequestUrl)); } pullRequestData = pullRequestManager.addPullRequestData(pullRequest, project); startBuild = pullRequestData.getLastUpdated().equals(pullRequest.getUpdatedAt()); } else if (pullRequestData.update(pullRequest)) { pullRequestData.save(); startBuild = true; } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Received event payload: " + prEventPayload); } if (startBuild) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine( "Cancelling previous running builds and starting new build for Pull request: " + pullRequestData); } cancelBuilds(pullRequestData); build(pullRequest, null, new TriggerCause(prEventPayload)); } else if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("No new build has been triggered for Pull request: " + pullRequestData); } }