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

Create PR comment on branch update failures #9434

Open
1 of 4 tasks
fgblomqvist opened this issue Apr 7, 2021 · 10 comments
Open
1 of 4 tasks

Create PR comment on branch update failures #9434

fgblomqvist opened this issue Apr 7, 2021 · 10 comments
Labels
priority-4-low Low priority, unlikely to be done unless it becomes important to more people type:feature Feature (new functionality) worker:pr Related to non-onboarding PR creation or update

Comments

@fgblomqvist
Copy link
Contributor

fgblomqvist commented Apr 7, 2021

What Renovate type, platform and version are you using?

Latest, self-hosted Renovate, on GitLab.

Describe the bug

If Renovate fails to update a branch for an MR, it doesn't add a comment to that MR.
E.g. I think the expected behavior would be this:

  1. Renovate creates a branch and PR successfully, all is good
  2. On another run, it wants to make changes to the branch
  3. It fails to make those changes (irrelevant of what the error is)
  4. Now it needs to check if an PR already exists, and if it does, add a comment explaining that it failed to update the branch so the MR should probably not be merged as-is (similar to the artifact update error).

At the moment, Renovate just returns if it fails with any of the branch updating logic:

} catch (err) /* istanbul ignore next */ {
if (err.statusCode === 404) {
logger.debug({ err }, 'Received a 404 error - aborting run');
throw new Error(REPOSITORY_CHANGED);
}
if (err.message === PLATFORM_RATE_LIMIT_EXCEEDED) {
logger.debug('Passing rate-limit-exceeded error up');
throw err;
}
if (err.message === REPOSITORY_CHANGED) {
logger.debug('Passing repository-changed error up');
throw err;
}
if (err.message?.startsWith('remote: Invalid username or password')) {
logger.debug('Throwing bad credentials');
throw new Error(PLATFORM_BAD_CREDENTIALS);
}
if (
err.message?.startsWith(
'ssh_exchange_identification: Connection closed by remote host'
)
) {
logger.debug('Throwing bad credentials');
throw new Error(PLATFORM_BAD_CREDENTIALS);
}
if (err.message === PLATFORM_BAD_CREDENTIALS) {
logger.debug('Passing bad-credentials error up');
throw err;
}
if (err.message === PLATFORM_INTEGRATION_UNAUTHORIZED) {
logger.debug('Passing integration-unauthorized error up');
throw err;
}
if (err.message === MANAGER_LOCKFILE_ERROR) {
logger.debug('Passing lockfile-error up');
throw err;
}
if (err.message?.includes('space left on device')) {
throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);
}
if (err.message === SYSTEM_INSUFFICIENT_DISK_SPACE) {
logger.debug('Passing disk-space error up');
throw err;
}
if (err.message.startsWith('Resource not accessible by integration')) {
logger.debug('Passing 403 error up');
throw err;
}
if (err.message === WORKER_FILE_UPDATE_FAILED) {
logger.warn('Error updating branch: update failure');
} else if (err.message.startsWith('bundler-')) {
// we have already warned inside the bundler artifacts error handling, so just return
return ProcessBranchResult.Error;
} else if (
err.messagee &&
err.message.includes('fatal: Authentication failed')
) {
throw new Error(PLATFORM_AUTHENTICATION_ERROR);
} else if (err.message?.includes('fatal: bad revision')) {
logger.debug({ err }, 'Aborting job due to bad revision error');
throw new Error(REPOSITORY_CHANGED);
} else if (err.message === CONFIG_VALIDATION) {
logger.debug('Passing config validation error up');
throw err;
} else if (err.message === TEMPORARY_ERROR) {
logger.debug('Passing TEMPORARY_ERROR error up');
throw err;
} else if (!(err instanceof ExternalHostError)) {
logger.warn({ err }, `Error updating branch`);
}
// Don't throw here - we don't want to stop the other renovations
return ProcessBranchResult.Error;
}

I think the way to approach this would be to refactor this processing a bit. First of all, probably move out the check for whether a PR already exists or not. Then you'd at least need to identify which errors to simply return on (things like invalid credentials and repo 404's). Finally, on all other errors, attempt to post the error to the PR (if it exists). Something like that.

Relevant debug logs
Here's an example that involves an LFSd package-lock.json, however Renovate's docker image does not yet support LFS so GitLab returns an error when Renovate tries to push a commit for this file:

Click me to see logs
[07:11:30] DEBUG: 2 file(s) to commit (repository=<snip>, branch=<snip>)
[07:11:30] DEBUG: Committing files to branch <snip> (repository=<snip>, branch=<snip>)
[07:11:31] DEBUG: git commit (repository=<snip>, branch=<snip>)
[07:11:31] "result": {
[07:11:31] "author": null,
[07:11:31] "branch": "<snip>",
[07:11:31] "commit": "26c827ab",
[07:11:31] "root": false,
[07:11:31] "summary": {"changes": 2, "insertions": 44781, "deletions": 85}
[07:11:31] }
[07:11:35] DEBUG: Unknown error committing files (repository=<snip>, branch=<snip>)
[07:11:35] "err": {
[07:11:35] "task": {
[07:11:35] "commands": [
[07:11:35] "push",
[07:11:35] "origin",
[07:11:35] "<snip>:<snip>",
[07:11:35] "--force",
[07:11:35] "-u",
[07:11:35] "--no-verify",
[07:11:35] "--verbose",
[07:11:35] "--porcelain"
[07:11:35] ],
[07:11:35] "format": "utf-8"
[07:11:35] },
[07:11:35] "message": "Pushing to <snip>\nPOST git-receive-pack (237751 bytes)\nremote: GitLab: File \"<snip>/package-lock.json\" is larger than the allowed size of 1 MB\nerror: failed to push some refs to '<snip>'\n",
[07:11:35] "stack": "Error: Pushing to <snip>\nPOST git-receive-pack (237751 bytes)\nremote: GitLab: File \"<snip>/package-lock.json\" is larger than the allowed size of 1 MB\nerror: failed to push some refs to '<snip>'\n\n    at GitExecutorChain.onFatalException (/usr/src/app/node_modules/simple-git/src/lib/runners/git-executor-chain.ts:76:77)\n    at GitExecutorChain.<anonymous> (/usr/src/app/node_modules/simple-git/src/lib/runners/git-executor-chain.ts:68:21)\n    at Generator.throw (<anonymous>)\n    at rejected (/usr/src/app/node_modules/simple-git/src/lib/runners/git-executor-chain.js:6:65)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (internal/process/task_queues.js:93:5)"
[07:11:35] }
[07:11:35] WARN: Error updating branch (repository=<snip>, branch=<snip>)
[07:11:35] "err": {
[07:11:35] "task": {
[07:11:35] "commands": [
[07:11:35] "push",
[07:11:35] "origin",
[07:11:35] "<snip>:<snip>",
[07:11:35] "--force",
[07:11:35] "-u",
[07:11:35] "--no-verify",
[07:11:35] "--verbose",
[07:11:35] "--porcelain"
[07:11:35] ],
[07:11:35] "format": "utf-8"
[07:11:35] },
[07:11:35] "message": "Pushing to <snip>\nPOST git-receive-pack (237751 bytes)\nremote: GitLab: File \"<snip>/package-lock.json\" is larger than the allowed size of 1 MB\nerror: failed to push some refs to '<snip>'\n",
[07:11:35] "stack": "Error: Pushing to <snip>\nPOST git-receive-pack (237751 bytes)\nremote: GitLab: File \"<snip>/package-lock.json\" is larger than the allowed size of 1 MB\nerror: failed to push some refs to '<snip>'\n\n    at GitExecutorChain.onFatalException (/usr/src/app/node_modules/simple-git/src/lib/runners/git-executor-chain.ts:76:77)\n    at GitExecutorChain.<anonymous> (/usr/src/app/node_modules/simple-git/src/lib/runners/git-executor-chain.ts:68:21)\n    at Generator.throw (<anonymous>)\n    at rejected (/usr/src/app/node_modules/simple-git/src/lib/runners/git-executor-chain.js:6:65)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (internal/process/task_queues.js:93:5)"
[07:11:35] }

Have you created a minimal reproduction repository?

  • I have provided a minimal reproduction repository
  • I don't have time for that, but it happens in a public repository I have linked to
  • I don't have time for that, and cannot share my private repository
  • The nature of this bug means it's impossible to reproduce publicly

Additional context

I don't think it should be necessary to create a repro repo. I think the relevant logic is here:

} catch (err) /* istanbul ignore next */ {
if (err.statusCode === 404) {
logger.debug({ err }, 'Received a 404 error - aborting run');
throw new Error(REPOSITORY_CHANGED);
}
if (err.message === PLATFORM_RATE_LIMIT_EXCEEDED) {
logger.debug('Passing rate-limit-exceeded error up');
throw err;
}
if (err.message === REPOSITORY_CHANGED) {
logger.debug('Passing repository-changed error up');
throw err;
}
if (err.message?.startsWith('remote: Invalid username or password')) {
logger.debug('Throwing bad credentials');
throw new Error(PLATFORM_BAD_CREDENTIALS);
}
if (
err.message?.startsWith(
'ssh_exchange_identification: Connection closed by remote host'
)
) {
logger.debug('Throwing bad credentials');
throw new Error(PLATFORM_BAD_CREDENTIALS);
}
if (err.message === PLATFORM_BAD_CREDENTIALS) {
logger.debug('Passing bad-credentials error up');
throw err;
}
if (err.message === PLATFORM_INTEGRATION_UNAUTHORIZED) {
logger.debug('Passing integration-unauthorized error up');
throw err;
}
if (err.message === MANAGER_LOCKFILE_ERROR) {
logger.debug('Passing lockfile-error up');
throw err;
}
if (err.message?.includes('space left on device')) {
throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);
}
if (err.message === SYSTEM_INSUFFICIENT_DISK_SPACE) {
logger.debug('Passing disk-space error up');
throw err;
}
if (err.message.startsWith('Resource not accessible by integration')) {
logger.debug('Passing 403 error up');
throw err;
}
if (err.message === WORKER_FILE_UPDATE_FAILED) {
logger.warn('Error updating branch: update failure');
} else if (err.message.startsWith('bundler-')) {
// we have already warned inside the bundler artifacts error handling, so just return
return ProcessBranchResult.Error;
} else if (
err.messagee &&
err.message.includes('fatal: Authentication failed')
) {
throw new Error(PLATFORM_AUTHENTICATION_ERROR);
} else if (err.message?.includes('fatal: bad revision')) {
logger.debug({ err }, 'Aborting job due to bad revision error');
throw new Error(REPOSITORY_CHANGED);
} else if (err.message === CONFIG_VALIDATION) {
logger.debug('Passing config validation error up');
throw err;
} else if (err.message === TEMPORARY_ERROR) {
logger.debug('Passing TEMPORARY_ERROR error up');
throw err;
} else if (!(err instanceof ExternalHostError)) {
logger.warn({ err }, `Error updating branch`);
}
// Don't throw here - we don't want to stop the other renovations
return ProcessBranchResult.Error;
}

I guess you could argue that this is more of a feature request than a bug report, so feel free to change if needed.

I'm not sure when Renovate decides to add comments, but if it e.g. fails to update an Artifact it does (which is very helpful). I think it would make sense/be expected that Renovate adds a comment in any scenario where it didn't successfully manipulate/create/delete the MR. Otherwise, the MR could look good and might be merged, even though something is wrong with it. If you check the Dep Dashboard, you will see that this MR had an error (but you can't expect everyone to do that, and some people don't even have the Dashboard enabled).

@fgblomqvist fgblomqvist added priority-5-triage status:requirements Full requirements are not yet known, so implementation should not be started type:bug Bug fix of existing functionality labels Apr 7, 2021
@viceice

This comment has been minimized.

@viceice viceice closed this as completed Apr 7, 2021
@viceice viceice removed the status:requirements Full requirements are not yet known, so implementation should not be started label Apr 7, 2021
@viceice

This comment has been minimized.

@viceice viceice marked this as a duplicate of #6842 Apr 7, 2021
@fgblomqvist
Copy link
Contributor Author

@viceice This is not a duplicate of those since this is about the fact that Renovate doesn't put a comment when it fails to update a branch. The error could be anything. What if GitLab returns "Error: Something went wrong"? It doesn't matter if the error is LFS-related or not, the behavior is still the same 🙂 .

@fgblomqvist
Copy link
Contributor Author

fgblomqvist commented Apr 7, 2021

To elaborate, this is the scenario:

  1. Renovate creates a branch and MR successfully, all is good
  2. On another run, it wants to make changes to the branch
  3. It fails to make those changes
  4. Now it needs to check if an MR already exists, and if it does, add a comment explaining that it failed to update the branch so the MR should probably not be merged

EDIT: Added this to the issue description.

@viceice
Copy link
Member

viceice commented Apr 7, 2021

Sure but the cause is the same. So feel free to add another pr to handle this specific git error in our git layer. 🤗

@viceice
Copy link
Member

viceice commented Apr 7, 2021

You should at least see a warning on the dashboard

@fgblomqvist
Copy link
Contributor Author

fgblomqvist commented Apr 7, 2021

Sure but the cause is the same. So feel free to add another pr to handle this specific git error in our git layer. 🤗

But what about the general case? Are you saying that for general errors it's better to assume that users will verify on the dashboard whether there are any errors with the MR? 🤔

@viceice
Copy link
Member

viceice commented Apr 8, 2021

Ok, can you please update the PR description to reflect what should be happen? Then reopen the issue.

@viceice viceice added type:feature Feature (new functionality) worker:pr Related to non-onboarding PR creation or update priority-3-medium Default priority, "should be done" but isn't prioritised ahead of others status:requirements Full requirements are not yet known, so implementation should not be started and removed type:bug Bug fix of existing functionality priority-5-triage labels Apr 8, 2021
@viceice viceice reopened this Apr 8, 2021
@viceice viceice changed the title "Error updating branch" does not result in comment on PR Create PR comment on branch update failures Apr 8, 2021
@viceice viceice marked this as not a duplicate of #6842 Apr 8, 2021
@fgblomqvist
Copy link
Contributor Author

Updated the description, let me know what you think! Idk if this is an easy task or not, but it may not be too bad.

@rarkins
Copy link
Collaborator

rarkins commented Apr 8, 2021

Should be easy to find and add the comment. The challenge may be removing it after without adding unnecessary API calls in the other 99.9% of cases

@rarkins rarkins added status:ready priority-4-low Low priority, unlikely to be done unless it becomes important to more people and removed status:requirements Full requirements are not yet known, so implementation should not be started priority-3-medium Default priority, "should be done" but isn't prioritised ahead of others labels Oct 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority-4-low Low priority, unlikely to be done unless it becomes important to more people type:feature Feature (new functionality) worker:pr Related to non-onboarding PR creation or update
Projects
None yet
Development

No branches or pull requests

3 participants