Skip to content
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
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ WildFly GitHub Bot helps you to keep your pull requests in the correct format.
This project is built with usage of Quarkus GitHub App: https://quarkiverse.github.io/quarkiverse-docs/quarkus-github-app/dev/index.html

## Functionality
* Expected format for Pull Requests - Defined in config file:
* Title - Regex, we expect to match for title of the Pull Request.
* Commit - Regex, we expect to match for at least one commit in the Pull Request.
* Description - Regexes, we expect to match for description of the Pull Request.
* _Format_ checks for Pull Requests - Defined in config file under `format`:
* _Title_ - Checks the title of the Pull Request against the `projectKey` pattern.
* _Commit_ - Checks at least one commit message against the `projectKey` pattern.
* _Description_ - Checks the description of the Pull Request against configured regexes.
* _Skip_ - Regex pattern(s) matched against PR description to skip format checks.
* _Activation Rules_ for matching on Pull Requests and applying __functionality__ - Defined in config file:
* __Notify__ - List of people to request Pull Request review. People, we can't request review from, we only cc notify them - Rule functionality.
* __Labels__ - Labels to apply on the Pull Request - Rule functionality.
* _Title_ - Regex, used on title of the Pull Request - Rule activation.
* _Body_ - Regex, used on body of the Pull Request - Rule activation.
* _TitleBody_ - Regex, used on either title or body of the Pull Request - Rule activation.
* _Directories_ - List of directories, if corresponding files are changed in the Pull Request - Rule activation.
* Option to disable format checks on Pull Request by adding message `@<github-app-name>[bot] skip format` in the description.
* Automatically append JIRA links into description of the Pull Request, if issue tracker number is detected in Title, Description or Commit.
* Automatically applies/removes labels on a Pull Request:
* `rebase-this` - depending on conflicts with `main` branch.
Expand Down Expand Up @@ -115,8 +115,9 @@ wildfly:
- github-user-handle1
- github-user-handle2
format:
skip: "\\[skip format\\]"
title:
message: Wrong content of the PR title
failMessage: Wrong content of the PR title
description: # 3
regexes:
- pattern: JIRA:\s+https://redhat.atlassian.net/browse/WFLY-\d+|https://redhat.atlassian.net/browse/WFLY-\d+
Expand All @@ -129,7 +130,7 @@ wildfly:
2. `title` - Checks the title of a PR by using a regular expression generated from `projectKey` field, which is by default "WFLY". You can find more information in [wildfly-bot-config-example.yml](wildfly-bot-config-example.yml)
3. `description` - Checks comments of a PR by using individual regular expressions in the `pattern` fields under `regexes`.
> For example, the correct format is "https://issues.jboss.org/browse/WFLY-11".
4. `message` - The text of an error message in the respective check.
4. `failMessage` - The message displayed when the respective check fails.
5. `emails` - List of emails to receive notifications.

