Skip to content
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

Handling error messaging when PR creation fails with Invalid code error #321

Merged
merged 5 commits into from
Mar 14, 2022
Merged

Handling error messaging when PR creation fails with Invalid code error #321

merged 5 commits into from
Mar 14, 2022

Conversation

avimanyum
Copy link
Contributor

There are cases when the PR creation fails and the exception message thrown looks like this:
{"message":"Validation Failed","errors":[{"resource":"PullRequest","field":"head","code":"invalid"}],"documentation_url":"https://docs.github.com/enterprise/3.1/rest/reference/pulls#create-a-pull-request"}

In such case, this line will throw a NullPointerException since the JsonArray does not have a field called message. Unfortunately, since this error is thrown inside the catch block, it is not handled and essentially terminates the process.

This PR checks for the existence of this key inside the Json object before trying to get it. If it does not find it there, it assumes that the error was due to the head having invalid code (error message shown above). In such a scenario, the method returns an error code of 1, so that we can proceed to safely deleting the forked repo here

@github-actions github-actions bot added the tests Improvements / maintenance to tests label Feb 25, 2022
log.info("error: {}", error);
if (error.startsWith("A pull request already exists")) {
log.info("NOTE: {} New commits may have been added to the pull request.", error);
return 0;
} else if (error.startsWith("No commits between")) {
} else if (error.startsWith("No commits between") || error.startsWith("PR head has invalid code.")) {
Copy link

Choose a reason for hiding this comment

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

Line is longer than 100 characters (found 113).

@codecov
Copy link

codecov bot commented Feb 25, 2022

Codecov Report

Merging #321 (c9bf244) into master (859c50c) will increase coverage by 0.05%.
The diff coverage is 80.00%.

❗ Current head c9bf244 differs from pull request most recent head 596a07d. Consider uploading reports for the commit 596a07d to get more accurate results

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #321      +/-   ##
============================================
+ Coverage     81.49%   81.55%   +0.05%     
- Complexity      263      265       +2     
============================================
  Files            19       19              
  Lines           935      938       +3     
  Branches        126      127       +1     
============================================
+ Hits            762      765       +3     
  Misses          142      142              
  Partials         31       31              
Impacted Files Coverage Δ
...sforce/dockerfileimageupdate/utils/GitHubUtil.java 72.81% <80.00%> (+0.81%) ⬆️

@avimanyum avimanyum added bug Bug fixes and removed tests Improvements / maintenance to tests labels Mar 8, 2022
@afalko afalko requested a review from cjneasbi March 14, 2022 17:18
if (errorJson.get(0).getAsJsonObject().has("message")) {
error = errorJson.get(0).getAsJsonObject().get("message").getAsString();
} else {
error = "PR head has invalid code.";
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does "invalid code" mean? What action should be taken to resolve if any?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The error message is trying to communicate that the field/keyword called "head" contains invalid data. When i saw this message, I manually deleted the fork and the next run was successful. This change will also do the same - deleted the fork.

log.info("error: {}", error);
if (error.startsWith("A pull request already exists")) {
log.info("NOTE: {} New commits may have been added to the pull request.", error);
return 0;
} else if (error.startsWith("No commits between")) {
} else if (error.startsWith("No commits between") || error.startsWith("PR head has invalid code.")) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Repeated error message. Let's make it a constant in this class

Copy link
Collaborator

@afalko afalko left a comment

Choose a reason for hiding this comment

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

LGTM, but I think we should improve the error message.

@github-actions github-actions bot added the tests Improvements / maintenance to tests label Mar 14, 2022
if (errorJson.get(0).getAsJsonObject().has("message")) {
error = errorJson.get(0).getAsJsonObject().get("message").getAsString();
} else {
// This case usually happens when the PR head has invalid data. Deleting the forked repo resolves it.
Copy link

Choose a reason for hiding this comment

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

Line is longer than 100 characters (found 117).

log.info("error: {}", error);
if (error.startsWith("A pull request already exists")) {
log.info("NOTE: {} New commits may have been added to the pull request.", error);
return 0;
} else if (error.startsWith("No commits between")) {
} else if (error.startsWith("No commits between") || error.startsWith(PR_INVALID_CODE)) {
Copy link

Choose a reason for hiding this comment

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

Line is longer than 100 characters (found 101).

@avimanyum avimanyum removed the tests Improvements / maintenance to tests label Mar 14, 2022
@github-actions github-actions bot added the tests Improvements / maintenance to tests label Mar 14, 2022
@@ -29,6 +29,7 @@
public class GitHubUtil {
private static final Logger log = LoggerFactory.getLogger(GitHubUtil.class);
public static final String NO_BRANCH_WARN_FORMAT = "Couldn't find branch `%s` in repo `%s`. Waiting a second...";
public static final String PR_INVALID_CODE = "The PR head has invalid data.";
Copy link
Collaborator

Choose a reason for hiding this comment

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

I still don't think a user or admin will understand this error message. Can we hint at what needs to be done to fix the PR?

@@ -29,6 +29,8 @@
public class GitHubUtil {
private static final Logger log = LoggerFactory.getLogger(GitHubUtil.class);
public static final String NO_BRANCH_WARN_FORMAT = "Couldn't find branch `%s` in repo `%s`. Waiting a second...";
public static final String PR_INVALID_CODE = "The PR head has invalid data. This might be because the repository was migrated to another organization." +
Copy link

Choose a reason for hiding this comment

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

Line is longer than 100 characters (found 157).

@@ -29,6 +29,8 @@
public class GitHubUtil {
private static final Logger log = LoggerFactory.getLogger(GitHubUtil.class);
public static final String NO_BRANCH_WARN_FORMAT = "Couldn't find branch `%s` in repo `%s`. Waiting a second...";
public static final String PR_INVALID_CODE = "The PR head has invalid data. This might be because the repository was migrated to another organization." +
Copy link

Choose a reason for hiding this comment

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

'+' should be on a new line.

@avimanyum avimanyum merged commit c498297 into salesforce:master Mar 14, 2022
@justinharringa
Copy link
Contributor

Hmm... Are there other scenarios that end up taking this path? My concern is that when you delete a fork, the API will lag by hours and may select a fork that is no longer there. Additionally, I believe this may have an effect on open PRs.

log.info("error: {}", error);
if (error.startsWith("A pull request already exists")) {
log.info("NOTE: {} New commits may have been added to the pull request.", error);
return 0;
} else if (error.startsWith("No commits between")) {
} else if (error.startsWith("No commits between") || error.startsWith(PR_INVALID_CODE)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Create a list of error prefixes and use stream operations

List<String> prefixes = Arrays.asList(PR_INVALID_CODE, "No commits between")

if(prefixes.anyMatch(prefix -> errors.startsWith(prefix))

This way if you add more prefixes the if statement doesn't change.

@@ -108,12 +110,18 @@ public int createPullReq(GHRepository origRepo, String branch,
log.warn("Handling error with pull request creation... {}", e.getMessage());
JsonElement root = JsonParser.parseString(e.getMessage());
JsonArray errorJson = root.getAsJsonObject().get("errors").getAsJsonArray();
String error = errorJson.get(0).getAsJsonObject().get("message").getAsString();
String error = "";
if (errorJson.get(0).getAsJsonObject().has("message")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Store the output of errorJson.get(0).getAsJsonObject() as a local variable. Call has and get on that variable. This removes the need to call get(0).getAsJsonObject() twice.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we ignoring other errors if multiple were returned?

error = errorJson.get(0).getAsJsonObject().get("message").getAsString();
} else {
// This case usually happens when the PR head has invalid data. Deleting the forked repo resolves it.
error = PR_INVALID_CODE;
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need this else. Just assign String error = PR_INVALID_CODE at 113.

GHRepository forkRepo = mock(GHRepository.class);
when(forkRepo.getOwnerName()).thenReturn("owner");
assertEquals(gitHubUtil.createPullReq(origRepo, "branch", forkRepo, "title", "body"), 1);
verify(origRepo, times(1)).createPullRequest(eq("title"), eq("owner:branch"), eq("master"), eq("body"));
Copy link
Contributor

Choose a reason for hiding this comment

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

times(1) is the default for verify, you can remove the second parameter.

@avimanyum
Copy link
Contributor Author

Hmm... Are there other scenarios that end up taking this path? My concern is that when you delete a fork, the API will lag by hours and may select a fork that is no longer there. Additionally, I believe this may have an effect on open PRs.

Hmm, in that case we might just want to make sure that we catch the exception by checking if the json field actually exists before accessing it, but not return 1 -> which is what triggers the delete of the fork.

@avimanyum
Copy link
Contributor Author

@cjneasbi Addressed your comments in this new PR - #331

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug fixes tests Improvements / maintenance to tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants