Skip to content

Add disable toggle and user required role configuration for rerun action #448

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@
import hudson.model.Job;
import hudson.model.ParametersAction;
import hudson.model.Run;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.ACLContext;
import jenkins.model.ParameterizedJobMixIn;

import io.jenkins.plugins.checks.github.status.GitHubStatusChecksProperties;

import io.jenkins.plugins.util.JenkinsFacade;

/**
Expand All @@ -45,20 +48,23 @@ public class CheckRunGHEventSubscriber extends GHEventsSubscriber {

private final JenkinsFacade jenkinsFacade;
private final SCMFacade scmFacade;
private final GitHubStatusChecksProperties githubStatusChecksProperties;

/**
* Construct the subscriber.
*/
public CheckRunGHEventSubscriber() {
this(new JenkinsFacade(), new SCMFacade());
this(new JenkinsFacade(), new SCMFacade(), new GitHubStatusChecksProperties());
}

@VisibleForTesting
CheckRunGHEventSubscriber(final JenkinsFacade jenkinsFacade, final SCMFacade scmFacade) {
CheckRunGHEventSubscriber(final JenkinsFacade jenkinsFacade, final SCMFacade scmFacade,
final GitHubStatusChecksProperties githubStatusChecksProperties) {
super();

this.jenkinsFacade = jenkinsFacade;
this.scmFacade = scmFacade;
this.githubStatusChecksProperties = githubStatusChecksProperties;
}

@Override
Expand Down Expand Up @@ -91,42 +97,66 @@ protected void onEvent(final GHSubscriberEvent event) {
LOGGER.log(Level.INFO, "Received rerun request through GitHub checks API.");
try (ACLContext ignored = ACL.as2(ACL.SYSTEM2)) {
String branchName = payloadJSON.getJSONObject("check_run").getJSONObject("check_suite").optString("head_branch");
scheduleRerun(checkRun, branchName);
final GHRepository repository = checkRun.getRepository();

Optional<Run<?, ?>> optionalRun = jenkinsFacade.getBuild(checkRun.getCheckRun().getExternalId());
if (optionalRun.isPresent()) {
Run<?, ?> run = optionalRun.get();
Job<?, ?> job = run.getParent();
boolean isDisableRerunAction = githubStatusChecksProperties.isDisableRerunAction(job);
String rerunActionRole = githubStatusChecksProperties.getRerunActionRole(job);

if (!isDisableRerunAction) {
if (!rerunActionRole.isBlank()) {
User user = User.get(checkRun.getSender().getLogin());
List<String> userRoles = user.getAuthorities();
if (userRoles.contains(rerunActionRole)) {
scheduleRerun(checkRun, branchName, run, job);
} else {
LOGGER.log(
Level.WARNING,
String.format(
"The user %s does not have the required %s role for the rerun action on job %s",
checkRun.getSender().getLogin(),
rerunActionRole,
jenkinsFacade.getFullNameOf(job)
)
);
}
} else {
scheduleRerun(checkRun, branchName, run, job);
}
} else {
LOGGER.log(Level.INFO, String.format("Rerun action is disabled for job %s", jenkinsFacade.getFullNameOf(job)));
}
}
else {
LOGGER.log(Level.WARNING, String.format("No build found for rerun request from repository: %s and id: %s",
repository.getFullName(), checkRun.getCheckRun().getExternalId()).replaceAll("[\r\n]", ""));
}
}
}
catch (IOException | JSONException e) {
throw new IllegalStateException("Could not parse check run event: " + payload.replaceAll("[\r\n]", ""), e);
}
}

