Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Update VSTS PR Jenkins build status back to VSTS #175

Merged
merged 21 commits into from
Sep 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d11525f
Merge remote-tracking branch 'refs/remotes/jenkinsci/master'
smile21prc Jun 23, 2017
8d33bd4
Merge branch 'master' of git://github.com/jenkinsci/tfs-plugin
smile21prc Aug 11, 2017
bb6d9c9
Merge remote-tracking branch 'upstream/master'
smile21prc Aug 22, 2017
e599ec7
Merge remote-tracking branch 'upstream/master'
smile21prc Aug 22, 2017
b92d2a9
Update VSTS PR Jenkins build status back to VSTS
smile21prc Sep 14, 2017
abf475b
More changes.
smile21prc Sep 14, 2017
45f897e
Remove redudant API
smile21prc Sep 14, 2017
cc9adb2
Add support of reporting build status of multi-jobs triggered by one PR
smile21prc Sep 15, 2017
6628c90
Add support of showing customized run config in VSTS PR Status UI.
smile21prc Sep 16, 2017
4d30307
Add a few null check.
smile21prc Sep 16, 2017
eb8fad7
Remove unnecessary status update.
smile21prc Sep 18, 2017
6e33741
Fixed status display typo
smile21prc Sep 18, 2017
a047e8d
Add jelly support
smile21prc Sep 19, 2017
614d260
Add a seperate checkbox for PR trigger, and fully enable its status u…
smile21prc Sep 20, 2017
7ee55be
Remove redundant entry in pom
smile21prc Sep 20, 2017
e617e3b
Address review comments.
smile21prc Sep 20, 2017
032b538
Address review comments.
smile21prc Sep 22, 2017
8de1f7a
Pass additional params to Jenkins build for PR job auto-gen
smile21prc Sep 22, 2017
868c8ba
Renaming to vstsBranchOrCommit
smile21prc Sep 25, 2017
530bb4b
Add constructor to allow creating a job trigger with job context param.
smile21prc Sep 26, 2017
d66e61b
Added support of branch-specific triggering for both PR and code push
smile21prc Sep 27, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 61 additions & 10 deletions tfs/src/main/java/hudson/plugins/tfs/JenkinsEventNotifier.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package hudson.plugins.tfs;

import hudson.plugins.tfs.model.ConnectionParameters;
import hudson.plugins.tfs.model.GitStatusContext;
import hudson.plugins.tfs.model.GitStatusState;
import hudson.plugins.tfs.model.JobCompletionEventArgs;
import hudson.plugins.tfs.model.PullRequestMergeCommitCreatedEventArgs;
import hudson.plugins.tfs.model.TeamGitStatus;
import hudson.plugins.tfs.util.TeamRestClient;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
Expand All @@ -17,6 +21,8 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
Expand Down Expand Up @@ -61,6 +67,46 @@ public static void sendJobCompletionEvent(final JSONObject payload) {
}
}

/**
* Send the build status of VSTS pull request back to connected TFS/VSTS servers only for those jobs kicked off by PRs.
*/
public static void sendPullRequestBuildStatusEvent(final CommitParameterAction commitParameter, final GitStatusState buildState, final String buildDescription, final String targetUrl, final String jobFullPath) {
try {
if (commitParameter != null) {
if (commitParameter instanceof PullRequestParameterAction) {
final PullRequestParameterAction prpa = (PullRequestParameterAction) commitParameter;
final PullRequestMergeCommitCreatedEventArgs pullRequestMergeCommitCreatedEventArgs = prpa.getPullRequestMergeCommitCreatedEventArgs();
sendPullRequestBuildStatusEvent(pullRequestMergeCommitCreatedEventArgs, buildState, buildDescription, targetUrl, jobFullPath);
}
}
} catch (final Exception e) {
log.warning("ERROR: sendPullRequestBuildStatusEvent fails due to exception: " + e.getMessage());
}
return;
}

/**
* Send the build status of VSTS pull request back to connected TFS/VSTS servers.
*/
public static void sendPullRequestBuildStatusEvent(final PullRequestMergeCommitCreatedEventArgs gitCodePushedEventArgs, final GitStatusState buildState, final String buildDescription, final String targetUrl, final String jobFullPath) {
try {
final TeamGitStatus status = new TeamGitStatus();
status.state = buildState;
status.description = buildDescription;
status.targetUrl = targetUrl;
status.context = new GitStatusContext(" ", StringUtils.stripEnd(jobFullPath, "/"));

final URI collectionUri = gitCodePushedEventArgs.collectionUri;
final TeamRestClient client = new TeamRestClient(collectionUri);
client.addPullRequestStatus(gitCodePushedEventArgs, status);
} catch (MalformedURLException e) {
log.warning("ERROR: sendPullRequestBuildStatusEvent fails due to MalformedURLException: " + e.getMessage());
} catch (IOException e) {
log.warning("ERROR: sendPullRequestBuildStatusEvent fails due to IOException: " + e.getMessage());
}
return;
}

