-
-
Notifications
You must be signed in to change notification settings - Fork 128
[JENKINS-71509] Clean up of GradleEnterpriseExceptionTaskListenerDecorator
#318
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
[JENKINS-71509] Clean up of GradleEnterpriseExceptionTaskListenerDecorator
#318
Conversation
| public OutputStream decorateLogger(Run build, OutputStream logger) { | ||
| InjectionConfig injectionConfig = InjectionConfig.get(); | ||
| if (injectionConfig.isEnabled() && injectionConfig.isCheckForBuildAgentErrors()) { | ||
| if (injectionConfig.isEnabled() && injectionConfig.isCheckForBuildAgentErrors() && build != null) { |
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.
Probably unnecessary, but core method does not specify nullability of the build argument, so being defensive.
src/main/java/hudson/plugins/gradle/injection/GradleEnterpriseExceptionLogProcessor.java
Outdated
Show resolved
Hide resolved
| @Override | ||
| public OutputStream decorate(@Nonnull OutputStream logger) { | ||
| if (isBuildAgentErrorsEnabled()) { | ||
| if (run != null) { |
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 fix. We cannot call isBuildAgentErrorsEnabled from the agent side, and even if this value were computed on the controller side and serialized, it would not help because run would still have been left null by deserialization and could not be used here. So simply disable the decorator when remoted.
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.
Could we use a more expressive condition to "know" we're on the controller ? Maybe jenkins.util.JenkinsJVM#isJenkinsJVM ?
As an additional safety net, I think we also need to combine the condition with isBuildAgentErrorsEnabled() (so only executed on the controller) even if it's already called upfront in hudson.plugins.gradle.injection.GradleEnterpriseExceptionTaskListenerDecoratorFactory#of.
Btw, org.jenkinsci.plugins.workflow.log.TaskListenerDecorator.Factory#of implementations are executed only on the controller, right?
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.
Could we use a more expressive condition to "know" we're on the controller ? Maybe
jenkins.util.JenkinsJVM#isJenkinsJVM?
We could, though it should not matter—if running on an agent, certainly run == null. A checkJenkinsJVM call could be added (inside the run != null block) as a matter of documentation, though it would perhaps just confuse the situation if later you do implement remote decoration (using some data structure that is safe in the agent JVM unlike Run).
we also need to combine the condition with
isBuildAgentErrorsEnabled()
Seems redundant since of already runs this check.
#ofimplementations are executed only on the controller, right?
Right.
| cleanup: | ||
| System.err.println('---%<--- agent logs') | ||
| agent.computer.logText.writeLogTo(0, System.err) | ||
| System.err.println('--->%---') |
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.
Otherwise you would not notice the errors. Currently JenkinsRule.create[Online]Slave does not stream logs. (InboundAgentRule does.)
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.
ooh I see, I wondered as well why I could not see the error
| withCredentials([string(credentialsId: 'my-creds', variable: 'PASSWORD')]) { | ||
| if (isUnix()) { | ||
| sh "echo password=\$PASSWORD" | ||
| sh 'echo password=$PASSWORD' |
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 original test was improperly interpolating the password in Groovy code on the controller, rather than using the environment variable, and so actually running the shell with e.g.
echo password=actual secret herePipeline prints a warning about this to the build log. Does not make much difference for purposes of the masking issue (since either way the shell step output contains the secret), but better to test the script that users are actually supposed to write.
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 did not see this warning in the test logs 🤔 but I understand the issue, quite sneaky!
…ond constructor was used from `GradleEnterpriseExceptionLogProcessorTest` mocks
|
@alextu there are ten test failures here, but these seem to be failing already in trunk. |
Thanks for your contribution! We will review it tomorrow, yes we have flakiness on ci.jenkins.io that we did not get a chance to tackle yet (we also build internally on our CI to make sure those are not "real" failures) |
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.
Looks good to me, @c00ler could you take a look next week ?
| @Override | ||
| public OutputStream decorate(@Nonnull OutputStream logger) { | ||
| if (isBuildAgentErrorsEnabled()) { | ||
| if (run != null) { |
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.
Could we use a more expressive condition to "know" we're on the controller ? Maybe jenkins.util.JenkinsJVM#isJenkinsJVM ?
As an additional safety net, I think we also need to combine the condition with isBuildAgentErrorsEnabled() (so only executed on the controller) even if it's already called upfront in hudson.plugins.gradle.injection.GradleEnterpriseExceptionTaskListenerDecoratorFactory#of.
Btw, org.jenkinsci.plugins.workflow.log.TaskListenerDecorator.Factory#of implementations are executed only on the controller, right?
| cleanup: | ||
| System.err.println('---%<--- agent logs') | ||
| agent.computer.logText.writeLogTo(0, System.err) | ||
| System.err.println('--->%---') |
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.
ooh I see, I wondered as well why I could not see the error
| withCredentials([string(credentialsId: 'my-creds', variable: 'PASSWORD')]) { | ||
| if (isUnix()) { | ||
| sh "echo password=\$PASSWORD" | ||
| sh 'echo password=$PASSWORD' |
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 did not see this warning in the test logs 🤔 but I understand the issue, quite sneaky!
Amends #312 by @alextu. While that appears to have worked, the way in which it worked was not reassuring—an exception is still thrown, but it gets caught and does not break
withCredentialsmasking. Better to avoid the exception to begin with. jenkinsci/workflow-durable-task-step-plugin#323 proposes to enableUSE_WATCHINGby default, in which case the scenario would apply to allgradleplugin users, not only those who are also runningopentelemetry.Running
git checkout gradle-2.8 -- src/main/java/hudson/plugins/gradle/injection/GradleEnterpriseExceptionTaskListenerDecoratorFactory.java ./gradlew -i :test --tests hudson.plugins.gradle.injection.BuildScanInjectionGradleWithDurableTaskStepUseWatchingIntegrationTest."credentials are always masked in logs"you can see the problem:
As Javadoc says, trying to access controller-only facilities such as
ExtensionListfrom withindecorateis not permitted. In fact the currentGradleEnterpriseExceptionTaskListenerDecoratorcould not possibly work remotely becauseGradleEnterpriseExceptionLogProcessorusesDefaultBuildAgentErrorListenerwhich can only run inside the controller as currently designed (accessingRunobjects and so forth). So unless and until that is redesigned to permit it to run inside the agent—ideally by streaming events directly to Gradle Enterprise, but failing that by calling back to the controller somewhat likeTimeoutStepdoes (discussion)—this feature just needs to be suppressed on the log ofshsteps running remotely.CC @daniel-beck