Log an appropriate AccessDenied message instead of throwing a RestClientException stacktrace
When the plugin finds a pattern that matches the configured patterns, it tries to access the issue status from the Jira instance. If it does not have the required permissions, it throws an ugly stacktrace instead of just stating in the build log that it doesn't have access to that issue.
This might be the beginning (or part of) a larger re-factoring of logging so that:
- Rest exceptions are not thrown back (at least if DEBUG is not enabled) and instead a user friendly message is logged
- that the log message goes to the build log and not (only) the Jenkins log, so that it's visible to the actual user accessing the build logs via Jenkins UI.
Jira REST client get issue error. cause: RestClientException{statusCode=Optional.of(403), errorCollections=[ErrorCollection{status=403, errors={}, errorMessages=[You do not have the permission to see the specified issue.]}]} RestClientException{statusCode=Optional.of(403), errorCollections=[ErrorCollection{status=403, errors={}, errorMessages=[You do not have the permission to see the specified issue.]}]} at PluginClassLoader for jira//com.atlassian.jira.rest.client.internal.async.AbstractAsynchronousRestClient$2.apply(AbstractAsynchronousRestClient.java:189) at PluginClassLoader for jira//com.atlassian.jira.rest.client.internal.async.AbstractAsynchronousRestClient$2.apply(AbstractAsynchronousRestClient.java:183) at PluginClassLoader for jira//com.atlassian.httpclient.api.ResponsePromiseMapFunction.apply(ResponsePromiseMapFunction.java:49) at PluginClassLoader for jira//com.atlassian.httpclient.api.ResponsePromiseMapFunction.apply(ResponsePromiseMapFunction.java:10) at PluginClassLoader for jira//io.atlassian.util.concurrent.Promises$OfStage.lambda$fold$4(Promises.java:332) at PluginClassLoader for jira//io.atlassian.util.concurrent.Promises.lambda$biFunction$7(Promises.java:422) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:614) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:914) at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:482) at PluginClassLoader for jira//com.atlassian.httpclient.apache.httpcomponents.CompletableFuturePromiseHttpPromiseAsyncClient.runInContext(CompletableFuturePromiseHttpPromiseAsyncClient.java:87) at PluginClassLoader for jira//com.atlassian.httpclient.apache.httpcomponents.CompletableFuturePromiseHttpPromiseAsyncClient$ThreadLocalDelegateRunnable.run(CompletableFuturePromiseHttpPromiseAsyncClient.java:158) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) Caused: java.util.concurrent.ExecutionException at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396) at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2096) at PluginClassLoader for jira//io.atlassian.util.concurrent.Promises$OfStage.get(Promises.java:357) at PluginClassLoader for jira//com.atlassian.jira.rest.client.internal.async.DelegatingPromise.get(DelegatingPromise.java:106) at PluginClassLoader for jira//hudson.plugins.jira.JiraRestService.getIssue(JiraRestService.java:170) at PluginClassLoader for jira//hudson.plugins.jira.JiraSession.getIssue(JiraSession.java:122) at PluginClassLoader for jira//hudson.plugins.jira.JiraSite.lambda$getIssue$0(JiraSite.java:1115) at PluginClassLoader for caffeine-api//com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2704) at java.base/java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1916) at PluginClassLoader for caffeine-api//com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2702) at PluginClassLoader for caffeine-api//com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2684) at PluginClassLoader for caffeine-api//com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:112) at PluginClassLoader for caffeine-api//com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:63) at PluginClassLoader for jira//hudson.plugins.jira.JiraSite.getIssue(JiraSite.java:1111) at PluginClassLoader for jira//hudson.plugins.jira.JiraJobAction.setAction(JiraJobAction.java:98) at PluginClassLoader for jira//hudson.plugins.jira.JiraJobAction$RunListenerImpl.onStarted(JiraJobAction.java:129) at PluginClassLoader for jira//hudson.plugins.jira.JiraJobAction$RunListenerImpl.onStarted(JiraJobAction.java:121) at hudson.model.listeners.RunListener.lambda$fireStarted$2(RunListener.java:246) at jenkins.util.Listeners.lambda$notify$0(Listeners.java:59) at jenkins.util.Listeners.notify(Listeners.java:67) at hudson.model.listeners.RunListener.fireStarted(RunListener.java:244) at PluginClassLoader for workflow-job//org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:308) at hudson.model.ResourceController.execute(ResourceController.java:101) at hudson.model.Executor.run(Executor.java:446)
Originally posted by @Maxo112 in #657
@rantoniuk
I think this is doable. In the first shot I can just solve only what is in the scope of this issue.
That would be to log the error from this specific method: JiraRestService.getIssue in build log and try to have some kind of general approach that can be later on applied everywhere. Right now I am not sure what all changes will be required, but it looks like we need a mechanism to use TaskListener wherever there is a need to log error in build log.
If this works then as a separate bigger enhancement, I can apply it in other places too.
Edit 1: Another point, scoped tokens work different from simple API tokens. During my testing when scoped token was not giving any response, I stumbled upon this page: https://community.atlassian.com/forums/Confluence-questions/Scoped-API-Token-returns-Unauthorized-for-simple-query/qaq-p/3023662
and from there to this one: https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#siteaccess
Which says, scoped token in jira cloud have different URL and need cloudid. So may be first there need to be a support for scoped token?
For this issue, I'd like it to be a complete approach of some sort - I mean a solution that would be applied to all methods of JiraRestService.java.
In the scope of that issue is another thing that isn't filed anywhere yet but I remember about it - there is a Validate button on the Jira configuration panel but that Validation is too simple. It happened many times during my testing that it returned OK but it didn't work for some reason (haven't had time back then to file an issue what exactly was the reason unfortunately).
Try to come up with an idea and test it with Jira Cloud - think about how this is going to help the end user find the root cause of the problem. When you're satisfied, open a PR and I'll take it for a spin.
So may be first there need to be a support for scoped token?
That should be a separate issue that we can work on if actually anyone needs it (votes for it).
Any Update here ?
Hi, I would like to work on this issue as my first Jenkins contribution.
Could you please assign it to me?