/**
* This is a helper method to get the JSON for a Jenkins object.
* @param url
Expand All @@ -81,17 +127,22 @@ public static String getApiJson(final String url) {
request.addHeader("User-Agent", "Jenkins-Self");

final HttpResponse response = client.execute(request);

try (BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent(), ENCODING))) {

final StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
result.append("\n");
final int statusCode = response.getStatusLine().getStatusCode();

if (statusCode <= HttpURLConnection.HTTP_ACCEPTED) {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent(), ENCODING))) {
final StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
result.append("\n");
}
return result.toString();
}
return result.toString();
} else {
log.warning("ERROR: getApiJson: (url=" + url + ") failed due to Http error #" + statusCode);
return null;
}
} catch (final IOException e) {
log.warning("ERROR: getApiJson: (url=" + url + ") " + e.getMessage());
Expand Down
66 changes: 66 additions & 0 deletions tfs/src/main/java/hudson/plugins/tfs/SafeParametersAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package hudson.plugins.tfs;

import hudson.EnvVars;
import hudson.Extension;
import hudson.model.EnvironmentContributor;
import hudson.model.ParameterValue;
import hudson.model.ParametersAction;
import hudson.model.Run;
import hudson.model.TaskListener;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* Extension class of ParametersAction to pass in parameters as safe parameters..
*/
@Restricted(NoExternalUse.class)
public class SafeParametersAction extends ParametersAction {

private List<ParameterValue> parameters;

public SafeParametersAction(final List<ParameterValue> parameters) {
this.parameters = parameters;
}

public SafeParametersAction(final ParameterValue... parameters) {
this(Arrays.asList(parameters));
}

@Override
public List<ParameterValue> getParameters() {
return Collections.unmodifiableList(parameters);
}

@Override
public ParameterValue getParameter(final String name) {
for (ParameterValue parameter : parameters) {
if (parameter != null && parameter.getName().equals(name)) {
return parameter;
}
}

return null;
}

/**
* Environment contributor for SafeParametersAction.
*/
@Extension
public static final class SafeParametersActionEnvironmentContributor extends EnvironmentContributor {

@Override
public void buildEnvironmentFor(final Run r, final EnvVars envs, final TaskListener listener) throws IOException, InterruptedException {
SafeParametersAction action = r.getAction(SafeParametersAction.class);
if (action != null) {
for (ParameterValue p : action.getParameters()) {
envs.putIfNotNull(p.getName(), String.valueOf(p.getValue()));
}
}
}
}
}
16 changes: 16 additions & 0 deletions tfs/src/main/java/hudson/plugins/tfs/TeamEventsEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
Expand Down Expand Up @@ -235,6 +237,20 @@ public static <T extends Trigger> T findTrigger(final Job<?, ?> job, final Class
return null;
}

// A job may have multiple triggers of the same type. For example, both TeamPRPushTrigger and TeamPushTrigger are TeamPushTrigger type.
public static <T extends Trigger> List<T> findTriggers(final Job<?, ?> job, final Class<T> tClass) {
List<T> triggerList = new ArrayList<>();
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
final ParameterizedJobMixIn.ParameterizedJob pJob = (ParameterizedJobMixIn.ParameterizedJob) job;
for (final Trigger trigger : pJob.getTriggers().values()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there not a getTriggers on non ParameterizedJobs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nop, I don't see one in its member list, if a job isn't a ParameterizedJob:

jobgetfunclist

if (tClass.isInstance(trigger)) {
triggerList.add(tClass.cast(trigger));
}
}
}
return triggerList;
}

/**
* A response contributor for triggering polling of a project.
*
Expand Down
46 changes: 46 additions & 0 deletions tfs/src/main/java/hudson/plugins/tfs/TeamPRPushTrigger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package hudson.plugins.tfs;

import hudson.Extension;
import hudson.model.Job;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

/**
* Triggers a build when we receive a TFS/Team Services Git code push event in a TFS pull request.
*/
public class TeamPRPushTrigger extends TeamPushTrigger {

private String targetBranches;

@DataBoundConstructor
public TeamPRPushTrigger() {
}

public TeamPRPushTrigger(final Job<?, ?> job, final String targetBranches, final String jobContext) {
this.job = job;
this.targetBranches = targetBranches;

setJobContext(jobContext);
}

public String getTargetBranches() {
return targetBranches;
}

@DataBoundSetter
public void setTargetBranches(final String targetBranches) {
this.targetBranches = targetBranches;
}

/**
* This class extends trigger descriptor class from TeamPushTrigger, creating a separate check box for TeamPRPushTrigger.
*/
@Extension
public static class DescriptorImpl extends TeamPushTrigger.DescriptorImpl {

@Override
public String getDisplayName() {
return "Build when a change is pushed to a TFS pull request";
}
}
}
15 changes: 11 additions & 4 deletions tfs/src/main/java/hudson/plugins/tfs/TeamPushCause.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@
public class TeamPushCause extends SCMTriggerCause {

private final String pushedBy;
private final String context;

public TeamPushCause(final String pushedBy) {
this("", pushedBy);
public TeamPushCause(final String pushedBy, final String context) {
this("", pushedBy, context);
}

public TeamPushCause(final File logFile, final String pushedBy) throws IOException {
public TeamPushCause(final File logFile, final String pushedBy, final String context) throws IOException {
super(logFile);
this.pushedBy = pushedBy;
this.context = context;
}

public TeamPushCause(final String pollingLog, final String pushedBy) {
public TeamPushCause(final String pollingLog, final String pushedBy, final String context) {
super(pollingLog);
this.pushedBy = pushedBy;
this.context = context;
}

@Override
Expand All @@ -43,4 +46,8 @@ public boolean equals(final Object o) {
public int hashCode() {
return super.hashCode();
}

public String getRunContext() {
return this.context;
}
}
Loading