private void scheduleRerun(final GHEventPayload.CheckRun checkRun, final String branchName) {
final GHRepository repository = checkRun.getRepository();

Optional<Run<?, ?>> optionalRun = jenkinsFacade.getBuild(checkRun.getCheckRun().getExternalId());
if (optionalRun.isPresent()) {
Run<?, ?> run = optionalRun.get();
Job<?, ?> job = run.getParent();
private void scheduleRerun(final GHEventPayload.CheckRun checkRun, final String branchName, final Run<?, ?> run, final Job<?, ?> job) {
Cause cause = new GitHubChecksRerunActionCause(checkRun.getSender().getLogin(), branchName);

Cause cause = new GitHubChecksRerunActionCause(checkRun.getSender().getLogin(), branchName);
List<Action> actions = new ArrayList<>();
actions.add(new CauseAction(cause));

List<Action> actions = new ArrayList<>();
actions.add(new CauseAction(cause));

ParametersAction paramAction = run.getAction(ParametersAction.class);
if (paramAction != null) {
actions.add(paramAction);
}
ParametersAction paramAction = run.getAction(ParametersAction.class);
if (paramAction != null) {
actions.add(paramAction);
}

ParameterizedJobMixIn.scheduleBuild2(job, 0, actions.toArray(new Action[0]));
ParameterizedJobMixIn.scheduleBuild2(job, 0, actions.toArray(new Action[0]));

LOGGER.log(Level.INFO, String.format("Scheduled rerun (build #%d) for job %s, requested by %s",
job.getNextBuildNumber(), jenkinsFacade.getFullNameOf(job),
checkRun.getSender().getLogin()).replaceAll("[\r\n]", ""));
}
else {
LOGGER.log(Level.WARNING, String.format("No build found for rerun request from repository: %s and id: %s",
repository.getFullName(), checkRun.getCheckRun().getExternalId()).replaceAll("[\r\n]", ""));
}
LOGGER.log(Level.INFO, String.format("Scheduled rerun (build #%d) for job %s, requested by %s",
job.getNextBuildNumber(), jenkinsFacade.getFullNameOf(job),
checkRun.getSender().getLogin()).replaceAll("[\r\n]", ""));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class GitHubSCMSourceStatusChecksTrait extends SCMSourceTrait implements
private String name = "Jenkins";
private boolean suppressLogs = false;
private boolean skipProgressUpdates = false;
private String rerunActionRole = "";
private boolean disableRerunAction = false;

/**
* Constructor for stapler.
Expand Down Expand Up @@ -79,10 +81,21 @@ public boolean isSuppressLogs() {
return suppressLogs;
}

@Override
public String getRerunActionRole() {
return rerunActionRole;
}

@Override
public boolean isDisableRerunAction() {
return disableRerunAction;
}

@Override
public boolean isSkipProgressUpdates() {
return skipProgressUpdates;
}


@DataBoundSetter
public void setSkipProgressUpdates(final boolean skipProgressUpdates) {
Expand Down Expand Up @@ -126,6 +139,16 @@ public void setSuppressLogs(final boolean suppressLogs) {
this.suppressLogs = suppressLogs;
}

@DataBoundSetter
public void setRerunActionRole(final String rerunActionRole) {
this.rerunActionRole = rerunActionRole;
}

@DataBoundSetter
public void setDisableRerunAction(final boolean disableRerunAction) {
this.disableRerunAction = disableRerunAction;
}

@Override
protected void decorateContext(final SCMSourceContext<?, ?> context) {
if (isSkipNotifications() && context instanceof GitHubSCMSourceContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ public interface GitHubStatusChecksConfigurations {
*/
boolean isSuppressLogs();

/**
* Defines whether a role is required to use the rerun action.
*
* @return the name of the role
*/
String getRerunActionRole();

/**
* Defines whether to disable rerun action.
*
* @return true to disable rerun action
*/
boolean isDisableRerunAction();

/**
* Returns whether to suppress progress updates from the {@code io.jenkins.plugins.checks.status.FlowExecutionAnalyzer}.
* Queued, Checkout and Completed will still run but not 'onNewHead'
Expand Down Expand Up @@ -62,6 +76,16 @@ public boolean isSuppressLogs() {
return false;
}

@Override
public String getRerunActionRole() {
return "";
}

@Override
public boolean isDisableRerunAction() {
return false;
}

@Override
public boolean isSkipProgressUpdates() {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ public boolean isSuppressLogs(final Job<?, ?> job) {
return getConfigurations(job).orElse(DEFAULT_CONFIGURATION).isSuppressLogs();
}

public String getRerunActionRole(final Job<?, ?> job) {
return getConfigurations(job).orElse(DEFAULT_CONFIGURATION).getRerunActionRole();
}

public boolean isDisableRerunAction(final Job<?, ?> job) {
return getConfigurations(job).orElse(DEFAULT_CONFIGURATION).isDisableRerunAction();
}

@Override
public boolean isSkipProgressUpdates(final Job<?, ?> job) {
return getConfigurations(job).orElse(DEFAULT_CONFIGURATION).isSkipProgressUpdates();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class GitSCMStatusChecksExtension extends GitSCMExtension implements GitH
private String name = "Jenkins";
private boolean suppressLogs;
private boolean skipProgressUpdates = false;
private String rerunActionRole = "";
private boolean disableRerunAction = false;

/**
* Constructor for stapler.
Expand Down Expand Up @@ -51,6 +53,16 @@ public boolean isSuppressLogs() {
return suppressLogs;
}

@Override
public String getRerunActionRole() {
return rerunActionRole;
}

@Override
public boolean isDisableRerunAction() {
return disableRerunAction;
}

@Override
public boolean isSkipProgressUpdates() {
return skipProgressUpdates;
Expand Down Expand Up @@ -93,6 +105,16 @@ public void setSuppressLogs(final boolean suppressLogs) {
this.suppressLogs = suppressLogs;
}

@DataBoundSetter
public void setRerunActionRole(final String rerunActionRole) {
this.rerunActionRole = rerunActionRole;
}

@DataBoundSetter
public void setDisableRerunAction(final boolean disableRerunAction) {
this.disableRerunAction = disableRerunAction;
}

/**
* Descriptor implementation for {@link GitSCMStatusChecksExtension}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,12 @@
<f:checkbox/>
</f:entry>

<f:entry title="${%User role required for rerun action}" field="rerunActionRole">
<f:textbox/>
</f:entry>

<f:entry title="Disable rerun action" field="disableRerunAction">
<f:checkbox/>
</f:entry>

</j:jelly>
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:g="/lib/github-checks/status">
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:g="/lib/github-checks/status">

<g:properties/>

<f:entry title="${%User role required for rerun action}" field="rerunActionRole">
<f:textbox/>
</f:entry>

<f:entry title="Disable rerun action" field="disableRerunAction">
<f:checkbox/>
</f:entry>

</j:jelly>
Loading
Loading