Search in sources :

Example 11 with JobTemplate

use of com.palantir.stash.stashbot.persistence.JobTemplate in project stashbot by palantir.

the class BuildSuccessReportingServlet method doGet.

@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    try {
        // Look at JenkinsManager class if you change this:
        // final two arguments could be empty...
        final String URL_FORMAT = "BASE_URL/REPO_ID/TYPE/STATE/BUILD_NUMBER/BUILD_HEAD[/MERGE_HEAD/PULLREQUEST_ID]";
        final String pathInfo = req.getPathInfo();
        final String[] parts = pathInfo.split("/");
        if (parts.length != 6 && parts.length != 8) {
            throw new IllegalArgumentException("The format of the URL is " + URL_FORMAT);
        }
        final int repoId;
        final RepositoryConfiguration rc;
        try {
            repoId = Integer.valueOf(parts[1]);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("The format of the URL is " + URL_FORMAT, e);
        }
        // This is necessary if we want unauthenticated users to be able to call this.  *sigh*
        RepoIdFetcherOperation getRepoId = new RepoIdFetcherOperation(repositoryService, repoId);
        ss.withPermission(Permission.REPO_READ, "BUILD SUCCESS REPORT").call(getRepoId);
        final Repository repo = getRepoId.getRepo();
        rc = configurationPersistanceManager.getRepositoryConfigurationForRepository(repo);
        if (repo == null) {
            throw new IllegalArgumentException("Unable to get a repository for id " + repoId);
        }
        JobTemplate jt = jtm.fromString(rc, parts[2].toLowerCase());
        if (jt == null) {
            throw new IllegalArgumentException("Unable to get a valid JobTemplate from " + parts[2]);
        }
        final State state = BuildStatus.State.fromString(parts[3]);
        if (state == null) {
            throw new IllegalArgumentException("The state must be 'successful', 'failed', or 'inprogress'");
        }
        final long buildNumber;
        try {
            buildNumber = Long.parseLong(parts[4]);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Unable to parse build number", e);
        }
        // TODO: ensure this hash actually exists?
        final String buildHead = parts[5];
        final String mergeHead;
        final long pullRequestId;
        final PullRequest pullRequest;
        final String retUrl;
        if (parts.length == 8 && !parts[6].isEmpty() && !parts[7].isEmpty()) {
            mergeHead = parts[6];
            try {
                // This is a pull request, so add a comment
                pullRequestId = Long.parseLong(parts[7]);
                PullRequestFetcherOperation prfo = new PullRequestFetcherOperation(pullRequestService, repoId, pullRequestId);
                ss.withPermission(Permission.REPO_READ, "BUILD SUCCESS REPORT").call(prfo);
                pullRequest = prfo.getPullRequest();
                if (pullRequest == null) {
                    throw new IllegalArgumentException("Unable to find pull request for repo id " + repo.getId().toString() + " pr id " + Long.toString(pullRequestId));
                }
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("Unable to parse pull request id " + parts[7], e);
            }
            retUrl = ub.getJenkinsTriggerUrl(repo, jt.getJobType(), buildHead, pullRequest);
        } else {
            mergeHead = null;
            pullRequestId = 0;
            pullRequest = null;
            retUrl = ub.getJenkinsTriggerUrl(repo, jt.getJobType(), buildHead, null);
        }
        if (mergeHead == null) {
            BuildStatus bs;
            bs = getSuccessStatus(repo, jt, state, buildNumber, buildHead);
            log.debug("Registering build status for buildHead " + buildHead + " " + bsToString(bs));
            BuildStatusAddOperation bssAdder = new BuildStatusAddOperation(buildStatusService, buildHead, bs);
            // Yeah, I know what you are thinking... "Admin permission?  To add a build status?"
            // I tried REPO_WRITE and REPO_ADMIN and neither was enough, but this worked!
            ss.withPermission(Permission.SYS_ADMIN, "BUILD SUCCESS REPORT").call(bssAdder);
            printOutput(req, res);
            return;
        }
        // arg order for bools is started, success, override, failed
        if (state.equals(State.SUCCESSFUL)) {
            configurationPersistanceManager.setPullRequestMetadata(pullRequest, mergeHead, buildHead, null, true, null, false);
        } else if (state.equals(State.INPROGRESS)) {
            configurationPersistanceManager.setPullRequestMetadata(pullRequest, mergeHead, buildHead, true, false, null, null);
        } else if (state.equals(State.FAILED)) {
            configurationPersistanceManager.setPullRequestMetadata(pullRequest, mergeHead, buildHead, null, false, null, true);
        }
        // mergeHead is not null *and* pullRequest is not null if we reach
        // here.
        final StringBuffer sb = new StringBuffer();
        final String url = getJenkinsUrl(repo, jt, buildNumber);
        /* NOTE: mergeHead and buildHead are the reverse of what you might
             * think, because we have to check out the "toRef" becasue it is
             * the ref that is guaranteed to be in the correct repo.
             * Nonetheless, buildHead is the commit that is being merged "into"
             * the target branch, which is the mergeHead variable here.
             */
        final int hashLength = 4;
        final String shortMergeHead = mergeHead.substring(0, hashLength);
        final String shortBuildHead = buildHead.substring(0, hashLength);
        final String mergeHeadUrl = ub.buildStashCommitUrl(repo, mergeHead);
        final String buildHeadUrl = ub.buildStashCommitUrl(repo, buildHead);
        final String mergeHeadLink = "[" + shortMergeHead + "](" + mergeHeadUrl + ")";
        final String buildHeadLink = "[" + shortBuildHead + "](" + buildHeadUrl + ")";
        final String consoleUrl = url + "/console";
        sb.append("*[Build #" + buildNumber + "](" + url + ") ");
        sb.append("(merging " + mergeHeadLink + " into " + buildHeadLink + ") ");
        switch(state) {
            case INPROGRESS:
                sb.append("is in progress...*");
                break;
            case SUCCESSFUL:
                sb.append("has **passed ✓**.*");
                break;
            case FAILED:
                sb.append("has* **FAILED ✖**. ");
                sb.append("([*Retrigger this build* ⟳](" + retUrl + ") *or* [*view console output* ☰](" + consoleUrl + ").)");
                break;
        }
        log.debug("Registering comment on pr for buildHead " + buildHead + " mergeHead " + mergeHead);
        // Still make comment so users can see links to build
        PullRequestCommentAddOperation prcao = new PullRequestCommentAddOperation(pullRequestService, repo.getId(), pullRequest.getId(), sb.toString());
        // So in order to create comments, we have to do it AS some user.  ss.doAsUser rather than ss.doWithPermission is the magic sauce here.
        JenkinsServerConfiguration jsc = configurationPersistanceManager.getJenkinsServerConfiguration(rc.getJenkinsServerName());
        StashUser user = us.findUserByNameOrEmail(jsc.getStashUsername());
        ss.impersonating(user, "BUILD SUCCESS REPORT").call(prcao);
        printOutput(req, res);
    } catch (SQLException e) {
        throw new RuntimeException("Unable to get configuration", e);
    } catch (Exception e) {
        throw new RuntimeException("Unable to report build status", e);
    }
}
Also used : SQLException(java.sql.SQLException) PullRequest(com.atlassian.stash.pull.PullRequest) JobTemplate(com.palantir.stash.stashbot.persistence.JobTemplate) ServletException(javax.servlet.ServletException) SQLException(java.sql.SQLException) IOException(java.io.IOException) BuildStatusAddOperation(com.palantir.stash.stashbot.util.BuildStatusAddOperation) Repository(com.atlassian.stash.repository.Repository) StashUser(com.atlassian.stash.user.StashUser) State(com.atlassian.stash.build.BuildStatus.State) BuildStatus(com.atlassian.stash.build.BuildStatus) InternalBuildStatus(com.atlassian.stash.internal.build.InternalBuildStatus) PullRequestCommentAddOperation(com.palantir.stash.stashbot.util.PullRequestCommentAddOperation) RepoIdFetcherOperation(com.palantir.stash.stashbot.util.RepoIdFetcherOperation) PullRequestFetcherOperation(com.palantir.stash.stashbot.util.PullRequestFetcherOperation) RepositoryConfiguration(com.palantir.stash.stashbot.persistence.RepositoryConfiguration) JenkinsServerConfiguration(com.palantir.stash.stashbot.persistence.JenkinsServerConfiguration)

Example 12 with JobTemplate

use of com.palantir.stash.stashbot.persistence.JobTemplate in project stashbot by palantir.

the class JenkinsJobXmlFormatter method generateJobXml.

public String generateJobXml(JobTemplate jobTemplate, Repository repo) throws SQLException {
    final VelocityContext vc = velocityManager.getVelocityContext();
    final RepositoryConfiguration rc = cpm.getRepositoryConfigurationForRepository(repo);
    final JenkinsServerConfiguration jsc = cpm.getJenkinsServerConfiguration(rc.getJenkinsServerName());
    RepositoryCloneLinksRequest rclr = new RepositoryCloneLinksRequest.Builder().repository(repo).protocol("http").user(null).build();
    String repositoryUrl = rs.getCloneLinks(rclr).iterator().next().getHref();
    String cleanRepositoryUrl = repositoryUrl;
    // Handle the various Authentication modes
    switch(jsc.getAuthenticationMode()) {
        case USERNAME_AND_PASSWORD:
            // manually insert the username and pw we are configured to use
            repositoryUrl = repositoryUrl.replace("://", "://" + jsc.getStashUsername() + ":" + jsc.getStashPassword() + "@");
            break;
        case CREDENTIAL_MANUALLY_CONFIGURED:
            vc.put("credentialUUID", jsc.getStashPassword());
            break;
    }
    vc.put("repositoryUrl", repositoryUrl);
    vc.put("cleanRepositoryUrl", cleanRepositoryUrl);
    vc.put("prebuildCommand", prebuildCommand(rc.getPrebuildCommand()));
    // TODO: figure out build command some other way?
    switch(jobTemplate.getJobType()) {
        case VERIFY_COMMIT:
            vc.put("buildCommand", buildCommand(rc.getVerifyBuildCommand()));
            break;
        case VERIFY_PR:
            vc.put("buildCommand", buildCommand(rc.getVerifyBuildCommand()));
            break;
        case PUBLISH:
            vc.put("buildCommand", buildCommand(rc.getPublishBuildCommand()));
            break;
        case NOOP:
            vc.put("buildCommand", buildCommand("/bin/true"));
            break;
    }
    // Add email notification stuff for all build types
    vc.put("isEmailNotificationsEnabled", rc.getEmailNotificationsEnabled());
    vc.put("emailRecipients", rc.getEmailRecipients());
    vc.put("isEmailForEveryUnstableBuild", rc.getEmailForEveryUnstableBuild());
    vc.put("isEmailSendToIndividuals", rc.getEmailSendToIndividuals());
    vc.put("isEmailPerModuleEmail", rc.getEmailPerModuleEmail());
    vc.put("startedCommand", curlCommandBuilder(repo, jobTemplate, rc, repositoryUrl, "inprogress"));
    vc.put("successCommand", curlCommandBuilder(repo, jobTemplate, rc, repositoryUrl, "successful"));
    vc.put("failedCommand", curlCommandBuilder(repo, jobTemplate, rc, repositoryUrl, "failed"));
    vc.put("repositoryLink", navBuilder.repo(repo).browse().buildAbsolute());
    vc.put("repositoryName", repo.getProject().getName() + " " + repo.getName());
    // Parameters are type-dependent for now
    ImmutableList.Builder<Map<String, String>> paramBuilder = new ImmutableList.Builder<Map<String, String>>();
    switch(jobTemplate.getJobType()) {
        case VERIFY_COMMIT:
            // repoId
            paramBuilder.add(ImmutableMap.of("name", "repoId", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "stash repository Id", "defaultValue", "unknown"));
            // buildHead
            paramBuilder.add(ImmutableMap.of("name", "buildHead", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "the change to build", "defaultValue", "head"));
            break;
        case VERIFY_PR:
            // repoId
            paramBuilder.add(ImmutableMap.of("name", "repoId", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "stash repository Id", "defaultValue", "unknown"));
            // buildHead
            paramBuilder.add(ImmutableMap.of("name", "buildHead", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "the change to build", "defaultValue", "head"));
            // pullRequestId
            paramBuilder.add(ImmutableMap.of("name", "pullRequestId", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "the pull request Id", "defaultValue", ""));
            break;
        case PUBLISH:
            // repoId
            paramBuilder.add(ImmutableMap.of("name", "repoId", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "stash repository Id", "defaultValue", "unknown"));
            // buildHead
            paramBuilder.add(ImmutableMap.of("name", "buildHead", "typeName", JenkinsBuildParamType.StringParameterDefinition.toString(), "description", "the change to build", "defaultValue", "head"));
            break;
        case NOOP:
            // no params
            break;
    }
    vc.put("paramaterList", paramBuilder.build());
    // Junit settings
    vc.put("isJunit", rc.getJunitEnabled());
    vc.put("junitPath", rc.getJunitPath());
    // Artifact settings
    vc.put("artifactsEnabled", rc.getArtifactsEnabled());
    vc.put("artifactsPath", rc.getArtifactsPath());
    // insert pinned data
    switch(jobTemplate.getJobType()) {
        case VERIFY_COMMIT:
        case VERIFY_PR:
            vc.put("isPinned", rc.getVerifyPinned());
            vc.put("label", rc.getVerifyLabel());
            break;
        case PUBLISH:
            vc.put("isPinned", rc.getPublishPinned());
            vc.put("label", rc.getPublishLabel());
            break;
        case NOOP:
            vc.put("isPinned", false);
            break;
    }
    StringWriter xml = new StringWriter();
    VelocityEngine ve = velocityManager.getVelocityEngine();
    Template template = ve.getTemplate(jobTemplate.getTemplateFile());
    template.merge(vc, xml);
    return xml.toString();
}
Also used : VelocityEngine(org.apache.velocity.app.VelocityEngine) StringWriter(java.io.StringWriter) VelocityContext(org.apache.velocity.VelocityContext) ImmutableList(com.google.common.collect.ImmutableList) StashbotUrlBuilder(com.palantir.stash.stashbot.urlbuilder.StashbotUrlBuilder) NavBuilder(com.atlassian.stash.nav.NavBuilder) RepositoryConfiguration(com.palantir.stash.stashbot.persistence.RepositoryConfiguration) JenkinsServerConfiguration(com.palantir.stash.stashbot.persistence.JenkinsServerConfiguration) RepositoryCloneLinksRequest(com.atlassian.stash.repository.RepositoryCloneLinksRequest) ImmutableMap(com.google.common.collect.ImmutableMap) Map(java.util.Map) Template(org.apache.velocity.Template) JobTemplate(com.palantir.stash.stashbot.persistence.JobTemplate)

