• Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • git-plugin
    • None

      Expected behavior: having "Wipe out workspace before build" unchecked would mean that the git plugin would not try to delete files in the workspace before building
      Actual behavior: having "Wipe out workspace before build" unchecked does not affect whether or not the git plugin tries to delete files in the workspace before building

      On version 1.5.0 of the git plugin (and judging by the source code, all versions since), the plugin unconditionally calls deleteContentsRecursive during the clone. This causes problems if the jenkins job running built any artifacts as another user, as they won't be able to be cleaned up. As there are checkboxes to indicate whether or not cleaning should occur, it seems like it would be nice to honor them.

      From src/main/java/org/jenkinsci/plugins/gitclient/CliGitAPIImpl.java, line 366-370:

      try {
          Util.deleteContentsRecursive(workspace);
      } catch (Exception e) {
          e.printStackTrace(listener.error("Failed to clean the workspace"));
          throw new GitException("Failed to delete workspace", e);
      }
      

      When there are files not able to be deleted by jenkins, the following stacktrace is helpfully spewed:

      ERROR: Failed to clean the workspace
      java.nio.file.AccessDeniedException: <REDACTED>
      	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
      	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
      	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
      	at sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:244)
      	at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
      	at java.nio.file.Files.delete(Files.java:1077)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:606)
      	at hudson.Util.deleteFile(Util.java:239)
      	at hudson.Util.deleteRecursive(Util.java:307)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:222)
      	at org.jenkinsci.plugins.gitclient.AbstractGitAPIImpl.clone(AbstractGitAPIImpl.java:59)
      	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.clone(CliGitAPIImpl.java:40)
      	at hudson.plugins.git.GitSCM$2.invoke(GitSCM.java:1012)
      	at hudson.plugins.git.GitSCM$2.invoke(GitSCM.java:948)
      	at hudson.FilePath$FileCallableWrapper.call(FilePath.java:2444)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:118)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:48)
      	at hudson.remoting.Request$2.run(Request.java:326)
      	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
      	at java.lang.Thread.run(Thread.java:744)
      ERROR: Error cloning remote repo 'origin' : Failed to delete workspace
      hudson.plugins.git.GitException: Failed to delete workspace
      	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:225)
      	at org.jenkinsci.plugins.gitclient.AbstractGitAPIImpl.clone(AbstractGitAPIImpl.java:59)
      	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.clone(CliGitAPIImpl.java:40)
      	at hudson.plugins.git.GitSCM$2.invoke(GitSCM.java:1012)
      	at hudson.plugins.git.GitSCM$2.invoke(GitSCM.java:948)
      	at hudson.FilePath$FileCallableWrapper.call(FilePath.java:2444)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:118)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:48)
      	at hudson.remoting.Request$2.run(Request.java:326)
      	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
      	at java.lang.Thread.run(Thread.java:744)
      Caused by: java.nio.file.AccessDeniedException: <REDACTED>
      	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
      	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
      	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
      	at sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:244)
      	at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
      	at java.nio.file.Files.delete(Files.java:1077)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:606)
      	at hudson.Util.deleteFile(Util.java:239)
      	at hudson.Util.deleteRecursive(Util.java:307)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at hudson.Util.deleteRecursive(Util.java:298)
      	at hudson.Util.deleteContentsRecursive(Util.java:204)
      	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:222)
      	... 13 more
      

          [JENKINS-22795] git plugin cleans workspace on initial clone

          This issue appeared in the commit history for the code in question.

          Matthaus Owens added a comment - This issue appeared in the commit history for the code in question.

          Mark Waite added a comment -

          I was unable to duplicate your bug report on multiple Linux and Windows machines using the current git client plugin (1.8.0) and the current git plugin (2.2.1). Can you provide more details as to how you see the problem?

          The steps I used:

          1. Create a multi-configuration git job using all Linux machines (elastic-axis plugin) to clone from a git protocol repository
          2. Run a Unix shell command in that job
            date >> ABC
            
          3. Run the job several times, confirming each time that the file ABC had more and more date output lines in the file

          Mark Waite added a comment - I was unable to duplicate your bug report on multiple Linux and Windows machines using the current git client plugin (1.8.0) and the current git plugin (2.2.1). Can you provide more details as to how you see the problem? The steps I used: Create a multi-configuration git job using all Linux machines (elastic-axis plugin) to clone from a git protocol repository Run a Unix shell command in that job date >> ABC Run the job several times, confirming each time that the file ABC had more and more date output lines in the file

          Mark Waite added a comment -

          I was unable duplicate the bug with similar steps from multiple Windows machines using a slightly different Windows batch command. More details are needed to illustrate how you've defined the job.

          Was the job originally defined with git plugin 1.5.0 and you're now using it with the current plugin, or are you truly only using git plugin 1.5.0?

          Have you tested with the current git plugin?

          Mark Waite added a comment - I was unable duplicate the bug with similar steps from multiple Windows machines using a slightly different Windows batch command. More details are needed to illustrate how you've defined the job. Was the job originally defined with git plugin 1.5.0 and you're now using it with the current plugin, or are you truly only using git plugin 1.5.0? Have you tested with the current git plugin?

          Mark Waite added a comment -

          Since I can't duplicate the problem and the submitter has not responded for 5 days, I'm closing this as "Cannot Reproduce".

          Mark Waite added a comment - Since I can't duplicate the problem and the submitter has not responded for 5 days, I'm closing this as "Cannot Reproduce".

          Tony Bridges added a comment -

          3 years later, I ran into this problem today.  In the project directory, there is a folder owned by root.  (via docker).  The job is not set to wipe the workspace, but the job fails trying to clean.  

          The log snip below jibes exactly with what Matthaus reported.  The reported issue is that the workspace is cleaned regardless of the clean setting in the job.

           
          13:56:58 Cloning repository ssh://mygerrit.mynet.net:29418/xyz.git*13:58:33* ERROR: Failed to clean the workspace*13:58:33* java.io.IOException: Unable to delete '/var/lib/Jenkins/workspace/mything/develop/XYZ_Build.Docker'. Tried 3 times (of a maximum of 3) waiting 0.1 sec between attempts.13:58:33 at hudson.Util.deleteContentsRecursive(Util.java:228)

          Tony Bridges added a comment - 3 years later, I ran into this problem today.  In the project directory, there is a folder owned by root.  (via docker).  The job is not set to wipe the workspace, but the job fails trying to clean.   The log snip below jibes exactly with what Matthaus reported.  The reported issue is that the workspace is cleaned regardless of the clean setting in the job.   13:56:58 Cloning repository ssh://mygerrit.mynet.net:29418/xyz.git*13:58:33* ERROR: Failed to clean the workspace*13:58:33* java.io.IOException: Unable to delete '/var/lib/Jenkins/workspace/mything/develop/XYZ_Build.Docker'. Tried 3 times (of a maximum of 3) waiting 0.1 sec between attempts. 13:58:33 at hudson.Util.deleteContentsRecursive(Util.java:228)

          Tony Bridges added a comment -

          fyi,  if it's not evident from the log, this happens on linux, where user-specific file permissions limit delete 

          Tony Bridges added a comment - fyi,  if it's not evident from the log, this happens on linux, where user-specific file permissions limit delete 

          Tony Bridges added a comment -

          reproduced both the unconditional delete AND the failure due to user permissions.

          Tony Bridges added a comment - reproduced both the unconditional delete AND the failure due to user permissions.

          Mark Waite added a comment - - edited

          tbridges, since you can duplicate it, and the original submitter was unable (or unwilling) to provide steps to duplicate the bug, can you provide those steps?

          I really need a sequence of steps which will allow anyone to duplicate the problem. Refer to "How to report an issue" for details of the types of information needed.

          Mark Waite added a comment - - edited tbridges , since you can duplicate it, and the original submitter was unable (or unwilling) to provide steps to duplicate the bug, can you provide those steps? I really need a sequence of steps which will allow anyone to duplicate the problem. Refer to " How to report an issue " for details of the types of information needed.

          Tony Bridges added a comment -

          I'm not sure why your tests didn't hit show the repos being wiped.  Maybe because the file in question (ABC) wasn't owned by git ?   (guess)

          My test conditions :

          1. maven job that pulls from a gerrit server.
          2. clean is turned off.  wipe workspace is turned off.
          3. my workspace is completely empty except for a folder and contents owned by root:root  (that's a side effect of the job that erases the entire workspace folder on the node not having sudo permissions)

          So, the startup condition is that the job workspace is empty except for a folder (and files) owned by root:root.  There is no .git folder.  The build runs as the build user.  This causes an exception, apparently while the plugin tried to incorrectly delete the contents.  Locally, that shows up as 'not a git repository' because .git is missing.  

          The point of commonality here is that both reports involve another user owning files in the file system. I suspect that the fault in deleteRecursive is more about the repos not being a git repository, but the question remains as to why it tries to delete anything at all ?

           

           

           

          Tony Bridges added a comment - I'm not sure why your tests didn't hit show the repos being wiped.  Maybe because the file in question (ABC) wasn't owned by git ?   (guess) My test conditions : maven job that pulls from a gerrit server. clean is turned off.  wipe workspace is turned off. my workspace is completely empty except for a folder and contents owned by root:root  (that's a side effect of the job that erases the entire workspace folder on the node not having sudo permissions) So, the startup condition is that the job workspace is empty except for a folder (and files) owned by root:root.  There is no .git folder.  The build runs as the build user.  This causes an exception, apparently while the plugin tried to incorrectly delete the contents.  Locally, that shows up as 'not a git repository' because .git is missing.   The point of commonality here is that both reports involve  another user owning files in the file system. I suspect that the fault in deleteRecursive is more about the repos not being a git repository, but the question remains as to why it tries to delete anything at all ?      

          Mark Waite added a comment -

          My tests with ABC should have detected the file being deleted, since the check was looking to see if content was appended to the file and if the prior content remained in the file. If the prior content had been removed, then the later read of the file ABC would not have included the earlier content.

          I'm suspicious that there are other settings in your job configuration which are causing the deleteRecursive() to be invoked. Can you share the config.xml file for the project which is showing the problem?

          Mark Waite added a comment - My tests with ABC should have detected the file being deleted, since the check was looking to see if content was appended to the file and if the prior content remained in the file. If the prior content had been removed, then the later read of the file ABC would not have included the earlier content. I'm suspicious that there are other settings in your job configuration which are causing the deleteRecursive() to be invoked. Can you share the config.xml file for the project which is showing the problem?

          Mark Waite added a comment -

          You mention that it is a maven job that pulls from the server. Any chance that maven job is running a "clean" and deleting files on its own?

          Is the maven job that is running a Jenkins maven job type, or a FreeStyle job that invokes maven as a build step?

          I've tried to duplicate the problem using a FreeStyle job on my lts-with-plugins docker image in a dedicated job. I don't see any deletion of repository contents in that job.

          Mark Waite added a comment - You mention that it is a maven job that pulls from the server. Any chance that maven job is running a "clean" and deleting files on its own? Is the maven job that is running a Jenkins maven job type, or a FreeStyle job that invokes maven as a build step? I've tried to duplicate the problem using a FreeStyle job on my lts-with-plugins docker image in a dedicated job . I don't see any deletion of repository contents in that job.

          Tony Bridges added a comment -

          maven job, but it's happening before maven takes control.  I actually have a git clean step in the job too, but we are not executing that yet either.  and even if that was the case, the stack trace is from the plugin, isn't it ?

           

          Tony Bridges added a comment - maven job, but it's happening before maven takes control.  I actually have a git clean step in the job too, but we are not executing that yet either.  and even if that was the case, the stack trace is from the plugin, isn't it ?  

          Mark Waite added a comment -

          If you're getting that stack trace, then yes, the stack trace is definitely from the plugin.

          Can you paste of copy of the stack trace you're getting? The stack trace in the bug description is from a 3 year old git client plugin version. I don't trust it to represent the current state of the git client plugin.

          Mark Waite added a comment - If you're getting that stack trace, then yes, the stack trace is definitely from the plugin. Can you paste of copy of the stack trace you're getting? The stack trace in the bug description is from a 3 year old git client plugin version. I don't trust it to represent the current state of the git client plugin.

          Tony Bridges added a comment -

          sent OOB.

          Tony Bridges added a comment - sent OOB.

          Mark Waite added a comment -

          I received it. What git client plugin version are you running? I need to checkout that version to match the line numbers in the stack trace to the source code.

          Mark Waite added a comment - I received it. What git client plugin version are you running? I need to checkout that version to match the line numbers in the stack trace to the source code.

          Tony Bridges added a comment -

          3.3.2

          Tony Bridges added a comment - 3.3.2

          Mark Waite added a comment -

          I suspect 3.3.2 is the git plugin version. That likely means you're using git client plugin 2.4.6. Can you confirm you're using git client plugin 2.4.6?

          Mark Waite added a comment - I suspect 3.3.2 is the git plugin version. That likely means you're using git client plugin 2.4.6. Can you confirm you're using git client plugin 2.4.6?

          Tony Bridges added a comment -

          correct, sorry.

           

          Tony Bridges added a comment - correct, sorry.  

          Mark Waite added a comment - - edited

          The plugin source code seems to support exactly what you described earlier. I hadn't understood the significance of what you were saying.

          I think that in order to duplicate the problem, I'll need to:

          1. Create a workspace which contains a file before Jenkins first uses that workspace. A pre-scm build step may be one way to show the problem. This is what you had said, and what I had failed to comprehend as the most critical difference between your case and my testing
          2. Clone the repository into that workspace
          3. Confirm that the workspace retains the file placed prior to first clone

          My earlier attempts, and my sample job, were all assuming that the "orphan" file did not need to arrive in the workspace prior to the first clone. The code appears to only scrub the workspace when it is performing the initial creation of the git structure in the workspace, not when it is later updating the git structure in the workspace.

          Mark Waite added a comment - - edited The plugin source code seems to support exactly what you described earlier. I hadn't understood the significance of what you were saying. I think that in order to duplicate the problem, I'll need to: Create a workspace which contains a file before Jenkins first uses that workspace. A pre-scm build step may be one way to show the problem. This is what you had said, and what I had failed to comprehend as the most critical difference between your case and my testing Clone the repository into that workspace Confirm that the workspace retains the file placed prior to first clone My earlier attempts, and my sample job, were all assuming that the "orphan" file did not need to arrive in the workspace prior to the first clone. The code appears to only scrub the workspace when it is performing the initial creation of the git structure in the workspace, not when it is later updating the git structure in the workspace.

          Tony Bridges added a comment -

          ahh, that's why this isn't more impactful then.  It would be highly unusual to have a non-empty workspace during the first clone.

          fwiw, I have a workaround for this - I fixed my workspace wiper - but I thought I'd post the repro for the plugin's benefit.

           

          Tony Bridges added a comment - ahh, that's why this isn't more impactful then.  It would be highly unusual to have a non-empty workspace during the first clone. fwiw, I have a workaround for this - I fixed my workspace wiper - but I thought I'd post the repro for the plugin's benefit.  

          Mark Waite added a comment -

          Thanks. I'm glad you've got a work around.

          I've included verification of the bug in my bug repro job, but don't plan to change anything in the plugin at this time to resolve it.

          When it comes time to fix this, it will require adding a new option to the plugin in the clone options section. The switch would be something like "don't clean on first clone into a workspace". That's a painful name to place in the clone options, and I'd prefer to avoid adding that until there are more indications that it will help many users.

          I'm sure there are Jenkins users that have an implicit assumption in their jobs that the plugin performs that clean. Adding the optional toggle to not clean on first clone would allow new users to skip the clean step, without breaking those users that unwittingly depend on the current clean before first clone.

          Mark Waite added a comment - Thanks. I'm glad you've got a work around. I've included verification of the bug in my bug repro job , but don't plan to change anything in the plugin at this time to resolve it. When it comes time to fix this, it will require adding a new option to the plugin in the clone options section. The switch would be something like "don't clean on first clone into a workspace". That's a painful name to place in the clone options, and I'd prefer to avoid adding that until there are more indications that it will help many users. I'm sure there are Jenkins users that have an implicit assumption in their jobs that the plugin performs that clean. Adding the optional toggle to not clean on first clone would allow new users to skip the clean step, without breaking those users that unwittingly depend on the current clean before first clone.

          One way of reproducing the problem is the following pipeline script: 

          node('master') {
            step([$class: 'WsCleanup'])
          
            sh 'touch newfile'
            sh 'ls -l newfile'
          
            checkout([$class: 'GitSCM', userRemoteConfigs: [[credentialsId: 'CREDENTIAL', url: 'REPO-URL']]])
          
            sh 'ls -l newfile'  // Fails
          }

           

          Jonas Lindström added a comment - One way of reproducing the problem is the following pipeline script:  node( 'master' ) { step([$class: 'WsCleanup' ]) sh 'touch newfile' sh 'ls -l newfile' checkout([$class: 'GitSCM' , userRemoteConfigs: [[credentialsId: 'CREDENTIAL' , url: 'REPO-URL' ]]]) sh 'ls -l newfile' // Fails }  

          Cristian Cureliuc added a comment - - edited

          There should definitely be an option not to delete the workspace when not empty, and even more, this default behavior is quite dangerous!

          The fact that at command line git clone does not work on a non empty directory makes a lot of sense and I was quite surprised to find out that to delete any existing files was in fact the default behavior of the git client plugin.

          After a jenkins and all plugins update including git client plugin, we noticed the following error when trying to run a build on a live project:

          ERROR: Workspace has a .git repository, but it appears to be corrupt.

          followed by a complete wipe out of the workspace. 

          What means "first clone"? That .git is not there? I wonder what happens if somebody specify a wrong directory for the workspace, one or two levels above the intended workspace, would it simply delete everything? That's how it looks from our following tests after this incident on our local server

          I guess that the painful name of such option is not the issue here, more painful is to lose all data and even the risk for that to happen, and not have the option to prevent that.

          Cristian Cureliuc added a comment - - edited There should definitely be an option not to delete the workspace when not empty, and even more, this default behavior is quite dangerous! The fact that at command line git clone does not work on a non empty directory makes a lot of sense and I was quite surprised to find out that to delete any existing files was in fact the default behavior of the git client plugin. After a jenkins and all plugins update including git client plugin, we noticed the following error when trying to run a build on a live project: ERROR: Workspace has a .git repository, but it appears to be corrupt. followed by a complete wipe out of the workspace.  What means "first clone"? That .git is not there? I wonder what happens if somebody specify a wrong directory for the workspace, one or two levels above the intended workspace, would it simply delete everything? That's how it looks from our following tests after this incident on our local server I guess that the painful name of such option is not the issue here, more painful is to lose all data and even the risk for that to happen, and not have the option to prevent that.

          Can we please have a reply with the intentions here? We have disabled all our projects waiting for a reaction for fixing this big issue on the git client plugin!

          This kind of problem makes jenkins not interesting for us anymore and we are considering alternate solutions. 

          And I think everybody agrees that the risk to lose all data with absolutely no warning and as default behavior and without even the possibility to disable this is not acceptable. In our case, it was a problem due to a hoster memory limitations which could happen to anybody!

          And since this seems like a very simple thing to fix, we do not really understand the lack of feedback here. Maybe this tells a lot about the interest here.

          Cristian Cureliuc added a comment - Can we please have a reply with the intentions here? We have disabled all our projects waiting for a reaction for fixing this big issue on the git client plugin! This kind of problem makes jenkins not interesting for us anymore and we are considering alternate solutions.  And I think everybody agrees that the risk to lose all data with absolutely no warning and as default behavior and without even the possibility to disable this is not acceptable. In our case, it was a problem due to a hoster memory limitations which could happen to anybody! And since this seems like a very simple thing to fix, we do not really understand the lack of feedback here. Maybe this tells a lot about the interest here.

          Mark Waite added a comment - - edited

          sologics I replied here and here. I am not working on this bug currently. I don't expect to work on this bug in the near future.

          I don't like the plugin behavior, but it is a pragmatic behavior, selected due to command line git behavior. When command line git is asked to fetch into an existing directory with existing files, there are many scenarios where command line git will fail the fetch. Rather than fail the fetch, stop the job, and report an error to the user, the git plugin decided many years ago to remove pre-existing files if it detected what appeared to be an incomplete or incorrect initial workspace.

          The earlier comments in the bug report show the difficulty I had duplicating the problem because that code is only executed on the path that creates the initial workspace. With a freestyle job, it can be duplicated by intentionally forcing an incorrect workspace location (bad practice) or by inserting a pre-SCM step which creates a file in the workspace before the git repository is fetched. Pipeline jobs can see the behavior by adding files to the workspace before the git repository is fetched.

          I've intentionally not modified this code. Changing the behavior of the git plugin for this case won't give command line git (or JGit) the ability to reliably fetch into a directory which includes unpredictable content. If the git plugin adds an option to "allow initial fetch to non-empty directory", there will still be use cases which can't be addressed because command line (or JGit) initial fetch fails with certain content in a directory.

          I'm sorry to hear you say:

          This kind of problem makes jenkins not interesting for us anymore and we are considering alternate solutions.

          Unfortunately, if I change the default behavior, I'm confident that I'll discover far more users who depend on the current behavior. They will assert strongly that the job of their continuous integration server is to checkout the code they said to checkout, and to continue behaving the way it did in the past.

          If an optional behavior is added, then that option needs to be selected by the user, and it then needs to be maintained and tested across multiple releases and multiple use cases. I haven't seen enough gain from the proposed optional behavior to justify the complexity and maintenance challenges of adding another optional behavior to the "Advanced checkout" options.

          Mark Waite added a comment - - edited sologics I replied here and here . I am not working on this bug currently. I don't expect to work on this bug in the near future. I don't like the plugin behavior, but it is a pragmatic behavior, selected due to command line git behavior. When command line git is asked to fetch into an existing directory with existing files, there are many scenarios where command line git will fail the fetch. Rather than fail the fetch, stop the job, and report an error to the user, the git plugin decided many years ago to remove pre-existing files if it detected what appeared to be an incomplete or incorrect initial workspace. The earlier comments in the bug report show the difficulty I had duplicating the problem because that code is only executed on the path that creates the initial workspace. With a freestyle job, it can be duplicated by intentionally forcing an incorrect workspace location (bad practice) or by inserting a pre-SCM step which creates a file in the workspace before the git repository is fetched. Pipeline jobs can see the behavior by adding files to the workspace before the git repository is fetched. I've intentionally not modified this code. Changing the behavior of the git plugin for this case won't give command line git (or JGit) the ability to reliably fetch into a directory which includes unpredictable content. If the git plugin adds an option to "allow initial fetch to non-empty directory", there will still be use cases which can't be addressed because command line (or JGit) initial fetch fails with certain content in a directory. I'm sorry to hear you say: This kind of problem makes jenkins not interesting for us anymore and we are considering alternate solutions. Unfortunately, if I change the default behavior, I'm confident that I'll discover far more users who depend on the current behavior. They will assert strongly that the job of their continuous integration server is to checkout the code they said to checkout, and to continue behaving the way it did in the past. If an optional behavior is added, then that option needs to be selected by the user, and it then needs to be maintained and tested across multiple releases and multiple use cases. I haven't seen enough gain from the proposed optional behavior to justify the complexity and maintenance challenges of adding another optional behavior to the "Advanced checkout" options.

          Hello Mark and thank you for your detailed reply,

          Makes sense of course to assure the stability of the plugin and to take all those aspects into consideration, but I suppose that it should not be such a struggle to add this option to the Advanced options, by default unchecked, for keeping the backwards compatibility and it should simply not allow for that deleteContentsRecursive function to execute under any conditions. Nothing to check across different platforms, future releases, etc.

          How to test this is very easy: we could reproduce this every single time by simply removing the .git metadata directory from the workspace, after adding a flag file for seeing if it survives the build. 

          If you allow me for a suggestion for the the option name, could be: "Prevent workspace cleanup if not empty", again, by default, unchecked.

          I think nobody would mind to have such an option there, hidden under Advanced, and I suppose it would make not only us very happy but also other users which for sure got into this but did not write here because, to be honest, this JIRA ticket was not one of the obvious of google search results, at least for me.

          Please consider this as one of the near future fixes, for us this is really a blocker in using the jenkins CI

          Best regards,

          Cristian

          Cristian Cureliuc added a comment - Hello Mark and thank you for your detailed reply, Makes sense of course to assure the stability of the plugin and to take all those aspects into consideration, but I suppose that it should not be such a struggle to add this option to the Advanced options, by default unchecked, for keeping the backwards compatibility and it should simply not allow for that deleteContentsRecursive function to execute under any conditions. Nothing to check across different platforms, future releases, etc. How to test this is very easy: we could reproduce this every single time by simply removing the .git metadata directory from the workspace, after adding a flag file for seeing if it survives the build.  If you allow me for a suggestion for the the option name, could be: "Prevent workspace cleanup if not empty", again, by default, unchecked. I think nobody would mind to have such an option there, hidden under Advanced, and I suppose it would make not only us very happy but also other users which for sure got into this but did not write here because, to be honest, this JIRA ticket was not one of the obvious of google search results, at least for me. Please consider this as one of the near future fixes, for us this is really a blocker in using the jenkins CI Best regards, Cristian

          Mark Waite added a comment -

          sologics I'm willing to review a pull request that implements what you've proposed. I don't plan to implement that myself.

          Mark Waite added a comment - sologics I'm willing to review a pull request that implements what you've proposed. I don't plan to implement that myself.

          Roy Dahan added a comment - - edited

          I don't know why we started hitting this lately, but we have the exact same problem.

          Every time we run a job, it tries to clean the workspace before cloning the repo.

          It wasn't the behaviour till recently and I'm not sure what has changed.

          Our job create a directory with some results and when it runs again, it cleans this directory although we didn't want it to.

           

          If this was one intention, one would use the options to clean the workspace.

          Roy Dahan added a comment - - edited I don't know why we started hitting this lately, but we have the exact same problem. Every time we run a job, it tries to clean the workspace before cloning the repo. It wasn't the behaviour till recently and I'm not sure what has changed. Our job create a directory with some results and when it runs again, it cleans this directory although we didn't want it to.   If this was one intention, one would use the options to clean the workspace.

          Mark Waite added a comment - - edited

          roydahan you may want to check the agent where that job is running. The removal of the contents only happens on the initial creation of the workspace, not on later requests to update an existing workspace. Something on the agent running the build may be causing the plugin to believe that it needs to perform a fresh clone rather than performing an incremental update.

          If you're using a Pipeline, you may also want to check the Pipeline definition that it does not include a separate call to deleteDir().

          Mark Waite added a comment - - edited roydahan you may want to check the agent where that job is running. The removal of the contents only happens on the initial creation of the workspace, not on later requests to update an existing workspace . Something on the agent running the build may be causing the plugin to believe that it needs to perform a fresh clone rather than performing an incremental update. If you're using a Pipeline, you may also want to check the Pipeline definition that it does not include a separate call to deleteDir().

          Roy Dahan added a comment - - edited

          I don't know if it's related, but few lines in the log before the delete it seems like the agent is started.

          It happens every run.

          (It's not a pipeline job)

          [ssh-agent] Looking for ssh-agent implementation...20:02:23 [ssh-agent] Exec ssh-agent (binary ssh-agent on a remote machine)20:02:23 $ ssh-agent*20:02:24* SSH_AUTH_SOCK=/tmp/ssh-3IVCGhG3LDLW/agent.20456*20:02:24* SSH_AGENT_PID=20458*20:02:24* [ssh-agent] Started.

          Roy Dahan added a comment - - edited I don't know if it's related, but few lines in the log before the delete it seems like the agent is started. It happens every run. (It's not a pipeline job) [ssh-agent] Looking for ssh-agent implementation...20:02:23 [ssh-agent] Exec ssh-agent (binary ssh-agent on a remote machine)20:02:23 $ ssh-agent*20:02:24* SSH_AUTH_SOCK=/tmp/ssh-3IVCGhG3LDLW/agent.20456*20:02:24* SSH_AGENT_PID=20458*20:02:24* [ssh-agent] Started.

          Mark Waite added a comment -

          The log entry you provided which mentions ssh-agent is from the ssh-agent plugin, not from the Jenkins agent. It is unlikely to be related to the deletion of files which exist in the workspace of a job before the first clone into the workspace.

          This bug report is describing a very specific condition which only exists when the workspace of a job is not empty the very first time that Jenkins uses the workspace. That is quite rare. Freestyle jobs usually create the workspace on the Jenkins agent the first time the job is run, then they reuse that workspace on later execution of the same job. When the workspace is created, it is empty and the deletion that is described in this bug report is harmless.

          There are Jenkins plugins which will allow Freestyle jobs to write files into the workspace after the job starts and before the git repository is cloned into the workspace. The deletion behavior described here will delete those files that are created in the workspace before the git repository is first cloned.

          I was trying to suggest earlier that you should confirm that the workspace where the files are being deleted has not been damaged or partially deleted by some other scripts or changes in your environment.

          Mark Waite added a comment - The log entry you provided which mentions ssh-agent is from the ssh-agent plugin, not from the Jenkins agent. It is unlikely to be related to the deletion of files which exist in the workspace of a job before the first clone into the workspace. This bug report is describing a very specific condition which only exists when the workspace of a job is not empty the very first time that Jenkins uses the workspace. That is quite rare. Freestyle jobs usually create the workspace on the Jenkins agent the first time the job is run, then they reuse that workspace on later execution of the same job. When the workspace is created, it is empty and the deletion that is described in this bug report is harmless. There are Jenkins plugins which will allow Freestyle jobs to write files into the workspace after the job starts and before the git repository is cloned into the workspace. The deletion behavior described here will delete those files that are created in the workspace before the git repository is first cloned. I was trying to suggest earlier that you should confirm that the workspace where the files are being deleted has not been damaged or partially deleted by some other scripts or changes in your environment.

            Unassigned Unassigned
            haus Matthaus Owens
            Votes:
            5 Vote for this issue
            Watchers:
            11 Start watching this issue

              Created:
              Updated: