jenkinsci / google-storage-plugin

This plugin provides the “Google Cloud Storage Uploader” post-build step for publishing build artifacts to Google Cloud Storage.
https://plugins.jenkins.io/google-storage-plugin/
Apache License 2.0
31 stars 57 forks source link

NullPointerException when trying to upload file from Windows agent #305

Open AbrilRBS opened 7 months ago

AbrilRBS commented 7 months ago

Jenkins and plugins versions report

Environment Jenkins: 2.440.2 OS: Linux - 5.4.129+ Java: 17.0.10 - Eclipse Adoptium (OpenJDK 64-Bit Server VM) --- google-oauth-plugin:1.330.vf5e86021cb_ec google-storage-plugin:1.360.v6ca_38618b_41f

(Note that as per company policy, I have had to trim the plugin list to just the releated ones, let me know if this looks like you could use some more in the list!)

What Operating System are you using (both controller, and any agents involved in the problem)?

Controller is Linux, Agent in Windows Server 2019

Reproduction steps

This small pipeline repro case:

pipeline {
    agent { label 'windows' } 
    stages {
        stage('test') {
            steps {
                bat 'echo hello > hello.txt'
                googleStorageUpload bucket: "gs://foobar/path/", credentialsId: 'credential', pattern: "hola.txt*"
            }
        }
    }
}

Expected Results

The hello.txt file is uploaded to our foobar/path bucket

Actual Results

I get a NullPointerException, with the following stacktrace:

Also:   hudson.remoting.Channel$CallSiteStackTrace: Remote call to windows
        at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1787)
        at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:356)
        at hudson.remoting.Channel.call(Channel.java:1003)
        at hudson.FilePath.act(FilePath.java:1321)
        at com.google.jenkins.plugins.storage.AbstractUpload.initiateUploadsAtWorkspace(AbstractUpload.java:400)
        at com.google.jenkins.plugins.storage.AbstractUpload.perform(AbstractUpload.java:176)
        at com.google.jenkins.plugins.storage.ClassicUploadStep.perform(ClassicUploadStep.java:188)
        at jenkins.tasks.SimpleBuildStep.perform(SimpleBuildStep.java:123)
        at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:101)
        at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:71)
        at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
        at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
Also:   org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: 7e6d6d85-952f-4ef9-bb57-92d867e75fd3
java.lang.NullPointerException
    at com.google.jenkins.plugins.storage.util.StorageUtil.getRelative(StorageUtil.java:47)
    at com.google.jenkins.plugins.storage.AbstractUpload$2.act(AbstractUpload.java:466)
    at com.google.jenkins.plugins.storage.util.RetryStorageOperation.performRequestWithReinitCredentials(RetryStorageOperation.java:114)
    at com.google.jenkins.plugins.storage.util.RetryStorageOperation.performRequestWithReinitCredentials(RetryStorageOperation.java:131)
    at com.google.jenkins.plugins.storage.AbstractUpload.performUploads(AbstractUpload.java:498)
    at com.google.jenkins.plugins.storage.AbstractUpload$1.call(AbstractUpload.java:403)
    at com.google.jenkins.plugins.storage.AbstractUpload$1.call(AbstractUpload.java:400)
    at hudson.remoting.UserRequest.perform(UserRequest.java:211)
    at hudson.remoting.UserRequest.perform(UserRequest.java:54)
    at hudson.remoting.Request$2.run(Request.java:377)
    at hudson.remoting.InterceptingExecutorService.lambda$wrap$0(InterceptingExecutorService.java:78)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    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:833)

Anything else?

The same works for our Linux and Macos agents

Are you interested in contributing a fix?

If I get pointed to the underlying issue, I'd be happy to :)

AbrilRBS commented 5 months ago

We found that the issue comes from two places:

Our current patch looks like this, with which we can upload files:

diff --git a/src/main/java/com/google/jenkins/plugins/storage/util/StorageUtil.java b/src/main/java/com/google/jenkins/plugins/storage/util/StorageUtil.java
index 7dd7e00..fc8d1e0 100644
--- a/src/main/java/com/google/jenkins/plugins/storage/util/StorageUtil.java
+++ b/src/main/java/com/google/jenkins/plugins/storage/util/StorageUtil.java
@@ -41,10 +41,12 @@ public class StorageUtil {
      */
     public static String getRelative(FilePath include, FilePath workspace) throws UploadException {
         LinkedList<String> segments = new LinkedList<String>();
+        String includePath = include.getRemote();
+        include = new FilePath(include.getChannel(), includePath.replace("\\", "/"));
         while (!include.equals(workspace)) {
             segments.push(include.getName());
             include = include.getParent();
-            if (Strings.isNullOrEmpty(include.getName())) {
+            if (include == null || Strings.isNullOrEmpty(include.getName())) {
                 // When we reach "/" we're done either way.
                 break;
             }