Example 13 with JobTemplate

use of com.palantir.stash.stashbot.persistence.JobTemplate in project stashbot by palantir.

the class JenkinsJobTest method testNewJobWorkflow.

@Test
public void testNewJobWorkflow() throws Exception {
    int sizeOfData = ao.count(JobTemplate.class);
    final String NEW_JOB = "newJobName";
    final String TEMPLATE_FILE = "verify-template.xml";
    JobTemplate newjob = jtm.getJobTemplate(NEW_JOB);
    Assert.assertEquals(newjob.getName(), NEW_JOB);
    Assert.assertEquals(newjob.getTemplateFile(), TEMPLATE_FILE);
    Assert.assertEquals(newjob.getJobType(), JobType.NOOP);
    int newSizeOfData = ao.count(JobTemplate.class);
    Assert.assertTrue(newSizeOfData == sizeOfData + 1);
}
Also used : JobTemplate(com.palantir.stash.stashbot.persistence.JobTemplate) Test(org.junit.Test)

Example 14 with JobTemplate

use of com.palantir.stash.stashbot.persistence.JobTemplate in project stashbot by palantir.

the class JenkinsJobTest method testCreatesDefaultObjects.

@Test
public void testCreatesDefaultObjects() throws Exception {
    JobTemplate jjtV = jtm.getDefaultVerifyJob();
    JobTemplate jjtP = jtm.getDefaultPublishJob();
    JobTemplate jjtPR = jtm.getDefaultVerifyPullRequestJob();
    Assert.assertEquals(jjtV.getName(), "verification");
    Assert.assertEquals(jjtPR.getName(), "verify-pr");
    Assert.assertEquals(jjtP.getName(), "publish");
    int newSizeOfData = ao.count(JobTemplate.class);
    Assert.assertTrue(newSizeOfData == 3);
}
Also used : JobTemplate(com.palantir.stash.stashbot.persistence.JobTemplate) Test(org.junit.Test)

