Groovy 无法使用Jenkinsfile/pipline插件将工作区识别为目录

Groovy 无法使用Jenkinsfile/pipline插件将工作区识别为目录,groovy,jenkins-pipeline,Groovy,Jenkins Pipeline,我试图在目录中递归搜索文件,因此无法使用FindFile。 我已经通过手动登录到从属服务器看到了这些目录,但在下面的代码中无法识别。当我使用isDirectory()时,它会显示false,因此稍后使用dir.listFiles()时,它会返回null 代码如下: def recursiveFileSearch(File dir, filename, filesPath) { File[] files = dir.listFiles() // It returns null here as

我试图在目录中递归搜索文件,因此无法使用FindFile。 我已经通过手动登录到从属服务器看到了这些目录,但在下面的代码中无法识别。当我使用isDirectory()时,它会显示false,因此稍后使用dir.listFiles()时,它会返回null

代码如下:

def recursiveFileSearch(File dir, filename, filesPath) {

  File[] files = dir.listFiles() // It returns null here as it cannot recognize it as directory
  echo "$files" 
  for (int i=0; i < files.size(); i++) {
    if (files[i].isDirectory()) {
      recursiveFileSearch(files[i], filename, filesPath)
    } else {
      if (files[i].getAbsolutePath().contains(filename)) {
        filesPath.add(files[i].getAbsolutePath())
        return filesPath
      }
    }
  }
  return filesPath
}

node('maven') {
      git 'https://github.com/rupalibehera/t3d.git'
      sh 'mvn clean install'
      File currentDir = new File(pwd())

      def isdir = currentDir.isDirectory()
      println "isdir:${isdir}" // The output here is False
      def isexist = currentDir.exists()
      println "isexist:${isexist}" // The output here is False
      def canread = currentDir.canRead()
      println "canread:${canread}" // The output here is False
      def filesPath = []
      def openshiftYaml = recursiveFileSearch(currentDir, "openshift.yml", filesPath)
} 
def recursiveFileSearch(文件目录、文件名、文件路径){
File[]files=dir.listFiles()//它在这里返回null,因为它无法将其识别为目录
回显“$files”
对于(int i=0;i
我不确定这里出了什么问题

但以下是一些观察结果:

  • 当我执行
    File currentDir=new File(“.”
    )时,它返回/并开始读取我不想要的完整根目录,并且在该目录中它也不将工作区识别为目录
  • 如果我在主节点上运行它,它执行得很好,但在我的用例中,它将始终是一个从节点
  • 我还检查了用户具有读/写/执行权限的目录的权限
非常感谢任何指点/帮助

我找到了答案, 要从Jenkinsfile搜索工作区中的任何文件,可以使用步骤, 我确实试过了,但我传递的球不正确。现在我就这么做了
def files=findFiles(glob:'**/openshift.yml')\\它返回文件路径

我找到了答案, 要从Jenkinsfile搜索工作区中的任何文件,可以使用步骤, 我确实试过了,但我传递的球不正确。现在我就这么做了
def files=findFiles(glob:'**/openshift.yml')\\它返回文件路径

通常,运行
sh
步骤来执行您需要的任何工作。您不能使用管道脚本中的
java.io.File
或类似内容。它不在代理上运行,而且也不安全,这就是为什么当沙盒模式保持打开(默认)时,任何此类尝试都将被拒绝的原因。

通常,运行
sh
步骤来执行您需要的任何工作。您不能使用管道脚本中的
java.io.File
或类似内容。它不在代理上运行,而且也不安全,这就是为什么当沙盒模式保持打开(默认)时,任何此类尝试都将被拒绝的原因。

您遇到了问题。我太清楚了。文件对象和NIO可以很好地分解路径,但它们的isDirectory存在,并且其他方法作为Jenkins文件的一部分在master上运行,而不是在节点上运行。因此,在master上使用的所有内容看起来都很棒,因为文件都在工作区中。在一个节点上全部使用失败

简言之,不要那样做。使用fileExists()pwd()、findFile等

如果您创建了一个shareLibrary,并且希望在Jenkins之外的代码上使用单元测试,那么您可以创建一个依赖于脚本对象的fascade(“来自管道的this”)

共享库类

class PipelineUtils implements Serializable {
    static def pipelineScript = null;

    /**
     * Setup this fascade with access to pipeline script methods
     * @param jenkinsPipelineScript
     * @return
     */
    static initialize(def jenkinsPipelineScript) {
        pipelineScript = jenkinsPipelineScript
    }

    /**
     * Use pipelineScript object ('this' from pipeline) to access fileExists
     * We cannot use Java File objects for detection as the pipeline script runs on master and uses delegation/serialization to
     * get to the node.  So, File.exists() will be false if the file was generated on the node and that node isn't master.
     * https://support.cloudbees.com/hc/en-us/articles/230922128-Pipeline-Using-java-io-File-in-a-Pipeline-description
     * @param target
     * @return true if path exists
     */
    static boolean exists(Path target) {
        if (!pipelineScript) {
            throw new Exception("PipelineUtils.initialize with pipeline script not called - access to pipeline 'this' required for access to file detection routines")
        }

        if (! target.parent) {
            throw new Exception('Please use absolutePaths with ${env.WORKSPACE}/path-to-file')
        }
        return pipelineScript.fileExists(target.toAbsolutePath().toString())
    }

    /**
     * Convert workspace relative path to absolute path
     * @param path relative path
     * @return node specific absolute path
     */
    static def relativeWorkspaceToAbsolutePath(String path) {
        Path pwd = Paths.get(pipelineScript.pwd())
        return pwd.resolve(path).toAbsolutePath().toString()
    }

    static void echo(def message) {
        pipelineScript.echo(message)
    }
}
测试类

PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists
Jenkinstep类{ 静态布尔文件存在(定义路径){ 返回新文件(路径).exists() }

}

在jenkins中的用法

PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists
在单元测试中的使用

PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists
你遇到了这个问题。我太清楚了。文件对象和NIO可以很好地分解路径,但它们的isDirectory存在,并且其他方法作为Jenkins文件的一部分在master上运行,而不是在节点上运行。因此,在master上使用的所有内容看起来都很棒,因为文件都在工作区中。在一个节点上全部使用失败

简言之,不要那样做。使用fileExists()pwd()、findFile等

如果您创建了一个shareLibrary,并且希望在Jenkins之外的代码上使用单元测试,那么您可以创建一个依赖于脚本对象的fascade(“来自管道的this”)

共享库类

class PipelineUtils implements Serializable {
    static def pipelineScript = null;

    /**
     * Setup this fascade with access to pipeline script methods
     * @param jenkinsPipelineScript
     * @return
     */
    static initialize(def jenkinsPipelineScript) {
        pipelineScript = jenkinsPipelineScript
    }

    /**
     * Use pipelineScript object ('this' from pipeline) to access fileExists
     * We cannot use Java File objects for detection as the pipeline script runs on master and uses delegation/serialization to
     * get to the node.  So, File.exists() will be false if the file was generated on the node and that node isn't master.
     * https://support.cloudbees.com/hc/en-us/articles/230922128-Pipeline-Using-java-io-File-in-a-Pipeline-description
     * @param target
     * @return true if path exists
     */
    static boolean exists(Path target) {
        if (!pipelineScript) {
            throw new Exception("PipelineUtils.initialize with pipeline script not called - access to pipeline 'this' required for access to file detection routines")
        }

        if (! target.parent) {
            throw new Exception('Please use absolutePaths with ${env.WORKSPACE}/path-to-file')
        }
        return pipelineScript.fileExists(target.toAbsolutePath().toString())
    }

    /**
     * Convert workspace relative path to absolute path
     * @param path relative path
     * @return node specific absolute path
     */
    static def relativeWorkspaceToAbsolutePath(String path) {
        Path pwd = Paths.get(pipelineScript.pwd())
        return pwd.resolve(path).toAbsolutePath().toString()
    }

    static void echo(def message) {
        pipelineScript.echo(message)
    }
}
测试类

PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists
Jenkinstep类{ 静态布尔文件存在(定义路径){ 返回新文件(路径).exists() }

}

在jenkins中的用法

PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists
在单元测试中的使用

PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists

你用的是什么版本的詹金斯?用户在此线程中报告了类似的问题,但是
pwd()
应该在最近的jenkins版本中工作。此外,您还可以尝试使用Workspace env变量,如果jenkins版本足够新,该变量应该在从属版本中可用。@Bricktop pwd()工作正常。它显示了正确的目录,但该目录未被代码识别为目录。jenkins版本为2.19.1,我也尝试过使用WORKSPACE env变量,但它不起作用,如/home/jenkins/WORKSPACE/所示,它实际上是在/home/jenkins/WORKSPACE/@2中执行的。但是无论如何,尽管它们具有正确的权限,但它们都不被视为目录。管道脚本总是在主机上进行计算,因此
文件
看起来像这样<代码>节点{}
对它来说毫无意义。不要在管道中使用
文件
。您使用的是什么版本的Jenkins?用户在此线程b中报告了类似的问题