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
Feature/hg hooks over tcp #1416
Conversation
We use JWT for session management, so we can disable shiro session management and this allows usage of SecurityManager outside of a http request.
try { | ||
hookHandler.run(); | ||
} finally { | ||
ThreadContext.unbindSubject(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would you unbind the subject here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This because the hook handler does a login, which binds a subject to the thread. We use a cached thread pool, which reuse existing threads and to avoid that a subject is used from a prior hook, we have to unbind it.
/** Field description */ | ||
public static final Set<Feature> FEATURES = | ||
EnumSet.of(Feature.COMBINED_DEFAULT_BRANCH); | ||
public static final Set<Feature> FEATURES = EnumSet.of(Feature.COMBINED_DEFAULT_BRANCH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this field protected
like SonarCloud suggests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why SonarQube thinks that this should be protected
, because FEATURES
is used by HgRepositoryHandler. Changing FEATURES
to protected
leads to a compiler error.
The failing build seams to come from the jest upgrade storybookjs/storybook#10942 |
The message pipeline seems broken with these changes. You can check this easily with the commit message checker and an arbitrary failing regex check. The corresponding error does not reach the client (neither cli nor internal editor) |
Okay, i'll take a look at this. |
I was able to fix the jest tests. |
May it be possible to "transmit" the transaction id to the hook handler, so that the logs can be assigned to the correct request? |
} catch (Exception ex) { | ||
LOG.warn("unknown error on hook occurred", ex); | ||
return error("unknown error"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This catch block fetches all Exceptions from plugins, like for example the commit message checker. I don't think that a warn log is appropriate for these cases. On the other hand exceptions that are not thrown on purpose by plugins can indicate a problem. Problem is: I don't know a way how to differentiate between them. The PathWP plugin for example uses a simple exception that derives from RuntimeException. So we cannot rely on the usage of ExceptionWithContext.
On second thought, I think would do this:
} catch (Exception ex) { | |
LOG.warn("unknown error on hook occurred", ex); | |
return error("unknown error"); | |
} catch (ExceptioWithContextn ex) { | |
LOG.debug("scm exception on hook occurred", ex); | |
return error(ex.getMessage()); | |
} catch (Exception ex) { | |
LOG.warn("unknown error on hook occurred", ex); | |
return error("unknown error"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've applied your suggestion, but i've passed the message of the exception instead of "unkown error". This restores the behaviour before that change, but i'm not sure if this is the best way. Because we could leak technical details on unwanted exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The leak is exactly why i've left it the way you've done it before for unknown exceptions. If you want to have proper messages, one should use ExceptioWithContext
.
scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/hooks/HookServer.java
Outdated
Show resolved
Hide resolved
scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/hooks/HookServer.java
Outdated
Show resolved
Hide resolved
scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/hooks/HookServer.java
Outdated
Show resolved
Hide resolved
scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java
Outdated
Show resolved
Hide resolved
…m-manager into feature/hg_hooks_over_tcp
Done |
Ok, don't know exactly how I got here, but I try to recap:
This is what I got now:
And here is the generic 500 exception:
I could reproduce this in a second repository: On the first change, I got the correct error message, the following commits hung up, after a restart I got generic exceptions due to the stack trace above. |
The problem was introduced with the passthrough of the transaction id. However i've modified the hook socket protocol to be more robust, because the former error has lead to an endless loop in the python process. With the new implementation this should never happen again. |
abaa7b9
to
c0ae910
Compare
Okay, now the process does not hang up, but again the error messages (for example from the custom message validator) are not propagated. |
This is interesting. Indeed I get the correct error messaage with a repository I've not used for testing this before, but not with the one I used for the last test. Is the latter one broken somehow? |
It is possible, that the old repository had a non finished transaction (abort: abandoned transaction found). This could happen with the prior version, when the pre receive hook hangs. I think it is possible to fix the abandoned transaction manually with |
Indeed this fixed this issue, thanks! We'll have a look at the code later and get back to you ;-) |
# Conflicts: # CHANGELOG.md
41953e1
to
8ee8c8b
Compare
Use waitFor instead of exitValue to wait for process to finish
Kudos, SonarCloud Quality Gate passed! |
Fixes a regression which was introduced with #1416. In #1416 we have reimplemented the way configuration is passed to the mercurial cgi handler. Before #1416 we used environment variables which are picked up by hgweb.py, after #1416 we pass mercurial configurations as command line parameters directly in the HgCGIServlet. But sadly the configuration option for httppostargs uses still an environment variable, which is not picked up by anyone. See #1525
Proposed changes
Implement mercurial hook callback over a separate tcp socket. This replaces the http based solution which is theoretically vulnerable to manipulated http request, see #1411 for more details.
The change is tested with https://github.com/scm-manager/hg-server-spec
Your checklist for this pull request
Checklist for branch merge request (not required for forks)