Example 15 with JobTemplate

use of com.palantir.stash.stashbot.persistence.JobTemplate in project stashbot by palantir.

the class JenkinsManagerTest method testUpdateJob.

@Test
public void testUpdateJob() throws Exception {
    String jobName = "somename_verification";
    Job existingJob = Mockito.mock(Job.class);
    Map<String, Job> jobMap = new HashMap<String, Job>();
    jobMap.put(jobName, existingJob);
    Mockito.when(jenkinsServer.getJobs()).thenReturn(jobMap);
    JobTemplate jt = jtm.getDefaultVerifyJob();
    jenkinsManager.updateJob(repo, jt);
    ArgumentCaptor<String> xmlCaptor = ArgumentCaptor.forClass(String.class);
    Mockito.verify(xmlFormatter).generateJobXml(jt, repo);
    Mockito.verify(jenkinsServer).updateJob(Mockito.anyString(), xmlCaptor.capture());
    Mockito.verify(jenkinsServer, Mockito.never()).createJob(Mockito.anyString(), Mockito.anyString());
    Assert.assertEquals(XML_STRING, xmlCaptor.getValue());
}
Also used : HashMap(java.util.HashMap) Job(com.offbytwo.jenkins.model.Job) JobTemplate(com.palantir.stash.stashbot.persistence.JobTemplate) Test(org.junit.Test)

Aggregations

JobTemplate (com.palantir.stash.stashbot.persistence.JobTemplate)21 Test (org.junit.Test)9 Job (com.offbytwo.jenkins.model.Job)6 RepositoryConfiguration (com.palantir.stash.stashbot.persistence.RepositoryConfiguration)5 JenkinsServerConfiguration (com.palantir.stash.stashbot.persistence.JenkinsServerConfiguration)4 IOException (java.io.IOException)4 SQLException (java.sql.SQLException)4 DBParam (net.java.ao.DBParam)4 PullRequest (com.atlassian.stash.pull.PullRequest)2 Repository (com.atlassian.stash.repository.Repository)2 JenkinsServer (com.offbytwo.jenkins.JenkinsServer)2 JobMapping (com.palantir.stash.stashbot.persistence.JobMapping)2 URISyntaxException (java.net.URISyntaxException)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 ServletException (javax.servlet.ServletException)2 HttpResponseException (org.apache.http.client.HttpResponseException)2 BuildStatus (com.atlassian.stash.build.BuildStatus)1 State (com.atlassian.stash.build.BuildStatus.State)1 InternalBuildStatus (com.atlassian.stash.internal.build.InternalBuildStatus)1