> [!IMPORTANT]
Expand All @@ -149,7 +150,7 @@ wildfly:
- github-user-handle2
format:
title:
message: Wrong content of the PR title
failMessage: Wrong content of the PR title
emails:
- nonexistingemail@whatever.com
- whoever@nonexistingmailingservice.com
Expand Down
17 changes: 8 additions & 9 deletions src/main/java/org/wildfly/bot/ConfigFileChangeProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.wildfly.bot.util.PullRequestLogger;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import org.jboss.logging.Logger;
import org.kohsuke.github.GHContent;
import org.kohsuke.github.GHEventPayload;
import org.kohsuke.github.GHFileNotFoundException;
Expand All @@ -33,11 +32,11 @@
public class ConfigFileChangeProcessor {

private static final String CHECK_NAME = "Configuration File";
private static final Logger LOG_DELEGATE = Logger.getLogger(ConfigFileChangeProcessor.class);
private final PullRequestLogger LOG = new PullRequestLogger(LOG_DELEGATE);
private static final String WARN_RULE = "[WARN] - %s";
private static final String ERROR_RULE = "[ERROR] - %s";

private final PullRequestLogger logger = PullRequestLogger.getLogger(ConfigFileChangeProcessor.class);

@Inject
GitHubConfigFileProviderImpl fileProvider;

Expand All @@ -52,7 +51,7 @@ void onFileChanged(
@PullRequest.Opened @PullRequest.Edited @PullRequest.Synchronize @PullRequest.Reopened @PullRequest.ReadyForReview GHEventPayload.PullRequest pullRequestPayload,
GitHub gitHub) throws IOException {
GHPullRequest pullRequest = pullRequestPayload.getPullRequest();
LOG.setPullRequest(pullRequest);
logger.setPullRequest(pullRequest);

GHRepository repository = pullRequest.getRepository();
for (GHPullRequestFileDetail changedFile : pullRequest.listFiles()) {
Expand All @@ -69,20 +68,20 @@ void onFileChanged(
List<String> problems = validateFile(file.get(), repository);
if (problems.isEmpty()) {
githubProcessor.commitStatusSuccess(pullRequest, CHECK_NAME, "Valid");
LOG.info("Configuration File check successful");
logger.info("Configuration File check successful");
} else {
githubProcessor.commitStatusError(pullRequest, CHECK_NAME,
"One or multiple rules are invalid, please see the comment stating the problems");
LOG.warnf("Configuration File check unsuccessful. %s", String.join(",", problems));
logger.warnf("Configuration File check unsuccessful. %s", String.join(",", problems));
}
githubProcessor.formatComment(pullRequest, RuntimeConstants.FAILED_CONFIGFILE_COMMENT, problems);
} else {
String message = "Configuration File check unsuccessful. Unable to correctly map loaded file to YAML.";
githubProcessor.commitStatusError(pullRequest, CHECK_NAME, message);
LOG.debugf(message);
logger.debugf(message);
}
} catch (JsonProcessingException e) {
LOG.errorf(e, "Unable to parse the configuration file from the repository %s",
logger.errorf(e, "Unable to parse the configuration file from the repository %s",
pullRequest.getHead().getRepository().getFullName());
githubProcessor.commitStatusError(pullRequest, CHECK_NAME, "Unable to parse the configuration file. " +
"Make sure it can be loaded to model at https://github.com/wildfly/wildfly-github-bot/blob/main/CONFIGURATION.yml");
Expand Down Expand Up @@ -131,7 +130,7 @@ List<String> validateFile(WildFlyConfigFile file, GHRepository repository) throw
"Server returned HTTP response code: 200, message: 'null' for URL: https://api.github.com/repos/"))) {
problems.add(ERROR_RULE.formatted("Rule [" + rule.toPrettyString()
+ "] has the following non-existing directory specified: " + directory));
LOG.debugf(e, "Exception on directories check caught");
logger.debugf(e, "Exception on directories check caught");
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/wildfly/bot/InstallationObserver.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@
@ApplicationScoped
public class InstallationObserver {

private static final Logger LOG = Logger.getLogger(InstallationObserver.class);
private static final Logger logger = Logger.getLogger(InstallationObserver.class);

@Inject
GitHubBotContextProvider botContextProvider;

void suspendedInstallation(@Installation.Suspend GHEventPayload.Installation installationPayload) {
GHAppInstallation installation = installationPayload.getInstallation();
LOG.infof(
logger.infof(
"%s has been suspended for following installation id: %d and will not be able to listen for any incoming Events.",
botContextProvider.getBotName(), installation.getAppId());
}

void unsuspendedInstallation(@Installation.Unsuspend GHEventPayload.Installation installationPayload) {
GHAppInstallation installation = installationPayload.getInstallation();
LOG.infof(
logger.infof(
"%s has been unsuspended for following installation id: %d and has started to listen for new incoming Events.",
botContextProvider.getBotName(), installation.getAppId());
}
Expand Down
59 changes: 29 additions & 30 deletions src/main/java/org/wildfly/bot/LifecycleProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.quarkiverse.githubapp.GitHubClientProvider;
import io.quarkiverse.githubapp.GitHubConfigFileProvider;

import io.quarkus.logging.Log;
import io.quarkus.runtime.StartupEvent;
import org.wildfly.bot.config.WildFlyBotConfig;
import org.wildfly.bot.model.RuntimeConstants;
Expand All @@ -14,7 +13,6 @@
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;

import jakarta.inject.Inject;
import org.jboss.logging.Logger;
import org.kohsuke.github.GHAppInstallation;
import org.kohsuke.github.GHRepository;
Expand All @@ -40,29 +38,30 @@ public class LifecycleProcessor {
---
This is a generated message, please do not respond.""";

private static final Logger LOG = Logger.getLogger(LifecycleProcessor.class);

@Inject
WildFlyBotConfig wildFlyBotConfig;

@Inject
GitHubClientProvider clientProvider;

@Inject
GitHubConfigFileProvider fileProvider;

@Inject
GitHubBotContextProvider botContextProvider;

@Inject
ConfigFileChangeProcessor configFileChangeProcessor;

@Inject
GithubProcessor githubProcessor;
private static final Logger logger = Logger.getLogger(LifecycleProcessor.class);

private final WildFlyBotConfig wildFlyBotConfig;
private final GitHubClientProvider clientProvider;
private final GitHubConfigFileProvider fileProvider;
private final GitHubBotContextProvider botContextProvider;
private final ConfigFileChangeProcessor configFileChangeProcessor;
private final GithubProcessor githubProcessor;

public LifecycleProcessor(WildFlyBotConfig wildFlyBotConfig, GitHubClientProvider clientProvider,
GitHubConfigFileProvider fileProvider, GitHubBotContextProvider botContextProvider,
ConfigFileChangeProcessor configFileChangeProcessor, GithubProcessor githubProcessor) {
// constructor injection
this.wildFlyBotConfig = wildFlyBotConfig;
this.clientProvider = clientProvider;
this.fileProvider = fileProvider;
this.botContextProvider = botContextProvider;
this.configFileChangeProcessor = configFileChangeProcessor;
this.githubProcessor = githubProcessor;
}

void onStart(@Observes StartupEvent event) {
if (wildFlyBotConfig.isDryRun()) {
Log.info(RuntimeConstants.DRY_RUN_PREPEND
logger.info(RuntimeConstants.DRY_RUN_PREPEND
.formatted("GitHub requests will only log statements and not send actual requests to GitHub."));
}

Expand All @@ -87,10 +86,10 @@ void onStart(@Observes StartupEvent event) {
Set.of(RuntimeConstants.LABEL_NEEDS_REBASE, RuntimeConstants.LABEL_FIX_ME));

if (problems.isEmpty()) {
LOG.infof("The configuration file from the repository %s was parsed successfully.",
logger.infof("The configuration file from the repository %s was parsed successfully.",
repository.getFullName());
} else {
LOG.errorf(
logger.errorf(
"The configuration file from the repository %s was not parsed successfully due to following problems: %s",
repository.getFullName(), problems);
githubProcessor.sendEmail(
Expand All @@ -100,25 +99,25 @@ void onStart(@Observes StartupEvent event) {
emailAddresses);
}
} catch (IllegalStateException e) {
LOG.errorf(e, "Unable to retrieve or parse the configuration file from the repository %s",
logger.errorf(e, "Unable to retrieve or parse the configuration file from the repository %s",
repository.getFullName());
}
}
}
} catch (IOException | IllegalStateException e) {
if (e instanceof IOException) {
LOG.warnf(e, "Unable to verify rules in repository.");
logger.warnf(e, "Unable to verify rules in repository.");
} else {
if (e.getCause() instanceof HttpException && e.getCause() != null
&& e.getCause().getMessage().contains("suspended")) {
LOG.warnf(
logger.warnf(
"Your installation has been suspended. No events will be received until you unsuspend the github app installation.");
} else {
LOG.errorf(e, "%s is unable to start.", botContextProvider.getBotName());
logger.errorf(e, "%s is unable to start.", botContextProvider.getBotName());
}
}
LOG.errorf(e, "Unable to correctly start %s for following installation id [%d]", botContextProvider.getBotName(),
installationId);
logger.errorf(e, "Unable to correctly start %s for following installation id [%d]",
botContextProvider.getBotName(), installationId);
}
}

Expand Down
Loading