├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── cd.yaml │ └── jenkins-security-scan.yml ├── .gitignore ├── .mvn ├── extensions.xml └── maven.config ├── Jenkinsfile ├── README.md ├── docs ├── CHANGELOG.md ├── JOB-DSL.md └── images │ └── file-operations.png ├── pom.xml └── src ├── main ├── java │ └── sp │ │ └── sd │ │ └── fileoperations │ │ ├── FileCopyOperation.java │ │ ├── FileCreateOperation.java │ │ ├── FileDeleteOperation.java │ │ ├── FileDownloadOperation.java │ │ ├── FileJoinOperation.java │ │ ├── FileOperation.java │ │ ├── FileOperationDescriptor.java │ │ ├── FileOperationsBuilder.java │ │ ├── FilePropertiesToJsonOperation.java │ │ ├── FileRenameOperation.java │ │ ├── FileTransformOperation.java │ │ ├── FileUnTarOperation.java │ │ ├── FileUnZipOperation.java │ │ ├── FileZipOperation.java │ │ ├── FolderCopyOperation.java │ │ ├── FolderCreateOperation.java │ │ ├── FolderDeleteOperation.java │ │ ├── FolderRenameOperation.java │ │ └── dsl │ │ ├── FileOperationsJobDslContext.java │ │ └── FileOperationsJobDslExtension.java └── resources │ ├── index.jelly │ └── sp │ └── sd │ └── fileoperations │ ├── FileCopyOperation │ ├── config.jelly │ ├── help-excludes.html │ ├── help-flattenFiles.html │ ├── help-includes.html │ ├── help-renameFiles.html │ ├── help-sourceCaptureExpression.html │ ├── help-targetLocation.html │ └── help-targetNameExpression.html │ ├── FileCreateOperation │ ├── config.jelly │ ├── help-fileContent.html │ └── help-fileName.html │ ├── FileDeleteOperation │ ├── config.jelly │ ├── help-excludes.html │ └── help-includes.html │ ├── FileDownloadOperation │ ├── config.jelly │ ├── help-targetLocation.html │ └── help-url.html │ ├── FileJoinOperation │ ├── config.jelly │ ├── help-sourceFile.html │ └── help-targetFile.html │ ├── FileOperationsBuilder │ └── config.jelly │ ├── FilePropertiesToJsonOperation │ ├── config.jelly │ ├── help-sourceFile.html │ └── help-targetFile.html │ ├── FileRenameOperation │ ├── config.jelly │ ├── help-destination.html │ └── help-source.html │ ├── FileTransformOperation │ ├── config.jelly │ ├── help-excludes.html │ └── help-includes.html │ ├── FileUnTarOperation │ ├── config.jelly │ ├── help-filePath.html │ └── help-targetLocation.html │ ├── FileUnZipOperation │ ├── config.jelly │ ├── help-filePath.html │ └── help-targetLocation.html │ ├── FileZipOperation │ ├── config.jelly │ ├── help-folderPath.html │ └── help-outputFolderPath.html │ ├── FolderCopyOperation │ ├── config.jelly │ ├── help-destinationFolderPath.html │ └── help-sourceFolderPath.html │ ├── FolderCreateOperation │ ├── config.jelly │ └── help-folderPath.html │ ├── FolderDeleteOperation │ ├── config.jelly │ └── help-folderPath.html │ └── FolderRenameOperation │ ├── config.jelly │ ├── help-destination.html │ └── help-source.html └── test ├── java └── sp │ └── sd │ └── fileoperations │ ├── FileCopyOperationTest.java │ ├── FileCreateOperationTest.java │ ├── FileDeleteOperationTest.java │ ├── FileDownloadOperationTest.java │ ├── FileJoinOperationTest.java │ ├── FileOperationDescriptorTest.java │ ├── FileOperationTest.java │ ├── FileOperationsBuilderTest.java │ ├── FilePropertiesToJsonOperationTest.java │ ├── FileRenameOperationTest.java │ ├── FileTransformOperationTest.java │ ├── FileUnTarOperationTest.java │ ├── FileUnZipOperationTest.java │ ├── FileZipOperationTest.java │ ├── FolderCopyOperationTest.java │ ├── FolderCreateOperationTest.java │ ├── FolderDeleteOperationTest.java │ └── FolderRenameOperationTest.java └── resources └── __files └── dummy.zip /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jenkinsci/file-operations-plugin-developers 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: maven 6 | directory: / 7 | schedule: 8 | interval: monthly 9 | - package-ecosystem: github-actions 10 | directory: / 11 | schedule: 12 | interval: monthly 13 | -------------------------------------------------------------------------------- /.github/workflows/cd.yaml: -------------------------------------------------------------------------------- 1 | # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins 2 | 3 | name: cd 4 | on: 5 | workflow_dispatch: 6 | check_run: 7 | types: 8 | - completed 9 | 10 | permissions: 11 | checks: read 12 | contents: write 13 | 14 | jobs: 15 | maven-cd: 16 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1 17 | secrets: 18 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} 19 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} 20 | -------------------------------------------------------------------------------- /.github/workflows/jenkins-security-scan.yml: -------------------------------------------------------------------------------- 1 | # Jenkins Security Scan 2 | # For more information, see: https://www.jenkins.io/doc/developer/security/scan/ 3 | 4 | name: Jenkins Security Scan 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | types: [opened, synchronize, reopened] 12 | workflow_dispatch: 13 | 14 | permissions: 15 | security-events: write 16 | contents: read 17 | actions: read 18 | 19 | jobs: 20 | security-scan: 21 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2 22 | with: 23 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate. 24 | # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default. 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X files 2 | .DS_Store 3 | 4 | # Intellij files 5 | *.iml 6 | .idea/* 7 | classes 8 | 9 | # Maven 10 | target/* 11 | pom.xml.releaseBackup 12 | release.properties 13 | 14 | # Jenkins workplace files 15 | /work 16 | 17 | # Gradle 18 | .gradle 19 | build 20 | libsrc/* 21 | 22 | # Eclipse 23 | /.classpath 24 | /.project 25 | /.settings* 26 | /target/ 27 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | io.jenkins.tools.incrementals 4 | git-changelist-maven-extension 5 | 1.8 6 | 7 | 8 | -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Pconsume-incrementals 2 | -Pmight-produce-incrementals 3 | -Dchangelist.format=%d.v%s 4 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | /* 2 | See the documentation for more options: 3 | https://github.com/jenkins-infra/pipeline-library/ 4 | */ 5 | buildPlugin( 6 | forkCount: '1C', // run this number of tests in parallel for faster feedback. If the number terminates with a 'C', the value will be multiplied by the number of available CPU cores 7 | useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests 8 | configurations: [ 9 | [platform: 'linux', jdk: 21], 10 | [platform: 'windows', jdk: 17], 11 | ]) 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # File Operations Plugin 2 | 3 | [![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/file-operations)](https://plugins.jenkins.io/file-operations) 4 | [![Coverage](https://ci.jenkins.io/job/Plugins/job/file-operations-plugin/job/main/badge/icon?status=${instructionCoverage}&subject=coverage&color=${colorInstructionCoverage})](https://ci.jenkins.io/job/Plugins/job/file-operations-plugin/job/main) 5 | [![LOC](https://ci.jenkins.io/job/Plugins/job/file-operations-plugin/job/main/badge/icon?job=test&status=${lineOfCode}&subject=line%20of%20code&color=blue)](https://ci.jenkins.io/job/Plugins/job/file-operations-plugin/job/main) 6 | [![Changelog](https://img.shields.io/github/v/tag/jenkinsci/file-operations-plugin?label=changelog)](https://github.com/jenkinsci/file-operations-plugin/blob/master/docs/CHANGELOG.md) 7 | [![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/file-operations?color=blue)](https://plugins.jenkins.io/file-operations) 8 | 9 | This plugin's main goal is to provide **cross platform** file operations as Build step. 10 | It also provides the same functionality as [Pipeline](https://plugins.jenkins.io/workflow-aggregator/) step. 11 | 12 | No need to search for *Nix or Win commands to do file operations. 13 | 14 | ## List of steps: 15 | 16 | 1. File **Copy** Operation 17 | 2. File **Delete** Operation 18 | 3. File **Create** Operation 19 | 4. File **Download** Operation 20 | 5. File **Transform** Operation 21 | 6. File **UnTar** Operation 22 | 7. File **UnZip** Operation 23 | 8. **Folder Create** Operation 24 | 9. **Folder Copy** Operation 25 | 10. **Folder Delete** Operation 26 | 11. File **Join** 27 | 12. File **Properties To Json** 28 | 13. File **Zip** Operation 29 | 14. **File Rename** Operation 30 | 15. **Folder Rename** Operation 31 | 32 | For more details about each step please refer to: [File Operations Steps](https://www.jenkins.io/doc/pipeline/steps/file-operations/) 33 | 34 | ## Pipeline Usage Examples 35 | 36 | This section provides examples of how to use the File Operations Plugin in Jenkins pipelines. These examples demonstrate the most common file operations, which you can easily incorporate into your own pipeline scripts. 37 | 38 | To use these examples in your Jenkins pipeline, follow these steps: 39 | 40 | 1. **`SetUp Your Jenkins Environment`**: Ensure that Jenkins is set up and that the File Operations Plugin is installed. 41 | 42 | 2. **`Create or Edit a Jenkins Pipeline Job`**: 43 | - Go to your Jenkins instance. 44 | - Create a new pipeline job or edit an existing one. 45 | 46 | 3. **`Add the Pipeline Script`**: Copy and paste the relevant example script into the pipeline script area of your job configuration. 47 | 48 | 4. **`Run the Pipeline`**: Save the job configuration and run the pipeline to see the file operations in action. 49 | 50 | ### 1. File Copy Operation 51 | 52 | This operation copies files from one location to another. It is useful for scenarios where you need to move or replicate files as part of your build process. 53 | 54 | ```groovy 55 | pipeline { 56 | agent any 57 | stages { 58 | stage('Copy Files') { 59 | steps { 60 | fileOperations([ 61 | fileCopyOperation(sourceFiles: 'src/*.txt', targetLocation: 'dest/') 62 | ]) 63 | } 64 | } 65 | } 66 | } 67 | ``` 68 | 69 | Explanation: 70 | **`sourceFiles`** :'src/*.txt': Specifies the files to copy from the source directory. In this case, all `.txt` files in the `src` directory. 71 | **`targetLocation`**:'dest/': Defines the destination directory where the files will be copied to. 72 | 73 | ### 2. File Deletion Operation 74 | 75 | This operation deletes files based on a specified pattern. It is useful for cleaning up old or unnecessary files during the build process. 76 | 77 | ```groovy 78 | pipeline { 79 | agent any 80 | stages { 81 | stage('Delete Files') { 82 | steps { 83 | fileOperations([ 84 | fileDeleteOperation(includeFilePattern: '**/old-files/*.log') 85 | ]) 86 | } 87 | } 88 | } 89 | } 90 | ``` 91 | Explanation: 92 | **`includeFilePattern`**: `'**/old-files/*.log'`: Specifies the pattern for files to delete. In this case, all `.log` files in any `old-files` directory. 93 | 94 | ### 3. File Create Operation 95 | 96 | This operation creates a new file with specified content. It is useful for generating configuration files or other necessary files as part of the build process. 97 | ```groovy 98 | pipeline { 99 | agent any 100 | stages { 101 | stage('Create File') { 102 | steps { 103 | fileOperations([ 104 | fileCreateOperation(filePath: 'newfile.txt', fileContent: 'Hello, World!') 105 | ]) 106 | } 107 | } 108 | } 109 | } 110 | ``` 111 | Explanation: 112 | 113 | **`filePath`**:`'newfile.txt'`: Specifies the path for the new file. 114 | **`fileContent`**: `'Hello, World!'`: Defines the content to be written to the new file. 115 | 116 | ### 4. File Download Operation 117 | This operation downloads a file from a specified URL and saves it to a designated location. It is useful for retrieving external resources or dependencies needed for the build. 118 | 119 | ```groovy 120 | pipeline { 121 | agent any 122 | stages { 123 | stage('Download File') { 124 | steps { 125 | fileOperations([ 126 | fileDownloadOperation(url: 'https://example.com/file.zip', targetLocation: 'downloads/') 127 | ]) 128 | } 129 | } 130 | } 131 | } 132 | ``` 133 | Explanation: 134 | 135 | **`url`**: `'https://example.com/file.zip'`: The URL of the file to download. 136 | **`targetLocation`**: `'downloads/'`: The directory where the downloaded file will be saved. 137 | 138 | 139 | ## Version History 140 | 141 | See the [changelog](docs/CHANGELOG.md) 142 | 143 | ## Build step usage screenshot 144 | 145 | ![](docs/images/file-operations.png) 146 | 147 | ## Job DSL 148 | 149 | See the [Job DSL usage example](docs/JOB-DSL.md). -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.10 4 | 5 | Release date: 17 May 2020 6 | 7 | - Add support for custom output folder in FileZipOperation. (#12) 8 | - Use HTTPS for licences URL. (#11) 9 | 10 | ## 1.9 11 | 12 | Release date: 8 March 2020 13 | 14 | - Updated documentation. (#10) 15 | - Support for renaming files within file copy operation. (#9) 16 | - Added proxy support for fileDownloadOperation. (#8) 17 | 18 | ## 1.8 19 | 20 | Release date: 25 November 2019 21 | 22 | - Code Improvements. (#7) 23 | - Added missing FileZipOperation method for access in JobDSL. (#6) 24 | - Fixed string comparisons. (#5) 25 | 26 | ## 1.7 27 | 28 | Release date: 4 September 2017 29 | 30 | - Added File Rename Operation 31 | - Added Folder Rename Operation 32 | 33 | ## 1.6 34 | 35 | Release date: 4 May 2017 36 | 37 | - Fixed download failed due to empty credentials even though if it 38 | open for public 39 | 40 | ## 1.5 41 | 42 | Release date: 7 April 2017 43 | 44 | - Added File Zip Operation 45 | 46 | ## 1.4 47 | 48 | Release date: 5 March 2017 49 | 50 | - Added Symbols for Jenkins pipeline 51 | 52 | ## 1.3 53 | 54 | Release date: 3 October 2016 55 | 56 | - Added Job DSL support 57 | 58 | ## 1.2 59 | Release date: 26 June 2016 60 | 61 | - Added 11 & 12 operations 62 | 63 | ## 1.1 64 | 65 | Release date: 28 May 2016 66 | 67 | - Added support for pipeline 68 | 69 | ## 1.0 70 | 71 | Release date: 22 April 2016 72 | 73 | - First public release with 1 to 10 operations -------------------------------------------------------------------------------- /docs/JOB-DSL.md: -------------------------------------------------------------------------------- 1 | # Job DSL usage 2 | 3 | ### Template 4 | 5 | ``` 6 | job { 7 | steps { 8 | fileOperations { 9 | fileCreateOperation(String fileName, String fileContent) 10 | fileCopyOperation(String includes, String excludes, String targetLocation, boolean flattenFiles, boolean renameFiles, String sourceCaptureExpression, String targetNameExpression) 11 | fileDeleteOperation(String includes, String excludes) 12 | fileDownloadOperation(String url, String userName, String password, String targetLocation, String targetFileName, String proxyHost, String proxyPort) 13 | fileJoinOperation(String sourceFile, String targetFile) 14 | filePropertiesToJsonOperation(String sourceFile, String targetFile) 15 | fileTransformOperation(String includes, String excludes) 16 | fileUnTarOperation(String filePath, String targetLocation, boolean isGZIP) 17 | fileUnZipOperation(String filePath, String targetLocation) 18 | folderCopyOperation(String sourceFolderPath, String destinationFolderPath) 19 | folderCreateOperation(String folderPath) 20 | folderDeleteOperation(String folderPath) 21 | fileRenameOperation(String source, String destination) 22 | folderRenameOperation(String source, String destination) 23 | } 24 | } 25 | } 26 | ``` 27 | 28 | ### Example 29 | 30 | ``` 31 | freeStyleJob('FileOperationsJob') { 32 | steps { 33 | fileOperations { 34 | fileCreateOperation('testdsl.txt','test content') 35 | fileCopyOperation('testdsl.txt','','.',false, true, ".*(?:\\\\|/)test-results-xml(?:\\\\|/).*-([\\d]+)(?:\\\\|/).*(?:\\\\|/)([^(?:\\\\|/)]+)$" , "$1-$2") 36 | fileDownloadOperation('http://192.168.56.1:8081/service/local/repositories/MyWorks/content/sp/sd/test-artifact/40/test-artifact-40-debug.zip','','','.','test.zip', 'proxy', '3128') 37 | fileDeleteOperation('testdsl.txt','') 38 | fileDeleteOperation('test.zip','') 39 | fileJoinOperation('testsource.txt','testtarget.txt') 40 | filePropertiesToJsonOperation('testsource.properties','testtarget.json') 41 | fileTransformOperation('testsource.txt','') 42 | fileUnTarOperation('package.tar','.',false) 43 | fileUnZipOperation('package.zip','.') 44 | folderCopyOperation('sourcefolder','destinationfolder') 45 | folderCreateOperation('newfolder') 46 | folderDeleteOperation('targetfolder') 47 | fileRenameOperation('test.txt', 'testrename.txt') 48 | folderRenameOperation('test', 'testrename') 49 | } 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /docs/images/file-operations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/file-operations-plugin/afd7a2b52f885b99cfcd2f81b3dfeb3be6a869f2/docs/images/file-operations.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | org.jenkins-ci.plugins 7 | plugin 8 | 5.17 9 | 10 | 11 | 12 | sp.sd 13 | file-operations 14 | ${changelist} 15 | hpi 16 | 17 | File Operations Plugin 18 | File Operations Plugin 19 | https://github.com/jenkinsci/file-operations-plugin 20 | 21 | 22 | MIT License 23 | https://opensource.org/licenses/MIT 24 | 25 | 26 | 27 | 28 | scm:git:https://github.com/${gitHubRepo}.git 29 | scm:git:git@github.com:${gitHubRepo}.git 30 | https://github.com/${gitHubRepo} 31 | ${scmTag} 32 | 33 | 34 | 35 | 999999-SNAPSHOT 36 | jenkinsci/file-operations-plugin 37 | 38 | 2.479 39 | ${jenkins.baseline}.3 40 | 41 | 42 | 43 | 44 | io.jenkins.tools.bom 45 | bom-${jenkins.baseline}.x 46 | 4845.v9163d3278e4f 47 | pom 48 | import 49 | 50 | 51 | 52 | 53 | 54 | io.jenkins.plugins 55 | apache-httpcomponents-client-5-api 56 | 57 | 58 | org.jenkins-ci.plugins 59 | jackson2-api 60 | 61 | 62 | org.jenkins-ci.plugins 63 | job-dsl 64 | true 65 | 66 | 67 | com.thoughtworks.xstream 68 | xstream 69 | test 70 | 71 | 72 | org.wiremock 73 | wiremock-standalone 74 | 3.13.0 75 | test 76 | 77 | 78 | 79 | 80 | 81 | repo.jenkins-ci.org 82 | https://repo.jenkins-ci.org/public/ 83 | 84 | 85 | 86 | 87 | repo.jenkins-ci.org 88 | https://repo.jenkins-ci.org/public/ 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileCopyOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Extension; 5 | import hudson.FilePath; 6 | import hudson.FilePath.FileCallable; 7 | import hudson.Launcher; 8 | import hudson.model.Run; 9 | import hudson.model.TaskListener; 10 | import hudson.remoting.VirtualChannel; 11 | import org.jenkinsci.Symbol; 12 | import org.jenkinsci.remoting.RoleChecker; 13 | import org.kohsuke.stapler.DataBoundConstructor; 14 | import org.kohsuke.stapler.DataBoundSetter; 15 | 16 | import java.io.File; 17 | import hudson.util.DirScanner; 18 | import java.io.Serializable; 19 | 20 | public class FileCopyOperation extends FileOperation implements Serializable { 21 | private final String includes; 22 | private final String excludes; 23 | private final String targetLocation; 24 | private final boolean flattenFiles; 25 | private final boolean renameFiles; 26 | private final String sourceCaptureExpression; 27 | private final String targetNameExpression; 28 | private Boolean useDefaultExcludes; 29 | 30 | @DataBoundConstructor 31 | public FileCopyOperation(String includes, 32 | String excludes, 33 | String targetLocation, 34 | boolean flattenFiles, 35 | boolean renameFiles, 36 | String sourceCaptureExpression, 37 | String targetNameExpression) { 38 | this.includes = includes; 39 | this.excludes = excludes; 40 | this.targetLocation = targetLocation; 41 | this.flattenFiles = flattenFiles; 42 | this.renameFiles = renameFiles; 43 | this.sourceCaptureExpression = sourceCaptureExpression; 44 | this.targetNameExpression = targetNameExpression; 45 | this.useDefaultExcludes = true; 46 | } 47 | 48 | public String getIncludes() { 49 | return includes; 50 | } 51 | 52 | public String getExcludes() { 53 | return excludes; 54 | } 55 | 56 | public String getTargetLocation() { 57 | return targetLocation; 58 | } 59 | 60 | public boolean getFlattenFiles() { 61 | return flattenFiles; 62 | } 63 | 64 | public boolean getRenameFiles() { 65 | return renameFiles; 66 | } 67 | 68 | public String getSourceCaptureExpression() { 69 | return sourceCaptureExpression; 70 | } 71 | 72 | public String getTargetNameExpression() { 73 | return targetNameExpression; 74 | } 75 | 76 | public boolean getUseDefaultExcludes() { 77 | return useDefaultExcludes; 78 | } 79 | 80 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 81 | boolean result = false; 82 | try { 83 | listener.getLogger().println("File Copy Operation:"); 84 | EnvVars envVars = run.getEnvironment(listener); 85 | try { 86 | FilePath ws = new FilePath(buildWorkspace, "."); 87 | result = ws.act(new TargetFileCallable(listener, 88 | envVars.expand(includes), 89 | envVars.expand(excludes), 90 | envVars.expand(targetLocation), 91 | flattenFiles, 92 | renameFiles, 93 | sourceCaptureExpression, 94 | targetNameExpression, 95 | useDefaultExcludes)); 96 | } catch (RuntimeException e) { 97 | listener.getLogger().println(e.getMessage()); 98 | throw e; 99 | } catch (Exception e) { 100 | listener.fatalError(e.getMessage()); 101 | return false; 102 | } 103 | 104 | } catch (Exception e) { 105 | listener.fatalError(e.getMessage()); 106 | } 107 | return result; 108 | } 109 | 110 | private static final class TargetFileCallable implements FileCallable { 111 | private static final long serialVersionUID = 1; 112 | private final TaskListener listener; 113 | private final String resolvedIncludes; 114 | private final String resolvedExcludes; 115 | private final String resolvedTargetLocation; 116 | private final boolean flattenFiles; 117 | private final boolean renameFiles; 118 | private final String sourceCaptureExpression; 119 | private final String targetNameExpression; 120 | private final boolean useDefaultExcludes; 121 | 122 | public TargetFileCallable(TaskListener Listener, 123 | String ResolvedIncludes, 124 | String ResolvedExcludes, 125 | String ResolvedTargetLocation, 126 | boolean flattenFiles, 127 | boolean renameFiles, 128 | String sourceCaptureExpression, 129 | String targetNameExpression, 130 | boolean UseDefaultExcludes) { 131 | this.listener = Listener; 132 | this.resolvedIncludes = ResolvedIncludes; 133 | this.resolvedExcludes = ResolvedExcludes; 134 | this.resolvedTargetLocation = ResolvedTargetLocation; 135 | this.flattenFiles = flattenFiles; 136 | this.renameFiles = renameFiles; 137 | this.sourceCaptureExpression = sourceCaptureExpression; 138 | this.targetNameExpression = targetNameExpression; 139 | this.useDefaultExcludes = UseDefaultExcludes; 140 | } 141 | 142 | @Override 143 | public Boolean invoke(File ws, VirtualChannel channel) { 144 | boolean result; 145 | try { 146 | FilePath fpWS = new FilePath(ws); 147 | FilePath fpTL = new FilePath(fpWS, resolvedTargetLocation); 148 | FilePath[] resolvedFiles = fpWS.list(resolvedIncludes, resolvedExcludes, useDefaultExcludes); 149 | if (resolvedFiles.length == 0) { 150 | listener.getLogger().println("0 files found for include pattern '" + resolvedIncludes + "' and exclude pattern '" + resolvedExcludes + "'"); 151 | } 152 | if (flattenFiles) { 153 | for (FilePath item : resolvedFiles) { 154 | if (renameFiles) { 155 | final String relativePath = item.getRemote() 156 | .replace(fpWS.getRemote(), "."); 157 | final String relativeTargetFileName = relativePath 158 | .replaceAll(sourceCaptureExpression, targetNameExpression); 159 | final String targetFileName = relativePath.equals(relativeTargetFileName) ? item.getName() : relativeTargetFileName; 160 | FilePath fpTF = new FilePath(fpTL, targetFileName); 161 | listener.getLogger().println("Copy from " + item.getRemote() + " to " + fpTF); 162 | item.copyTo(fpTF); 163 | } else { 164 | listener.getLogger().println(item.getRemote()); 165 | item.copyTo(new FilePath(fpTL, item.getName())); 166 | } 167 | } 168 | result = true; 169 | } else { 170 | for (FilePath item : resolvedFiles) { 171 | listener.getLogger().println(item.getRemote()); 172 | } 173 | fpWS.copyRecursiveTo(new DirScanner.Glob(resolvedIncludes, resolvedExcludes, useDefaultExcludes), fpTL, resolvedIncludes); 174 | result = true; 175 | } 176 | } catch (RuntimeException e) { 177 | listener.fatalError(e.getMessage()); 178 | throw e; 179 | } catch (Exception e) { 180 | listener.fatalError(e.getMessage()); 181 | result = false; 182 | } 183 | return result; 184 | } 185 | 186 | @Override 187 | public void checkRoles(RoleChecker checker) throws SecurityException { 188 | 189 | } 190 | } 191 | 192 | @Extension 193 | @Symbol("fileCopyOperation") 194 | public static class DescriptorImpl extends FileOperationDescriptor { 195 | public String getDisplayName() { 196 | return "File Copy"; 197 | } 198 | } 199 | 200 | @DataBoundSetter 201 | public void setUseDefaultExcludes(boolean useDefaultExcludes) { 202 | this.useDefaultExcludes = useDefaultExcludes; 203 | } 204 | 205 | protected Object readResolve() { 206 | if (useDefaultExcludes == null) { 207 | useDefaultExcludes = true; 208 | } 209 | return this; 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileCreateOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FileCreateOperation extends FileOperation implements Serializable { 22 | private final String fileName; 23 | private final String fileContent; 24 | 25 | @DataBoundConstructor 26 | public FileCreateOperation(String fileName, String fileContent) { 27 | this.fileName = fileName; 28 | this.fileContent = fileContent; 29 | } 30 | 31 | public String getFileName() { 32 | return fileName; 33 | } 34 | 35 | public String getFileContent() { 36 | return fileContent; 37 | } 38 | 39 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 40 | boolean result = false; 41 | try { 42 | listener.getLogger().println("File Create Operation:"); 43 | EnvVars envVars = run.getEnvironment(listener); 44 | try { 45 | FilePath ws = new FilePath(buildWorkspace, "."); 46 | result = ws.act(new TargetFileCallable(listener, envVars.expand(fileName), envVars.expand(fileContent), envVars)); 47 | } catch (Exception e) { 48 | listener.fatalError(e.getMessage()); 49 | return false; 50 | } 51 | } catch (Exception e) { 52 | listener.fatalError(e.getMessage()); 53 | } 54 | return result; 55 | } 56 | 57 | private static final class TargetFileCallable implements FileCallable { 58 | private static final long serialVersionUID = 1; 59 | private final TaskListener listener; 60 | private final EnvVars environment; 61 | private final String resolvedFileName; 62 | private final String resolvedFileContent; 63 | 64 | public TargetFileCallable(TaskListener Listener, String ResolvedFileName, String ResolvedFileContent, EnvVars environment) { 65 | this.listener = Listener; 66 | this.resolvedFileName = ResolvedFileName; 67 | this.resolvedFileContent = ResolvedFileContent; 68 | this.environment = environment; 69 | } 70 | 71 | @Override 72 | public Boolean invoke(File ws, VirtualChannel channel) { 73 | boolean result; 74 | try { 75 | FilePath fpWS = new FilePath(ws); 76 | FilePath fpTL = new FilePath(fpWS, resolvedFileName); 77 | if (fpTL.exists()) { 78 | listener.getLogger().println(resolvedFileName + " file already exists, replacing the content with the provided content."); 79 | } 80 | listener.getLogger().println("Creating file: " + fpTL.getRemote()); 81 | fpTL.write(resolvedFileContent, "UTF-8"); 82 | result = true; 83 | } catch (RuntimeException e) { 84 | listener.fatalError(e.getMessage()); 85 | throw e; 86 | } catch (Exception e) { 87 | listener.fatalError(e.getMessage()); 88 | result = false; 89 | } 90 | return result; 91 | } 92 | 93 | @Override 94 | public void checkRoles(RoleChecker checker) throws SecurityException { 95 | 96 | } 97 | } 98 | 99 | @Extension 100 | @Symbol("fileCreateOperation") 101 | public static class DescriptorImpl extends FileOperationDescriptor { 102 | public String getDisplayName() { 103 | return "File Create"; 104 | } 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileDeleteOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | import org.kohsuke.stapler.DataBoundSetter; 13 | 14 | import java.io.File; 15 | 16 | import hudson.FilePath.FileCallable; 17 | import hudson.remoting.VirtualChannel; 18 | import org.jenkinsci.remoting.RoleChecker; 19 | 20 | import java.io.Serializable; 21 | 22 | public class FileDeleteOperation extends FileOperation implements Serializable { 23 | private final String includes; 24 | private final String excludes; 25 | private Boolean useDefaultExcludes; 26 | 27 | @DataBoundConstructor 28 | public FileDeleteOperation(String includes, String excludes) { 29 | this.includes = includes; 30 | this.excludes = excludes; 31 | this.useDefaultExcludes = true; 32 | } 33 | 34 | public String getIncludes() { 35 | return includes; 36 | } 37 | 38 | public String getExcludes() { 39 | return excludes; 40 | } 41 | 42 | public boolean getUseDefaultExcludes() { 43 | return useDefaultExcludes; 44 | } 45 | 46 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 47 | boolean result = false; 48 | try { 49 | listener.getLogger().println("File Delete Operation:"); 50 | EnvVars envVars = run.getEnvironment(listener); 51 | try { 52 | FilePath ws = new FilePath(buildWorkspace, "."); 53 | result = ws.act(new TargetFileCallable(listener, envVars.expand(includes), envVars.expand(excludes), useDefaultExcludes)); 54 | } catch (Exception e) { 55 | listener.fatalError(e.getMessage()); 56 | return false; 57 | } 58 | 59 | } catch (Exception e) { 60 | listener.fatalError(e.getMessage()); 61 | } 62 | return result; 63 | } 64 | 65 | private static final class TargetFileCallable implements FileCallable { 66 | private static final long serialVersionUID = 1; 67 | private final TaskListener listener; 68 | private final String resolvedIncludes; 69 | private final String resolvedExcludes; 70 | private final boolean useDefaultExcludes; 71 | 72 | public TargetFileCallable(TaskListener Listener, String ResolvedIncludes, String ResolvedExcludes, boolean UseDefaultExcludes) { 73 | this.listener = Listener; 74 | this.resolvedIncludes = ResolvedIncludes; 75 | this.resolvedExcludes = ResolvedExcludes; 76 | this.useDefaultExcludes = UseDefaultExcludes; 77 | } 78 | 79 | @Override 80 | public Boolean invoke(File ws, VirtualChannel channel) { 81 | boolean result = false; 82 | try { 83 | FilePath fpWS = new FilePath(ws); 84 | FilePath[] resolvedFiles = fpWS.list(resolvedIncludes, resolvedExcludes, useDefaultExcludes); 85 | if (resolvedFiles.length == 0) { 86 | listener.getLogger().println("0 files found for include pattern '" + resolvedIncludes + "' and exclude pattern '" + resolvedExcludes + "'"); 87 | result = true; 88 | } 89 | for (FilePath fp : resolvedFiles) { 90 | listener.getLogger().println(fp.getRemote() + " deleting...."); 91 | if (fp.isDirectory()) { 92 | try { 93 | fp.deleteRecursive(); 94 | result = true; 95 | listener.getLogger().println("Success."); 96 | } catch (RuntimeException e) { 97 | listener.fatalError(e.getMessage()); 98 | throw e; 99 | } catch (Exception e) { 100 | listener.fatalError(e.getMessage()); 101 | result = false; 102 | } 103 | } else { 104 | try { 105 | result = fp.delete(); 106 | listener.getLogger().println("Success."); 107 | } catch (RuntimeException e) { 108 | listener.fatalError(e.getMessage()); 109 | throw e; 110 | } catch (Exception e) { 111 | listener.fatalError(e.getMessage()); 112 | result = false; 113 | } 114 | } 115 | 116 | } 117 | } catch (RuntimeException e) { 118 | listener.fatalError(e.getMessage()); 119 | throw e; 120 | } catch (Exception e) { 121 | listener.fatalError(e.getMessage()); 122 | result = false; 123 | } 124 | return result; 125 | } 126 | 127 | @Override 128 | public void checkRoles(RoleChecker checker) throws SecurityException { 129 | 130 | } 131 | } 132 | 133 | @Extension 134 | @Symbol("fileDeleteOperation") 135 | public static class DescriptorImpl extends FileOperationDescriptor { 136 | public String getDisplayName() { 137 | return "File Delete"; 138 | } 139 | } 140 | 141 | @DataBoundSetter 142 | public void setUseDefaultExcludes(boolean useDefaultExcludes) { 143 | this.useDefaultExcludes = useDefaultExcludes; 144 | } 145 | 146 | protected Object readResolve() { 147 | if (useDefaultExcludes == null) { 148 | useDefaultExcludes = true; 149 | } 150 | return this; 151 | } 152 | } -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileDownloadOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import edu.umd.cs.findbugs.annotations.NonNull; 4 | import hudson.EnvVars; 5 | import hudson.Launcher; 6 | import hudson.Extension; 7 | import hudson.FilePath; 8 | import hudson.model.Run; 9 | import hudson.model.TaskListener; 10 | 11 | import hudson.util.Secret; 12 | 13 | import org.apache.hc.client5.http.auth.AuthCache; 14 | import org.apache.hc.client5.http.impl.DefaultRedirectStrategy; 15 | import org.apache.hc.client5.http.impl.classic.*; 16 | import org.jenkinsci.Symbol; 17 | import org.kohsuke.stapler.DataBoundConstructor; 18 | 19 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 20 | 21 | import java.io.FileOutputStream; 22 | import java.io.File; 23 | import java.io.OutputStream; 24 | 25 | import hudson.FilePath.FileCallable; 26 | import hudson.remoting.VirtualChannel; 27 | import org.apache.hc.core5.http.HttpEntity; 28 | import org.apache.hc.core5.http.HttpHost; 29 | import org.apache.hc.core5.http.HttpStatus; 30 | import org.apache.hc.client5.http.auth.AuthScope; 31 | import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; 32 | import org.apache.hc.client5.http.classic.methods.HttpGet; 33 | import org.apache.hc.client5.http.impl.auth.BasicAuthCache; 34 | import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; 35 | import org.apache.hc.client5.http.protocol.HttpClientContext; 36 | import org.apache.hc.client5.http.impl.auth.BasicScheme; 37 | import org.jenkinsci.remoting.RoleChecker; 38 | 39 | import java.io.Serial; 40 | import java.io.Serializable; 41 | import java.net.URI; 42 | 43 | 44 | public class FileDownloadOperation extends FileOperation implements Serializable { 45 | private final String url; 46 | private final String userName; 47 | private final String targetLocation; 48 | private final String targetFileName; 49 | private final String password; 50 | private final String proxyHost; 51 | private final String proxyPort; 52 | 53 | @DataBoundConstructor 54 | public FileDownloadOperation(String url, String userName, String password, String targetLocation, String targetFileName, String proxyHost, String proxyPort) { 55 | this.url = url; 56 | this.userName = userName; 57 | this.targetLocation = targetLocation; 58 | this.targetFileName = targetFileName; 59 | this.password = Secret.fromString(password).getEncryptedValue(); 60 | this.proxyHost=proxyHost; 61 | this.proxyPort=proxyPort; 62 | } 63 | 64 | public String getUrl() { 65 | return url; 66 | } 67 | 68 | public String getUserName() { 69 | return userName; 70 | } 71 | 72 | public String getTargetLocation() { 73 | return targetLocation; 74 | } 75 | 76 | public String getTargetFileName() { 77 | return targetFileName; 78 | } 79 | 80 | @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") 81 | public String getPassword() { 82 | return Secret.decrypt(password).getPlainText(); 83 | } 84 | 85 | public String getProxyHost() { 86 | return proxyHost; 87 | } 88 | 89 | public String getProxyPort() { 90 | return proxyPort; 91 | } 92 | 93 | @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") 94 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 95 | boolean result = false; 96 | try { 97 | listener.getLogger().println("File Download Operation:"); 98 | EnvVars envVars = run.getEnvironment(listener); 99 | try { 100 | FilePath ws = new FilePath(buildWorkspace, "."); 101 | result = ws.act(new TargetFileCallable(listener, 102 | envVars.expand(url), 103 | envVars.expand(userName), 104 | envVars.expand(Secret.decrypt(password).getPlainText()), 105 | envVars.expand(targetLocation), 106 | envVars.expand(targetFileName), 107 | envVars.expand(proxyHost), 108 | envVars.expand(proxyPort))); 109 | } catch (Exception e) { 110 | listener.fatalError(e.getMessage()); 111 | return false; 112 | } 113 | 114 | } catch (Exception e) { 115 | listener.fatalError(e.getMessage()); 116 | } 117 | return result; 118 | } 119 | 120 | private static final class TargetFileCallable implements FileCallable { 121 | @Serial 122 | private static final long serialVersionUID = 1; 123 | private final TaskListener listener; 124 | private final String resolvedUrl; 125 | private final String resolvedUserName; 126 | private final String resolvedTargetLocation; 127 | private final String resolvedTargetFileName; 128 | private final String resolvedPassword; 129 | private final String proxyHost; 130 | private final String proxyPort; 131 | 132 | public TargetFileCallable(TaskListener Listener, String ResolvedUrl, String ResolvedUserName, String ResolvedPassword, String ResolvedTargetLocation, String ResolvedTargetFileName, String proxyHost, String proxyPort) { 133 | this.listener = Listener; 134 | this.resolvedUrl = ResolvedUrl; 135 | this.resolvedUserName = ResolvedUserName; 136 | this.resolvedTargetLocation = ResolvedTargetLocation; 137 | this.resolvedTargetFileName = ResolvedTargetFileName; 138 | this.resolvedPassword = ResolvedPassword; 139 | this.proxyHost = proxyHost; 140 | this.proxyPort = proxyPort; 141 | } 142 | 143 | @Override 144 | public Boolean invoke(File ws, VirtualChannel channel) { 145 | try { 146 | FilePath fpWS = new FilePath(ws); 147 | FilePath fpTL = new FilePath(fpWS, resolvedTargetLocation); 148 | FilePath fpTLF = new FilePath(fpTL, resolvedTargetFileName); 149 | File fTarget = new File(fpTLF.toURI()); 150 | URI uri = new URI(resolvedUrl); 151 | listener.getLogger().println("Started downloading file from " + resolvedUrl); 152 | HttpHost host = new HttpHost(uri.getScheme(), uri.getHost(), uri.getPort()); 153 | BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); 154 | UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(resolvedUserName, resolvedPassword.toCharArray()); 155 | credsProvider.setCredentials(new AuthScope(uri.getHost(), uri.getPort()), credentials); 156 | AuthCache authCache = new BasicAuthCache(); 157 | BasicScheme basicAuth = new BasicScheme(); 158 | basicAuth.initPreemptive(credentials); 159 | authCache.put(host, basicAuth); 160 | 161 | HttpClientBuilder httpClientBuilder = HttpClients.custom() 162 | .setDefaultCredentialsProvider(credsProvider); 163 | 164 | if (proxyHost != null && !proxyHost.isEmpty() 165 | && proxyPort != null && proxyPort.matches("[0-9]+")) { 166 | HttpHost proxy = new HttpHost(proxyHost, Integer.parseInt(proxyPort)); 167 | httpClientBuilder.setProxy(proxy); 168 | } 169 | 170 | CloseableHttpClient httpClient = httpClientBuilder.setRedirectStrategy(DefaultRedirectStrategy.INSTANCE).build(); 171 | HttpGet httpGet = new HttpGet(uri); 172 | HttpClientContext localContext = HttpClientContext.create(); 173 | if (!resolvedUserName.isEmpty() && !resolvedPassword.isEmpty()) { 174 | localContext.setAuthCache(authCache); 175 | } 176 | return httpClient.execute(host, httpGet, localContext, response -> { 177 | HttpEntity entity = response.getEntity(); 178 | try (OutputStream fosTarget = new FileOutputStream(fTarget)) { 179 | if (response.getCode() != HttpStatus.SC_OK) { 180 | return false; 181 | } else { 182 | entity.writeTo(fosTarget); 183 | listener.getLogger().println("Completed downloading file."); 184 | return true; 185 | } 186 | } 187 | }); 188 | } catch (RuntimeException e) { 189 | listener.fatalError(e.getMessage()); 190 | throw e; 191 | } catch (Exception e) { 192 | listener.fatalError(e.getMessage()); 193 | return false; 194 | } 195 | } 196 | 197 | @Override 198 | public void checkRoles(RoleChecker checker) throws SecurityException { 199 | 200 | } 201 | } 202 | 203 | @Extension 204 | @Symbol("fileDownloadOperation") 205 | public static class DescriptorImpl extends FileOperationDescriptor { 206 | @NonNull 207 | @Override 208 | public String getDisplayName() { 209 | return "File Download"; 210 | } 211 | 212 | } 213 | 214 | } 215 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileJoinOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FileJoinOperation extends FileOperation implements Serializable { 22 | private final String sourceFile; 23 | private final String targetFile; 24 | 25 | @DataBoundConstructor 26 | public FileJoinOperation(String sourceFile, String targetFile) { 27 | this.sourceFile = sourceFile; 28 | this.targetFile = targetFile; 29 | } 30 | 31 | public String getSourceFile() { 32 | return sourceFile; 33 | } 34 | 35 | public String getTargetFile() { 36 | return targetFile; 37 | } 38 | 39 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 40 | boolean result = false; 41 | try { 42 | listener.getLogger().println("File Join Operation:"); 43 | EnvVars envVars = run.getEnvironment(listener); 44 | try { 45 | FilePath ws = new FilePath(buildWorkspace, "."); 46 | result = ws.act(new TargetFileCallable(listener, envVars.expand(sourceFile), envVars.expand(targetFile), envVars)); 47 | } catch (Exception e) { 48 | listener.fatalError(e.getMessage()); 49 | return false; 50 | } 51 | } catch (Exception e) { 52 | listener.fatalError(e.getMessage()); 53 | } 54 | return result; 55 | } 56 | 57 | private static final class TargetFileCallable implements FileCallable { 58 | private static final long serialVersionUID = 1; 59 | private final TaskListener listener; 60 | private final EnvVars environment; 61 | private final String resolvedSourceFile; 62 | private final String resolvedTargetFile; 63 | 64 | public TargetFileCallable(TaskListener Listener, String ResolvedSourceFile, String ResolvedTargetFile, EnvVars environment) { 65 | this.listener = Listener; 66 | this.resolvedSourceFile = ResolvedSourceFile; 67 | this.resolvedTargetFile = ResolvedTargetFile; 68 | this.environment = environment; 69 | } 70 | 71 | @Override 72 | public Boolean invoke(File ws, VirtualChannel channel) { 73 | boolean result; 74 | try { 75 | FilePath fpWS = new FilePath(ws); 76 | FilePath fpSL = new FilePath(fpWS, resolvedSourceFile); 77 | FilePath fpTL = new FilePath(fpWS, resolvedTargetFile); 78 | if (!fpTL.exists()) { 79 | listener.getLogger().println(resolvedSourceFile + " file doesn't exists, the target file remains as is."); 80 | } 81 | 82 | String fileContent = ""; 83 | String sourceFileContents = fpSL.readToString(); 84 | String targetFileContents = fpTL.readToString(); 85 | String eol = System.getProperty("line.separator"); 86 | 87 | if(targetFileContents.endsWith(eol)){ 88 | fileContent = targetFileContents.concat(sourceFileContents); 89 | }else{ 90 | fileContent = targetFileContents.concat(eol + sourceFileContents); 91 | } 92 | fpTL.write(fileContent, "UTF-8"); 93 | result = true; 94 | listener.getLogger().println("Joining file: from source " + fpSL.getRemote() + " to target " + fpTL.getRemote()); 95 | } catch (RuntimeException e) { 96 | listener.fatalError(e.getMessage()); 97 | throw e; 98 | } catch (Exception e) { 99 | listener.fatalError(e.getMessage()); 100 | result = false; 101 | } 102 | return result; 103 | } 104 | 105 | @Override 106 | public void checkRoles(RoleChecker checker) throws SecurityException { 107 | 108 | } 109 | } 110 | 111 | @Extension 112 | @Symbol("fileJoinOperation") 113 | public static class DescriptorImpl extends FileOperationDescriptor { 114 | public String getDisplayName() { 115 | return "File Join"; 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.FilePath; 4 | import hudson.Launcher; 5 | import hudson.model.AbstractDescribableImpl; 6 | import hudson.model.TaskListener; 7 | import hudson.model.Run; 8 | 9 | public abstract class FileOperation extends AbstractDescribableImpl { 10 | public abstract boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener); 11 | } -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileOperationDescriptor.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.model.Descriptor; 4 | 5 | public abstract class FileOperationDescriptor extends Descriptor { 6 | 7 | } -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileOperationsBuilder.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.AbortException; 4 | import hudson.FilePath; 5 | import hudson.Launcher; 6 | import hudson.Extension; 7 | import hudson.model.AbstractProject; 8 | import hudson.model.Descriptor; 9 | import hudson.model.Run; 10 | import hudson.model.TaskListener; 11 | import hudson.tasks.Builder; 12 | import hudson.tasks.BuildStepDescriptor; 13 | import org.jenkinsci.Symbol; 14 | import org.kohsuke.stapler.DataBoundConstructor; 15 | 16 | import java.util.List; 17 | import java.util.ArrayList; 18 | 19 | import jenkins.model.Jenkins; 20 | import jenkins.tasks.SimpleBuildStep; 21 | 22 | import edu.umd.cs.findbugs.annotations.NonNull; 23 | import java.util.Collections; 24 | 25 | public class FileOperationsBuilder extends Builder implements SimpleBuildStep { 26 | 27 | private final List fileOperations; 28 | 29 | @DataBoundConstructor 30 | public FileOperationsBuilder(List fileOperations) { 31 | this.fileOperations = fileOperations == null ? new ArrayList() : new ArrayList(fileOperations); 32 | } 33 | 34 | public List getFileOperations() { 35 | return Collections.unmodifiableList(fileOperations); 36 | } 37 | 38 | @Override 39 | public void perform(@NonNull Run build, @NonNull FilePath workspace, @NonNull Launcher launcher, @NonNull TaskListener listener) 40 | throws AbortException { 41 | boolean result = false; 42 | if (fileOperations.size() > 0) { 43 | for (FileOperation item : fileOperations) { 44 | result = item.runOperation(build, workspace, launcher, listener); 45 | if (!result) break; 46 | } 47 | } else { 48 | listener.getLogger().println("No File Operation added."); 49 | result = true; 50 | } 51 | if (!result) { 52 | throw new AbortException("File Operations failed."); 53 | } 54 | } 55 | 56 | 57 | @Override 58 | public DescriptorImpl getDescriptor() { 59 | return (DescriptorImpl) super.getDescriptor(); 60 | } 61 | 62 | 63 | @Extension 64 | @Symbol("fileOperations") 65 | public static final class DescriptorImpl extends BuildStepDescriptor { 66 | 67 | public DescriptorImpl() { 68 | load(); 69 | } 70 | 71 | public boolean isApplicable(Class aClass) { 72 | return true; 73 | } 74 | 75 | public String getDisplayName() { 76 | return "File Operations"; 77 | } 78 | 79 | 80 | @SuppressWarnings("unused") 81 | public List getFileOperationDescriptors() { 82 | List result = new ArrayList<>(); 83 | Jenkins j = Jenkins.getInstance(); 84 | if (j == null) { 85 | return result; 86 | } 87 | for (Descriptor d : j.getDescriptorList(FileOperation.class)) { 88 | if (d instanceof FileOperationDescriptor) { 89 | FileOperationDescriptor descriptor = (FileOperationDescriptor) d; 90 | result.add(descriptor); 91 | } 92 | } 93 | return result; 94 | } 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FilePropertiesToJsonOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.databind.node.ObjectNode; 6 | import hudson.EnvVars; 7 | import hudson.Launcher; 8 | import hudson.Extension; 9 | import hudson.FilePath; 10 | import hudson.model.Run; 11 | import hudson.model.TaskListener; 12 | 13 | import org.jenkinsci.Symbol; 14 | import org.kohsuke.stapler.DataBoundConstructor; 15 | 16 | import java.io.File; 17 | 18 | import hudson.FilePath.FileCallable; 19 | import hudson.remoting.VirtualChannel; 20 | import org.jenkinsci.remoting.RoleChecker; 21 | 22 | import java.io.Serializable; 23 | import java.util.Properties; 24 | import java.util.regex.Pattern; 25 | 26 | public class FilePropertiesToJsonOperation extends FileOperation implements Serializable { 27 | private final String sourceFile; 28 | private final String targetFile; 29 | 30 | @DataBoundConstructor 31 | public FilePropertiesToJsonOperation(String sourceFile, String targetFile) { 32 | this.sourceFile = sourceFile; 33 | this.targetFile = targetFile; 34 | } 35 | 36 | public String getSourceFile() { 37 | return sourceFile; 38 | } 39 | 40 | public String getTargetFile() { 41 | return targetFile; 42 | } 43 | 44 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 45 | boolean result = false; 46 | try { 47 | listener.getLogger().println("File Properties To Json Operation:"); 48 | EnvVars envVars = run.getEnvironment(listener); 49 | try { 50 | FilePath ws = new FilePath(buildWorkspace, "."); 51 | result = ws.act(new TargetFileCallable(listener, envVars.expand(sourceFile), envVars.expand(targetFile), envVars)); 52 | } catch (Exception e) { 53 | listener.fatalError(e.getMessage()); 54 | return false; 55 | } 56 | } catch (Exception e) { 57 | listener.fatalError(e.getMessage()); 58 | } 59 | return result; 60 | } 61 | 62 | private static final class TargetFileCallable implements FileCallable { 63 | private static final long serialVersionUID = 1; 64 | private final TaskListener listener; 65 | private final EnvVars environment; 66 | private final String resolvedSourceFile; 67 | private final String resolvedTargetFile; 68 | 69 | public TargetFileCallable(TaskListener Listener, String ResolvedSourceFile, String ResolvedTargetFile, EnvVars environment) { 70 | this.listener = Listener; 71 | this.resolvedSourceFile = ResolvedSourceFile; 72 | this.resolvedTargetFile = ResolvedTargetFile; 73 | this.environment = environment; 74 | } 75 | 76 | @Override 77 | public Boolean invoke(File ws, VirtualChannel channel) { 78 | boolean result = false; 79 | try { 80 | FilePath fpWS = new FilePath(ws); 81 | FilePath fpSL = new FilePath(fpWS, resolvedSourceFile); 82 | FilePath fpTL = new FilePath(fpWS, resolvedTargetFile); 83 | if (!fpTL.exists()) { 84 | listener.getLogger().println(resolvedSourceFile + " file doesn't exists, the target file remains as is."); 85 | } else { 86 | String fileContent = ""; 87 | Properties sourceProperties = new Properties(); 88 | sourceProperties.load(fpSL.read()); 89 | fpTL.write(convertToJson(sourceProperties), "UTF-8"); 90 | result = true; 91 | listener.getLogger().println("Creating Json: from source " + fpSL.getRemote() + " to target " + fpTL.getRemote()); 92 | } 93 | } catch (RuntimeException e) { 94 | listener.fatalError(e.getMessage()); 95 | throw e; 96 | } catch (Exception e) { 97 | listener.fatalError(e.getMessage()); 98 | result = false; 99 | } 100 | return result; 101 | } 102 | 103 | private static final Pattern floatPattern = Pattern.compile("^[0-9]+(\\.[0-9]+)?$"); 104 | private static final Pattern intPattern = Pattern.compile("^[0-9]+$"); 105 | 106 | private static String convertToJson(Properties properties) { 107 | ObjectMapper objectMapper = new ObjectMapper(); 108 | ObjectNode json = objectMapper.createObjectNode(); 109 | for (Object key : properties.keySet()) { 110 | String value = properties.getProperty(key.toString()); 111 | if (value.equals("true") || value.equals("false")) { 112 | json.put(key.toString(), Boolean.parseBoolean(value)); 113 | } else if (intPattern.matcher(value).matches()) { 114 | json.put(key.toString(), Integer.parseInt(value)); 115 | } else if (floatPattern.matcher(value).matches()) { 116 | json.put(key.toString(), Float.parseFloat(value)); 117 | } else { 118 | json.put(key.toString(), value); 119 | } 120 | } 121 | JsonNode rootNode = json; 122 | return rootNode.toString(); 123 | } 124 | 125 | @Override 126 | public void checkRoles(RoleChecker checker) throws SecurityException { 127 | 128 | } 129 | } 130 | 131 | @Extension 132 | @Symbol("filePropertiesToJsonOperation") 133 | public static class DescriptorImpl extends FileOperationDescriptor { 134 | public String getDisplayName() { 135 | return "File Properties to Json"; 136 | } 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileRenameOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Extension; 5 | import hudson.FilePath; 6 | import hudson.FilePath.FileCallable; 7 | import hudson.Launcher; 8 | import hudson.model.Run; 9 | import hudson.model.TaskListener; 10 | import hudson.remoting.VirtualChannel; 11 | import org.jenkinsci.Symbol; 12 | import org.jenkinsci.remoting.RoleChecker; 13 | import org.kohsuke.stapler.DataBoundConstructor; 14 | 15 | import java.io.File; 16 | import java.io.Serializable; 17 | 18 | public class FileRenameOperation extends FileOperation implements Serializable { 19 | private final String source; 20 | private final String destination; 21 | 22 | @DataBoundConstructor 23 | public FileRenameOperation(String source, String destination) { 24 | this.source = source; 25 | this.destination = destination; 26 | } 27 | 28 | public String getSource() { 29 | return source; 30 | } 31 | 32 | public String getDestination() { 33 | return destination; 34 | } 35 | 36 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 37 | boolean result = false; 38 | try { 39 | listener.getLogger().println("File Rename Operation:"); 40 | EnvVars envVars = run.getEnvironment(listener); 41 | try { 42 | FilePath ws = new FilePath(buildWorkspace, "."); 43 | result = ws.act(new TargetFileCallable(listener, envVars.expand(source), envVars.expand(destination))); 44 | } catch (RuntimeException e) { 45 | listener.getLogger().println(e.getMessage()); 46 | throw e; 47 | } catch (Exception e) { 48 | listener.fatalError(e.getMessage()); 49 | return false; 50 | } 51 | 52 | } catch (Exception e) { 53 | listener.fatalError(e.getMessage()); 54 | } 55 | return result; 56 | } 57 | 58 | private static final class TargetFileCallable implements FileCallable { 59 | private static final long serialVersionUID = 1; 60 | private final TaskListener listener; 61 | private final String resolvedSource; 62 | private final String resolvedDestination; 63 | 64 | public TargetFileCallable(TaskListener Listener, String ResolvedSource, String ResolvedDestination) { 65 | this.listener = Listener; 66 | this.resolvedSource = ResolvedSource; 67 | this.resolvedDestination = ResolvedDestination; 68 | } 69 | 70 | @Override 71 | public Boolean invoke(File ws, VirtualChannel channel) { 72 | boolean result = false; 73 | try { 74 | FilePath fpWS = new FilePath(ws); 75 | FilePath fpSL = new FilePath(fpWS, resolvedSource); 76 | if(fpSL.exists()) { 77 | FilePath fpDL = new FilePath(fpWS, resolvedDestination); 78 | fpSL.renameTo(fpDL); 79 | result = true; 80 | } 81 | else { 82 | listener.fatalError("The source file"+ fpSL.getRemote() +" doesn't exist."); 83 | } 84 | } catch (RuntimeException e) { 85 | listener.fatalError(e.getMessage()); 86 | throw e; 87 | } catch (Exception e) { 88 | listener.fatalError(e.getMessage()); 89 | result = false; 90 | } 91 | return result; 92 | } 93 | 94 | @Override 95 | public void checkRoles(RoleChecker checker) throws SecurityException { 96 | 97 | } 98 | } 99 | 100 | @Extension 101 | @Symbol("fileRenameOperation") 102 | public static class DescriptorImpl extends FileOperationDescriptor { 103 | public String getDisplayName() { 104 | return "File Rename"; 105 | } 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileTransformOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | import org.kohsuke.stapler.DataBoundSetter; 13 | 14 | import java.io.File; 15 | 16 | import hudson.FilePath.FileCallable; 17 | import hudson.remoting.VirtualChannel; 18 | import org.jenkinsci.remoting.RoleChecker; 19 | 20 | import java.io.Serializable; 21 | 22 | public class FileTransformOperation extends FileOperation implements Serializable { 23 | private final String includes; 24 | private final String excludes; 25 | private Boolean useDefaultExcludes; 26 | 27 | @DataBoundConstructor 28 | public FileTransformOperation(String includes, String excludes) { 29 | this.includes = includes; 30 | this.excludes = excludes; 31 | this.useDefaultExcludes = true; 32 | } 33 | 34 | public String getIncludes() { 35 | return includes; 36 | } 37 | 38 | public String getExcludes() { 39 | return excludes; 40 | } 41 | 42 | public boolean getUseDefaultExcludes() { 43 | return useDefaultExcludes; 44 | } 45 | 46 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 47 | boolean result = false; 48 | try { 49 | listener.getLogger().println("File Transform Operation:"); 50 | EnvVars envVars = run.getEnvironment(listener); 51 | try { 52 | FilePath ws = new FilePath(buildWorkspace, "."); 53 | result = ws.act(new TargetFileCallable(listener, envVars.expand(includes), envVars.expand(excludes), useDefaultExcludes, envVars)); 54 | } catch (Exception e) { 55 | listener.fatalError(e.getMessage()); 56 | return false; 57 | } 58 | 59 | } catch (Exception e) { 60 | listener.fatalError(e.getMessage()); 61 | } 62 | return result; 63 | } 64 | 65 | private static final class TargetFileCallable implements FileCallable { 66 | private static final long serialVersionUID = 1; 67 | private final TaskListener listener; 68 | private final EnvVars environment; 69 | private final String resolvedIncludes; 70 | private final String resolvedExcludes; 71 | private final boolean useDefaultExcludes; 72 | 73 | public TargetFileCallable(TaskListener Listener, String ResolvedIncludes, String ResolvedExcludes, boolean UseDefaultExcludes, EnvVars environment) { 74 | this.listener = Listener; 75 | this.resolvedIncludes = ResolvedIncludes; 76 | this.resolvedExcludes = ResolvedExcludes; 77 | this.useDefaultExcludes = UseDefaultExcludes; 78 | this.environment = environment; 79 | } 80 | 81 | @Override 82 | public Boolean invoke(File ws, VirtualChannel channel) { 83 | boolean result = false; 84 | try { 85 | FilePath fpWS = new FilePath(ws); 86 | FilePath[] resolvedFiles = fpWS.list(resolvedIncludes, resolvedExcludes, useDefaultExcludes); 87 | if (resolvedFiles.length == 0) { 88 | listener.getLogger().println("0 files found for include pattern '" + resolvedIncludes + "' and exclude pattern '" + resolvedExcludes + "'"); 89 | result = true; 90 | } else { 91 | for (FilePath item : resolvedFiles) { 92 | listener.getLogger().println("Transforming: " + item.getRemote()); 93 | String fileContent = item.readToString(); 94 | item.deleteContents(); 95 | item.write(environment.expand(fileContent), "UTF-8"); 96 | result = true; 97 | } 98 | } 99 | } catch (RuntimeException e) { 100 | listener.fatalError(e.getMessage()); 101 | throw e; 102 | } catch (Exception e) { 103 | listener.fatalError(e.getMessage()); 104 | result = false; 105 | } 106 | return result; 107 | } 108 | 109 | @Override 110 | public void checkRoles(RoleChecker checker) throws SecurityException { 111 | 112 | } 113 | } 114 | 115 | @Extension 116 | @Symbol("fileTransformOperation") 117 | public static class DescriptorImpl extends FileOperationDescriptor { 118 | public String getDisplayName() { 119 | return "File Transform"; 120 | } 121 | } 122 | 123 | @DataBoundSetter 124 | public void setUseDefaultExcludes(boolean useDefaultExcludes) { 125 | this.useDefaultExcludes = useDefaultExcludes; 126 | } 127 | 128 | protected Object readResolve() { 129 | if (useDefaultExcludes == null) { 130 | useDefaultExcludes = true; 131 | } 132 | return this; 133 | } 134 | } -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileUnTarOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FileUnTarOperation extends FileOperation implements Serializable { 22 | private final String filePath; 23 | private final String targetLocation; 24 | private final boolean isGZIP; 25 | 26 | @DataBoundConstructor 27 | public FileUnTarOperation(String filePath, String targetLocation, boolean isGZIP) { 28 | this.filePath = filePath; 29 | this.targetLocation = targetLocation; 30 | this.isGZIP = isGZIP; 31 | } 32 | 33 | public String getFilePath() { 34 | return filePath; 35 | } 36 | 37 | public String getTargetLocation() { 38 | return targetLocation; 39 | } 40 | 41 | public boolean getIsGZIP() { 42 | return isGZIP; 43 | } 44 | 45 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 46 | boolean result = false; 47 | try { 48 | listener.getLogger().println("Untar File Operation:"); 49 | EnvVars envVars = run.getEnvironment(listener); 50 | try { 51 | FilePath ws = new FilePath(buildWorkspace, "."); 52 | result = ws.act(new TargetFileCallable(listener, envVars.expand(filePath), envVars.expand(targetLocation), isGZIP)); 53 | } catch (RuntimeException e) { 54 | listener.getLogger().println(e.getMessage()); 55 | throw e; 56 | } catch (Exception e) { 57 | listener.fatalError(e.getMessage()); 58 | return false; 59 | } 60 | 61 | } catch (Exception e) { 62 | listener.fatalError(e.getMessage()); 63 | } 64 | return result; 65 | } 66 | 67 | private static final class TargetFileCallable implements FileCallable { 68 | private static final long serialVersionUID = 1; 69 | private final TaskListener listener; 70 | private final String resolvedFilePath; 71 | private final String resolvedTargetLocation; 72 | private final boolean isGZIP; 73 | 74 | public TargetFileCallable(TaskListener Listener, String ResolvedFilePath, String ResolvedTargetLocation, boolean isGZIP) { 75 | this.listener = Listener; 76 | this.resolvedFilePath = ResolvedFilePath; 77 | this.resolvedTargetLocation = ResolvedTargetLocation; 78 | this.isGZIP = isGZIP; 79 | } 80 | 81 | @Override 82 | public Boolean invoke(File ws, VirtualChannel channel) { 83 | boolean result; 84 | try { 85 | FilePath fpWS = new FilePath(ws); 86 | FilePath fpSrcTar = new FilePath(fpWS, resolvedFilePath); 87 | FilePath fpTL = new FilePath(fpWS, resolvedTargetLocation); 88 | listener.getLogger().println("Untarring " + resolvedFilePath + " to " + fpTL.getRemote()); 89 | if (!fpTL.exists()) { 90 | fpTL.mkdirs(); 91 | } 92 | if (isGZIP) { 93 | fpSrcTar.untar(fpTL, FilePath.TarCompression.GZIP); 94 | result = true; 95 | listener.getLogger().println("Untar completed."); 96 | } else { 97 | fpSrcTar.untar(fpTL, FilePath.TarCompression.NONE); 98 | result = true; 99 | listener.getLogger().println("Untar completed."); 100 | } 101 | 102 | } catch (RuntimeException e) { 103 | listener.fatalError(e.getMessage()); 104 | throw e; 105 | } catch (Exception e) { 106 | listener.fatalError(e.getMessage()); 107 | result = false; 108 | } 109 | return result; 110 | } 111 | 112 | @Override 113 | public void checkRoles(RoleChecker checker) throws SecurityException { 114 | 115 | } 116 | } 117 | 118 | @Extension 119 | @Symbol("fileUnTarOperation") 120 | public static class DescriptorImpl extends FileOperationDescriptor { 121 | public String getDisplayName() { 122 | return "Untar"; 123 | } 124 | 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileUnZipOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FileUnZipOperation extends FileOperation implements Serializable { 22 | private final String filePath; 23 | private final String targetLocation; 24 | 25 | @DataBoundConstructor 26 | public FileUnZipOperation(String filePath, String targetLocation) { 27 | this.filePath = filePath; 28 | this.targetLocation = targetLocation; 29 | } 30 | 31 | public String getFilePath() { 32 | return filePath; 33 | } 34 | 35 | public String getTargetLocation() { 36 | return targetLocation; 37 | } 38 | 39 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 40 | boolean result = false; 41 | try { 42 | listener.getLogger().println("Unzip File Operation:"); 43 | EnvVars envVars = run.getEnvironment(listener); 44 | try { 45 | FilePath ws = new FilePath(buildWorkspace, "."); 46 | result = ws.act(new TargetFileCallable(listener, envVars.expand(filePath), envVars.expand(targetLocation))); 47 | } catch (RuntimeException e) { 48 | listener.getLogger().println(e.getMessage()); 49 | throw e; 50 | } catch (Exception e) { 51 | listener.fatalError(e.getMessage()); 52 | return false; 53 | } 54 | 55 | } catch (Exception e) { 56 | listener.fatalError(e.getMessage()); 57 | } 58 | return result; 59 | } 60 | 61 | private static final class TargetFileCallable implements FileCallable { 62 | private static final long serialVersionUID = 1; 63 | private final TaskListener listener; 64 | private final String resolvedFilePath; 65 | private final String resolvedTargetLocation; 66 | 67 | public TargetFileCallable(TaskListener Listener, String ResolvedFilePath, String ResolvedTargetLocation) { 68 | this.listener = Listener; 69 | this.resolvedFilePath = ResolvedFilePath; 70 | this.resolvedTargetLocation = ResolvedTargetLocation; 71 | } 72 | 73 | @Override 74 | public Boolean invoke(File ws, VirtualChannel channel) { 75 | boolean result; 76 | try { 77 | FilePath fpWS = new FilePath(ws); 78 | FilePath fpSrcZip = new FilePath(fpWS, resolvedFilePath); 79 | FilePath fpTL = new FilePath(fpWS, resolvedTargetLocation); 80 | listener.getLogger().println("Unzipping " + resolvedFilePath + " to " + fpTL.getRemote()); 81 | if (!fpTL.exists()) { 82 | fpTL.mkdirs(); 83 | } 84 | fpSrcZip.unzip(fpTL); 85 | result = true; 86 | listener.getLogger().println("Unzip completed."); 87 | } catch (RuntimeException e) { 88 | listener.fatalError(e.getMessage()); 89 | throw e; 90 | } catch (Exception e) { 91 | listener.fatalError(e.getMessage()); 92 | result = false; 93 | } 94 | return result; 95 | } 96 | 97 | @Override 98 | public void checkRoles(RoleChecker checker) throws SecurityException { 99 | 100 | } 101 | } 102 | 103 | @Extension 104 | @Symbol("fileUnZipOperation") 105 | public static class DescriptorImpl extends FileOperationDescriptor { 106 | public String getDisplayName() { 107 | return "Unzip"; 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FileZipOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Extension; 5 | import hudson.FilePath; 6 | import hudson.Launcher; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | import hudson.remoting.VirtualChannel; 10 | import org.jenkinsci.Symbol; 11 | import org.jenkinsci.remoting.RoleChecker; 12 | import org.kohsuke.stapler.DataBoundConstructor; 13 | 14 | import java.io.File; 15 | import java.io.Serializable; 16 | 17 | public class FileZipOperation extends FileOperation implements Serializable { 18 | 19 | private final String folderPath; 20 | private final String outputFolderPath; 21 | 22 | @DataBoundConstructor 23 | public FileZipOperation(String folderPath, String outputFolderPath) { 24 | this.folderPath = folderPath; 25 | this.outputFolderPath = outputFolderPath; 26 | } 27 | 28 | public String getFolderPath() { 29 | return folderPath; 30 | } 31 | 32 | public String getOutputFolderPath() { 33 | return outputFolderPath; 34 | } 35 | 36 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 37 | boolean result = false; 38 | try { 39 | listener.getLogger().println("File Zip Operation:"); 40 | EnvVars envVars = run.getEnvironment(listener); 41 | try { 42 | FilePath ws = new FilePath(buildWorkspace, "."); 43 | result = ws.act(new TargetFileCallable(listener, envVars.expand(folderPath), envVars.expand(outputFolderPath), envVars)); 44 | } catch (Exception e) { 45 | listener.fatalError(e.getMessage()); 46 | return false; 47 | } 48 | } catch (Exception e) { 49 | listener.fatalError(e.getMessage()); 50 | } 51 | return result; 52 | } 53 | 54 | private static final class TargetFileCallable implements FilePath.FileCallable { 55 | private static final long serialVersionUID = 1; 56 | private final TaskListener listener; 57 | private final EnvVars environment; 58 | private final String resolvedFolderPath; 59 | private final String outputFolderPath; 60 | 61 | public TargetFileCallable(TaskListener Listener, String ResolvedFolderPath, String outputFolderPath, EnvVars environment) { 62 | this.listener = Listener; 63 | this.resolvedFolderPath = ResolvedFolderPath; 64 | this.outputFolderPath = outputFolderPath; 65 | this.environment = environment; 66 | } 67 | 68 | @Override 69 | public Boolean invoke(File ws, VirtualChannel channel) { 70 | boolean result; 71 | try { 72 | FilePath fpWS = new FilePath(ws); 73 | FilePath fpWSOutput = 74 | new FilePath(fpWS, (outputFolderPath != null ? outputFolderPath : "")); 75 | FilePath fpTL = new FilePath(fpWS, resolvedFolderPath); 76 | listener.getLogger().println( 77 | "Creating Zip file of " + fpTL.getRemote() + " in " + fpWSOutput); 78 | fpTL.zip(new FilePath(fpWSOutput, fpTL.getName() + ".zip")); 79 | result = true; 80 | } catch (RuntimeException e) { 81 | listener.fatalError(e.getMessage()); 82 | throw e; 83 | } catch (Exception e) { 84 | listener.fatalError(e.getMessage()); 85 | result = false; 86 | } 87 | return result; 88 | } 89 | 90 | @Override 91 | public void checkRoles(RoleChecker checker) throws SecurityException { 92 | 93 | } 94 | } 95 | 96 | @Extension 97 | @Symbol("fileZipOperation") 98 | public static class DescriptorImpl extends FileOperationDescriptor { 99 | public String getDisplayName() { 100 | return "File Zip"; 101 | } 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FolderCopyOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FolderCopyOperation extends FileOperation implements Serializable { 22 | private final String sourceFolderPath; 23 | private final String destinationFolderPath; 24 | 25 | @DataBoundConstructor 26 | public FolderCopyOperation(String sourceFolderPath, String destinationFolderPath) { 27 | this.sourceFolderPath = sourceFolderPath; 28 | this.destinationFolderPath = destinationFolderPath; 29 | } 30 | 31 | public String getSourceFolderPath() { 32 | return sourceFolderPath; 33 | } 34 | 35 | public String getDestinationFolderPath() { 36 | return destinationFolderPath; 37 | } 38 | 39 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 40 | boolean result = false; 41 | try { 42 | listener.getLogger().println("Folder Copy Operation:"); 43 | EnvVars envVars = run.getEnvironment(listener); 44 | try { 45 | FilePath ws = new FilePath(buildWorkspace, "."); 46 | result = ws.act(new TargetFileCallable(listener, envVars.expand(sourceFolderPath), envVars.expand(destinationFolderPath), envVars)); 47 | } catch (Exception e) { 48 | listener.fatalError(e.getMessage()); 49 | return false; 50 | } 51 | } catch (Exception e) { 52 | listener.fatalError(e.getMessage()); 53 | } 54 | return result; 55 | } 56 | 57 | private static final class TargetFileCallable implements FileCallable { 58 | private static final long serialVersionUID = 1; 59 | private final TaskListener listener; 60 | private final EnvVars environment; 61 | private final String resolvedSourceFolderPath; 62 | private final String resolvedDestinationFolderPath; 63 | 64 | public TargetFileCallable(TaskListener Listener, String ResolvedSourceFolderPath, String ResolvedDestinationFolderPath, EnvVars environment) { 65 | this.listener = Listener; 66 | this.resolvedSourceFolderPath = ResolvedSourceFolderPath; 67 | this.resolvedDestinationFolderPath = ResolvedDestinationFolderPath; 68 | this.environment = environment; 69 | } 70 | 71 | @Override 72 | public Boolean invoke(File ws, VirtualChannel channel) { 73 | boolean result; 74 | try { 75 | FilePath fpWS = new FilePath(ws); 76 | FilePath fpSF = new FilePath(fpWS, resolvedSourceFolderPath); 77 | FilePath fpTL = new FilePath(fpWS, resolvedDestinationFolderPath); 78 | listener.getLogger().println("Copying folder: " + fpSF.getRemote() + " to " + fpTL.getRemote()); 79 | fpSF.copyRecursiveTo(fpTL); 80 | result = true; 81 | } catch (RuntimeException e) { 82 | listener.fatalError(e.getMessage()); 83 | throw e; 84 | } catch (Exception e) { 85 | listener.fatalError(e.getMessage()); 86 | result = false; 87 | } 88 | return result; 89 | } 90 | 91 | @Override 92 | public void checkRoles(RoleChecker checker) throws SecurityException { 93 | 94 | } 95 | } 96 | 97 | @Extension 98 | @Symbol("folderCopyOperation") 99 | public static class DescriptorImpl extends FileOperationDescriptor { 100 | public String getDisplayName() { 101 | return "Folder Copy"; 102 | } 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FolderCreateOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FolderCreateOperation extends FileOperation implements Serializable { 22 | private final String folderPath; 23 | 24 | @DataBoundConstructor 25 | public FolderCreateOperation(String folderPath) { 26 | this.folderPath = folderPath; 27 | } 28 | 29 | public String getFolderPath() { 30 | return folderPath; 31 | } 32 | 33 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 34 | boolean result = false; 35 | try { 36 | listener.getLogger().println("Folder Create Operation:"); 37 | EnvVars envVars = run.getEnvironment(listener); 38 | try { 39 | FilePath ws = new FilePath(buildWorkspace, "."); 40 | result = ws.act(new TargetFileCallable(listener, envVars.expand(folderPath), envVars)); 41 | } catch (Exception e) { 42 | listener.fatalError(e.getMessage()); 43 | return false; 44 | } 45 | } catch (Exception e) { 46 | listener.fatalError(e.getMessage()); 47 | } 48 | return result; 49 | } 50 | 51 | private static final class TargetFileCallable implements FileCallable { 52 | private static final long serialVersionUID = 1; 53 | private final TaskListener listener; 54 | private final EnvVars environment; 55 | private final String resolvedFolderPath; 56 | 57 | public TargetFileCallable(TaskListener Listener, String ResolvedFolderPath, EnvVars environment) { 58 | this.listener = Listener; 59 | this.resolvedFolderPath = ResolvedFolderPath; 60 | this.environment = environment; 61 | } 62 | 63 | @Override 64 | public Boolean invoke(File ws, VirtualChannel channel) { 65 | boolean result; 66 | try { 67 | FilePath fpWS = new FilePath(ws); 68 | FilePath fpTL = new FilePath(fpWS, resolvedFolderPath); 69 | listener.getLogger().println("Creating folder: " + fpTL.getRemote()); 70 | fpTL.mkdirs(); 71 | result = true; 72 | } catch (RuntimeException e) { 73 | listener.fatalError(e.getMessage()); 74 | throw e; 75 | } catch (Exception e) { 76 | listener.fatalError(e.getMessage()); 77 | result = false; 78 | } 79 | return result; 80 | } 81 | 82 | @Override 83 | public void checkRoles(RoleChecker checker) throws SecurityException { 84 | 85 | } 86 | } 87 | 88 | @Extension 89 | @Symbol("folderCreateOperation") 90 | public static class DescriptorImpl extends FileOperationDescriptor { 91 | public String getDisplayName() { 92 | return "Folder Create"; 93 | } 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FolderDeleteOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Launcher; 5 | import hudson.Extension; 6 | import hudson.FilePath; 7 | import hudson.model.Run; 8 | import hudson.model.TaskListener; 9 | 10 | import org.jenkinsci.Symbol; 11 | import org.kohsuke.stapler.DataBoundConstructor; 12 | 13 | import java.io.File; 14 | 15 | import hudson.FilePath.FileCallable; 16 | import hudson.remoting.VirtualChannel; 17 | import org.jenkinsci.remoting.RoleChecker; 18 | 19 | import java.io.Serializable; 20 | 21 | public class FolderDeleteOperation extends FileOperation implements Serializable { 22 | private final String folderPath; 23 | 24 | @DataBoundConstructor 25 | public FolderDeleteOperation(String folderPath) { 26 | this.folderPath = folderPath; 27 | } 28 | 29 | public String getFolderPath() { 30 | return folderPath; 31 | } 32 | 33 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 34 | boolean result = false; 35 | try { 36 | listener.getLogger().println("Folder Delete Operation:"); 37 | EnvVars envVars = run.getEnvironment(listener); 38 | try { 39 | FilePath ws = new FilePath(buildWorkspace, "."); 40 | result = ws.act(new TargetFileCallable(listener, envVars.expand(folderPath), envVars)); 41 | } catch (Exception e) { 42 | listener.fatalError(e.getMessage()); 43 | return false; 44 | } 45 | } catch (Exception e) { 46 | listener.fatalError(e.getMessage()); 47 | } 48 | return result; 49 | } 50 | 51 | private static final class TargetFileCallable implements FileCallable { 52 | private static final long serialVersionUID = 1; 53 | private final TaskListener listener; 54 | private final EnvVars environment; 55 | private final String resolvedFolderPath; 56 | 57 | public TargetFileCallable(TaskListener Listener, String ResolvedFolderPath, EnvVars environment) { 58 | this.listener = Listener; 59 | this.resolvedFolderPath = ResolvedFolderPath; 60 | this.environment = environment; 61 | } 62 | 63 | @Override 64 | public Boolean invoke(File ws, VirtualChannel channel) { 65 | boolean result; 66 | try { 67 | FilePath fpWS = new FilePath(ws); 68 | FilePath fpTL = new FilePath(fpWS, resolvedFolderPath); 69 | listener.getLogger().println("Deleting folder: " + fpTL.getRemote()); 70 | fpTL.deleteRecursive(); 71 | result = true; 72 | } catch (RuntimeException e) { 73 | listener.fatalError(e.getMessage()); 74 | throw e; 75 | } catch (Exception e) { 76 | listener.fatalError(e.getMessage()); 77 | result = false; 78 | } 79 | return result; 80 | } 81 | 82 | @Override 83 | public void checkRoles(RoleChecker checker) throws SecurityException { 84 | 85 | } 86 | } 87 | 88 | @Extension 89 | @Symbol("folderDeleteOperation") 90 | public static class DescriptorImpl extends FileOperationDescriptor { 91 | public String getDisplayName() { 92 | return "Folder Delete"; 93 | } 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/FolderRenameOperation.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.Extension; 5 | import hudson.FilePath; 6 | import hudson.FilePath.FileCallable; 7 | import hudson.Launcher; 8 | import hudson.model.Run; 9 | import hudson.model.TaskListener; 10 | import hudson.remoting.VirtualChannel; 11 | import org.jenkinsci.Symbol; 12 | import org.jenkinsci.remoting.RoleChecker; 13 | import org.kohsuke.stapler.DataBoundConstructor; 14 | 15 | import java.io.File; 16 | import java.io.Serializable; 17 | 18 | public class FolderRenameOperation extends FileOperation implements Serializable { 19 | private final String source; 20 | private final String destination; 21 | 22 | @DataBoundConstructor 23 | public FolderRenameOperation(String source, String destination) { 24 | this.source = source; 25 | this.destination = destination; 26 | } 27 | 28 | public String getSource() { 29 | return source; 30 | } 31 | 32 | public String getDestination() { 33 | return destination; 34 | } 35 | 36 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 37 | boolean result = false; 38 | try { 39 | listener.getLogger().println("Folder Rename Operation:"); 40 | EnvVars envVars = run.getEnvironment(listener); 41 | try { 42 | FilePath ws = new FilePath(buildWorkspace, "."); 43 | result = ws.act(new TargetFileCallable(listener, envVars.expand(source), envVars.expand(destination))); 44 | } catch (RuntimeException e) { 45 | listener.getLogger().println(e.getMessage()); 46 | throw e; 47 | } catch (Exception e) { 48 | listener.fatalError(e.getMessage()); 49 | return false; 50 | } 51 | 52 | } catch (Exception e) { 53 | listener.fatalError(e.getMessage()); 54 | } 55 | return result; 56 | } 57 | 58 | private static final class TargetFileCallable implements FileCallable { 59 | private static final long serialVersionUID = 1; 60 | private final TaskListener listener; 61 | private final String resolvedSource; 62 | private final String resolvedDestination; 63 | 64 | public TargetFileCallable(TaskListener Listener, String ResolvedSource, String ResolvedDestination) { 65 | this.listener = Listener; 66 | this.resolvedSource = ResolvedSource; 67 | this.resolvedDestination = ResolvedDestination; 68 | } 69 | 70 | @Override 71 | public Boolean invoke(File ws, VirtualChannel channel) { 72 | boolean result = false; 73 | try { 74 | FilePath fpWS = new FilePath(ws); 75 | FilePath fpSL = new FilePath(fpWS, resolvedSource); 76 | if(fpSL.exists()) { 77 | FilePath fpDL = new FilePath(fpWS, resolvedDestination); 78 | fpSL.renameTo(fpDL); 79 | result = true; 80 | } 81 | else { 82 | listener.fatalError("The source folder"+ fpSL.getRemote() +" doesn't exist."); 83 | } 84 | } catch (RuntimeException e) { 85 | listener.fatalError(e.getMessage()); 86 | throw e; 87 | } catch (Exception e) { 88 | listener.fatalError(e.getMessage()); 89 | result = false; 90 | } 91 | return result; 92 | } 93 | 94 | @Override 95 | public void checkRoles(RoleChecker checker) throws SecurityException { 96 | 97 | } 98 | } 99 | 100 | @Extension 101 | @Symbol("folderRenameOperation") 102 | public static class DescriptorImpl extends FileOperationDescriptor { 103 | public String getDisplayName() { 104 | return "Folder Rename"; 105 | } 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/dsl/FileOperationsJobDslContext.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations.dsl; 2 | 3 | import javaposse.jobdsl.dsl.Context; 4 | import sp.sd.fileoperations.FileCopyOperation; 5 | import sp.sd.fileoperations.FileCreateOperation; 6 | import sp.sd.fileoperations.FileDeleteOperation; 7 | import sp.sd.fileoperations.FileDownloadOperation; 8 | import sp.sd.fileoperations.FileJoinOperation; 9 | import sp.sd.fileoperations.FileOperation; 10 | import sp.sd.fileoperations.FilePropertiesToJsonOperation; 11 | import sp.sd.fileoperations.FileRenameOperation; 12 | import sp.sd.fileoperations.FileTransformOperation; 13 | import sp.sd.fileoperations.FileUnTarOperation; 14 | import sp.sd.fileoperations.FileUnZipOperation; 15 | import sp.sd.fileoperations.FileZipOperation; 16 | import sp.sd.fileoperations.FolderCopyOperation; 17 | import sp.sd.fileoperations.FolderCreateOperation; 18 | import sp.sd.fileoperations.FolderDeleteOperation; 19 | import sp.sd.fileoperations.FolderRenameOperation; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | public class FileOperationsJobDslContext implements Context { 25 | final List fileOperations = new ArrayList<>(); 26 | 27 | public void fileCreateOperation(String fileName, String fileContent) { 28 | FileCreateOperation fileCreateOperation = new FileCreateOperation(fileName, fileContent); 29 | fileOperations.add(fileCreateOperation); 30 | } 31 | 32 | public void fileCopyOperation(String includes, 33 | String excludes, 34 | String targetLocation, 35 | boolean flattenFiles, 36 | boolean renameFiles, 37 | String sourceCaptureExpression, 38 | String targetNameExpression, 39 | boolean useDefaultExcludes) { 40 | FileCopyOperation fileCopyOperation = new FileCopyOperation(includes, 41 | excludes, 42 | targetLocation, 43 | flattenFiles, 44 | renameFiles, 45 | sourceCaptureExpression, 46 | targetNameExpression); 47 | fileCopyOperation.setUseDefaultExcludes(useDefaultExcludes); 48 | fileOperations.add(fileCopyOperation); 49 | } 50 | 51 | public void fileCopyOperation(String includes, 52 | String excludes, 53 | String targetLocation, 54 | boolean flattenFiles, 55 | boolean renameFiles, 56 | String sourceCaptureExpression, 57 | String targetNameExpression) { 58 | fileCopyOperation(includes, 59 | excludes, 60 | targetLocation, 61 | flattenFiles, 62 | renameFiles, 63 | sourceCaptureExpression, 64 | targetNameExpression, 65 | true); 66 | } 67 | 68 | public void fileDeleteOperation(String includes, String excludes, boolean useDefaultExcludes) { 69 | FileDeleteOperation fileDeleteOperation = new FileDeleteOperation(includes, excludes); 70 | fileDeleteOperation.setUseDefaultExcludes(useDefaultExcludes); 71 | fileOperations.add(fileDeleteOperation); 72 | } 73 | 74 | public void fileDeleteOperation(String includes, String excludes) { 75 | fileDeleteOperation(includes, excludes, true); 76 | } 77 | 78 | public void fileDownloadOperation(String url, String userName, String password, String targetLocation, String targetFileName, String proxyHost, String proxyPort) { 79 | FileDownloadOperation fileDownloadOperation = new FileDownloadOperation(url, userName, password, targetLocation, targetFileName, proxyHost, proxyPort); 80 | fileOperations.add(fileDownloadOperation); 81 | } 82 | 83 | public void fileJoinOperation(String sourceFile, String targetFile) { 84 | FileJoinOperation fileJoinOperation = new FileJoinOperation(sourceFile, targetFile); 85 | fileOperations.add(fileJoinOperation); 86 | } 87 | 88 | public void filePropertiesToJsonOperation(String sourceFile, String targetFile) { 89 | FilePropertiesToJsonOperation filePropertiesToJsonOperation = new FilePropertiesToJsonOperation(sourceFile, targetFile); 90 | fileOperations.add(filePropertiesToJsonOperation); 91 | } 92 | 93 | public void fileTransformOperation(String includes, String excludes, boolean useDefaultExcludes) { 94 | FileTransformOperation fileTransformOperation = new FileTransformOperation(includes, excludes); 95 | fileTransformOperation.setUseDefaultExcludes(useDefaultExcludes); 96 | fileOperations.add(fileTransformOperation); 97 | } 98 | 99 | public void fileTransformOperation(String includes, String excludes) { 100 | fileTransformOperation(includes, excludes, true); 101 | } 102 | 103 | public void fileUnTarOperation(String filePath, String targetLocation, boolean isGZIP) { 104 | FileUnTarOperation fileUnTarOperation = new FileUnTarOperation(filePath, targetLocation, isGZIP); 105 | fileOperations.add(fileUnTarOperation); 106 | } 107 | 108 | public void fileUnZipOperation(String filePath, String targetLocation) { 109 | FileUnZipOperation fileUnZipOperation = new FileUnZipOperation(filePath, targetLocation); 110 | fileOperations.add(fileUnZipOperation); 111 | } 112 | 113 | public void fileZipOperation(String folderPath, String outputFolderPath) { 114 | FileZipOperation fileZipOperation = new FileZipOperation(folderPath, outputFolderPath); 115 | fileOperations.add(fileZipOperation); 116 | } 117 | 118 | public void folderCopyOperation(String sourceFolderPath, String destinationFolderPath) { 119 | FolderCopyOperation folderCopyOperation = new FolderCopyOperation(sourceFolderPath, destinationFolderPath); 120 | fileOperations.add(folderCopyOperation); 121 | } 122 | 123 | public void folderCreateOperation(String folderPath) { 124 | FolderCreateOperation folderCreateOperation = new FolderCreateOperation(folderPath); 125 | fileOperations.add(folderCreateOperation); 126 | } 127 | 128 | public void folderDeleteOperation(String folderPath) { 129 | FolderDeleteOperation folderDeleteOperation = new FolderDeleteOperation(folderPath); 130 | fileOperations.add(folderDeleteOperation); 131 | } 132 | 133 | public void fileRenameOperation(String source, String destination) { 134 | FileRenameOperation fileRenameOperation = new FileRenameOperation(source, destination); 135 | fileOperations.add(fileRenameOperation); 136 | } 137 | 138 | public void folderRenameOperation(String source, String destination) { 139 | FolderRenameOperation folderRenameOperation = new FolderRenameOperation(source, destination); 140 | fileOperations.add(folderRenameOperation); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/sp/sd/fileoperations/dsl/FileOperationsJobDslExtension.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations.dsl; 2 | 3 | import hudson.Extension; 4 | import javaposse.jobdsl.dsl.RequiresPlugin; 5 | import javaposse.jobdsl.dsl.helpers.step.StepContext; 6 | import javaposse.jobdsl.plugin.ContextExtensionPoint; 7 | import javaposse.jobdsl.plugin.DslExtensionMethod; 8 | import sp.sd.fileoperations.FileOperationsBuilder; 9 | 10 | @Extension(optional = true) 11 | public class FileOperationsJobDslExtension extends ContextExtensionPoint { 12 | @RequiresPlugin(id = "file-operations", minimumVersion = "1.2") 13 | @DslExtensionMethod(context = StepContext.class) 14 | public Object fileOperations(Runnable closure) { 15 | FileOperationsJobDslContext context = new FileOperationsJobDslContext(); 16 | executeInContext(closure, context); 17 | return new FileOperationsBuilder(context.fileOperations); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | This plugin's main goal is to provide File Operations as Build Step. 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-excludes.html: -------------------------------------------------------------------------------- 1 |
2 | Files excluded from copying, this supports ant-style file pattern ex: target/*/final*.xml 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-flattenFiles.html: -------------------------------------------------------------------------------- 1 |
2 | If selected, files are copied directly to the target location without preserving 3 | source file sub-directory structure. 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-includes.html: -------------------------------------------------------------------------------- 1 |
2 | Files included to copy, this supports ant-style file pattern ex: target/*/final*.xml 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-renameFiles.html: -------------------------------------------------------------------------------- 1 |
2 | By default, the file name of the source file is preserved. When flattening 3 | files, this can cause problems if files of the same name exist in multiple 4 | source sub-directories. Selecting this option allows the output file name 5 | to be manipulated to avoid file name clashes. Only used for setting flattenFiles: true. 6 |
7 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-sourceCaptureExpression.html: -------------------------------------------------------------------------------- 1 |
2 | Java-style regular expression that is run against the workspace relative path of each 3 | matching source file. This should be used to capture parts of the path that 4 | will be used in the target name expression to make each file name unique 5 | across all subdirectories. 6 | If path not match the regex the file is copied directly to the target location. 7 | If the includes path is not handled within the regex the sub-directory structure will be preserved. 8 |

9 | Example:
10 | 11 |

12 |             // folllowing structure:
13 |             // dir1/info-app.txt
14 |             // dir1/error-app.txt
15 |             fileOperations([fileCopyOperation(
16 |                 includes: '**/dir1/*.txt',
17 |                 targetLocation: 'logs/',
18 |                 flattenFiles: true,
19 |                 renameFiles: true,
20 |                 sourceCaptureExpression: 'dir1/(.*)-app\\.txt$',
21 |                 targetNameExpression: '$1.log')
22 |             ])
23 |         
24 | 25 | will result in: 26 | 27 |
28 |             logs/info.log
29 |             logs/error.log
30 |         
31 |
32 |

33 |
34 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-targetLocation.html: -------------------------------------------------------------------------------- 1 |
2 | Destination folder location to copy the files. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCopyOperation/help-targetNameExpression.html: -------------------------------------------------------------------------------- 1 |
2 | An expression that provides the desired target file name. This can reference 3 | variables captured in the source capture expression by using $1, $2 etc. 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCreateOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCreateOperation/help-fileContent.html: -------------------------------------------------------------------------------- 1 |
2 | File content to be created, use environment variables where needed. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileCreateOperation/help-fileName.html: -------------------------------------------------------------------------------- 1 |
2 | Path and Name of the file to be created in workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileDeleteOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileDeleteOperation/help-excludes.html: -------------------------------------------------------------------------------- 1 |
2 | Files excluded from deleting, this supports ant-style file pattern ex: target/*/final*.xml 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileDeleteOperation/help-includes.html: -------------------------------------------------------------------------------- 1 |
2 | Files included to delete, this supports ant-style file pattern ex: target/*/final*.xml 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileDownloadOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileDownloadOperation/help-targetLocation.html: -------------------------------------------------------------------------------- 1 |
2 | Destination location to download the file. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileDownloadOperation/help-url.html: -------------------------------------------------------------------------------- 1 |
2 | Url of the file to download. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileJoinOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileJoinOperation/help-sourceFile.html: -------------------------------------------------------------------------------- 1 |
2 | Source file path to copy the content. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileJoinOperation/help-targetFile.html: -------------------------------------------------------------------------------- 1 |
2 | Target file path to append the content from source file. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileOperationsBuilder/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FilePropertiesToJsonOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FilePropertiesToJsonOperation/help-sourceFile.html: -------------------------------------------------------------------------------- 1 |
2 | Source file path of properties. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FilePropertiesToJsonOperation/help-targetFile.html: -------------------------------------------------------------------------------- 1 |
2 | Target file path to create or update with json data. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileRenameOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileRenameOperation/help-destination.html: -------------------------------------------------------------------------------- 1 |
2 | Destination file location to rename. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileRenameOperation/help-source.html: -------------------------------------------------------------------------------- 1 |
2 | File to be renamed. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileTransformOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileTransformOperation/help-excludes.html: -------------------------------------------------------------------------------- 1 |
2 | Files excluded from copying, this supports ant-style file pattern ex: target/*/final*.xml 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileTransformOperation/help-includes.html: -------------------------------------------------------------------------------- 1 |
2 | Files included to copy, this supports ant-style file pattern ex: target/*/final*.xml 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileUnTarOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileUnTarOperation/help-filePath.html: -------------------------------------------------------------------------------- 1 |
2 | Source tar file location. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileUnTarOperation/help-targetLocation.html: -------------------------------------------------------------------------------- 1 |
2 | Destination folder location to untar the files. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileUnZipOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileUnZipOperation/help-filePath.html: -------------------------------------------------------------------------------- 1 |
2 | Source zip file location. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileUnZipOperation/help-targetLocation.html: -------------------------------------------------------------------------------- 1 |
2 | Destination folder location to unzip the files. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileZipOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileZipOperation/help-folderPath.html: -------------------------------------------------------------------------------- 1 |
2 | Path of the file or folder to create a zip file for, relative to the workspace directory. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FileZipOperation/help-outputFolderPath.html: -------------------------------------------------------------------------------- 1 |
2 | Path to a target directory for the zip file, relative to the workspace directory. 3 | Defaults to workspace directory if not defined. 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderCopyOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderCopyOperation/help-destinationFolderPath.html: -------------------------------------------------------------------------------- 1 |
2 | Destination folder location to copy the files. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderCopyOperation/help-sourceFolderPath.html: -------------------------------------------------------------------------------- 1 |
2 | Folder to be copied. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderCreateOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderCreateOperation/help-folderPath.html: -------------------------------------------------------------------------------- 1 |
2 | Path and Name of the folder to be created in workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderDeleteOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderDeleteOperation/help-folderPath.html: -------------------------------------------------------------------------------- 1 |
2 | Path and Name of the folder to be deleted in workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderRenameOperation/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderRenameOperation/help-destination.html: -------------------------------------------------------------------------------- 1 |
2 | Destination folder name to rename. Base directory is workspace. 3 |
4 | -------------------------------------------------------------------------------- /src/main/resources/sp/sd/fileoperations/FolderRenameOperation/help-source.html: -------------------------------------------------------------------------------- 1 |
2 | Folder to be renamed. 3 |
4 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileCopyOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import com.thoughtworks.xstream.XStream; 10 | import com.thoughtworks.xstream.security.AnyTypePermission; 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Test; 13 | import org.jvnet.hudson.test.JenkinsRule; 14 | import org.jvnet.hudson.test.WithoutJenkins; 15 | 16 | import hudson.model.FreeStyleBuild; 17 | import hudson.model.FreeStyleProject; 18 | import hudson.model.Result; 19 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 20 | 21 | @WithJenkins 22 | class FileCopyOperationTest { 23 | 24 | private JenkinsRule jenkins; 25 | 26 | @BeforeEach 27 | void setUp(JenkinsRule rule) { 28 | jenkins = rule; 29 | } 30 | 31 | @Test 32 | @WithoutJenkins 33 | void testDefaults() { 34 | FileCopyOperation fco = new FileCopyOperation("**/*.config", "**/*.xml", "target", true, false, null, null); 35 | assertEquals("**/*.config", fco.getIncludes()); 36 | assertEquals("**/*.xml", fco.getExcludes()); 37 | assertEquals("target", fco.getTargetLocation()); 38 | assertTrue(fco.getFlattenFiles()); 39 | assertFalse(fco.getRenameFiles()); 40 | assertNull(fco.getSourceCaptureExpression()); 41 | assertNull(fco.getTargetNameExpression()); 42 | assertTrue(fco.getUseDefaultExcludes()); 43 | } 44 | 45 | @Test 46 | void testRunFileOperationWithFileOperationBuildStepNoFlatten() throws Exception { 47 | // Given 48 | List fop = new ArrayList<>(); 49 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classA/TestA.xml", "")); 50 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classB/TestB.xml", "")); 51 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classB/TestB.xml", "")); 52 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classC/TestC.xml", "")); 53 | fop.add(new FileCopyOperation("test-results-xml/**/*.xml", "", "test-results", false, false, null, null)); 54 | 55 | // When 56 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 57 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 58 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 59 | 60 | // Then 61 | assertEquals(Result.SUCCESS, build.getResult()); 62 | assertTrue(build.getWorkspace().child("test-results/test-results-xml/pod-0/classA/TestA.xml").exists()); 63 | assertTrue(build.getWorkspace().child("test-results/test-results-xml/pod-0/classB/TestB.xml").exists()); 64 | assertTrue(build.getWorkspace().child("test-results/test-results-xml/pod-1/classB/TestB.xml").exists()); 65 | assertTrue(build.getWorkspace().child("test-results/test-results-xml/pod-1/classC/TestC.xml").exists()); 66 | } 67 | 68 | 69 | @Test 70 | void testRunFileOperationWithFileOperationBuildStepWithFlatten() throws Exception { 71 | // Given 72 | List fop = new ArrayList<>(); 73 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classA/TestA.xml", "")); 74 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classB/TestB.xml", "")); 75 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classB/TestB.xml", "")); 76 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classC/TestC.xml", "")); 77 | fop.add(new FileCopyOperation("test-results-xml/**/*.xml", "", "test-results", true, false, null, null)); 78 | 79 | // When 80 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 81 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 82 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 83 | 84 | // Then 85 | assertEquals(Result.SUCCESS, build.getResult()); 86 | assertTrue(build.getWorkspace().child("test-results/TestA.xml").exists()); 87 | assertTrue(build.getWorkspace().child("test-results/TestB.xml").exists()); 88 | assertTrue(build.getWorkspace().child("test-results/TestC.xml").exists()); 89 | } 90 | 91 | @Test 92 | void testRunFileOperationWithFileOperationBuildStepWithFlattenAndRename() throws Exception { 93 | // Required to handle test being run on either Windows or Unix systems 94 | String dirSep = "(?:\\\\|/)"; 95 | 96 | // Given 97 | List fop = new ArrayList<>(); 98 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classA/TestA.xml", "")); 99 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classB/TestB.xml", "")); 100 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classB/TestB.xml", "")); 101 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classC/TestC.xml", "")); 102 | fop.add(new FileCopyOperation( 103 | "test-results-xml/**/*.xml", 104 | "", 105 | "test-results", 106 | true, 107 | true, 108 | ".*" + dirSep + "test-results-xml" + dirSep + ".*-([\\d]+)" + 109 | dirSep + ".*" + dirSep + "([^" + dirSep + "]+)$", 110 | "$1-$2")); 111 | 112 | // When 113 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 114 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 115 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 116 | 117 | // Then 118 | assertEquals(Result.SUCCESS, build.getResult()); 119 | assertTrue(build.getWorkspace().child("test-results/0-TestA.xml").exists()); 120 | assertTrue(build.getWorkspace().child("test-results/0-TestB.xml").exists()); 121 | assertTrue(build.getWorkspace().child("test-results/1-TestB.xml").exists()); 122 | assertTrue(build.getWorkspace().child("test-results/1-TestC.xml").exists()); 123 | } 124 | 125 | /** 126 | * @see "help-sourceCaptureExpression.html" 127 | */ 128 | @Test 129 | void testFileCopyOperationForSourceCaptureExpressionExample() throws Exception { 130 | // Required to handle test being run on either Windows or Unix systems 131 | String dirSep = "(?:\\\\|/)"; 132 | 133 | // Given 134 | List fop = new ArrayList<>(); 135 | fop.add(new FileCreateOperation("dir1/info-app.txt", "")); 136 | fop.add(new FileCreateOperation("dir1/error-app.txt", "")); 137 | fop.add(new FileCopyOperation( 138 | "**/dir1/*.txt", 139 | "", 140 | "logs", 141 | true, 142 | true, 143 | "dir1" + dirSep + "(.*)-app\\.txt$", 144 | "$1.log")); 145 | 146 | // When 147 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 148 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 149 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 150 | 151 | // Then 152 | assertEquals(Result.SUCCESS, build.getResult()); 153 | assertTrue(build.getWorkspace().child("logs/info.log").exists()); 154 | assertTrue(build.getWorkspace().child("logs/error.log").exists()); 155 | } 156 | 157 | /** 158 | * Files will not be flatten because includes path is not included in sourceCaptureExpression. 159 | * 160 | * @see "https://github.com/jenkinsci/file-operations-plugin/issues/101" 161 | */ 162 | @Test 163 | void testFileCopyOperationWithFlattenAndRenameFileWithoutMatchingRegex() throws Exception { 164 | // Given 165 | List fop = new ArrayList<>(); 166 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classA/TestA.xml", "")); 167 | fop.add(new FileCreateOperation("test-results-xml/pod-0/classA/Test-rename-A.xml", "")); 168 | fop.add(new FileCreateOperation("test-results-xml/pod-1/classB/TestB.xml", "")); 169 | fop.add(new FileCopyOperation( 170 | "test-results-xml/**/*.xml", 171 | "", 172 | "test-results", 173 | true, 174 | true, 175 | ".*Test-rename-(.*)\\.xml$", 176 | "Test$1.log")); 177 | 178 | // When 179 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 180 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 181 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 182 | 183 | // Then 184 | assertEquals(Result.SUCCESS, build.getResult()); 185 | assertTrue(build.getWorkspace().child("test-results/TestA.xml").exists()); 186 | assertTrue(build.getWorkspace().child("test-results/TestA.log").exists()); 187 | assertTrue(build.getWorkspace().child("test-results/TestB.xml").exists()); 188 | } 189 | 190 | @Test 191 | void testRunFileOperationWithFileOperationBuildStepWithDefaultExcludes() throws Exception { 192 | // Given 193 | FileCreateOperation fileCreateOperation = new FileCreateOperation(".gitignore", ""); 194 | FileCopyOperation fileCopyOperation = new FileCopyOperation(".gitignore", "", "output", false, false, null, null); 195 | List fop = Arrays.asList(fileCreateOperation, fileCopyOperation); 196 | 197 | // When 198 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 199 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 200 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 201 | 202 | // Then 203 | assertEquals(Result.SUCCESS, build.getResult()); 204 | assertTrue(build.getWorkspace().child(".gitignore").exists()); 205 | assertFalse(build.getWorkspace().child("output/.gitignore").exists()); 206 | } 207 | 208 | @Test 209 | void testRunFileOperationWithFileOperationBuildStepWithoutDefaultExcludes() throws Exception { 210 | // Given 211 | FileCreateOperation fileCreateOperation = new FileCreateOperation(".gitignore", ""); 212 | FileCopyOperation fileCopyOperation = new FileCopyOperation(".gitignore", "", "output", false, false, null, null); 213 | fileCopyOperation.setUseDefaultExcludes(false); 214 | List fop = Arrays.asList(fileCreateOperation, fileCopyOperation); 215 | 216 | // When 217 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 218 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 219 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 220 | 221 | // Then 222 | assertEquals(Result.SUCCESS, build.getResult()); 223 | assertTrue(build.getWorkspace().child(".gitignore").exists()); 224 | assertTrue(build.getWorkspace().child("output/.gitignore").exists()); 225 | } 226 | 227 | @Test 228 | @WithoutJenkins 229 | void testSerializeWithXStream() { 230 | // Given 231 | FileCopyOperation originalObject = new FileCopyOperation("include", "exclude", "output", false, false, null, null); 232 | originalObject.setUseDefaultExcludes(false); 233 | 234 | // When 235 | XStream xstream = new XStream(); 236 | xstream.addPermission(AnyTypePermission.ANY); 237 | String serializedObjectXml = xstream.toXML(originalObject); 238 | FileCopyOperation deserializedObject = (FileCopyOperation)xstream.fromXML(serializedObjectXml); 239 | 240 | // Then 241 | assertEquals(originalObject.getIncludes(), deserializedObject.getIncludes()); 242 | assertEquals(originalObject.getExcludes(), deserializedObject.getExcludes()); 243 | assertEquals(originalObject.getTargetLocation(), deserializedObject.getTargetLocation()); 244 | assertEquals(originalObject.getFlattenFiles(), deserializedObject.getFlattenFiles()); 245 | assertEquals(originalObject.getRenameFiles(), deserializedObject.getRenameFiles()); 246 | assertEquals(originalObject.getSourceCaptureExpression(), deserializedObject.getSourceCaptureExpression()); 247 | assertEquals(originalObject.getTargetNameExpression(), deserializedObject.getTargetNameExpression()); 248 | assertEquals(originalObject.getUseDefaultExcludes(), deserializedObject.getUseDefaultExcludes()); 249 | } 250 | 251 | @Test 252 | @WithoutJenkins 253 | void testSerializeWithXStreamBackwardsCompatibility() { 254 | // Given 255 | String serializedObjectXml = 256 | "" + 257 | " include" + 258 | " exclude" + 259 | " output" + 260 | " false" + 261 | " false" + 262 | ""; 263 | 264 | // When 265 | XStream xstream = new XStream(); 266 | xstream.alias("FileCopyOperation", FileCopyOperation.class); 267 | xstream.addPermission(AnyTypePermission.ANY); 268 | FileCopyOperation deserializedObject = (FileCopyOperation)xstream.fromXML(serializedObjectXml); 269 | 270 | // Then 271 | assertTrue(deserializedObject.getUseDefaultExcludes()); 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileCreateOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import hudson.EnvVars; 7 | import hudson.model.FreeStyleBuild; 8 | import hudson.model.Result; 9 | import hudson.model.FreeStyleProject; 10 | import hudson.slaves.EnvironmentVariablesNodeProperty; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import org.junit.jupiter.api.BeforeEach; 16 | import org.junit.jupiter.api.Test; 17 | import org.jvnet.hudson.test.JenkinsRule; 18 | import org.jvnet.hudson.test.WithoutJenkins; 19 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 20 | 21 | @WithJenkins 22 | class FileCreateOperationTest { 23 | 24 | private JenkinsRule jenkins; 25 | 26 | @BeforeEach 27 | void setUp(JenkinsRule rule) { 28 | jenkins = rule; 29 | } 30 | 31 | @Test 32 | @WithoutJenkins 33 | void testDefaults() { 34 | FileCreateOperation fco = new FileCreateOperation("NewFileName.txt", "This is File Content"); 35 | assertEquals("NewFileName.txt", fco.getFileName()); 36 | assertEquals("This is File Content", fco.getFileContent()); 37 | } 38 | 39 | @Test 40 | void testRunFileOperationWithFileOperationBuildStep() throws Exception { 41 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 42 | FileCreateOperation fco = new FileCreateOperation("NewFileName.txt", "This is File Content"); 43 | List fop = new ArrayList<>(); 44 | fop.add(fco); 45 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 46 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 47 | assertEquals(Result.SUCCESS, build.getResult()); 48 | assertTrue(build.getWorkspace().child("NewFileName.txt").exists()); 49 | } 50 | 51 | @Test 52 | void testRunFileOperationWithFileOperationBuildStepWithTokens() throws Exception { 53 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 54 | EnvVars envVars = prop.getEnvVars(); 55 | envVars.put("TextFileName", "NewFileName.txt"); 56 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 57 | 58 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 59 | FileCreateOperation fco = new FileCreateOperation("$TextFileName", "This is File Content"); 60 | List fop = new ArrayList<>(); 61 | fop.add(fco); 62 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 63 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 64 | assertEquals(Result.SUCCESS, build.getResult()); 65 | assertTrue(build.getWorkspace().child("NewFileName.txt").exists()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileDeleteOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import com.thoughtworks.xstream.XStream; 6 | import com.thoughtworks.xstream.security.AnyTypePermission; 7 | import hudson.EnvVars; 8 | import hudson.model.FreeStyleBuild; 9 | import hudson.model.Result; 10 | import hudson.model.FreeStyleProject; 11 | import hudson.slaves.EnvironmentVariablesNodeProperty; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | import org.junit.jupiter.api.BeforeEach; 18 | import org.junit.jupiter.api.Test; 19 | import org.jvnet.hudson.test.JenkinsRule; 20 | import org.jvnet.hudson.test.WithoutJenkins; 21 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 22 | 23 | @WithJenkins 24 | class FileDeleteOperationTest { 25 | 26 | private JenkinsRule jenkins; 27 | 28 | @BeforeEach 29 | void setUp(JenkinsRule rule) { 30 | jenkins = rule; 31 | } 32 | 33 | @Test 34 | @WithoutJenkins 35 | void testDefaults() { 36 | FileDeleteOperation fdo = new FileDeleteOperation("**/*.txt", "**/*.xml"); 37 | assertEquals("**/*.txt", fdo.getIncludes()); 38 | assertEquals("**/*.xml", fdo.getExcludes()); 39 | assertTrue(fdo.getUseDefaultExcludes()); 40 | } 41 | 42 | @Test 43 | void testRunFileOperationWithFileOperationBuildStep() throws Exception { 44 | // Given 45 | FileCreateOperation fco = new FileCreateOperation("NewFileName.txt", "This is File Content"); 46 | FileDeleteOperation fdo = new FileDeleteOperation("**/*.txt", "**/*.xml"); 47 | List fop = new ArrayList<>(); 48 | fop.add(fco); 49 | fop.add(fdo); 50 | 51 | // When 52 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 53 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 54 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 55 | 56 | // Then 57 | assertEquals(Result.SUCCESS, build.getResult()); 58 | assertFalse(build.getWorkspace().child("NewFileName.txt").exists()); 59 | } 60 | 61 | @Test 62 | void testRunFileOperationWithFileOperationBuildStepWithTokens() throws Exception { 63 | // Given 64 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 65 | EnvVars envVars = prop.getEnvVars(); 66 | envVars.put("TextFileName", "NewFileName.txt"); 67 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 68 | 69 | FileCreateOperation fco = new FileCreateOperation("$TextFileName", "This is File Content"); 70 | FileDeleteOperation fdo = new FileDeleteOperation("**/*.txt", "**/*.xml"); 71 | List fop = new ArrayList<>(); 72 | fop.add(fco); 73 | fop.add(fdo); 74 | 75 | // When 76 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 77 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 78 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 79 | 80 | // Then 81 | assertEquals(Result.SUCCESS, build.getResult()); 82 | assertFalse(build.getWorkspace().child("NewFileName.txt").exists()); 83 | } 84 | 85 | @Test 86 | void testRunFileOperationWithFileOperationBuildStepWithDefaultExcludes() throws Exception { 87 | // Given 88 | FileCreateOperation fco = new FileCreateOperation(".gitignore", "This is File Content"); 89 | FileDeleteOperation fdo = new FileDeleteOperation(".gitignore", ""); 90 | List fop = Arrays.asList(fco, fdo); 91 | 92 | // When 93 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 94 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 95 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 96 | 97 | // Then 98 | assertEquals(Result.SUCCESS, build.getResult()); 99 | assertTrue(build.getWorkspace().child(".gitignore").exists()); 100 | } 101 | 102 | @Test 103 | void testRunFileOperationWithFileOperationBuildStepWithoutDefaultExcludes() throws Exception { 104 | // Given 105 | FileCreateOperation fco = new FileCreateOperation(".gitignore", "This is File Content"); 106 | FileDeleteOperation fdo = new FileDeleteOperation(".gitignore", ""); 107 | fdo.setUseDefaultExcludes(false); 108 | List fop = Arrays.asList(fco, fdo); 109 | 110 | // When 111 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 112 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 113 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 114 | 115 | // Then 116 | assertEquals(Result.SUCCESS, build.getResult()); 117 | assertFalse(build.getWorkspace().child(".gitignore").exists()); 118 | } 119 | 120 | @Test 121 | @WithoutJenkins 122 | void testSerializeWithXStream() { 123 | // Given 124 | FileDeleteOperation originalObject = new FileDeleteOperation("include", "exclude"); 125 | originalObject.setUseDefaultExcludes(false); 126 | 127 | // When 128 | XStream xstream = new XStream(); 129 | xstream.addPermission(AnyTypePermission.ANY); 130 | String serializedObjectXml = xstream.toXML(originalObject); 131 | FileDeleteOperation deserializedObject = (FileDeleteOperation)xstream.fromXML(serializedObjectXml); 132 | 133 | // Then 134 | assertEquals(originalObject.getIncludes(), deserializedObject.getIncludes()); 135 | assertEquals(originalObject.getExcludes(), deserializedObject.getExcludes()); 136 | assertEquals(originalObject.getUseDefaultExcludes(), deserializedObject.getUseDefaultExcludes()); 137 | } 138 | 139 | @Test 140 | @WithoutJenkins 141 | void testSerializeWithXStreamBackwardsCompatibility() { 142 | // Given 143 | String serializedObjectXml = "includeexclude"; 144 | 145 | // When 146 | XStream xstream = new XStream(); 147 | xstream.alias("FileDeleteOperation", FileDeleteOperation.class); 148 | xstream.addPermission(AnyTypePermission.ANY); 149 | FileDeleteOperation deserializedObject = (FileDeleteOperation)xstream.fromXML(serializedObjectXml); 150 | 151 | // Then 152 | assertTrue(deserializedObject.getUseDefaultExcludes()); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileDownloadOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import com.github.tomakehurst.wiremock.junit5.WireMockExtension; 4 | import hidden.jth.org.apache.commons.lang3.RandomStringUtils; 5 | import hudson.model.FreeStyleProject; 6 | import hudson.model.Run; 7 | import hudson.model.TaskListener; 8 | import org.apache.hc.core5.http.HttpHeaders; 9 | import org.apache.hc.core5.http.HttpStatus; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.RegisterExtension; 13 | import org.jvnet.hudson.test.JenkinsRule; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | import java.io.File; 17 | 18 | import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; 19 | import static com.github.tomakehurst.wiremock.client.WireMock.get; 20 | import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; 21 | import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; 22 | import static org.junit.jupiter.api.Assertions.assertEquals; 23 | import static org.junit.jupiter.api.Assertions.assertFalse; 24 | import static org.junit.jupiter.api.Assertions.assertTrue; 25 | 26 | /** 27 | * Test class to validate {@link FileDownloadOperation}. 28 | */ 29 | @WithJenkins 30 | class FileDownloadOperationTest { 31 | 32 | // matches the file in __files 33 | private static final String DUMMY_ZIP = "dummy.zip"; 34 | private static final String TEST_PATH = "/test/" + DUMMY_ZIP; 35 | 36 | @RegisterExtension 37 | static WireMockExtension wireMock = WireMockExtension.newInstance() 38 | .options(options().dynamicPort()) 39 | .build(); 40 | 41 | private JenkinsRule jenkins; 42 | 43 | @BeforeEach 44 | void setUp(JenkinsRule rule) { 45 | jenkins = rule; 46 | } 47 | 48 | @Test 49 | void shouldDownload() throws Exception { 50 | // endpoint without authentication 51 | wireMock.stubFor(get(urlEqualTo(TEST_PATH)) 52 | .willReturn(aResponse() 53 | .withStatus(HttpStatus.SC_OK) 54 | .withBodyFile(DUMMY_ZIP) // matches the file in __files 55 | .withHeader(HttpHeaders.CONTENT_TYPE, "application/zip"))); 56 | 57 | // define operation & run 58 | FreeStyleProject project = jenkins.createFreeStyleProject(); 59 | Run run = project.scheduleBuild2(0).get(); 60 | FileDownloadOperation operation = new FileDownloadOperation( 61 | wireMock.baseUrl() + TEST_PATH, 62 | "", 63 | "", 64 | run.getRootDir().getAbsolutePath(), 65 | DUMMY_ZIP, 66 | null, 67 | null); 68 | boolean result = operation.runOperation(run, jenkins.jenkins.getWorkspaceFor(project), null, TaskListener.NULL); 69 | File download = new File(operation.getTargetLocation(), operation.getTargetFileName()); 70 | 71 | // validate 72 | assertTrue(result); 73 | assertTrue(download.exists()); 74 | assertTrue(download.length() > 0); 75 | } 76 | 77 | @Test 78 | void shouldDownloadWithBasicAuth() throws Exception { 79 | String username = RandomStringUtils.secure().nextAlphabetic(10); 80 | String password = RandomStringUtils.secure().nextAlphabetic(10); 81 | 82 | // endpoint with authentication 83 | wireMock.stubFor(get(urlEqualTo(TEST_PATH)) 84 | .withBasicAuth(username, password) 85 | .willReturn(aResponse() 86 | .withStatus(HttpStatus.SC_OK) 87 | .withBodyFile(DUMMY_ZIP) // matches the file in __files 88 | .withHeader(HttpHeaders.CONTENT_TYPE, "application/zip"))); 89 | 90 | // define operation & run 91 | FreeStyleProject project = jenkins.createFreeStyleProject(); 92 | Run run = project.scheduleBuild2(0).get(); 93 | FileDownloadOperation operation = new FileDownloadOperation( 94 | wireMock.baseUrl() + TEST_PATH, 95 | username, 96 | password, 97 | run.getRootDir().getAbsolutePath(), 98 | DUMMY_ZIP, 99 | null, 100 | null); 101 | boolean result = operation.runOperation(run, jenkins.jenkins.getWorkspaceFor(project), null, TaskListener.NULL); 102 | File download = new File(operation.getTargetLocation(), operation.getTargetFileName()); 103 | 104 | // validate 105 | assertTrue(result); 106 | assertTrue(download.exists()); 107 | assertTrue(download.length() > 0); 108 | } 109 | 110 | @Test 111 | void shouldFailWithBadCredentials() throws Exception { 112 | String username = RandomStringUtils.secure().nextAlphabetic(10); 113 | String password = RandomStringUtils.secure().nextAlphabetic(10); 114 | 115 | // endpoint with authentication 116 | wireMock.stubFor(get(urlEqualTo(TEST_PATH)) 117 | .withBasicAuth(username, password) 118 | .willReturn(aResponse() 119 | .withStatus(HttpStatus.SC_OK) 120 | .withBodyFile(DUMMY_ZIP) // matches the file in __files 121 | .withHeader(HttpHeaders.CONTENT_TYPE, "application/zip"))); 122 | 123 | // define operation & run 124 | FreeStyleProject project = jenkins.createFreeStyleProject(); 125 | Run run = project.scheduleBuild2(0).get(); 126 | FileDownloadOperation operation = new FileDownloadOperation( 127 | wireMock.baseUrl() + TEST_PATH, 128 | RandomStringUtils.secure().nextAlphabetic(10), 129 | RandomStringUtils.secure().nextAlphabetic(10), 130 | run.getRootDir().getAbsolutePath(), 131 | DUMMY_ZIP, 132 | null, 133 | null); 134 | boolean result = operation.runOperation(run, jenkins.jenkins.getWorkspaceFor(project), null, TaskListener.NULL); 135 | File download = new File(operation.getTargetLocation(), operation.getTargetFileName()); 136 | 137 | // validate 138 | assertFalse(result); 139 | assertTrue(download.exists()); // empty file created 140 | assertEquals(0, download.length()); // empty file created 141 | } 142 | } -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileJoinOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import hudson.EnvVars; 6 | import hudson.FilePath; 7 | import hudson.model.FreeStyleBuild; 8 | import hudson.model.FreeStyleProject; 9 | import hudson.model.Result; 10 | import hudson.slaves.EnvironmentVariablesNodeProperty; 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Test; 13 | import org.jvnet.hudson.test.JenkinsRule; 14 | import org.jvnet.hudson.test.WithoutJenkins; 15 | 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.List; 18 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 19 | 20 | @WithJenkins 21 | class FileJoinOperationTest { 22 | 23 | private JenkinsRule jenkins; 24 | 25 | @BeforeEach 26 | void setUp(JenkinsRule rule) { 27 | jenkins = rule; 28 | } 29 | 30 | @Test 31 | @WithoutJenkins 32 | void testDefaults() { 33 | FileJoinOperation fjo = new FileJoinOperation("source.txt", "target.txt"); 34 | assertEquals("source.txt", fjo.getSourceFile()); 35 | assertEquals("target.txt", fjo.getTargetFile()); 36 | } 37 | 38 | @Test 39 | void testRunFileJoinOperation() throws Exception { 40 | FreeStyleProject project = jenkins.createFreeStyleProject("fileJoinTest"); 41 | 42 | FilePath sourceFile = new FilePath(jenkins.jenkins.getWorkspaceFor(project), "source.txt"); 43 | sourceFile.write("Source File Content", StandardCharsets.UTF_8.name()); 44 | 45 | FilePath targetFile = new FilePath(jenkins.jenkins.getWorkspaceFor(project), "target.txt"); 46 | targetFile.write("Target File Content", StandardCharsets.UTF_8.name()); 47 | 48 | FileJoinOperation fileJoinOp = new FileJoinOperation("source.txt", "target.txt"); 49 | project.getBuildersList().add(new FileOperationsBuilder(List.of(fileJoinOp))); 50 | 51 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 52 | assertEquals(Result.SUCCESS, build.getResult()); 53 | 54 | String expectedContent = "Target File Content" + System.lineSeparator() + "Source File Content"; 55 | String actualContent = targetFile.readToString(); 56 | assertEquals(expectedContent, actualContent); 57 | } 58 | 59 | @Test 60 | void testRunFileJoinOperationWithTokens() throws Exception { 61 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 62 | EnvVars envVars = prop.getEnvVars(); 63 | envVars.put("SOURCE_FILE", "source.txt"); 64 | envVars.put("TARGET_FILE", "target.txt"); 65 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 66 | 67 | FreeStyleProject project = jenkins.createFreeStyleProject("fileJoinTestWithTokens"); 68 | 69 | FilePath sourceFile = new FilePath(jenkins.jenkins.getWorkspaceFor(project), "source.txt"); 70 | sourceFile.write("Source File Content", StandardCharsets.UTF_8.name()); 71 | 72 | FilePath targetFile = new FilePath(jenkins.jenkins.getWorkspaceFor(project), "target.txt"); 73 | targetFile.write("Target File Content", StandardCharsets.UTF_8.name()); 74 | 75 | FileJoinOperation fileJoinOp = new FileJoinOperation("$SOURCE_FILE", "$TARGET_FILE"); 76 | project.getBuildersList().add(new FileOperationsBuilder(List.of(fileJoinOp))); 77 | 78 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 79 | assertEquals(Result.SUCCESS, build.getResult()); 80 | 81 | String expectedContent = "Target File Content" + System.lineSeparator() + "Source File Content"; 82 | String actualContent = targetFile.readToString(); 83 | assertEquals(expectedContent, actualContent); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileOperationDescriptorTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.jvnet.hudson.test.WithoutJenkins; 7 | 8 | class FileOperationDescriptorTest { 9 | 10 | @Test 11 | @WithoutJenkins 12 | void testFileOperationDescriptor() { 13 | // Test with a real implementation that exists in the codebase 14 | FileOperationDescriptor descriptor = new FileZipOperation.DescriptorImpl(); 15 | assertEquals("File Zip", descriptor.getDisplayName()); 16 | 17 | // Test another implementation 18 | FileOperationDescriptor descriptor2 = new FileUnZipOperation.DescriptorImpl(); 19 | assertEquals("Unzip", descriptor2.getDisplayName()); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertFalse; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.jvnet.hudson.test.WithoutJenkins; 8 | 9 | import hudson.FilePath; 10 | import hudson.Launcher; 11 | import hudson.model.Run; 12 | import hudson.model.TaskListener; 13 | 14 | class FileOperationTest { 15 | 16 | @Test 17 | @WithoutJenkins 18 | void testAbstractFileOperation() { 19 | // Create a concrete implementation of the abstract class for testing 20 | FileOperation operation = new FileOperation() { 21 | @Override 22 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 23 | // Test implementation that returns true 24 | return true; 25 | } 26 | }; 27 | 28 | // Create a second implementation that returns false 29 | FileOperation operationFalse = new FileOperation() { 30 | @Override 31 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 32 | // Test implementation that returns false 33 | return false; 34 | } 35 | }; 36 | 37 | // Test that the operation methods work as expected 38 | assertTrue(operation.runOperation(null, null, null, null)); 39 | assertFalse(operationFalse.runOperation(null, null, null, null)); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileOperationsBuilderTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import hudson.model.FreeStyleBuild; 6 | import hudson.model.Result; 7 | import hudson.model.FreeStyleProject; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | import org.jvnet.hudson.test.JenkinsRule; 15 | import org.jvnet.hudson.test.WithoutJenkins; 16 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 17 | 18 | @WithJenkins 19 | class FileOperationsBuilderTest { 20 | 21 | private JenkinsRule jenkins; 22 | 23 | @BeforeEach 24 | void setUp(JenkinsRule rule) { 25 | jenkins = rule; 26 | } 27 | 28 | @Test 29 | @WithoutJenkins 30 | void testDefaults() { 31 | FileOperationsBuilder fob = new FileOperationsBuilder(null); 32 | assertEquals(0, fob.getFileOperations().size()); 33 | } 34 | 35 | @Test 36 | @WithoutJenkins 37 | void testSettersAndGetters() { 38 | List fo = new ArrayList<>(); 39 | FileOperationsBuilder fob = new FileOperationsBuilder(fo); 40 | assertEquals(0, fob.getFileOperations().size()); 41 | } 42 | 43 | @Test 44 | void testAddFileOperationToBuildSteps() throws Exception { 45 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 46 | p1.getBuildersList().add(new FileOperationsBuilder(null)); 47 | assertEquals(1, p1.getBuildersList().size()); 48 | } 49 | 50 | @Test 51 | void testRunWithOutFileOperationWithFileOperationBuildStep() throws Exception { 52 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 53 | p1.getBuildersList().add(new FileOperationsBuilder(null)); 54 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 55 | assertEquals(Result.SUCCESS, build.getResult()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FilePropertiesToJsonOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.OutputStream; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Properties; 10 | 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Test; 13 | import org.jvnet.hudson.test.JenkinsRule; 14 | import org.jvnet.hudson.test.WithoutJenkins; 15 | 16 | import hudson.FilePath; 17 | import hudson.model.FreeStyleBuild; 18 | import hudson.model.FreeStyleProject; 19 | import hudson.model.Result; 20 | import com.fasterxml.jackson.databind.JsonNode; 21 | import com.fasterxml.jackson.databind.ObjectMapper; 22 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 23 | 24 | @WithJenkins 25 | class FilePropertiesToJsonOperationTest { 26 | 27 | private JenkinsRule jenkins; 28 | 29 | @BeforeEach 30 | void setUp(JenkinsRule rule) { 31 | jenkins = rule; 32 | } 33 | 34 | @Test 35 | @WithoutJenkins 36 | void testGetters() { 37 | FilePropertiesToJsonOperation operation = new FilePropertiesToJsonOperation("source.properties", "target.json"); 38 | assertEquals("source.properties", operation.getSourceFile()); 39 | assertEquals("target.json", operation.getTargetFile()); 40 | } 41 | 42 | @Test 43 | void testRunOperationWithValidFile() throws Exception { 44 | FreeStyleProject project = jenkins.createFreeStyleProject("test-properties-to-json"); 45 | 46 | // Get the workspace 47 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 48 | 49 | // Create a properties file in the workspace 50 | FilePath propsFile = workspace.child("test.properties"); 51 | 52 | // Create properties content 53 | Properties props = new Properties(); 54 | props.setProperty("stringProp", "value"); 55 | props.setProperty("intProp", "123"); 56 | props.setProperty("floatProp", "123.45"); 57 | props.setProperty("boolProp", "true"); 58 | 59 | // Save properties to file using FilePath API 60 | try (OutputStream os = propsFile.write()) { 61 | props.store(os, "Test Properties"); 62 | } 63 | 64 | // Make sure the target file exists first 65 | FilePath targetFile = workspace.child("output.json"); 66 | targetFile.write("{}", "UTF-8"); 67 | 68 | // Configure the operation 69 | List operations = new ArrayList<>(); 70 | operations.add(new FilePropertiesToJsonOperation("test.properties", "output.json")); 71 | 72 | // Add the operation to the project 73 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 74 | 75 | // Run the build 76 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 77 | 78 | // Assert build success 79 | assertEquals(Result.SUCCESS, build.getResult()); 80 | 81 | // Verify JSON file exists and contains correct content 82 | FilePath jsonFile = workspace.child("output.json"); 83 | assertTrue(jsonFile.exists()); 84 | 85 | // Parse and verify JSON content 86 | ObjectMapper mapper = new ObjectMapper(); 87 | JsonNode jsonNode = mapper.readTree(jsonFile.read()); 88 | assertEquals("value", jsonNode.get("stringProp").asText()); 89 | assertEquals(123, jsonNode.get("intProp").asInt()); 90 | assertEquals(123.45f, jsonNode.get("floatProp").floatValue(), 0.001); 91 | assertTrue(jsonNode.get("boolProp").asBoolean()); 92 | } 93 | 94 | @Test 95 | void testRunOperationWithNonExistentFile() throws Exception { 96 | FreeStyleProject project = jenkins.createFreeStyleProject("test-properties-nonexistent"); 97 | 98 | // Get the workspace 99 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 100 | 101 | // Create target file with content 102 | FilePath targetFile = workspace.child("output.json"); 103 | targetFile.write("{\"test\":\"original\"}", "UTF-8"); 104 | 105 | // Configure the operation with non-existent source file 106 | List operations = new ArrayList<>(); 107 | operations.add(new FilePropertiesToJsonOperation("nonexistent.properties", "output.json")); 108 | 109 | // Add the operation to the project 110 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 111 | 112 | // Run the build 113 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 114 | 115 | // Assert build failure due to missing file 116 | assertEquals(Result.FAILURE, build.getResult()); 117 | } 118 | } -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileRenameOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.FilePath; 5 | import hudson.model.FreeStyleBuild; 6 | import hudson.model.FreeStyleProject; 7 | import hudson.model.Result; 8 | import hudson.slaves.EnvironmentVariablesNodeProperty; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.jvnet.hudson.test.JenkinsRule; 12 | 13 | import java.util.List; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | import static org.junit.jupiter.api.Assertions.*; 17 | 18 | @WithJenkins 19 | class FileRenameOperationTest { 20 | 21 | private JenkinsRule jenkins; 22 | 23 | @BeforeEach 24 | void setUp(JenkinsRule rule) { 25 | jenkins = rule; 26 | } 27 | 28 | @Test 29 | void testDefaults() { 30 | String source = "source.txt"; 31 | String destination = "destination.txt"; 32 | FileRenameOperation operation = new FileRenameOperation(source, destination); 33 | 34 | assertEquals(source, operation.getSource()); 35 | assertEquals(destination, operation.getDestination()); 36 | } 37 | 38 | @Test 39 | void testRunFileRenameOperation() throws Exception { 40 | FreeStyleProject project = jenkins.createFreeStyleProject("fileRenameTest"); 41 | 42 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 43 | FilePath sourceFile = new FilePath(workspace, "source.txt"); 44 | FilePath destinationFile = new FilePath(workspace, "destination.txt"); 45 | 46 | sourceFile.write("Sample content", "UTF-8"); 47 | 48 | FileRenameOperation operation = new FileRenameOperation("source.txt", "destination.txt"); 49 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 50 | 51 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 52 | assertEquals(Result.SUCCESS, build.getResult()); 53 | 54 | assertFalse(sourceFile.exists(), "The source file should have been renamed"); 55 | assertTrue(destinationFile.exists(), "The destination file should exist"); 56 | } 57 | 58 | @Test 59 | void testRunFileRenameOperationWithTokens() throws Exception { 60 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 61 | EnvVars envVars = prop.getEnvVars(); 62 | envVars.put("SOURCE_FILE", "source.txt"); 63 | envVars.put("DESTINATION_FILE", "destination.txt"); 64 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 65 | 66 | FreeStyleProject project = jenkins.createFreeStyleProject("fileRenameTestWithTokens"); 67 | 68 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 69 | FilePath sourceFile = new FilePath(workspace, "source.txt"); 70 | FilePath destinationFile = new FilePath(workspace, "destination.txt"); 71 | 72 | sourceFile.write("Sample content", "UTF-8"); 73 | 74 | FileRenameOperation operation = new FileRenameOperation("$SOURCE_FILE", "$DESTINATION_FILE"); 75 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 76 | 77 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 78 | assertEquals(Result.SUCCESS, build.getResult()); 79 | 80 | assertFalse(sourceFile.exists(), "The source file should have been renamed"); 81 | assertTrue(destinationFile.exists(), "The destination file should exist"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileTransformOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import com.thoughtworks.xstream.XStream; 6 | import com.thoughtworks.xstream.security.AnyTypePermission; 7 | import hudson.EnvVars; 8 | import hudson.FilePath; 9 | import hudson.Launcher; 10 | import hudson.model.FreeStyleBuild; 11 | import hudson.model.FreeStyleProject; 12 | import hudson.model.Result; 13 | import hudson.model.Run; 14 | import hudson.model.TaskListener; 15 | import hudson.slaves.EnvironmentVariablesNodeProperty; 16 | import org.junit.jupiter.api.BeforeEach; 17 | import org.junit.jupiter.api.Test; 18 | import org.jvnet.hudson.test.JenkinsRule; 19 | import org.jvnet.hudson.test.WithoutJenkins; 20 | 21 | import java.util.Arrays; 22 | import java.util.List; 23 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 24 | 25 | @WithJenkins 26 | class FileTransformOperationTest { 27 | 28 | private JenkinsRule jenkins; 29 | 30 | @BeforeEach 31 | void setUp(JenkinsRule rule) { 32 | jenkins = rule; 33 | } 34 | 35 | @Test 36 | @WithoutJenkins 37 | void testDefaults() { 38 | FileTransformOperation fto = new FileTransformOperation("NewFileName.config", "**/*.xml"); 39 | assertEquals("NewFileName.config", fto.getIncludes()); 40 | assertEquals("**/*.xml", fto.getExcludes()); 41 | assertTrue(fto.getUseDefaultExcludes()); 42 | } 43 | 44 | static final class FileOperationPutEnvironment extends FileOperation { 45 | public final transient JenkinsRule jenkins; 46 | public final transient String key; 47 | public final transient String value; 48 | 49 | public FileOperationPutEnvironment(JenkinsRule jenkins, String key, String value) { 50 | this.jenkins = jenkins; 51 | this.key = key; 52 | this.value = value; 53 | } 54 | 55 | public boolean runOperation(Run run, FilePath buildWorkspace, Launcher launcher, TaskListener listener) { 56 | assertDoesNotThrow(() -> { 57 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 58 | EnvVars envVars = prop.getEnvVars(); 59 | envVars.put(key, value); 60 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 61 | }, "Unexpected exception during environment put."); 62 | return true; 63 | } 64 | } 65 | 66 | @Test 67 | void testRunFileOperationWithFileOperationBuildStepWithTokens() throws Exception { 68 | // Given 69 | FileCreateOperation fco = new FileCreateOperation("TestFile.txt", "$Content"); 70 | FileOperationPutEnvironment fpo = new FileOperationPutEnvironment(jenkins, "Content", "ReplacementContent"); 71 | FileTransformOperation fto = new FileTransformOperation("TestFile.txt", ""); 72 | List fop = Arrays.asList(fco, fpo, fto); 73 | 74 | // When 75 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 76 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 77 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 78 | 79 | // Then 80 | assertEquals(Result.SUCCESS, build.getResult()); 81 | assertEquals("ReplacementContent", build.getWorkspace().child("TestFile.txt").readToString()); 82 | } 83 | 84 | @Test 85 | void testRunFileOperationWithFileOperationBuildStepWithDefaultExcludes() throws Exception { 86 | // Given 87 | FileCreateOperation fco = new FileCreateOperation(".gitignore", "$Content"); 88 | FileOperationPutEnvironment fpo = new FileOperationPutEnvironment(jenkins, "Content", "ReplacementContent"); 89 | FileTransformOperation fto = new FileTransformOperation(".gitignore", ""); 90 | List fop = Arrays.asList(fco, fpo, fto); 91 | 92 | // When 93 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 94 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 95 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 96 | 97 | // Then 98 | assertEquals(Result.SUCCESS, build.getResult()); 99 | assertTrue(build.getWorkspace().child(".gitignore").exists()); 100 | assertEquals("$Content", build.getWorkspace().child(".gitignore").readToString()); 101 | } 102 | 103 | @Test 104 | void testRunFileOperationWithFileOperationBuildStepWithoutDefaultExcludes() throws Exception { 105 | // Given 106 | FileCreateOperation fco = new FileCreateOperation(".gitignore", "$Content"); 107 | FileOperationPutEnvironment fpo = new FileOperationPutEnvironment(jenkins, "Content", "ReplacementContent"); 108 | FileTransformOperation fto = new FileTransformOperation(".gitignore", ""); 109 | fto.setUseDefaultExcludes(false); 110 | List fop = Arrays.asList(fco, fpo, fto); 111 | 112 | // When 113 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 114 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 115 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 116 | 117 | // Then 118 | assertEquals(Result.SUCCESS, build.getResult()); 119 | assertEquals("ReplacementContent", build.getWorkspace().child(".gitignore").readToString()); 120 | } 121 | 122 | @Test 123 | @WithoutJenkins 124 | void testSerializeWithXStream() { 125 | // Given 126 | FileTransformOperation originalObject = new FileTransformOperation("include", "exclude"); 127 | originalObject.setUseDefaultExcludes(false); 128 | 129 | // When 130 | XStream xstream = new XStream(); 131 | xstream.addPermission(AnyTypePermission.ANY); 132 | String serializedObjectXml = xstream.toXML(originalObject); 133 | FileTransformOperation deserializedObject = (FileTransformOperation)xstream.fromXML(serializedObjectXml); 134 | 135 | // Then 136 | assertEquals(originalObject.getIncludes(), deserializedObject.getIncludes()); 137 | assertEquals(originalObject.getExcludes(), deserializedObject.getExcludes()); 138 | assertEquals(originalObject.getUseDefaultExcludes(), deserializedObject.getUseDefaultExcludes()); 139 | } 140 | 141 | @Test 142 | @WithoutJenkins 143 | void testSerializeWithXStreamBackwardsCompatibility() { 144 | // Given 145 | String serializedObjectXml = "includeexclude"; 146 | 147 | // When 148 | XStream xstream = new XStream(); 149 | xstream.alias("FileTransformOperation", FileTransformOperation.class); 150 | xstream.addPermission(AnyTypePermission.ANY); 151 | FileTransformOperation deserializedObject = (FileTransformOperation)xstream.fromXML(serializedObjectXml); 152 | 153 | // Then 154 | assertTrue(deserializedObject.getUseDefaultExcludes()); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileUnTarOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.io.InputStream; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 10 | import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; 11 | import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; 12 | import org.apache.commons.io.IOUtils; 13 | import org.junit.jupiter.api.BeforeEach; 14 | import org.junit.jupiter.api.Test; 15 | import org.jvnet.hudson.test.JenkinsRule; 16 | import org.jvnet.hudson.test.WithoutJenkins; 17 | 18 | import hudson.FilePath; 19 | import hudson.model.FreeStyleBuild; 20 | import hudson.model.FreeStyleProject; 21 | import hudson.model.Result; 22 | 23 | import java.io.FileOutputStream; 24 | import java.io.BufferedOutputStream; 25 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 26 | 27 | @WithJenkins 28 | class FileUnTarOperationTest { 29 | 30 | private JenkinsRule jenkins; 31 | 32 | @BeforeEach 33 | void setUp(JenkinsRule rule) { 34 | jenkins = rule; 35 | } 36 | 37 | @Test 38 | @WithoutJenkins 39 | void testGetters() { 40 | FileUnTarOperation operation = new FileUnTarOperation("test.tar", "target", true); 41 | assertEquals("test.tar", operation.getFilePath()); 42 | assertEquals("target", operation.getTargetLocation()); 43 | assertTrue(operation.getIsGZIP()); 44 | 45 | // Test with isGZIP false 46 | FileUnTarOperation operation2 = new FileUnTarOperation("test.tar", "target", false); 47 | assertFalse(operation2.getIsGZIP()); 48 | } 49 | 50 | @Test 51 | void testUnTarRegularTarFile() throws Exception { 52 | FreeStyleProject project = jenkins.createFreeStyleProject("test-untar-regular"); 53 | 54 | // Get workspace 55 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 56 | 57 | // Create test content 58 | String testContent = "test content"; 59 | FilePath sourceFile = workspace.child("source-file.txt"); 60 | sourceFile.write(testContent, "UTF-8"); 61 | 62 | // Create tar file 63 | FilePath tarFile = workspace.child("test.tar"); 64 | try (TarArchiveOutputStream out = new TarArchiveOutputStream( 65 | new BufferedOutputStream(new FileOutputStream(tarFile.getRemote())))) { 66 | out.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 67 | 68 | // Create entry for the file 69 | TarArchiveEntry entry = new TarArchiveEntry("source-file.txt"); 70 | entry.setSize(sourceFile.length()); 71 | out.putArchiveEntry(entry); 72 | 73 | // Copy file content to tar 74 | try (InputStream in = sourceFile.read()) { 75 | IOUtils.copy(in, out); 76 | } 77 | 78 | // Close the entry 79 | out.closeArchiveEntry(); 80 | out.finish(); 81 | } 82 | 83 | // Configure the operation 84 | List operations = new ArrayList<>(); 85 | operations.add(new FileUnTarOperation("test.tar", "extracted", false)); 86 | 87 | // Add the operation to the project 88 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 89 | 90 | // Run the build 91 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 92 | 93 | // Assert build success 94 | assertEquals(Result.SUCCESS, build.getResult()); 95 | 96 | // Verify extracted file exists 97 | FilePath extractedFile = workspace.child("extracted/source-file.txt"); 98 | assertTrue(extractedFile.exists()); 99 | assertEquals(testContent, extractedFile.readToString()); 100 | } 101 | 102 | @Test 103 | void testUnTarGzipFile() throws Exception { 104 | FreeStyleProject project = jenkins.createFreeStyleProject("test-untar-gzip"); 105 | 106 | // Get workspace 107 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 108 | 109 | // Create test content 110 | String testContent = "test gzip content"; 111 | FilePath sourceFile = workspace.child("source-file.txt"); 112 | sourceFile.write(testContent, "UTF-8"); 113 | 114 | // Create tar.gz file 115 | FilePath tarGzFile = workspace.child("test.tar.gz"); 116 | try (TarArchiveOutputStream out = new TarArchiveOutputStream( 117 | new GzipCompressorOutputStream( 118 | new BufferedOutputStream(new FileOutputStream(tarGzFile.getRemote()))))) { 119 | out.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 120 | 121 | // Create entry for the file 122 | TarArchiveEntry entry = new TarArchiveEntry("source-file.txt"); 123 | entry.setSize(sourceFile.length()); 124 | out.putArchiveEntry(entry); 125 | 126 | // Copy file content to tar 127 | try (InputStream in = sourceFile.read()) { 128 | IOUtils.copy(in, out); 129 | } 130 | 131 | // Close the entry 132 | out.closeArchiveEntry(); 133 | out.finish(); 134 | } 135 | 136 | // Configure the operation 137 | List operations = new ArrayList<>(); 138 | operations.add(new FileUnTarOperation("test.tar.gz", "extracted-gz", true)); 139 | 140 | // Add the operation to the project 141 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 142 | 143 | // Run the build 144 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 145 | 146 | // Assert build success 147 | assertEquals(Result.SUCCESS, build.getResult()); 148 | 149 | // Verify extracted file exists 150 | FilePath extractedFile = workspace.child("extracted-gz/source-file.txt"); 151 | assertTrue(extractedFile.exists()); 152 | assertEquals(testContent, extractedFile.readToString()); 153 | } 154 | 155 | @Test 156 | void testUnTarNonExistentFile() throws Exception { 157 | FreeStyleProject project = jenkins.createFreeStyleProject("test-untar-nonexistent"); 158 | 159 | // Configure the operation with non-existent source file 160 | List operations = new ArrayList<>(); 161 | operations.add(new FileUnTarOperation("nonexistent.tar", "extracted", false)); 162 | 163 | // Add the operation to the project 164 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 165 | 166 | // Run the build 167 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 168 | 169 | // Assert build failure due to missing file 170 | assertEquals(Result.FAILURE, build.getResult()); 171 | } 172 | } -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileUnZipOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.OutputStream; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.zip.ZipEntry; 10 | import java.util.zip.ZipOutputStream; 11 | 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | import org.jvnet.hudson.test.JenkinsRule; 15 | import org.jvnet.hudson.test.WithoutJenkins; 16 | 17 | import hudson.FilePath; 18 | import hudson.model.FreeStyleBuild; 19 | import hudson.model.FreeStyleProject; 20 | import hudson.model.Result; 21 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 22 | 23 | @WithJenkins 24 | class FileUnZipOperationTest { 25 | 26 | private JenkinsRule jenkins; 27 | 28 | @BeforeEach 29 | void setUp(JenkinsRule rule) { 30 | jenkins = rule; 31 | } 32 | 33 | @Test 34 | @WithoutJenkins 35 | void testGetters() { 36 | FileUnZipOperation operation = new FileUnZipOperation("test.zip", "target"); 37 | assertEquals("test.zip", operation.getFilePath()); 38 | assertEquals("target", operation.getTargetLocation()); 39 | } 40 | 41 | @Test 42 | void testUnzipFile() throws Exception { 43 | FreeStyleProject project = jenkins.createFreeStyleProject("test-unzip"); 44 | 45 | // Get workspace 46 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 47 | 48 | // Create test content 49 | String testContent = "test content for zip file"; 50 | String nestedContent = "nested content"; 51 | 52 | // Create a zip file directly in the workspace 53 | FilePath zipFile = workspace.child("test.zip"); 54 | 55 | try (OutputStream os = zipFile.write(); 56 | ZipOutputStream zipOut = new ZipOutputStream(os)) { 57 | 58 | // Add a file entry 59 | ZipEntry entry = new ZipEntry("test-file.txt"); 60 | zipOut.putNextEntry(entry); 61 | zipOut.write(testContent.getBytes()); 62 | zipOut.closeEntry(); 63 | 64 | // Add a directory entry 65 | ZipEntry dirEntry = new ZipEntry("test-dir/"); 66 | zipOut.putNextEntry(dirEntry); 67 | zipOut.closeEntry(); 68 | 69 | // Add a file in the directory 70 | ZipEntry nestedEntry = new ZipEntry("test-dir/nested-file.txt"); 71 | zipOut.putNextEntry(nestedEntry); 72 | zipOut.write(nestedContent.getBytes()); 73 | zipOut.closeEntry(); 74 | } 75 | 76 | // Configure the operation 77 | List operations = new ArrayList<>(); 78 | operations.add(new FileUnZipOperation("test.zip", "extracted")); 79 | 80 | // Add the operation to the project 81 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 82 | 83 | // Run the build 84 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 85 | 86 | // Assert build success 87 | assertEquals(Result.SUCCESS, build.getResult()); 88 | 89 | // Verify extracted files exist 90 | FilePath extractedDir = workspace.child("extracted"); 91 | assertTrue(extractedDir.exists()); 92 | 93 | FilePath extractedFile = extractedDir.child("test-file.txt"); 94 | assertTrue(extractedFile.exists()); 95 | assertEquals(testContent, extractedFile.readToString()); 96 | 97 | FilePath extractedNestedDir = extractedDir.child("test-dir"); 98 | assertTrue(extractedNestedDir.exists()); 99 | 100 | FilePath extractedNestedFile = extractedNestedDir.child("nested-file.txt"); 101 | assertTrue(extractedNestedFile.exists()); 102 | assertEquals(nestedContent, extractedNestedFile.readToString()); 103 | } 104 | 105 | @Test 106 | void testUnzipToExistingDirectory() throws Exception { 107 | FreeStyleProject project = jenkins.createFreeStyleProject("test-unzip-existing-dir"); 108 | 109 | // Get workspace 110 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 111 | 112 | // Create a pre-existing target directory with a file 113 | FilePath existingDir = workspace.child("existing-dir"); 114 | existingDir.mkdirs(); 115 | FilePath existingFile = existingDir.child("existing-file.txt"); 116 | existingFile.write("existing content", "UTF-8"); 117 | 118 | // Create a zip file in the workspace 119 | FilePath zipFile = workspace.child("test.zip"); 120 | String newContent = "new content"; 121 | 122 | try (OutputStream os = zipFile.write(); 123 | ZipOutputStream zipOut = new ZipOutputStream(os)) { 124 | 125 | ZipEntry entry = new ZipEntry("new-file.txt"); 126 | zipOut.putNextEntry(entry); 127 | zipOut.write(newContent.getBytes()); 128 | zipOut.closeEntry(); 129 | } 130 | 131 | // Configure the operation 132 | List operations = new ArrayList<>(); 133 | operations.add(new FileUnZipOperation("test.zip", "existing-dir")); 134 | 135 | // Add the operation to the project 136 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 137 | 138 | // Run the build 139 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 140 | 141 | // Assert build success 142 | assertEquals(Result.SUCCESS, build.getResult()); 143 | 144 | // Verify both files exist 145 | assertTrue(existingFile.exists()); 146 | assertEquals("existing content", existingFile.readToString()); 147 | 148 | FilePath newFile = existingDir.child("new-file.txt"); 149 | assertTrue(newFile.exists()); 150 | assertEquals(newContent, newFile.readToString()); 151 | } 152 | 153 | @Test 154 | void testUnzipNonExistentFile() throws Exception { 155 | FreeStyleProject project = jenkins.createFreeStyleProject("test-unzip-nonexistent"); 156 | 157 | // Configure the operation with non-existent source file 158 | List operations = new ArrayList<>(); 159 | operations.add(new FileUnZipOperation("nonexistent.zip", "extracted")); 160 | 161 | // Add the operation to the project 162 | project.getBuildersList().add(new FileOperationsBuilder(operations)); 163 | 164 | // Run the build 165 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 166 | 167 | // Assert build failure due to missing file 168 | assertEquals(Result.FAILURE, build.getResult()); 169 | } 170 | } -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FileZipOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | import org.jvnet.hudson.test.WithoutJenkins; 12 | 13 | import hudson.model.FreeStyleBuild; 14 | import hudson.model.FreeStyleProject; 15 | import hudson.model.Result; 16 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 17 | 18 | @WithJenkins 19 | class FileZipOperationTest { 20 | 21 | private JenkinsRule jenkins; 22 | 23 | @BeforeEach 24 | void setUp(JenkinsRule rule) { 25 | jenkins = rule; 26 | } 27 | 28 | @Test 29 | @WithoutJenkins 30 | void testDefaults() { 31 | FileZipOperation fzo = new FileZipOperation("source", null); 32 | assertEquals("source", fzo.getFolderPath()); 33 | assertNull(fzo.getOutputFolderPath()); 34 | } 35 | 36 | @Test 37 | void testRunFileOperationZipDirectoryToDefaultOutput() throws Exception { 38 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 39 | List fop = new ArrayList<>(); 40 | fop.add(new FileCreateOperation("source-directory/nested-folder1/TestFile1-1", "")); 41 | fop.add(new FileCreateOperation("source-directory/nested-folder2/TestFile2-1", "")); 42 | fop.add(new FileCreateOperation("source-directory/nested-folder2/TestFile2-2", "")); 43 | fop.add(new FileZipOperation("source-directory", null)); 44 | fop.add(new FileUnZipOperation("source-directory.zip", "unzipped-directory")); 45 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 46 | 47 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 48 | 49 | assertEquals(Result.SUCCESS, build.getResult()); 50 | assertTrue(build.getWorkspace().child("unzipped-directory").exists()); 51 | assertTrue(build.getWorkspace().child("unzipped-directory/source-directory/nested-folder1/TestFile1-1").exists()); 52 | assertTrue(build.getWorkspace().child("unzipped-directory/source-directory/nested-folder2/TestFile2-1").exists()); 53 | assertTrue(build.getWorkspace().child("unzipped-directory/source-directory/nested-folder2/TestFile2-2").exists()); 54 | } 55 | 56 | @Test 57 | void testRunFileOperationZipFileToDefaultOutput() throws Exception { 58 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 59 | List fop = new ArrayList<>(); 60 | fop.add(new FileCreateOperation("source-directory/nested-folder1/TestFile1-1", "")); 61 | fop.add(new FileZipOperation("source-directory/nested-folder1/TestFile1-1", null)); 62 | fop.add(new FileUnZipOperation("TestFile1-1.zip", "unzipped-directory")); 63 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 64 | 65 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 66 | 67 | assertEquals(Result.SUCCESS, build.getResult()); 68 | assertTrue(build.getWorkspace().child("unzipped-directory").exists()); 69 | assertTrue(build.getWorkspace().child("unzipped-directory/TestFile1-1").exists()); 70 | } 71 | 72 | @Test 73 | void testRunFileOperationZipDirectoryToCustomOutput() throws Exception { 74 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 75 | List fop = new ArrayList<>(); 76 | fop.add(new FileCreateOperation("source-directory/nested-folder1/TestFile1-1", "")); 77 | fop.add(new FileCreateOperation("source-directory/nested-folder2/TestFile2-1", "")); 78 | fop.add(new FileCreateOperation("source-directory/nested-folder2/TestFile2-2", "")); 79 | fop.add(new FileZipOperation("source-directory", "output-directory/nested-output-folder1")); 80 | fop.add(new FileUnZipOperation( 81 | "output-directory/nested-output-folder1/source-directory.zip", 82 | "unzipped-directory")); 83 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 84 | 85 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 86 | 87 | assertEquals(Result.SUCCESS, build.getResult()); 88 | assertTrue(build.getWorkspace().child("unzipped-directory").exists()); 89 | assertTrue(build.getWorkspace().child("unzipped-directory/source-directory/nested-folder1/TestFile1-1").exists()); 90 | assertTrue(build.getWorkspace().child("unzipped-directory/source-directory/nested-folder2/TestFile2-1").exists()); 91 | assertTrue(build.getWorkspace().child("unzipped-directory/source-directory/nested-folder2/TestFile2-2").exists()); 92 | } 93 | 94 | @Test 95 | void testRunFileOperationZipFileToCustomOutput() throws Exception { 96 | FreeStyleProject p1 = jenkins.createFreeStyleProject("build1"); 97 | List fop = new ArrayList<>(); 98 | fop.add(new FileCreateOperation("source-directory/nested-folder1/TestFile1-1", "")); 99 | fop.add(new FileZipOperation( 100 | "source-directory/nested-folder1/TestFile1-1", 101 | "output-directory/nested-output-folder1")); 102 | fop.add(new FileUnZipOperation( 103 | "output-directory/nested-output-folder1/TestFile1-1.zip", 104 | "unzipped-directory")); 105 | p1.getBuildersList().add(new FileOperationsBuilder(fop)); 106 | 107 | FreeStyleBuild build = p1.scheduleBuild2(0).get(); 108 | 109 | assertEquals(Result.SUCCESS, build.getResult()); 110 | assertTrue(build.getWorkspace().child("unzipped-directory").exists()); 111 | assertTrue(build.getWorkspace().child("unzipped-directory/TestFile1-1").exists()); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FolderCopyOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.FilePath; 5 | import hudson.model.FreeStyleBuild; 6 | import hudson.model.FreeStyleProject; 7 | import hudson.model.Result; 8 | import hudson.slaves.EnvironmentVariablesNodeProperty; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.jvnet.hudson.test.JenkinsRule; 12 | 13 | import java.util.List; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | import static org.junit.jupiter.api.Assertions.assertEquals; 17 | import static org.junit.jupiter.api.Assertions.assertTrue; 18 | 19 | @WithJenkins 20 | class FolderCopyOperationTest { 21 | 22 | private JenkinsRule jenkins; 23 | 24 | @BeforeEach 25 | void setUp(JenkinsRule rule) { 26 | jenkins = rule; 27 | } 28 | 29 | @Test 30 | void testDefaults() { 31 | String sourceFolderPath = "sourceFolder"; 32 | String destinationFolderPath = "destinationFolder"; 33 | FolderCopyOperation operation = new FolderCopyOperation(sourceFolderPath, destinationFolderPath); 34 | 35 | assertEquals(sourceFolderPath, operation.getSourceFolderPath()); 36 | assertEquals(destinationFolderPath, operation.getDestinationFolderPath()); 37 | } 38 | 39 | @Test 40 | void testRunFolderCopyOperation() throws Exception { 41 | FreeStyleProject project = jenkins.createFreeStyleProject("folderCopyTest"); 42 | 43 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 44 | FilePath sourceFolder = new FilePath(workspace, "sourceFolder"); 45 | FilePath destinationFolder = new FilePath(workspace, "destinationFolder"); 46 | 47 | sourceFolder.mkdirs(); 48 | FilePath fileInSource = new FilePath(sourceFolder, "file.txt"); 49 | fileInSource.write("Sample content", "UTF-8"); 50 | 51 | FolderCopyOperation operation = new FolderCopyOperation("sourceFolder", "destinationFolder"); 52 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 53 | 54 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 55 | assertEquals(Result.SUCCESS, build.getResult()); 56 | 57 | FilePath copiedFile = new FilePath(destinationFolder, "file.txt"); 58 | assertTrue(destinationFolder.exists(), "The destination folder should have been created"); 59 | assertTrue(copiedFile.exists(), "The file should have been copied to the destination folder"); 60 | assertEquals("Sample content", copiedFile.readToString()); 61 | } 62 | 63 | @Test 64 | void testRunFolderCopyOperationWithTokens() throws Exception { 65 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 66 | EnvVars envVars = prop.getEnvVars(); 67 | envVars.put("SOURCE_FOLDER", "sourceFolder"); 68 | envVars.put("DESTINATION_FOLDER", "destinationFolder"); 69 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 70 | 71 | FreeStyleProject project = jenkins.createFreeStyleProject("folderCopyTestWithTokens"); 72 | 73 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 74 | FilePath sourceFolder = new FilePath(workspace, "sourceFolder"); 75 | FilePath destinationFolder = new FilePath(workspace, "destinationFolder"); 76 | 77 | sourceFolder.mkdirs(); 78 | FilePath fileInSource = new FilePath(sourceFolder, "file.txt"); 79 | fileInSource.write("Sample content", "UTF-8"); 80 | 81 | FolderCopyOperation operation = new FolderCopyOperation("$SOURCE_FOLDER", "$DESTINATION_FOLDER"); 82 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 83 | 84 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 85 | assertEquals(Result.SUCCESS, build.getResult()); 86 | 87 | FilePath copiedFile = new FilePath(destinationFolder, "file.txt"); 88 | assertTrue(destinationFolder.exists(), "The destination folder should have been created"); 89 | assertTrue(copiedFile.exists(), "The file should have been copied to the destination folder"); 90 | assertEquals("Sample content", copiedFile.readToString()); 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FolderCreateOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.FilePath; 5 | import hudson.model.FreeStyleBuild; 6 | import hudson.model.FreeStyleProject; 7 | import hudson.model.Result; 8 | import hudson.slaves.EnvironmentVariablesNodeProperty; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.jvnet.hudson.test.JenkinsRule; 12 | 13 | import java.util.List; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | import static org.junit.jupiter.api.Assertions.assertEquals; 17 | import static org.junit.jupiter.api.Assertions.assertTrue; 18 | 19 | @WithJenkins 20 | class FolderCreateOperationTest { 21 | 22 | private JenkinsRule jenkins; 23 | 24 | @BeforeEach 25 | void setUp(JenkinsRule rule) { 26 | jenkins = rule; 27 | } 28 | @Test 29 | void testDefaults() { 30 | String defaultFolderPath = "defaultFolder"; 31 | FolderCreateOperation operation = new FolderCreateOperation(defaultFolderPath); 32 | 33 | assertEquals(defaultFolderPath, operation.getFolderPath()); 34 | } 35 | 36 | @Test 37 | void testRunFolderCreateOperation() throws Exception { 38 | FreeStyleProject project = jenkins.createFreeStyleProject("folderCreateTest"); 39 | 40 | String folderPath = "newFolder"; 41 | FolderCreateOperation operation = new FolderCreateOperation(folderPath); 42 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 43 | 44 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 45 | assertEquals(Result.SUCCESS, build.getResult()); 46 | 47 | FilePath folder = new FilePath(jenkins.jenkins.getWorkspaceFor(project), folderPath); 48 | assertTrue(folder.exists() && folder.isDirectory(), "The folder should have been created"); 49 | } 50 | 51 | @Test 52 | void testRunFolderCreateOperationWithTokens() throws Exception { 53 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 54 | EnvVars envVars = prop.getEnvVars(); 55 | envVars.put("FOLDER_PATH", "tokenFolder"); 56 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 57 | 58 | FreeStyleProject project = jenkins.createFreeStyleProject("folderCreateTestWithTokens"); 59 | 60 | FolderCreateOperation operation = new FolderCreateOperation("$FOLDER_PATH"); 61 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 62 | 63 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 64 | assertEquals(Result.SUCCESS, build.getResult()); 65 | 66 | FilePath folder = new FilePath(jenkins.jenkins.getWorkspaceFor(project), "tokenFolder"); 67 | assertTrue(folder.exists() && folder.isDirectory(), "The folder should have been created"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FolderDeleteOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.FilePath; 5 | import hudson.model.FreeStyleBuild; 6 | import hudson.model.FreeStyleProject; 7 | import hudson.model.Result; 8 | import hudson.slaves.EnvironmentVariablesNodeProperty; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.jvnet.hudson.test.JenkinsRule; 12 | 13 | import java.util.List; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | import static org.junit.jupiter.api.Assertions.assertEquals; 17 | import static org.junit.jupiter.api.Assertions.assertFalse; 18 | 19 | @WithJenkins 20 | class FolderDeleteOperationTest { 21 | 22 | private JenkinsRule jenkins; 23 | 24 | @BeforeEach 25 | void setUp(JenkinsRule rule) { 26 | jenkins = rule; 27 | } 28 | 29 | @Test 30 | void testDefaults() { 31 | String folderPath = "folderToDelete"; 32 | FolderDeleteOperation operation = new FolderDeleteOperation(folderPath); 33 | 34 | assertEquals(folderPath, operation.getFolderPath()); 35 | } 36 | 37 | @Test 38 | void testRunFolderDeleteOperation() throws Exception { 39 | FreeStyleProject project = jenkins.createFreeStyleProject("folderDeleteTest"); 40 | 41 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 42 | FilePath folderToDelete = new FilePath(workspace, "folderToDelete"); 43 | 44 | folderToDelete.mkdirs(); 45 | FilePath fileInFolder = new FilePath(folderToDelete, "file.txt"); 46 | fileInFolder.write("Sample content", "UTF-8"); 47 | 48 | FolderDeleteOperation operation = new FolderDeleteOperation("folderToDelete"); 49 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 50 | 51 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 52 | assertEquals(Result.SUCCESS, build.getResult()); 53 | 54 | assertFalse(folderToDelete.exists(), "The folder should have been deleted"); 55 | } 56 | 57 | @Test 58 | void testRunFolderDeleteOperationWithTokens() throws Exception { 59 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 60 | EnvVars envVars = prop.getEnvVars(); 61 | envVars.put("FOLDER_TO_DELETE", "folderToDelete"); 62 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 63 | 64 | FreeStyleProject project = jenkins.createFreeStyleProject("folderDeleteTestWithTokens"); 65 | 66 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 67 | FilePath folderToDelete = new FilePath(workspace, "folderToDelete"); 68 | 69 | folderToDelete.mkdirs(); 70 | FilePath fileInFolder = new FilePath(folderToDelete, "file.txt"); 71 | fileInFolder.write("Sample content", "UTF-8"); 72 | 73 | FolderDeleteOperation operation = new FolderDeleteOperation("$FOLDER_TO_DELETE"); 74 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 75 | 76 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 77 | assertEquals(Result.SUCCESS, build.getResult()); 78 | 79 | assertFalse(folderToDelete.exists(), "The folder should have been deleted"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/sp/sd/fileoperations/FolderRenameOperationTest.java: -------------------------------------------------------------------------------- 1 | package sp.sd.fileoperations; 2 | 3 | import hudson.EnvVars; 4 | import hudson.FilePath; 5 | import hudson.model.FreeStyleBuild; 6 | import hudson.model.FreeStyleProject; 7 | import hudson.model.Result; 8 | import hudson.slaves.EnvironmentVariablesNodeProperty; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.jvnet.hudson.test.JenkinsRule; 12 | 13 | import java.util.List; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | import static org.junit.jupiter.api.Assertions.*; 17 | 18 | @WithJenkins 19 | class FolderRenameOperationTest { 20 | 21 | private JenkinsRule jenkins; 22 | 23 | @BeforeEach 24 | void setUp(JenkinsRule rule) { 25 | jenkins = rule; 26 | } 27 | 28 | @Test 29 | void testDefaults() { 30 | String sourceFolder = "sourceFolder"; 31 | String destinationFolder = "destinationFolder"; 32 | FolderRenameOperation operation = new FolderRenameOperation(sourceFolder, destinationFolder); 33 | 34 | assertEquals(sourceFolder, operation.getSource()); 35 | assertEquals(destinationFolder, operation.getDestination()); 36 | } 37 | 38 | @Test 39 | void testRunFolderRenameOperation() throws Exception { 40 | FreeStyleProject project = jenkins.createFreeStyleProject("folderRenameTest"); 41 | 42 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 43 | FilePath sourceFolder = new FilePath(workspace, "sourceFolder"); 44 | FilePath destinationFolder = new FilePath(workspace, "destinationFolder"); 45 | 46 | sourceFolder.mkdirs(); 47 | FilePath fileInSource = new FilePath(sourceFolder, "file.txt"); 48 | fileInSource.write("Sample content", "UTF-8"); 49 | 50 | FolderRenameOperation operation = new FolderRenameOperation("sourceFolder", "destinationFolder"); 51 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 52 | 53 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 54 | assertEquals(Result.SUCCESS, build.getResult()); 55 | 56 | assertFalse(sourceFolder.exists(), "The source folder should have been renamed"); 57 | FilePath renamedFile = new FilePath(destinationFolder, "file.txt"); 58 | assertTrue(renamedFile.exists(), "The file should have been moved to the destination folder"); 59 | assertEquals("Sample content", renamedFile.readToString()); 60 | } 61 | 62 | @Test 63 | void testRunFolderRenameOperationWithTokens() throws Exception { 64 | EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); 65 | EnvVars envVars = prop.getEnvVars(); 66 | envVars.put("SOURCE_FOLDER", "sourceFolder"); 67 | envVars.put("DESTINATION_FOLDER", "destinationFolder"); 68 | jenkins.jenkins.getGlobalNodeProperties().add(prop); 69 | 70 | FreeStyleProject project = jenkins.createFreeStyleProject("folderRenameTestWithTokens"); 71 | 72 | FilePath workspace = jenkins.jenkins.getWorkspaceFor(project); 73 | FilePath sourceFolder = new FilePath(workspace, "sourceFolder"); 74 | FilePath destinationFolder = new FilePath(workspace, "destinationFolder"); 75 | 76 | sourceFolder.mkdirs(); 77 | FilePath fileInSource = new FilePath(sourceFolder, "file.txt"); 78 | fileInSource.write("Sample content", "UTF-8"); 79 | 80 | FolderRenameOperation operation = new FolderRenameOperation("$SOURCE_FOLDER", "$DESTINATION_FOLDER"); 81 | project.getBuildersList().add(new FileOperationsBuilder(List.of(operation))); 82 | 83 | FreeStyleBuild build = project.scheduleBuild2(0).get(); 84 | assertEquals(Result.SUCCESS, build.getResult()); 85 | 86 | assertFalse(sourceFolder.exists(), "The source folder should have been renamed"); 87 | FilePath renamedFile = new FilePath(destinationFolder, "file.txt"); 88 | assertTrue(renamedFile.exists(), "The file should have been moved to the destination folder"); 89 | assertEquals("Sample content", renamedFile.readToString()); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/test/resources/__files/dummy.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/file-operations-plugin/afd7a2b52f885b99cfcd2f81b3dfeb3be6a869f2/src/test/resources/__files/dummy.zip --------------------------------------------------------------------------------