├── .gitignore ├── CHANGELOG.md ├── Jenkinsfile ├── Jenkinsfile.yaml ├── LICENSE ├── README.md ├── images └── branch-source.png ├── pom.xml ├── scripts └── hello.sh ├── src ├── main │ ├── java │ │ └── io │ │ │ └── jenkins │ │ │ └── plugins │ │ │ └── sprp │ │ │ ├── YamlBranchProjectFactory.java │ │ │ ├── YamlFlowDefinition.java │ │ │ ├── YamlMultiBranchProjectFactory.java │ │ │ ├── YamlToPipeline.java │ │ │ ├── exception │ │ │ └── ConversionException.java │ │ │ ├── generators │ │ │ ├── AgentGenerator.java │ │ │ ├── ArchiveArtifactStageGenerator.java │ │ │ ├── CustomSectionGenerator.java │ │ │ ├── EnvironmentGenerator.java │ │ │ ├── GitPushStageGenerator.java │ │ │ ├── PipelineGenerator.java │ │ │ ├── PostGenerator.java │ │ │ ├── PublishReportsAndArtifactsStageGenerator.java │ │ │ ├── StageGenerator.java │ │ │ └── StepGenerator.java │ │ │ ├── git │ │ │ ├── GitConfig.java │ │ │ ├── GitOperations.java │ │ │ └── GitPushStep.java │ │ │ └── models │ │ │ ├── Agent.java │ │ │ ├── ArtifactPublishingConfig.java │ │ │ ├── Configuration.java │ │ │ ├── Credential.java │ │ │ ├── CustomPipelineSection.java │ │ │ ├── Environment.java │ │ │ ├── Post.java │ │ │ ├── ReportsAndArtifactsInfo.java │ │ │ ├── Stage.java │ │ │ ├── Step.java │ │ │ └── YamlPipeline.java │ └── resources │ │ ├── index.jelly │ │ └── io │ │ └── jenkins │ │ └── plugins │ │ └── sprp │ │ └── Messages.properties └── test │ └── java │ └── io │ └── jenkins │ └── plugins │ └── sprp │ ├── FullPipelineGenerationTest.java │ ├── YamlToPipelineTest.java │ └── generators │ ├── AgentGeneratorTest.java │ ├── ArchiveArtifactStageGeneratorTest.java │ ├── CustomSectionGeneratorTest.java │ ├── EnvironmentGeneratorTest.java │ ├── GitPushStageGeneratorTest.java │ ├── PostGeneratorTest.java │ ├── PublishReportsAndArtifactsStageGenaratorTest.java │ ├── StageGeneratorTest.java │ └── StepGeneratorTest.java └── yamlExamples ├── AgentExamples.md ├── ConfigurationExample.md ├── EnvironmentExample.md ├── Jenkinsfile.yaml ├── MultipleStagesExample.md ├── Readme.md └── SimpleStageExample.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | target/ 4 | work/ -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | === 3 | 4 | # 1.0-alpha-1 5 | 6 | Release date: July 6, 2018 7 | 8 | Initial Release 9 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | buildPlugin() -------------------------------------------------------------------------------- /Jenkinsfile.yaml: -------------------------------------------------------------------------------- 1 | agent: 2 | # Docket image agent example 3 | # label: my_label 4 | # customWorkspace: path_to_workspace 5 | # dockerImage: maven:3-alpine 6 | # args: -v /tmp:/tmp 7 | 8 | # tools needs to be defined in the tool configuration 9 | tools: 10 | maven : maven_3.0.1 11 | jdk : jdk8 12 | 13 | configuration: 14 | # Push PR changes to the target branch if the build will be success. 15 | # default value will be false 16 | pushPrOnSuccess: false 17 | 18 | prApprovers: 19 | - username1 20 | - username2 21 | - username3 22 | 23 | # Study about the reports type. Urgent 24 | reports: 25 | - location_of_report_1 26 | - location_of_report_2 27 | 28 | environment: 29 | variables: 30 | variable_1: value_1 31 | variable_2: value_2 32 | 33 | # Credentials contains only two fields. See pipeline file for how it will be used 34 | credentials: 35 | - credentialId : fileCredentialId 36 | variable : FILE 37 | 38 | # Username will be accessed by LOGIN_USR and Password will be accessed by LOGIN_PSW 39 | - credentialId : dummyGitRepo 40 | variable : LOGIN 41 | 42 | stages: 43 | - name: satge1 44 | agent: any 45 | steps: 46 | - sh: 47 | script: "scripts/hello" 48 | - sh: "scripts/hello" 49 | - sleep: 50 | time: 2 51 | # Configurator.lookup() in JCasc plugin returns null for java.util.concurrent.TimeUnit which is an Enum class 52 | # jira link: https://issues.jenkins-ci.org/browse/JENKINS-52443 53 | # unit: SECONDS 54 | - sleep: 2 55 | - junit: 56 | testResults: "target/**.xml" 57 | allowEmptyResults: true 58 | testDataPublishers: 59 | - AutomateTestDataPublisher 60 | - JunitResultPublisher: 61 | urlOverride: "urlOverride" 62 | # JCasc plugin having problem in configuring below class 63 | # jira link: https://issues.jenkins-ci.org/browse/JENKINS-52444 64 | 65 | - JiraTestDataPublisher: 66 | configs: 67 | - SelectableFields: 68 | fieldKey: "SelectableFields key" 69 | value: "SelectableFields value" 70 | 71 | projectKey: "project key" 72 | issueType: "issue type" 73 | autoRaiseIssue: true 74 | 75 | 76 | post: 77 | failure: 78 | - sh: "scripts/hello" 79 | post: 80 | always: 81 | - sh: "scripts/hello" 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple Pull Request job plugin for Jenkins 2 | 3 | [![Join the chat at https://gitter.im/jenkinsci/simple-pull-request-job-plugin](https://badges.gitter.im/jenkinsci/simple-pull-request-job-plugin.svg)](https://gitter.im/jenkinsci/simple-pull-request-job-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | This project aims to develop a Job Plugin which can interact with Bitbucket Server, Bitbucket Cloud, and Github whenever a pull request is created or updated. Users should be able to configure job type using YAML file which will be placed in root directory of the Git repository being the subject of the PR. 6 | 7 | ### Overview 8 | 9 | This plugin take build.yaml file (which will be stored in root location of repository which has to be built of target branch) 10 | and converts it to Declarative pipeline code internally and build the repository. Yaml syntax is very similar to Declarative 11 | pipeline code and examples can be found [here](yamlExamples). 12 | 13 | ### How to run this plugin 14 | 15 | Till this point of time plugin is tested with GitHub plugin, ans it needs to be installed on the jenkins instance. 16 | 1. Create a multibranch project. 17 | 2. In Branch sources add GitHub (Needs to install Github Plugin) 18 | 3. Set required credentials, owner and repository. 19 | 4. Set behaviours as follows. 20 | ![branch-source](images/branch-source.png) 21 | 22 | 5. Scroll down to Build Configuration and select "by Jenkinsfile.yaml". 23 | 6. Edit anyother configurations and hit save. Plugin will automatiacally 24 | discover all the branches and pull requests and start to build them 25 | according to "Jenkinsfile.yaml". 26 | 27 | To run the demo repository configure the GitHub branch source as shown in the above 28 | figure. Don't specify git credentials (As no one except @gautamabhishek have them) 29 | and the build will be successful except one git push step at the last. Everyone can 30 | also use "Scan Repository Now" and "Build Now" (for all branches and PRs). 31 | 32 | [Demo repository](https://github.com/gautamabhishek46/dummy) 33 | 34 | #### Jenkinsfile.yaml example 35 | ```yaml 36 | agent: any 37 | 38 | buildResultPaths: 39 | - path-1 40 | - path-2 41 | 42 | testResultPaths: 43 | - path-1 44 | - path-2 45 | 46 | stages: 47 | - name: First 48 | steps: 49 | - sh './scripts/hello' 50 | defaultParameter: ./scripts/hello 51 | - name: Build 52 | steps: 53 | - stepName: sh 54 | parameters: 55 | script: ./scripts/build 56 | - name: Tests 57 | steps: 58 | - stepName: sh 59 | defaultParameter: ./scripts/hello 60 | 61 | archiveArtifacts: 62 | - Jenkinsfile.yaml 63 | - scripts/hello.sh 64 | 65 | artifactPublishingConfig: # Details are not correct 66 | host: 192.32.52.12 67 | user: user53 68 | credentialId: dummyGitRepo 69 | 70 | publishArtifacts: 71 | - from: Jenkinsfile.yaml 72 | to: ~/archives 73 | - from: scripts/hello.sh 74 | to: ~/archives 75 | 76 | ``` 77 | 78 | #### Simple agent example 79 | ```yaml 80 | agent: 81 | label: 'my-label' 82 | customWorkspace: 'path-to-workspace' 83 | ``` 84 | 85 | 86 | #### Agent with docker image example 87 | ```yaml 88 | agent: 89 | label: 'my-label' 90 | customWorkspace: 'path-to-workspace' 91 | dockerImage: 'image-name' 92 | args: 'some argument' # optional 93 | ``` 94 | 95 | #### Agent with dockerfile example 96 | ```yaml 97 | agent: 98 | label: 'my-label' 99 | customWorkspace: 'path-to-workspace' 100 | dockerfile: 'image-name' 101 | dir: 'path-to-directory' 102 | args: 'some argument' # optional 103 | ``` 104 | 105 | Note: 106 | 1. Agent arguments are same as declarative pipeline agent arguments except "dockerImage". 107 | 2. Don't use dockerImage and dockerfile parameters simultaneously, else it will result in errors. 108 | 3. The build will be started for pull request and normal branches after branch indexing. 109 | 4. Sections such as tools, post, when, ect are not supported at this point in time. 110 | 111 | If there is a need to call a script then use "sh" step name and just give the relative path of 112 | the script without extension (.bat or .sh). plugin will detect the machine (linux or windows) and 113 | add the extension on its own. 114 | 115 | Users can declare any number of stages but stages named 'Build' and 'Tests' must be declared by the 116 | user. These two stages can contain simple echo steps also. It is needed because at this stage 117 | plugin generate post sections in these two stages to archive artifacts, publish reports and to 118 | push the changes to target branch. 119 | 120 | Only xml reports are supported at this point in time. 121 | 122 | ### Future tasks 123 | 124 | 1. Support the “when” Declarative Pipeline directive 125 | 2. Detect the presence of certain types of the report based on a conventional location, and automatically publish them. If the reports are not in a conventional location, users could specify the location using the YML file. 126 | 3. Support build from webhook of diffrent platforms (like GitHub, Bitbucket, etc). -------------------------------------------------------------------------------- /images/branch-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/simple-pull-request-job-plugin/281a7b43ed86ef5815669e3480972f1d336dffba/images/branch-source.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.jenkins-ci.plugins 6 | plugin 7 | 3.18 8 | 9 | 10 | io.jenkins.plugins 11 | simple-pull-request-job 12 | 1.0-alpha-4-SNAPSHOT 13 | hpi 14 | 15 | 16 | 2.138.1 17 | 8 18 | true 19 | 20 | Simple Pull Request Job Plugin 21 | Simple pull request job plugin. This plugin will use YAML to configure a job for pull request. 22 | 23 | 24 | MIT License 25 | https://opensource.org/licenses/MIT 26 | 27 | 28 | 29 | 30 | org.jenkins-ci.plugins 31 | structs 32 | 1.15 33 | 34 | 35 | org.jenkins-ci.plugins 36 | scm-api 37 | 2.2.8 38 | 39 | 40 | org.jenkins-ci.plugins 41 | script-security 42 | 1.46 43 | 44 | 45 | org.jenkins-ci.plugins 46 | cloudbees-folder 47 | 6.5.1 48 | 49 | 50 | org.jenkins-ci.plugins.workflow 51 | workflow-scm-step 52 | 2.7 53 | 54 | 55 | org.jenkins-ci.plugins.workflow 56 | workflow-multibranch 57 | 2.20 58 | 59 | 60 | org.jenkins-ci.plugins.workflow 61 | workflow-step-api 62 | 2.16 63 | 64 | 65 | org.jenkins-ci.plugins.workflow 66 | workflow-basic-steps 67 | 2.11 68 | test 69 | 70 | 71 | org.jenkins-ci.plugins.workflow 72 | workflow-durable-task-step 73 | 2.13 74 | test 75 | 76 | 77 | org.jenkins-ci.plugins.workflow 78 | workflow-support 79 | 2.20 80 | test 81 | 82 | 83 | org.jenkins-ci.plugins.workflow 84 | workflow-cps 85 | 2.57 86 | compile 87 | 88 | 89 | org.jenkins-ci.plugins.workflow 90 | workflow-api 91 | 2.29 92 | compile 93 | 94 | 95 | org.jenkins-ci.plugins.workflow 96 | workflow-job 97 | 2.25 98 | compile 99 | 100 | 101 | org.jenkins-ci.plugins 102 | git-client 103 | 2.7.3 104 | compile 105 | 106 | 107 | org.jenkins-ci.plugins 108 | git 109 | 3.9.1 110 | 111 | 112 | org.jenkins-ci.plugins 113 | jackson2-api 114 | 2.8.11.3 115 | 116 | 117 | org.jenkins-ci.plugins 118 | credentials 119 | 2.1.18 120 | 121 | 122 | org.jenkins-ci.plugins 123 | junit 124 | 1.26.1 125 | 126 | 127 | org.jenkins-ci 128 | annotation-indexer 129 | 1.12 130 | 131 | 132 | io.jenkins 133 | configuration-as-code 134 | 1.0 135 | 136 | 137 | org.yaml 138 | snakeyaml 139 | 1.23 140 | 141 | 142 | org.jenkinsci.plugins 143 | pipeline-model-api 144 | 1.3.2 145 | 146 | 147 | 148 | 149 | 150 | 151 | gautamabhishek46 152 | Abhishek Gautam 153 | gautam.abhishek46@gmail.com 154 | 155 | 156 | 157 | 158 | scm:git:git://github.com/jenkinsci/simple-pull-request-job-plugin.git 159 | scm:git:git@github.com:jenkinsci/simple-pull-request-job-plugin.git 160 | https://github.com/jenkinsci/simple-pull-request-job-plugin 161 | HEAD 162 | 163 | 164 | 165 | 166 | repo.jenkins-ci.org 167 | https://repo.jenkins-ci.org/public/ 168 | 169 | 170 | 171 | 172 | repo.jenkins-ci.org 173 | https://repo.jenkins-ci.org/public/ 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /scripts/hello.sh: -------------------------------------------------------------------------------- 1 | echo "Hello!! from pipeline generator" -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/YamlBranchProjectFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2018 CloudBees, Inc, Abhishek Gautam (@gautamabhishek46). 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package io.jenkins.plugins.sprp; 26 | 27 | import hudson.Extension; 28 | import hudson.model.TaskListener; 29 | import jenkins.scm.api.SCMProbeStat; 30 | import jenkins.scm.api.SCMSource; 31 | import jenkins.scm.api.SCMSourceCriteria; 32 | import org.apache.commons.lang.StringUtils; 33 | import org.jenkinsci.plugins.workflow.flow.FlowDefinition; 34 | import org.jenkinsci.plugins.workflow.multibranch.AbstractWorkflowBranchProjectFactory; 35 | import org.kohsuke.accmod.Restricted; 36 | import org.kohsuke.accmod.restrictions.NoExternalUse; 37 | import org.kohsuke.stapler.DataBoundConstructor; 38 | import org.kohsuke.stapler.DataBoundSetter; 39 | 40 | import java.io.IOException; 41 | import java.util.logging.Logger; 42 | 43 | /** 44 | * Recognizes and builds {@code Jenkinsfile.yaml}. 45 | * Original code: org.jenkinsci.plugins.workflow.multibranch.YamlBranchProjectFactory 46 | */ 47 | public class YamlBranchProjectFactory extends AbstractWorkflowBranchProjectFactory { 48 | private static final Logger LOGGER = Logger.getLogger(YamlBranchProjectFactory.class.getName()); 49 | static final String YAML_SCRIPT = "Jenkinsfile.yaml"; 50 | static final String YML_SCRIPT = "Jenkinsfile.yml"; 51 | private String scriptPath = YAML_SCRIPT; 52 | 53 | @DataBoundConstructor 54 | public YamlBranchProjectFactory() { 55 | } 56 | 57 | public Object readResolve() { 58 | if (this.scriptPath == null) { 59 | this.scriptPath = YAML_SCRIPT; 60 | } 61 | return this; 62 | } 63 | 64 | public String getScriptPath() { 65 | return scriptPath; 66 | } 67 | 68 | @DataBoundSetter 69 | public void setScriptPath(String scriptPath) { 70 | if (StringUtils.isEmpty(scriptPath)) { 71 | this.scriptPath = YAML_SCRIPT; 72 | } else { 73 | this.scriptPath = scriptPath; 74 | } 75 | } 76 | 77 | @Override 78 | protected FlowDefinition createDefinition() { 79 | return new YamlFlowDefinition(scriptPath); 80 | } 81 | 82 | @Override 83 | protected SCMSourceCriteria getSCMSourceCriteria(SCMSource source) { 84 | return new SCMSourceCriteria() { 85 | @Override 86 | public boolean isHead(SCMSourceCriteria.Probe probe, TaskListener listener) throws IOException { 87 | while (true) { 88 | SCMProbeStat stat = probe.stat(scriptPath); 89 | switch (stat.getType()) { 90 | case NONEXISTENT: 91 | // Handle default yml case. 92 | if (scriptPath.equals(YAML_SCRIPT)) { 93 | scriptPath = YML_SCRIPT; 94 | } 95 | if (stat.getAlternativePath() != null) { 96 | listener.getLogger().format("‘%s’ not found (but found ‘%s’, search is case sensitive)%n", scriptPath, stat.getAlternativePath()); 97 | } else { 98 | listener.getLogger().format("‘%s’ not found%n", scriptPath); 99 | } 100 | return false; 101 | case DIRECTORY: 102 | listener.getLogger().format("‘%s’ found but is a directory not a file%n", scriptPath); 103 | return false; 104 | default: 105 | listener.getLogger().format("‘%s’ found%n", scriptPath); 106 | return isCorrectYAMLFile(scriptPath); 107 | } 108 | } 109 | } 110 | 111 | @Override 112 | public int hashCode() { 113 | return getClass().hashCode(); 114 | } 115 | 116 | @Override 117 | public boolean equals(Object obj) { 118 | return getClass().isInstance(obj); 119 | } 120 | }; 121 | } 122 | 123 | @Extension 124 | @Restricted(NoExternalUse.class) 125 | public static class DescriptorImpl extends AbstractWorkflowBranchProjectFactoryDescriptor { 126 | @Override 127 | public String getDisplayName() { 128 | return "by " + YAML_SCRIPT; 129 | } 130 | } 131 | 132 | private boolean isCorrectYAMLFile(String path) { 133 | String[] paths = path.split("/"); 134 | String filename = paths[paths.length - 1]; 135 | String[] exts = filename.split("\\."); 136 | String extension = exts[exts.length - 1]; 137 | return extension.equals("yaml") || extension.equals("yml"); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/YamlFlowDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2018 Abhishek Gautam (@gautamabhishek46). 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package io.jenkins.plugins.sprp; 26 | 27 | import hudson.Extension; 28 | import hudson.model.Action; 29 | import hudson.model.ItemGroup; 30 | import hudson.model.Queue; 31 | import hudson.model.TaskListener; 32 | import hudson.plugins.git.GitSCM; 33 | import io.jenkins.plugins.sprp.git.GitConfig; 34 | import jenkins.branch.Branch; 35 | import jenkins.scm.api.SCMFileSystem; 36 | import jenkins.scm.api.SCMHead; 37 | import jenkins.scm.api.SCMRevision; 38 | import jenkins.scm.api.SCMSource; 39 | import jenkins.scm.api.mixin.ChangeRequestSCMHead2; 40 | import org.jenkinsci.plugins.workflow.cps.CpsFlowExecution; 41 | import org.jenkinsci.plugins.workflow.flow.FlowDefinition; 42 | import org.jenkinsci.plugins.workflow.flow.FlowDefinitionDescriptor; 43 | import org.jenkinsci.plugins.workflow.flow.FlowExecution; 44 | import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner; 45 | import org.jenkinsci.plugins.workflow.job.WorkflowJob; 46 | import org.jenkinsci.plugins.workflow.job.WorkflowRun; 47 | import org.jenkinsci.plugins.workflow.multibranch.BranchJobProperty; 48 | import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject; 49 | import org.kohsuke.accmod.Restricted; 50 | import org.kohsuke.accmod.restrictions.NoExternalUse; 51 | 52 | import javax.annotation.Nonnull; 53 | import java.io.IOException; 54 | import java.io.InputStream; 55 | import java.util.List; 56 | 57 | public class YamlFlowDefinition extends FlowDefinition { 58 | private String scriptPath; 59 | 60 | public YamlFlowDefinition(String scriptPath) { 61 | this.scriptPath = scriptPath; 62 | } 63 | 64 | public Object readResolve() { 65 | if (this.scriptPath == null) { 66 | this.scriptPath = "Jenkinsfile.yaml"; 67 | } 68 | return this; 69 | } 70 | 71 | @Override 72 | public FlowExecution create(FlowExecutionOwner owner, TaskListener listener, 73 | List actions) throws Exception { 74 | Queue.Executable exec = owner.getExecutable(); 75 | if (!(exec instanceof WorkflowRun)) { 76 | throw new IllegalStateException("inappropriate context"); 77 | } 78 | 79 | WorkflowRun build = (WorkflowRun) exec; 80 | WorkflowJob job = build.getParent(); 81 | BranchJobProperty property = job.getProperty(BranchJobProperty.class); 82 | 83 | Branch branch = property.getBranch(); 84 | ItemGroup parent = job.getParent(); 85 | 86 | if (!(parent instanceof WorkflowMultiBranchProject)) { 87 | throw new IllegalStateException("inappropriate context"); 88 | } 89 | 90 | SCMSource scmSource = ((WorkflowMultiBranchProject) parent).getSCMSource(branch.getSourceId()); 91 | 92 | if (scmSource == null) { 93 | throw new IllegalStateException(branch.getSourceId() + " not found"); 94 | } 95 | 96 | GitConfig gitConfig = new GitConfig(); 97 | 98 | SCMHead head = branch.getHead(); 99 | 100 | if ("Pull Request".equals(head.getPronoun())) { 101 | ChangeRequestSCMHead2 changeRequestSCMHead2 = (ChangeRequestSCMHead2) branch.getHead(); 102 | head = changeRequestSCMHead2.getTarget(); 103 | } 104 | 105 | SCMRevision tip = scmSource.fetch(head, listener); 106 | 107 | if (tip == null) { 108 | throw new IllegalStateException("Cannot determine the revision."); 109 | } 110 | 111 | SCMRevision rev = scmSource.getTrustedRevision(tip, listener); 112 | GitSCM gitSCM = (GitSCM) scmSource.build(head, rev); 113 | 114 | gitConfig.setGitUrl(gitSCM.getUserRemoteConfigs().get(0).getUrl()); 115 | gitConfig.setCredentialsId(gitSCM.getUserRemoteConfigs().get(0).getCredentialsId()); 116 | gitConfig.setGitBranch(head.getName()); 117 | 118 | String script; 119 | try (SCMFileSystem fs = SCMFileSystem.of(scmSource, head, rev)) { 120 | if (fs != null) { 121 | InputStream yamlInputStream = fs.child(scriptPath).content(); 122 | listener.getLogger().println("Path of yaml/yml config file: " + fs.child(scriptPath).getPath()); 123 | YamlToPipeline y = new YamlToPipeline(); 124 | script = y.generatePipeline(yamlInputStream, gitConfig, listener); 125 | } else { 126 | throw new IOException("SCM not supported"); 127 | // FIXME implement full checkout 128 | } 129 | } 130 | 131 | listener.getLogger().println(script); 132 | return new CpsFlowExecution(script, false, owner); 133 | } 134 | 135 | @Extension 136 | @Restricted(NoExternalUse.class) 137 | public static class DescriptorImpl extends FlowDefinitionDescriptor { 138 | 139 | @Nonnull 140 | @Override 141 | public String getDisplayName() { 142 | return Messages.YAML_FlowDefinition_DescriptorImpl_DisplayName(); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/YamlMultiBranchProjectFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2015-2018 CloudBees, Inc, Abhishek Gautam (@gautamabhishek46). 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package io.jenkins.plugins.sprp; 26 | 27 | import hudson.Extension; 28 | import jenkins.branch.MultiBranchProjectFactory; 29 | import jenkins.branch.MultiBranchProjectFactoryDescriptor; 30 | import jenkins.scm.api.SCMSource; 31 | import jenkins.scm.api.SCMSourceCriteria; 32 | import org.apache.commons.lang.StringUtils; 33 | import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectFactory; 34 | import org.kohsuke.accmod.Restricted; 35 | import org.kohsuke.accmod.restrictions.NoExternalUse; 36 | import org.kohsuke.stapler.DataBoundConstructor; 37 | import org.kohsuke.stapler.DataBoundSetter; 38 | 39 | import java.io.IOException; 40 | 41 | /** 42 | * Defines organization folders by {@link YamlBranchProjectFactory}. 43 | * Original code: org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectFactory 44 | */ 45 | public class YamlMultiBranchProjectFactory extends WorkflowMultiBranchProjectFactory { 46 | private String scriptPath = YamlBranchProjectFactory.YAML_SCRIPT; 47 | 48 | @DataBoundConstructor 49 | public YamlMultiBranchProjectFactory() { 50 | } 51 | 52 | public Object readResolve() { 53 | if (this.scriptPath == null) { 54 | this.scriptPath = YamlBranchProjectFactory.YAML_SCRIPT; 55 | } 56 | 57 | return this; 58 | } 59 | 60 | public String getScriptPath() { 61 | return scriptPath; 62 | } 63 | 64 | @DataBoundSetter 65 | public void setScriptPath(String scriptPath) { 66 | if (StringUtils.isEmpty(scriptPath)) { 67 | this.scriptPath = YamlBranchProjectFactory.YAML_SCRIPT; 68 | } else { 69 | this.scriptPath = scriptPath; 70 | } 71 | } 72 | 73 | @Override 74 | protected SCMSourceCriteria getSCMSourceCriteria(SCMSource source) { 75 | return newProjectFactorySCMSourceCriteria(source); 76 | } 77 | 78 | private org.jenkinsci.plugins.workflow.multibranch.AbstractWorkflowBranchProjectFactory newProjectFactory() { 79 | YamlBranchProjectFactory workflowBranchProjectFactory = new YamlBranchProjectFactory(); 80 | workflowBranchProjectFactory.setScriptPath(scriptPath); 81 | return workflowBranchProjectFactory; 82 | } 83 | 84 | private SCMSourceCriteria newProjectFactorySCMSourceCriteria(SCMSource source) { 85 | YamlBranchProjectFactory workflowBranchProjectFactory = new YamlBranchProjectFactory(); 86 | workflowBranchProjectFactory.setScriptPath(scriptPath); 87 | return workflowBranchProjectFactory.getSCMSourceCriteria(source); 88 | } 89 | 90 | @Override 91 | protected void customize(org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject project) 92 | throws IOException, InterruptedException { 93 | project.setProjectFactory(newProjectFactory()); 94 | } 95 | 96 | @Extension 97 | @Restricted(NoExternalUse.class) 98 | public static class DescriptorImpl extends MultiBranchProjectFactoryDescriptor { 99 | 100 | @Override 101 | public MultiBranchProjectFactory newInstance() { 102 | return new org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectFactory(); 103 | } 104 | 105 | @Override 106 | public String getDisplayName() { 107 | return "Pipeline " + YamlBranchProjectFactory.YAML_SCRIPT; 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/YamlToPipeline.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp; 2 | 3 | import hudson.model.TaskListener; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.generators.PipelineGenerator; 6 | import io.jenkins.plugins.sprp.git.GitConfig; 7 | import io.jenkins.plugins.sprp.models.*; 8 | import org.yaml.snakeyaml.Yaml; 9 | import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; 10 | 11 | import javax.annotation.CheckForNull; 12 | import javax.annotation.Nonnull; 13 | import java.io.InputStream; 14 | import java.util.ArrayList; 15 | import java.util.LinkedHashMap; 16 | import java.util.Map; 17 | 18 | public class YamlToPipeline { 19 | public String generatePipeline(@Nonnull InputStream yamlScriptInputStream, 20 | @CheckForNull GitConfig gitConfig, 21 | @Nonnull TaskListener listener) 22 | throws ConversionException { 23 | ArrayList scriptLines = new ArrayList<>(); 24 | 25 | YamlPipeline yamlPipeline = loadYaml(yamlScriptInputStream, listener); 26 | 27 | scriptLines.add("pipeline {"); 28 | 29 | // Adding outer agent and tools section 30 | scriptLines.addAll(PipelineGenerator.convert("agent", yamlPipeline.getAgent())); 31 | 32 | // Adding environment 33 | scriptLines.addAll(PipelineGenerator.convert("environment", yamlPipeline.getEnvironment())); 34 | 35 | // Stages begin 36 | scriptLines.add("stages {"); 37 | 38 | if (yamlPipeline.getSteps() != null) { 39 | scriptLines.add("stage('Build') {"); 40 | scriptLines.add("steps {"); 41 | 42 | for (LinkedHashMap step : yamlPipeline.getSteps()) { 43 | for (Map.Entry entry : step.entrySet()) { 44 | scriptLines.addAll(PipelineGenerator.convert("step", entry.getValue())); 45 | } 46 | } 47 | 48 | scriptLines.add("}"); 49 | scriptLines.add("}"); 50 | } 51 | 52 | if (yamlPipeline.getStages() != null) { 53 | for (Stage stage : yamlPipeline.getStages()) { 54 | scriptLines.addAll(PipelineGenerator.convert("stage", stage)); 55 | } 56 | } 57 | 58 | // Archive artifacts stage 59 | scriptLines.addAll(PipelineGenerator.convert("archiveArtifactStage", yamlPipeline.getArchiveArtifacts())); 60 | 61 | ReportsAndArtifactsInfo reportsAndArtifactsInfo = new ReportsAndArtifactsInfo(); 62 | reportsAndArtifactsInfo.setArtifactPublishingConfig(yamlPipeline.getArtifactPublishingConfig()); 63 | reportsAndArtifactsInfo.setReports(yamlPipeline.getReports()); 64 | reportsAndArtifactsInfo.setPublishArtifacts(yamlPipeline.getPublishArtifacts()); 65 | 66 | scriptLines.addAll(PipelineGenerator.convert("publishReportsAndArtifactsStage", reportsAndArtifactsInfo)); 67 | 68 | // This stage will always be generated at last, because if anyone of the above stage fails then we 69 | // will not push the code to target branch 70 | if (yamlPipeline.getConfiguration() != null && yamlPipeline.getConfiguration().isPushPrOnSuccess()) { 71 | if (gitConfig == null) { 72 | throw new ConversionException("Git Configuration is not defined, but it is required for the Git Push"); 73 | } 74 | scriptLines.addAll(PipelineGenerator.convert("gitPushStage", gitConfig)); 75 | } 76 | 77 | scriptLines.add("}"); 78 | 79 | scriptLines.addAll(PipelineGenerator.convert("post", yamlPipeline.getPost())); 80 | 81 | for (CustomPipelineSection section : yamlPipeline.getSections()) { 82 | scriptLines.addAll(PipelineGenerator.convert(section)); 83 | } 84 | 85 | scriptLines.add("}"); 86 | return PipelineGenerator.autoAddTabs(scriptLines); 87 | } 88 | 89 | public YamlPipeline loadYaml(InputStream yamlScriptInputStream, TaskListener listener) { 90 | CustomClassLoaderConstructor constructor = new CustomClassLoaderConstructor(this.getClass().getClassLoader()); 91 | Yaml yaml = new Yaml(constructor); 92 | YamlPipeline yamlPipeline = yaml.loadAs(yamlScriptInputStream, YamlPipeline.class); 93 | 94 | if (yamlPipeline.getStages() != null && yamlPipeline.getSteps() != null) { 95 | throw new IllegalStateException("Only one of 'steps' or 'stages' must be present in the YAML file."); 96 | } 97 | 98 | return yamlPipeline; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/exception/ConversionException.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.exception; 2 | 3 | public class ConversionException extends Exception { 4 | 5 | public ConversionException(String message) { 6 | super(message); 7 | } 8 | 9 | public ConversionException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/AgentGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.models.Agent; 5 | import org.jenkinsci.Symbol; 6 | import org.kohsuke.accmod.Restricted; 7 | import org.kohsuke.accmod.restrictions.NoExternalUse; 8 | 9 | import javax.annotation.Nonnull; 10 | import java.util.ArrayList; 11 | import java.util.LinkedHashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Extension 16 | @Symbol("agent") 17 | @Restricted(NoExternalUse.class) 18 | public class AgentGenerator extends PipelineGenerator { 19 | 20 | @Nonnull 21 | @Override 22 | public List toPipeline(Agent agent) { 23 | ArrayList agentLines = new ArrayList<>(); 24 | 25 | if (agent == null) { 26 | agentLines.add("agent any"); 27 | } else if (agent.getAnyOrNone() != null) 28 | agentLines.add("agent " + agent.getAnyOrNone()); 29 | else if(agent.isNone()) { 30 | agentLines.add("agent none"); 31 | } 32 | else { 33 | 34 | if (agent.getDockerImage() != null) { 35 | agentLines.add("agent {"); 36 | agentLines.add("docker {"); 37 | agentLines.add("image '" + agent.getDockerImage() + "'"); 38 | 39 | if (agent.getArgs() != null) { 40 | agentLines.add("args '" + agent.getArgs() + "'"); 41 | } 42 | 43 | agentLines.add("alwaysPull " + agent.getAlwaysPull() + ""); 44 | agentLines.addAll(getCommonOptionsOfAgent(agent)); 45 | agentLines.add("}"); 46 | agentLines.add("}"); 47 | } else if (agent.getDockerfile() != null) { 48 | agentLines.add("agent {"); 49 | agentLines.add("dockerfile {"); 50 | agentLines.add("filename '" + agent.getDockerfile() + "'"); 51 | 52 | if (agent.getDir() != null) { 53 | agentLines.add("dir '" + agent.getDir() + "'"); 54 | } 55 | 56 | if (agent.getArgs() != null) { 57 | agentLines.add("additionalBuildArgs '" + agent.getArgs() + "'"); 58 | } 59 | 60 | agentLines.addAll(getCommonOptionsOfAgent(agent)); 61 | agentLines.add("}"); 62 | agentLines.add("}"); 63 | } else if (agent.getLabel() != null || agent.getCustomWorkspace() != null) { 64 | agentLines.add("agent {"); 65 | agentLines.add("node {"); 66 | agentLines.addAll(getCommonOptionsOfAgent(agent)); 67 | agentLines.add("}"); 68 | agentLines.add("}"); 69 | } else { 70 | agentLines.add("agent any"); 71 | } 72 | } 73 | 74 | if (agent != null) { 75 | agentLines.addAll(getTools(agent.getTools())); 76 | } 77 | 78 | return agentLines; 79 | } 80 | 81 | @Override 82 | public boolean canConvert(@Nonnull Object object) { 83 | return object instanceof Agent; 84 | } 85 | 86 | private List getCommonOptionsOfAgent(Agent agent) { 87 | ArrayList snippetLines = new ArrayList<>(); 88 | 89 | if (agent.getLabel() != null) { 90 | snippetLines.add("label '" + agent.getLabel() + "'"); 91 | } 92 | 93 | if (agent.getCustomWorkspace() != null) { 94 | snippetLines.add("customWorkspace '" + agent.getCustomWorkspace() + "'"); 95 | } 96 | 97 | if (agent.getDockerfile() != null || agent.getDockerImage() != null) { 98 | snippetLines.add("reuseNode " + agent.getReuseNode() + ""); 99 | } 100 | 101 | return snippetLines; 102 | } 103 | 104 | private List getTools(LinkedHashMap tools) { 105 | ArrayList snippetLines = new ArrayList<>(); 106 | 107 | if (tools == null) { 108 | return snippetLines; 109 | } 110 | 111 | snippetLines.add("tools {"); 112 | 113 | for (Map.Entry entry : tools.entrySet()) { 114 | snippetLines.add(entry.getKey() + " '" + entry.getValue() + "'"); 115 | } 116 | 117 | snippetLines.add("}"); 118 | 119 | return snippetLines; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/ArchiveArtifactStageGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import org.jenkinsci.Symbol; 5 | import org.kohsuke.accmod.Restricted; 6 | import org.kohsuke.accmod.restrictions.NoExternalUse; 7 | 8 | import javax.annotation.Nonnull; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Extension 13 | @Symbol("archiveArtifactStage") 14 | @Restricted(NoExternalUse.class) 15 | public class ArchiveArtifactStageGenerator extends PipelineGenerator> { 16 | 17 | @Nonnull 18 | @Override 19 | public List toPipeline(ArrayList paths) { 20 | ArrayList snippetLines = new ArrayList<>(); 21 | 22 | if (paths == null) { 23 | return snippetLines; 24 | } 25 | 26 | snippetLines.add("stage('Archive artifacts') {"); 27 | snippetLines.add("steps {"); 28 | 29 | for (String p : paths) { 30 | snippetLines.add("archiveArtifacts artifacts: '" + p + "'"); 31 | } 32 | 33 | snippetLines.add("}"); 34 | snippetLines.add("}"); 35 | 36 | return snippetLines; 37 | } 38 | 39 | @Override 40 | public boolean canConvert(@Nonnull Object object) { 41 | if(object instanceof ArrayList){ 42 | return ((ArrayList) object).get(0) instanceof String; 43 | } 44 | 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/CustomSectionGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.models.CustomPipelineSection; 6 | import org.jenkinsci.Symbol; 7 | import org.kohsuke.accmod.Restricted; 8 | import org.kohsuke.accmod.restrictions.NoExternalUse; 9 | 10 | import javax.annotation.CheckForNull; 11 | import javax.annotation.Nonnull; 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | /** 16 | * Converter for {@link CustomPipelineSection}. 17 | * @author Oleg Nenashev 18 | */ 19 | @Extension 20 | @Symbol("custom") 21 | @Restricted(NoExternalUse.class) 22 | public class CustomSectionGenerator extends PipelineGenerator { 23 | 24 | @Nonnull 25 | @Override 26 | public List toPipeline(@CheckForNull CustomPipelineSection section) 27 | throws ConversionException { 28 | if (section == null) { 29 | return Collections.emptyList(); 30 | } 31 | 32 | PipelineGenerator gen = PipelineGenerator.lookupForName(section.getName()); 33 | if (gen == null) { 34 | throw new ConversionException("No converter for Custom Pipeline Section: " + section.getName()); 35 | } 36 | return gen.toPipeline(section.getData()); 37 | } 38 | 39 | @Override 40 | public boolean canConvert(@Nonnull Object object) { 41 | return object instanceof CustomPipelineSection; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/EnvironmentGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.models.Credential; 5 | import io.jenkins.plugins.sprp.models.Environment; 6 | import org.jenkinsci.Symbol; 7 | import org.kohsuke.accmod.Restricted; 8 | import org.kohsuke.accmod.restrictions.NoExternalUse; 9 | 10 | import javax.annotation.Nonnull; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Extension 16 | @Symbol("environment") 17 | @Restricted(NoExternalUse.class) 18 | public class EnvironmentGenerator extends PipelineGenerator { 19 | 20 | @Nonnull 21 | @Override 22 | public List toPipeline(Environment environment) { 23 | ArrayList snippetLines = new ArrayList<>(); 24 | 25 | if (environment == null || (environment.getVariables() == null && environment.getCredentials() == null)) { 26 | return snippetLines; 27 | } 28 | 29 | snippetLines.add("environment {"); 30 | 31 | for (Map.Entry entry : environment.getVariables().entrySet()) { 32 | snippetLines.add(entry.getKey() + " = '" + entry.getValue() + "'"); 33 | } 34 | 35 | for (Credential credential : environment.getCredentials()) { 36 | snippetLines.add(credential.getVariable() + " = credentials('" + credential.getCredentialId() + "')"); 37 | } 38 | 39 | snippetLines.add("}"); 40 | 41 | return snippetLines; 42 | } 43 | 44 | @Override 45 | public boolean canConvert(@Nonnull Object object) { 46 | return object instanceof Environment; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/GitPushStageGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.git.GitConfig; 5 | import org.jenkinsci.Symbol; 6 | import org.kohsuke.accmod.Restricted; 7 | import org.kohsuke.accmod.restrictions.NoExternalUse; 8 | 9 | import javax.annotation.Nonnull; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | @Extension 14 | @Symbol("gitPushStage") 15 | @Restricted(NoExternalUse.class) 16 | public class GitPushStageGenerator extends PipelineGenerator { 17 | 18 | @Nonnull 19 | @Override 20 | public List toPipeline(GitConfig gitConfig) { 21 | ArrayList snippetLines = new ArrayList<>(); 22 | 23 | if(gitConfig == null){ 24 | return snippetLines; 25 | } 26 | 27 | snippetLines.add("stage('Git Push') {"); 28 | snippetLines.add("steps {"); 29 | snippetLines.add("gitPush " + 30 | "credentialId: \"" + gitConfig.getCredentialsId() + "\"," + 31 | "url: \"" + gitConfig.getGitUrl() + "\"," + 32 | "branch: \"" + gitConfig.getGitBranch() + "\""); 33 | 34 | snippetLines.add("}"); 35 | snippetLines.add("}"); 36 | return snippetLines; 37 | } 38 | 39 | @Override 40 | public boolean canConvert(@Nonnull Object object) { 41 | return object instanceof GitConfig; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/PipelineGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.ExtensionList; 4 | import hudson.ExtensionPoint; 5 | import io.jenkins.plugins.sprp.exception.ConversionException; 6 | import org.apache.commons.lang.StringUtils; 7 | import org.apache.log4j.Logger; 8 | import org.jenkinsci.plugins.structs.SymbolLookup; 9 | 10 | import javax.annotation.CheckForNull; 11 | import javax.annotation.Nonnull; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | 16 | public abstract class PipelineGenerator implements ExtensionPoint { 17 | static private Logger logger = Logger.getLogger(PipelineGenerator.class.getClass().getName()); 18 | 19 | @Nonnull 20 | public abstract List toPipeline(@CheckForNull T object) throws ConversionException; 21 | 22 | public abstract boolean canConvert(@Nonnull Object object); 23 | 24 | public static ExtensionList all() { 25 | return ExtensionList.lookup(PipelineGenerator.class); 26 | } 27 | 28 | @CheckForNull 29 | public static PipelineGenerator lookupForName(@Nonnull String name) { 30 | return SymbolLookup.get().find(PipelineGenerator.class, name); 31 | } 32 | 33 | @CheckForNull 34 | public static T lookupConverter(Class clazz) { 35 | for (PipelineGenerator gen : all()) { 36 | if (clazz.equals(gen.getClass())) { 37 | return clazz.cast(gen); 38 | } 39 | } 40 | return null; 41 | } 42 | 43 | @Nonnull 44 | public static T lookupConverterOrFail(Class clazz) 45 | throws ConversionException { 46 | T converter = lookupConverter(clazz); 47 | if (converter == null) { 48 | throw new ConversionException("Failed to find converter: " + clazz); 49 | } 50 | return converter; 51 | } 52 | 53 | @CheckForNull 54 | public static PipelineGenerator lookup(@Nonnull Object object) { 55 | for (PipelineGenerator gen : all()) { 56 | if (gen.canConvert(object)) { 57 | return gen; 58 | } 59 | } 60 | return null; 61 | } 62 | 63 | @Nonnull 64 | public static List convert(@Nonnull Object object) throws ConversionException { 65 | PipelineGenerator gen = lookup(object); 66 | if (gen == null) { 67 | // TODO: add better diagnostics (field matching) 68 | throw new ConversionException("Cannot find converter for the object: " + object.getClass()); 69 | } 70 | //TODO: handle raw type conversion risks 71 | return gen.toPipeline(object); 72 | } 73 | 74 | @Nonnull 75 | public static List convert(@Nonnull String converterName, @CheckForNull Object object) throws ConversionException { 76 | PipelineGenerator gen = lookupForName(converterName); 77 | if (gen == null) { 78 | // TODO: add better diagnostics (field matching) 79 | throw new ConversionException("Cannot find converter for the type: " + converterName); 80 | } 81 | //TODO: handle raw type conversion risks 82 | return gen.toPipeline(object); 83 | } 84 | 85 | public static String autoAddTabs(ArrayList snippetLines) { 86 | int numOfTabs = 0; 87 | StringBuilder snippet = new StringBuilder(); 88 | 89 | for (String str : snippetLines) { 90 | if (str.startsWith("}")) { 91 | numOfTabs--; 92 | } 93 | 94 | if (numOfTabs != 0) { 95 | snippet.append(StringUtils.repeat("\t", numOfTabs)); 96 | } 97 | 98 | snippet.append(str).append("\n"); 99 | 100 | if (str.endsWith("{")) { 101 | numOfTabs++; 102 | } 103 | } 104 | 105 | return snippet.toString(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/PostGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.models.Post; 6 | import io.jenkins.plugins.sprp.models.Step; 7 | import org.jenkinsci.Symbol; 8 | import org.kohsuke.accmod.Restricted; 9 | import org.kohsuke.accmod.restrictions.NoExternalUse; 10 | 11 | import javax.annotation.Nonnull; 12 | import java.util.ArrayList; 13 | import java.util.LinkedHashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | @Extension 18 | @Symbol("post") 19 | @Restricted(NoExternalUse.class) 20 | public class PostGenerator extends PipelineGenerator { 21 | 22 | @Nonnull 23 | @Override 24 | public List toPipeline(Post postSection) throws ConversionException { 25 | ArrayList snippetLines = new ArrayList<>(); 26 | 27 | if (postSection == null) { 28 | return snippetLines; 29 | } 30 | 31 | snippetLines.add("post {"); 32 | 33 | snippetLines.addAll(getPostConditionSnippetIfNonNull("always", postSection.getAlways())); 34 | snippetLines.addAll(getPostConditionSnippetIfNonNull("changed", postSection.getChanged())); 35 | snippetLines.addAll(getPostConditionSnippetIfNonNull("fixed", postSection.getFixed())); 36 | snippetLines.addAll(getPostConditionSnippetIfNonNull("regression", postSection.getRegression())); 37 | snippetLines.addAll(getPostConditionSnippetIfNonNull("aborted", postSection.getAborted())); 38 | snippetLines.addAll(getPostConditionSnippetIfNonNull("failure", postSection.getFailure())); 39 | snippetLines.addAll(getPostConditionSnippetIfNonNull("success", postSection.getSuccess())); 40 | snippetLines.addAll(getPostConditionSnippetIfNonNull("unstable", postSection.getUnstable())); 41 | snippetLines.addAll(getPostConditionSnippetIfNonNull("cleanup", postSection.getCleanup())); 42 | 43 | snippetLines.add("}"); 44 | 45 | return snippetLines; 46 | } 47 | 48 | @Override 49 | public boolean canConvert(@Nonnull Object object) { 50 | return object instanceof Post; 51 | } 52 | 53 | private List getPostConditionSnippetIfNonNull(String postCondition, ArrayList> steps) 54 | throws ConversionException { 55 | ArrayList snippetLines = new ArrayList<>(); 56 | if (steps != null) { 57 | snippetLines.add(postCondition + " {"); 58 | 59 | for (LinkedHashMap step : steps) { 60 | for (Map.Entry entry : step.entrySet()) { 61 | snippetLines.addAll(PipelineGenerator.convert("step", entry.getValue())); 62 | } 63 | } 64 | 65 | snippetLines.add("}"); 66 | } 67 | 68 | return snippetLines; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/PublishReportsAndArtifactsStageGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.models.ArtifactPublishingConfig; 5 | import io.jenkins.plugins.sprp.models.ReportsAndArtifactsInfo; 6 | import org.jenkinsci.Symbol; 7 | import org.kohsuke.accmod.Restricted; 8 | import org.kohsuke.accmod.restrictions.NoExternalUse; 9 | 10 | import javax.annotation.Nonnull; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | 15 | @Extension 16 | @Symbol("publishReportsAndArtifactsStage") 17 | @Restricted(NoExternalUse.class) 18 | public class PublishReportsAndArtifactsStageGenerator extends PipelineGenerator { 19 | 20 | @Nonnull 21 | @Override 22 | public List toPipeline(ReportsAndArtifactsInfo reportsAndArtifactsInfo) { 23 | ArrayList snippetLines = new ArrayList<>(); 24 | 25 | if(reportsAndArtifactsInfo == null){ 26 | return snippetLines; 27 | } 28 | 29 | ArrayList reports = reportsAndArtifactsInfo.getReports(); 30 | ArtifactPublishingConfig config = reportsAndArtifactsInfo.getArtifactPublishingConfig(); 31 | ArrayList> publishArtifacts = reportsAndArtifactsInfo.getPublishArtifacts(); 32 | 33 | 34 | 35 | if (reports == null && config == null) { 36 | return snippetLines; 37 | } 38 | 39 | snippetLines.add("stage('Publish reports & artifacts') {"); 40 | snippetLines.add("steps {"); 41 | 42 | if (reports != null) { 43 | snippetLines.addAll(getPublishReportSnippet(reports)); 44 | } 45 | 46 | if (config != null) { 47 | snippetLines.add("" + "withCredentials([file(credentialsId: '" + config.getCredentialId() + "', variable: 'FILE')]) {"); 48 | 49 | for (HashMap artifact : publishArtifacts) { 50 | snippetLines.add("sh 'scp -i $FILE " + artifact.get("from") + " " + config.getUser() + "@" + config.getHost() + ":" + artifact.get("to") + "'"); 51 | } 52 | 53 | snippetLines.add("}"); 54 | } 55 | 56 | snippetLines.add("}"); 57 | snippetLines.add("}"); 58 | 59 | return snippetLines; 60 | } 61 | 62 | @Override 63 | public boolean canConvert(@Nonnull Object object) { 64 | return object instanceof PublishReportsAndArtifactsStageGenerator; 65 | } 66 | 67 | private List getPublishReportSnippet(ArrayList paths) { 68 | ArrayList snippetLines = new ArrayList<>(); 69 | 70 | for (String p : paths) { 71 | snippetLines.add("junit '" + p + "'"); 72 | } 73 | 74 | return snippetLines; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/StageGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.models.Agent; 6 | import io.jenkins.plugins.sprp.models.Stage; 7 | import io.jenkins.plugins.sprp.models.Step; 8 | import org.jenkinsci.Symbol; 9 | import org.kohsuke.accmod.Restricted; 10 | import org.kohsuke.accmod.restrictions.NoExternalUse; 11 | 12 | import javax.annotation.Nonnull; 13 | import java.util.ArrayList; 14 | import java.util.LinkedHashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | @Extension 19 | @Symbol("stage") 20 | @Restricted(NoExternalUse.class) 21 | public class StageGenerator extends PipelineGenerator { 22 | 23 | @Nonnull 24 | @Override 25 | public List toPipeline(Stage stage) throws ConversionException { 26 | ArrayList snippetLines = new ArrayList<>(); 27 | 28 | if(stage == null){ 29 | return snippetLines; 30 | } 31 | 32 | String stageName = stage.getName(); 33 | 34 | snippetLines.add("stage('" + stageName + "') {"); 35 | 36 | final Agent agent = stage.getAgent(); 37 | if (agent != null && !agent.getAnyOrNone().equals("any")) { 38 | AgentGenerator gen = lookupConverterOrFail(AgentGenerator.class); 39 | snippetLines.addAll(gen.toPipeline(agent)); 40 | } 41 | 42 | snippetLines.add("steps {"); 43 | 44 | for (LinkedHashMap step : stage.getSteps()) { 45 | for (Map.Entry entry : step.entrySet()) { 46 | snippetLines.addAll(PipelineGenerator.convert("step", entry.getValue())); 47 | } 48 | } 49 | 50 | snippetLines.add("}"); 51 | 52 | snippetLines.addAll(PipelineGenerator.convert("post", stage.getPost())); 53 | 54 | snippetLines.add("}"); 55 | 56 | return snippetLines; 57 | } 58 | 59 | @Override 60 | public boolean canConvert(@Nonnull Object object) { 61 | return object instanceof Stage; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/generators/StepGenerator.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import hudson.Extension; 4 | import hudson.model.Descriptor; 5 | import io.jenkins.plugins.casc.ConfigurationContext; 6 | import io.jenkins.plugins.casc.Configurator; 7 | import io.jenkins.plugins.casc.ConfiguratorException; 8 | import io.jenkins.plugins.casc.ConfiguratorRegistry; 9 | import io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator; 10 | import io.jenkins.plugins.casc.model.Mapping; 11 | import io.jenkins.plugins.casc.model.Scalar; 12 | import io.jenkins.plugins.casc.model.Sequence; 13 | import io.jenkins.plugins.sprp.exception.ConversionException; 14 | import io.jenkins.plugins.sprp.models.Step; 15 | import org.jenkinsci.Symbol; 16 | import org.jenkinsci.plugins.workflow.cps.Snippetizer; 17 | import org.jenkinsci.plugins.workflow.steps.StepDescriptor; 18 | import org.kohsuke.accmod.Restricted; 19 | import org.kohsuke.accmod.restrictions.NoExternalUse; 20 | 21 | import javax.annotation.Nonnull; 22 | import java.lang.reflect.Constructor; 23 | import java.lang.reflect.InvocationTargetException; 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | @Extension 29 | @Symbol("step") 30 | @Restricted(NoExternalUse.class) 31 | public class StepGenerator extends PipelineGenerator { 32 | 33 | @Nonnull 34 | @Override 35 | public List toPipeline(Step step) throws ConversionException { 36 | ArrayList pipelineStep = new ArrayList<>(); 37 | pipelineStep.add(stepConfigurator(step)); 38 | return pipelineStep; 39 | } 40 | 41 | @Override 42 | public boolean canConvert(@Nonnull Object object) { 43 | return object instanceof Step; 44 | } 45 | 46 | private String stepConfigurator(Step step) throws ConversionException { 47 | if (step == null) 48 | return "\n"; 49 | 50 | String snippet; 51 | Object stepObject; 52 | Descriptor stepDescriptor = StepDescriptor.byFunctionName(step.getStepName()); 53 | 54 | if (stepDescriptor == null) { 55 | throw new ConversionException("No step exist with the name " + step.getStepName()); 56 | } 57 | 58 | Class clazz = stepDescriptor.clazz; 59 | 60 | if (step.getDefaultParameter() != null) { 61 | 62 | Constructor constructor = DataBoundConfigurator.getDataBoundConstructor(clazz); 63 | 64 | if (constructor != null && constructor.getParameterCount() == 1) { 65 | try { 66 | stepObject = constructor.newInstance(step.getDefaultParameter()); 67 | } catch (InvocationTargetException e) { 68 | throw new ConversionException("Error while invoking constructor " + constructor.getName() + 69 | " with parameter type " + constructor.getParameters()[0].getType(), e); 70 | } catch (InstantiationException e) { 71 | throw new ConversionException("Error while instantiating" + step.getStepName() + 72 | " step object with constructor " + constructor.getName(), e); 73 | } catch (IllegalAccessException e) { 74 | throw new ConversionException("Unknown error while instantiating an object of step " + 75 | step.getStepName() + " with default parameter"); 76 | } 77 | } else { 78 | throw new ConversionException("No suitable constructor found for default parameter of step " 79 | + step.getStepName()); 80 | } 81 | } else { 82 | Mapping mapping = doMappingForMap(step.getParameters()); 83 | 84 | ConfigurationContext context = new ConfigurationContext(ConfiguratorRegistry.get()); 85 | Configurator configurator = ConfiguratorRegistry.get().lookup(clazz); 86 | 87 | if (configurator != null) { 88 | try { 89 | stepObject = configurator.configure(mapping, context); 90 | } catch (ConfiguratorException e) { 91 | throw new ConversionException("JCasC plugin is not able to configure the step + " + step.getStepName(), e); 92 | } 93 | } else { 94 | throw new ConversionException("No step with name '" + step.getStepName() + 95 | "' exist. Have you installed required plugin."); 96 | } 97 | } 98 | 99 | snippet = Snippetizer.object2Groovy(stepObject); 100 | return snippet; 101 | } 102 | 103 | private Mapping doMappingForMap(Map map) throws ConversionException { 104 | Mapping mapping = new Mapping(); 105 | 106 | for (Map.Entry entry : map.entrySet()) { 107 | if (entry.getValue() instanceof Map) { 108 | mapping.put(entry.getKey(), doMappingForMap((Map) entry.getValue())); 109 | } else if (entry.getValue() instanceof List) { 110 | mapping.put(entry.getKey(), doMappingForSequence((List) entry.getValue())); 111 | } else { 112 | mapping.put(entry.getKey(), doMappingForScalar(entry.getValue())); 113 | } 114 | } 115 | 116 | return mapping; 117 | } 118 | 119 | private Scalar doMappingForScalar(Object object) throws ConversionException { 120 | Scalar scalar; 121 | 122 | if (object instanceof String) { 123 | scalar = new Scalar((String) object); 124 | } else if (object instanceof Number) { 125 | scalar = new Scalar((Number) object); 126 | } else if (object instanceof Enum) { 127 | scalar = new Scalar((Enum) object); 128 | } else if (object instanceof Boolean) { 129 | scalar = new Scalar((Boolean) object); 130 | } else { 131 | throw new ConversionException(object.getClass() + " is not supported."); 132 | } 133 | 134 | return scalar; 135 | } 136 | 137 | private Sequence doMappingForSequence(List objects) throws ConversionException { 138 | Sequence sequence = new Sequence(); 139 | 140 | for (Object object : objects) { 141 | if (object instanceof Map) { 142 | sequence.add(doMappingForMap((Map) object)); 143 | } else if (object instanceof Sequence) { 144 | sequence.add(doMappingForSequence((List) object)); 145 | } else { 146 | sequence.add(doMappingForScalar(object)); 147 | } 148 | } 149 | 150 | return sequence; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/git/GitConfig.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.git; 2 | 3 | public class GitConfig { 4 | private String gitUrl; 5 | private String gitBranch; 6 | private String credentialsId; 7 | 8 | public GitConfig() { 9 | } 10 | 11 | public String getCredentialsId() { 12 | return credentialsId; 13 | } 14 | 15 | public void setCredentialsId(String credentialsId) { 16 | this.credentialsId = credentialsId; 17 | } 18 | 19 | public String getGitBranch() { 20 | return gitBranch; 21 | } 22 | 23 | public void setGitBranch(String gitBranch) { 24 | this.gitBranch = gitBranch; 25 | } 26 | 27 | public String getGitUrl() { 28 | return gitUrl; 29 | } 30 | 31 | public void setGitUrl(String gitUrl) { 32 | this.gitUrl = gitUrl; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/git/GitOperations.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.git; 2 | 3 | import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials; 4 | import hudson.EnvVars; 5 | import hudson.FilePath; 6 | import hudson.model.TaskListener; 7 | import hudson.plugins.git.Branch; 8 | import org.eclipse.jgit.lib.ObjectId; 9 | import org.eclipse.jgit.transport.RefSpec; 10 | import org.eclipse.jgit.transport.URIish; 11 | import org.jenkinsci.plugins.gitclient.*; 12 | 13 | import java.io.IOException; 14 | import java.net.URISyntaxException; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Objects; 18 | import java.util.Set; 19 | 20 | public class GitOperations { 21 | private static final String DUMMY_BRANCH_NAME = "DUMMY_8DD2963"; // Just to avoid duplicate branch name 22 | private FilePath workspace; 23 | private TaskListener listener; 24 | private EnvVars envVars; 25 | private String url; 26 | private GitClient git; 27 | private String currentBranch; 28 | private String currentBranchSHA1; 29 | 30 | public GitOperations(FilePath workspace, TaskListener listener, EnvVars envVars, String url) throws IOException, InterruptedException { 31 | this.workspace = workspace; 32 | this.envVars = envVars; 33 | this.listener = listener; 34 | this.url = url; 35 | this.currentBranch = null; 36 | 37 | initialiseGitClient(); 38 | } 39 | 40 | private void initialiseGitClient() throws IOException, InterruptedException { 41 | git = Git.with(listener, envVars) 42 | .in(workspace) 43 | .using("git") 44 | .getClient(); 45 | } 46 | 47 | 48 | public void setEnvVars(EnvVars envVars) throws IOException, InterruptedException { 49 | this.envVars = envVars; 50 | initialiseGitClient(); 51 | } 52 | 53 | public TaskListener getListener() { 54 | return listener; 55 | } 56 | 57 | public void setWorkspace(FilePath workspace) throws IOException, InterruptedException { 58 | this.workspace = workspace; 59 | initialiseGitClient(); 60 | } 61 | 62 | public String getCurrentBranch() { 63 | return currentBranch; 64 | } 65 | 66 | public void setCurrentBranch(String currentBranch) { 67 | this.currentBranch = currentBranch; 68 | } 69 | 70 | public boolean cloneTheRepo(String branch) { 71 | CloneCommand clone = git.clone_(); 72 | ArrayList refSpecs = new ArrayList<>(); 73 | clone.url(url); 74 | 75 | if (branch != null && !branch.equals("")) { 76 | refSpecs.add(new RefSpec() 77 | .setSourceDestination("+refs/heads/" + branch, "refs/remotes/origin/" + branch)); 78 | clone.refspecs(refSpecs); 79 | } 80 | 81 | try { 82 | clone.execute(); 83 | } catch (InterruptedException e) { 84 | listener.getLogger().println("Error while cloning branch " + branch + "from " + url); 85 | listener.getLogger().println(e.getMessage()); 86 | return false; 87 | } 88 | 89 | listener.getLogger().println("Cloned branch " + branch + " successfully from " + url + "."); 90 | return checkout(branch); 91 | } 92 | 93 | public boolean fetch(String branch, List refSpecs) { 94 | FetchCommand fetch = git.fetch_(); 95 | ArrayList rfs = new ArrayList<>(); 96 | 97 | if (branch != null && !branch.equals("")) { 98 | rfs.add(new RefSpec().setSourceDestination(branch, branch)); 99 | } 100 | 101 | fetch.prune(true); 102 | 103 | try { 104 | fetch.from(new URIish(this.url), rfs); 105 | fetch.execute(); 106 | } catch (InterruptedException e) { 107 | listener.getLogger().println("Error while fetching branch from " + url); 108 | listener.getLogger().println(e.getMessage()); 109 | return false; 110 | } catch (URISyntaxException e) { 111 | listener.getLogger().println("Invalid repository url"); 112 | return false; 113 | } 114 | 115 | listener.getLogger().println("Fetch successful from " + url + "."); 116 | return checkout(branch); 117 | } 118 | 119 | public boolean checkout(String branch) { 120 | CheckoutCommand checkoutCommand = git.checkout(); 121 | checkoutCommand.branch(branch); 122 | String tempCurrentBranchSHA1 = getObjectIdOfLocalBranch(branch).name(); 123 | checkoutCommand.ref(currentBranchSHA1); 124 | 125 | try { 126 | checkoutCommand.execute(); 127 | } catch (InterruptedException e) { 128 | listener.getLogger().println("Error while checkout to branch " + branch); 129 | listener.getLogger().println(e.getMessage()); 130 | return false; 131 | } 132 | 133 | listener.getLogger().println("Cloned branch " + branch + " successfully."); 134 | setCurrentBranch(branch); 135 | currentBranchSHA1 = tempCurrentBranchSHA1; 136 | return true; 137 | } 138 | 139 | public boolean pullChangesOfPullrequest(int PR_Number, String branch) throws InterruptedException { 140 | if (!cloneTheRepo(branch)) 141 | return false; 142 | 143 | FetchCommand fetchCommand = git.fetch_(); 144 | 145 | ArrayList refSpecs = new ArrayList<>(); 146 | refSpecs.add(new RefSpec().setSourceDestination("pull/" + PR_Number + "/head", DUMMY_BRANCH_NAME)); 147 | 148 | try { 149 | fetchCommand.from(new URIish(this.url), refSpecs); 150 | fetchCommand.execute(); 151 | } catch (InterruptedException e) { 152 | listener.getLogger().println("Error while fetching from " + url); 153 | listener.getLogger().println(e.getMessage()); 154 | return false; 155 | } catch (URISyntaxException e) { 156 | listener.getLogger().println("Invalid repository url"); 157 | return false; 158 | } 159 | 160 | listener.getLogger().println("Fetched successfully."); 161 | 162 | if (!merge(Objects.requireNonNull(getObjectIdOfLocalBranch(DUMMY_BRANCH_NAME)).name())) 163 | return false; 164 | 165 | return deleteBranch(DUMMY_BRANCH_NAME); 166 | } 167 | 168 | public boolean merge(String rev) { 169 | listener.getLogger().println("Merging started with rev " + rev + "."); 170 | MergeCommand mergeCommand = git.merge(); 171 | mergeCommand.setRevisionToMerge(ObjectId.fromString(rev)); 172 | mergeCommand.setMessage("Merging to build the pull request."); 173 | mergeCommand.setCommit(true); 174 | 175 | try { 176 | mergeCommand.execute(); 177 | } catch (InterruptedException e) { 178 | listener.getLogger().println("Error while merging."); 179 | listener.getLogger().println(e.getMessage()); 180 | return false; 181 | } 182 | 183 | return true; 184 | } 185 | 186 | private boolean deleteBranch(String branch) { 187 | try { 188 | git.deleteBranch(branch); 189 | return true; 190 | } catch (InterruptedException e) { 191 | e.printStackTrace(); 192 | return false; 193 | } 194 | } 195 | 196 | public boolean push(boolean fromHead) { 197 | PushCommand pushCommand = git.push(); 198 | 199 | try { 200 | pushCommand.to(new URIish(this.url)); 201 | } catch (URISyntaxException e) { 202 | e.printStackTrace(); 203 | return false; 204 | } 205 | 206 | // https://stackoverflow.com/a/4183856/6693569 207 | // At this point the pointer may be at detached HEAD 208 | if (fromHead) 209 | pushCommand.ref("HEAD:" + currentBranch); 210 | else 211 | pushCommand.ref(currentBranch); 212 | 213 | pushCommand.force(true); 214 | 215 | try { 216 | pushCommand.execute(); 217 | } catch (InterruptedException e) { 218 | listener.getLogger().println("Error while pushing the branch " + currentBranch); 219 | e.printStackTrace(); 220 | return false; 221 | } 222 | 223 | listener.getLogger().println("Branch " + currentBranch + " pushed successfully."); 224 | return true; 225 | } 226 | 227 | public void setUsernameAndPasswordCredential(StandardUsernameCredentials cred) { 228 | git.setCredentials(cred); 229 | } 230 | 231 | private String extractObjectIdFromBranch(String branch) { 232 | String objectId; 233 | int branchLen = branch.length(); 234 | objectId = branch.substring(branchLen - 41, branchLen - 1); 235 | return objectId; 236 | } 237 | 238 | private ObjectId getObjectIdOfLocalBranch(String branch) { 239 | try { 240 | Set allBranches = (Set) git.getBranches(); 241 | 242 | ArrayList branches = new ArrayList<>(); 243 | 244 | for (Branch b : allBranches) { 245 | if (b.toString().contains(branch)) { 246 | branches.add(b); 247 | } 248 | } 249 | 250 | if (branches.size() > 1) { 251 | allBranches.clear(); 252 | allBranches.addAll(branches); 253 | branches.clear(); 254 | 255 | for (Branch b : allBranches) { 256 | if (!b.toString().contains("remotes")) { 257 | System.out.println("found: " + b.toString()); 258 | branches.add(b); 259 | } 260 | } 261 | } 262 | 263 | listener.getLogger().println("Number of branches: " + branches.size()); 264 | 265 | if (branches.size() > 1) { 266 | listener.getLogger().println("More than one branches found containing " + branch); 267 | for (Branch b : branches) { 268 | listener.getLogger().print(" - " + b.toString() + " : "); 269 | listener.getLogger().println(extractObjectIdFromBranch(b.toString())); 270 | } 271 | return null; 272 | } else if (branches.size() == 1) 273 | return ObjectId.fromString(extractObjectIdFromBranch(branches.get(0).toString())); 274 | else { 275 | listener.getLogger().println("Cannot find a branch with name : " + branch); 276 | return null; 277 | } 278 | } catch (InterruptedException e) { 279 | e.printStackTrace(); 280 | listener.getLogger().println("Error while getting ObjectId of branch : " + branch); 281 | return null; 282 | } 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/git/GitPushStep.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.git; 2 | 3 | import com.cloudbees.plugins.credentials.CredentialsMatchers; 4 | import com.cloudbees.plugins.credentials.CredentialsProvider; 5 | import com.cloudbees.plugins.credentials.common.StandardCredentials; 6 | import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials; 7 | import hudson.EnvVars; 8 | import hudson.Extension; 9 | import hudson.FilePath; 10 | import hudson.model.Queue; 11 | import hudson.model.TaskListener; 12 | import hudson.model.queue.Tasks; 13 | import org.jenkinsci.Symbol; 14 | import org.jenkinsci.plugins.workflow.job.WorkflowJob; 15 | import org.jenkinsci.plugins.workflow.steps.*; 16 | import org.kohsuke.accmod.Restricted; 17 | import org.kohsuke.accmod.restrictions.NoExternalUse; 18 | import org.kohsuke.stapler.DataBoundConstructor; 19 | 20 | import java.util.Collections; 21 | import java.util.Set; 22 | 23 | public class GitPushStep extends Step { 24 | private String credentialId; 25 | private String url; 26 | private String branch; 27 | 28 | @DataBoundConstructor 29 | public GitPushStep(String credentialId, String url, String branch) { 30 | this.credentialId = credentialId; 31 | this.url = url; 32 | this.branch = branch; 33 | } 34 | 35 | public String getCredentialId() { 36 | return credentialId; 37 | } 38 | 39 | public String getBranch() { 40 | return branch; 41 | } 42 | 43 | public String getUrl() { 44 | return url; 45 | } 46 | 47 | public StepExecution start(StepContext context) throws Exception { 48 | return new GitPushStep.Execution(this.credentialId, this.url, this.branch, context); 49 | } 50 | 51 | public static class Execution extends SynchronousStepExecution { 52 | private static final long serialVersionUID = 1L; 53 | 54 | private final String credentialId; 55 | private final String url; 56 | private final String branch; 57 | 58 | Execution(String credentialId, String url, String branch, StepContext context) { 59 | super(context); 60 | this.credentialId = credentialId; 61 | this.url = url; 62 | this.branch = branch; 63 | } 64 | 65 | protected Void run() throws Exception { 66 | FilePath ws = getContext().get(FilePath.class); 67 | TaskListener listener = this.getContext().get(TaskListener.class); 68 | EnvVars envVars = getContext().get(EnvVars.class); 69 | WorkflowJob job = getContext().get(WorkflowJob.class); 70 | GitOperations gitOperations = new GitOperations(ws, listener, envVars, url); 71 | StandardCredentials c = CredentialsMatchers.firstOrNull( 72 | CredentialsProvider.lookupCredentials( 73 | StandardCredentials.class, 74 | job, 75 | Tasks.getAuthenticationOf((Queue.Task) job)), 76 | CredentialsMatchers.withId(credentialId)); 77 | 78 | gitOperations.setUsernameAndPasswordCredential((StandardUsernameCredentials) c); 79 | gitOperations.setCurrentBranch(branch); 80 | gitOperations.push(true); 81 | return null; 82 | } 83 | } 84 | 85 | @Symbol("gitPush") 86 | @Extension 87 | @Restricted(NoExternalUse.class) 88 | public static class DescriptorImpl extends StepDescriptor { 89 | public DescriptorImpl() { 90 | } 91 | 92 | public String getFunctionName() { 93 | return "gitPush"; 94 | } 95 | 96 | public String getDisplayName() { 97 | return "Git push step"; 98 | } 99 | 100 | public Set> getRequiredContext() { 101 | return Collections.singleton(TaskListener.class); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Agent.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import org.eclipse.jgit.errors.NotSupportedException; 4 | 5 | import java.util.LinkedHashMap; 6 | 7 | public class Agent { 8 | private String label; 9 | private String customWorkspace; 10 | private String dockerImage; 11 | private boolean alwaysPull; 12 | private String args; 13 | private String dockerfile; 14 | private String dir; 15 | private boolean reuseNode; 16 | private String anyOrNone; 17 | private boolean none; 18 | 19 | // LinkedHashMap is used to preserve the order of insertion in tools as some tests may fail 20 | private LinkedHashMap tools; 21 | 22 | public Agent(){} 23 | 24 | public Agent(String anyOrNone) throws NotSupportedException { 25 | if(anyOrNone.equals("any") || anyOrNone.equals("none")) { 26 | this.anyOrNone = anyOrNone; 27 | } else { 28 | throw new NotSupportedException("Agent type " + anyOrNone + "is not supported."); 29 | } 30 | } 31 | 32 | public String getLabel() { 33 | return label; 34 | } 35 | 36 | public void setLabel(String label) { 37 | this.label = label; 38 | } 39 | 40 | public String getCustomWorkspace() { 41 | return customWorkspace; 42 | } 43 | 44 | public void setCustomWorkspace(String customWorkspace) { 45 | this.customWorkspace = customWorkspace; 46 | } 47 | 48 | public String getArgs() { 49 | return args; 50 | } 51 | 52 | public void setArgs(String args) { 53 | this.args = args; 54 | } 55 | 56 | public String getDockerfile() { 57 | return dockerfile; 58 | } 59 | 60 | public void setDockerfile(String dockerfile) { 61 | this.dockerfile = dockerfile; 62 | } 63 | 64 | public String getDir() { 65 | return dir; 66 | } 67 | 68 | public void setDir(String dir) { 69 | this.dir = dir; 70 | } 71 | 72 | public String getDockerImage() { 73 | return this.dockerImage; 74 | } 75 | 76 | public void setDockerImage(String dockerImage) { 77 | this.dockerImage = dockerImage; 78 | } 79 | 80 | public boolean getAlwaysPull() { 81 | return alwaysPull; 82 | } 83 | 84 | public void setAlwaysPull(boolean alwaysPull) { 85 | this.alwaysPull = alwaysPull; 86 | } 87 | 88 | public boolean getReuseNode() { 89 | return this.reuseNode; 90 | } 91 | 92 | public void setReuseNode(boolean reuseNode) { 93 | this.reuseNode = reuseNode; 94 | } 95 | 96 | public String getAnyOrNone() { 97 | return anyOrNone; 98 | } 99 | 100 | public void setAnyOrNone(String anyOrNone) { 101 | this.anyOrNone = anyOrNone; 102 | } 103 | 104 | public LinkedHashMap getTools() { 105 | return tools; 106 | } 107 | 108 | public boolean isNone() { 109 | return none; 110 | } 111 | 112 | public void setNone(boolean none) { 113 | this.none = none; 114 | } 115 | 116 | public void setTools(LinkedHashMap tools) { 117 | this.tools = tools; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/ArtifactPublishingConfig.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | public class ArtifactPublishingConfig { 4 | private String host; 5 | private String user; 6 | private String credentialId; 7 | 8 | public ArtifactPublishingConfig() { 9 | } 10 | 11 | public String getCredentialId() { 12 | return credentialId; 13 | } 14 | 15 | public void setCredentialId(String credentialId) { 16 | this.credentialId = credentialId; 17 | } 18 | 19 | public String getUser() { 20 | return user; 21 | } 22 | 23 | public void setUser(String user) { 24 | this.user = user; 25 | } 26 | 27 | public String getHost() { 28 | return host; 29 | } 30 | 31 | public void setHost(String host) { 32 | this.host = host; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Configuration.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import javax.annotation.CheckForNull; 4 | import javax.annotation.Nonnull; 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | 10 | public class Configuration { 11 | private boolean pushPrOnSuccess; 12 | private ArrayList prApprovers; 13 | 14 | private String gitCredentialId; 15 | private ArtifactPublishingConfig artifactPublishingConfig; 16 | private ArrayList archiveArtifacts; 17 | private ArrayList reports; 18 | private ArrayList> publishArtifacts; 19 | private String findBugs; 20 | 21 | @CheckForNull 22 | private ArrayList sections; 23 | 24 | public ArrayList getReports() { 25 | return reports; 26 | } 27 | 28 | public void setReports(ArrayList reports) { 29 | this.reports = reports; 30 | } 31 | 32 | public String getGitCredentialId() { 33 | return gitCredentialId; 34 | } 35 | 36 | public void setGitCredentialId(String gitCredentialId) { 37 | this.gitCredentialId = gitCredentialId; 38 | } 39 | 40 | public ArtifactPublishingConfig getArtifactPublishingConfig() { 41 | return artifactPublishingConfig; 42 | } 43 | 44 | public void setArtifactPublishingConfig(ArtifactPublishingConfig artifactPublishingConfig) { 45 | this.artifactPublishingConfig = artifactPublishingConfig; 46 | } 47 | 48 | public ArrayList> getPublishArtifacts() { 49 | return publishArtifacts; 50 | } 51 | 52 | public void setPublishArtifacts(ArrayList> publishArtifacts) { 53 | this.publishArtifacts = publishArtifacts; 54 | } 55 | 56 | public String getFindBugs() { 57 | return findBugs; 58 | } 59 | 60 | public void setFindBugs(String findBugs) { 61 | this.findBugs = findBugs; 62 | } 63 | 64 | public ArrayList getArchiveArtifacts() { 65 | return archiveArtifacts; 66 | } 67 | 68 | public void setArchiveArtifacts(ArrayList archiveArtifacts) { 69 | this.archiveArtifacts = archiveArtifacts; 70 | } 71 | 72 | @Nonnull 73 | public List getSections() { 74 | return this.sections != null ? this.sections : Collections.emptyList(); 75 | } 76 | 77 | public void setSections(@CheckForNull ArrayList sections) { 78 | this.sections = sections; 79 | } 80 | 81 | public ArrayList getPrApprovers() { 82 | return prApprovers; 83 | } 84 | 85 | public void setPrApprovers(ArrayList prApprovers) { 86 | this.prApprovers = prApprovers; 87 | } 88 | 89 | public boolean isPushPrOnSuccess() { 90 | return pushPrOnSuccess; 91 | } 92 | 93 | public void setPushPrOnSuccess(boolean pushPrOnSuccess) { 94 | this.pushPrOnSuccess = pushPrOnSuccess; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Credential.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | public class Credential { 4 | private String credentialId; 5 | private String variable; 6 | 7 | public String getCredentialId() { 8 | return credentialId; 9 | } 10 | 11 | public void setCredentialId(String credentialId) { 12 | this.credentialId = credentialId; 13 | } 14 | 15 | public String getVariable() { 16 | return variable; 17 | } 18 | 19 | public void setVariable(String variable) { 20 | this.variable = variable; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/CustomPipelineSection.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import javax.annotation.CheckForNull; 4 | 5 | /** 6 | * @author Oleg Nenashev 7 | */ 8 | public class CustomPipelineSection { 9 | private String name; 10 | @CheckForNull 11 | private Object data; 12 | 13 | public void setName(String name) { 14 | this.name = name; 15 | } 16 | 17 | public void setData(Object data) { 18 | this.data = data; 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | @CheckForNull 26 | public Object getData() { 27 | return data; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Environment.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | public class Environment { 7 | private ArrayList credentials; 8 | private HashMap variables; 9 | 10 | public ArrayList getCredentials() { 11 | return credentials; 12 | } 13 | 14 | public void setCredentials(ArrayList credentials) { 15 | this.credentials = credentials; 16 | } 17 | 18 | public HashMap getVariables() { 19 | return variables; 20 | } 21 | 22 | public void setVariables(HashMap variables) { 23 | this.variables = variables; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Post.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedHashMap; 5 | 6 | public class Post { 7 | private ArrayList> always; 8 | private ArrayList> changed; 9 | private ArrayList> fixed; 10 | private ArrayList> regression; 11 | private ArrayList> aborted; 12 | private ArrayList> failure; 13 | private ArrayList> success; 14 | private ArrayList> unstable; 15 | private ArrayList> cleanup; 16 | 17 | public ArrayList> getAborted() { 18 | return aborted; 19 | } 20 | 21 | public void setAborted(ArrayList> aborted) { 22 | this.aborted = Stage.generateSteps(aborted); 23 | } 24 | 25 | public ArrayList> getAlways() { 26 | return always; 27 | } 28 | 29 | public void setAlways(ArrayList> always) { 30 | this.always = Stage.generateSteps(always); 31 | } 32 | 33 | public ArrayList> getChanged() { 34 | return changed; 35 | } 36 | 37 | public void setChanged(ArrayList> changed) { 38 | this.changed = Stage.generateSteps(changed); 39 | } 40 | 41 | public ArrayList> getCleanup() { 42 | return cleanup; 43 | } 44 | 45 | 46 | public void setCleanup(ArrayList> cleanup) { 47 | this.cleanup = Stage.generateSteps(cleanup); 48 | } 49 | 50 | public ArrayList> getFailure() { 51 | return failure; 52 | } 53 | 54 | public void setFailure(ArrayList> failure) { 55 | this.failure = Stage.generateSteps(failure); 56 | } 57 | 58 | public ArrayList> getFixed() { 59 | return fixed; 60 | } 61 | 62 | public void setFixed(ArrayList> fixed) { 63 | this.fixed = Stage.generateSteps(fixed); 64 | } 65 | 66 | public ArrayList> getRegression() { 67 | return regression; 68 | } 69 | 70 | public void setRegression(ArrayList> regression) { 71 | this.regression = Stage.generateSteps(regression); 72 | } 73 | 74 | public ArrayList> getSuccess() { 75 | return success; 76 | } 77 | 78 | public void setSuccess(ArrayList> success) { 79 | this.success = Stage.generateSteps(success); 80 | } 81 | 82 | public ArrayList> getUnstable() { 83 | return unstable; 84 | } 85 | 86 | public void setUnstable(ArrayList> unstable) { 87 | this.unstable = Stage.generateSteps(unstable); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/ReportsAndArtifactsInfo.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | public class ReportsAndArtifactsInfo { 7 | 8 | private ArrayList reports; 9 | private ArtifactPublishingConfig artifactPublishingConfig; 10 | private ArrayList> publishArtifacts; 11 | 12 | public ArrayList> getPublishArtifacts() { 13 | return publishArtifacts; 14 | } 15 | 16 | public void setPublishArtifacts(ArrayList> publishArtifacts) { 17 | this.publishArtifacts = publishArtifacts; 18 | } 19 | 20 | public ArrayList getReports() { 21 | return reports; 22 | } 23 | 24 | public void setReports(ArrayList reports) { 25 | this.reports = reports; 26 | } 27 | 28 | public ArtifactPublishingConfig getArtifactPublishingConfig() { 29 | return artifactPublishingConfig; 30 | } 31 | 32 | public void setArtifactPublishingConfig(ArtifactPublishingConfig config) { 33 | this.artifactPublishingConfig = config; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Stage.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import javax.annotation.CheckForNull; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | 9 | public class Stage { 10 | private String name; 11 | @CheckForNull 12 | private Agent agent; 13 | private ArrayList> steps; 14 | private Post post; 15 | 16 | public Stage() { 17 | } 18 | 19 | static ArrayList> generateSteps(ArrayList> stepsList) { 20 | ArrayList> generatedSteps = new ArrayList<>(); 21 | for (LinkedHashMap yamlStepObj : stepsList) { 22 | LinkedHashMap stepObj = new LinkedHashMap<>(); 23 | Step step = new Step(); 24 | 25 | // Below for loop will run only once as it will have only one step 26 | for (Map.Entry entry : yamlStepObj.entrySet()) { 27 | step.setStepName(entry.getKey()); 28 | if (entry.getValue().getClass() == LinkedHashMap.class) { 29 | step.setParameters((HashMap) entry.getValue()); 30 | } else { 31 | step.setDefaultParameter(entry.getValue()); 32 | } 33 | } 34 | 35 | stepObj.put(step.getStepName(), step); 36 | generatedSteps.add(stepObj); 37 | } 38 | 39 | return generatedSteps; 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public void setName(String name) { 47 | this.name = name; 48 | } 49 | 50 | public Post getPost() { 51 | return post; 52 | } 53 | 54 | public void setPost(Post post) { 55 | this.post = post; 56 | } 57 | 58 | public ArrayList> getSteps() { 59 | return steps; 60 | } 61 | 62 | public void setSteps(ArrayList> stepsList) { 63 | this.steps = generateSteps(stepsList); 64 | } 65 | 66 | @CheckForNull 67 | public Agent getAgent() { 68 | return agent; 69 | } 70 | 71 | public void setAgent(Agent agent) { 72 | this.agent = agent; 73 | 74 | if (this.agent.getTools() != null) { 75 | throw new IllegalStateException("\"tools\" is not allowed inside a stage agent."); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/Step.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import javax.annotation.Nonnull; 4 | import java.util.HashMap; 5 | 6 | public class Step { 7 | @Nonnull 8 | private String stepName; 9 | private Object defaultParameter; 10 | private HashMap parameters; 11 | 12 | public Step() { 13 | stepName = ""; 14 | } 15 | 16 | @Nonnull 17 | public String getStepName() { 18 | return stepName; 19 | } 20 | 21 | public void setStepName(@Nonnull String stepName) { 22 | this.stepName = stepName; 23 | } 24 | 25 | public HashMap getParameters() { 26 | return parameters; 27 | } 28 | 29 | public void setParameters(HashMap parameters) { 30 | this.parameters = parameters; 31 | } 32 | 33 | public Object getDefaultParameter() { 34 | return defaultParameter; 35 | } 36 | 37 | public void setDefaultParameter(Object defaultParameter) { 38 | this.defaultParameter = defaultParameter; 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/io/jenkins/plugins/sprp/models/YamlPipeline.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.models; 2 | 3 | import javax.annotation.Nonnull; 4 | import java.util.*; 5 | 6 | public class YamlPipeline { 7 | private Agent agent; 8 | private ArrayList stages; 9 | private Post post; 10 | private ArrayList> steps; 11 | private Configuration configuration; 12 | private Environment environment; 13 | 14 | public YamlPipeline() { 15 | } 16 | 17 | public Agent getAgent() { 18 | return agent; 19 | } 20 | 21 | public void setAgent(Agent agent) { 22 | this.agent = agent; 23 | } 24 | 25 | public Configuration getConfiguration() { 26 | return configuration; 27 | } 28 | 29 | public void setConfiguration(Configuration configuration) { 30 | this.configuration = configuration; 31 | } 32 | 33 | public String getGitCredentialId() { 34 | return configuration.getGitCredentialId(); 35 | } 36 | 37 | public ArtifactPublishingConfig getArtifactPublishingConfig() { 38 | return configuration.getArtifactPublishingConfig(); 39 | } 40 | 41 | public ArrayList> getPublishArtifacts() { 42 | return configuration.getPublishArtifacts(); 43 | } 44 | 45 | public ArrayList getArchiveArtifacts() { 46 | return configuration.getArchiveArtifacts(); 47 | } 48 | 49 | public ArrayList getStages() { 50 | return stages; 51 | } 52 | 53 | public void setStages(ArrayList passedStages) { 54 | this.stages = passedStages; 55 | } 56 | 57 | public ArrayList getReports() { 58 | return configuration.getReports(); 59 | } 60 | 61 | public String getFindBugs() { 62 | return configuration.getFindBugs(); 63 | } 64 | 65 | public Environment getEnvironment() { 66 | return environment; 67 | } 68 | 69 | public void setEnvironment(Environment environment) { 70 | this.environment = environment; 71 | } 72 | 73 | public Post getPost() { 74 | return post; 75 | } 76 | 77 | public void setPost(Post post) { 78 | this.post = post; 79 | } 80 | 81 | public ArrayList> getSteps() { 82 | return steps; 83 | } 84 | 85 | public void setSteps(ArrayList> steps) { 86 | this.steps = Stage.generateSteps(steps); 87 | } 88 | 89 | @Nonnull 90 | public List getSections() { 91 | return configuration != null ? configuration.getSections() : Collections.emptyList(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | TODO 4 |
5 | -------------------------------------------------------------------------------- /src/main/resources/io/jenkins/plugins/sprp/Messages.properties: -------------------------------------------------------------------------------- 1 | YAML_FlowDefinition.DescriptorImpl.DisplayName=YAML configuration for multibranch pipeline -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/FullPipelineGenerationTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp; 2 | 3 | import io.jenkins.plugins.sprp.exception.ConversionException; 4 | import org.apache.tools.ant.filters.StringInputStream; 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.jvnet.hudson.test.JenkinsRule; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class FullPipelineGenerationTest { 12 | @Rule 13 | public JenkinsRule jenkinsRule = new JenkinsRule(); 14 | 15 | @Test 16 | public void test1() throws ConversionException { 17 | String yamlPipeline = 18 | "agent:\n" + 19 | " label: my_label\n" + 20 | "\n" + 21 | " tools:\n" + 22 | " maven : maven_3.0.1\n" + 23 | " jdk : jdk8\n" + 24 | "\n" + 25 | "configuration:\n" + 26 | " pushPrOnSuccess: false\n" + 27 | "\n" + 28 | " prApprovers:\n" + 29 | " - username1\n" + 30 | " - username2\n" + 31 | " - username3\n" + 32 | "\n" + 33 | " reports:\n" + 34 | " - location_of_report_1\n" + 35 | " - location_of_report_2\n" + 36 | "\n" + 37 | "environment:\n" + 38 | " variables:\n" + 39 | " variable_1: value_1\n" + 40 | " variable_2: value_2\n" + 41 | "\n" + 42 | " credentials:\n" + 43 | " - credentialId : fileCredentialId\n" + 44 | " variable : FILE\n" + 45 | "\n" + 46 | " - credentialId : dummyGitRepo\n" + 47 | " variable : LOGIN\n" + 48 | "\n" + 49 | "stages:\n" + 50 | " - name: satge1\n" + 51 | " agent: any\n" + 52 | " steps:\n" + 53 | " - sh:\n" + 54 | " script: \"scripts/hello\"\n" + 55 | " - sh: \"scripts/hello\"\n" + 56 | " - sleep:\n" + 57 | " time: 2\n" + 58 | " - sleep: 2\n" + 59 | "\n" + 60 | "\n" + 61 | " post:\n" + 62 | " failure:\n" + 63 | " - sh: \"scripts/hello\"\n" + 64 | "post:\n" + 65 | " always:\n" + 66 | " - sh: \"scripts/hello\""; 67 | 68 | YamlToPipeline yamlToPipeline = new YamlToPipeline(); 69 | 70 | StringInputStream inputStream = new StringInputStream(yamlPipeline); 71 | 72 | String actualPipeline = yamlToPipeline.generatePipeline(inputStream,null, jenkinsRule.createTaskListener()); 73 | 74 | String expectedPipeline = 75 | "pipeline {\n" + 76 | "\tagent {\n" + 77 | "\t\tnode {\n" + 78 | "\t\t\tlabel 'my_label'\n" + 79 | "\t\t}\n" + 80 | "\t}\n" + 81 | "\ttools {\n" + 82 | "\t\tmaven 'maven_3.0.1'\n" + 83 | "\t\tjdk 'jdk8'\n" + 84 | "\t}\n" + 85 | "\tenvironment {\n" + 86 | "\t\tvariable_1 = 'value_1'\n" + 87 | "\t\tvariable_2 = 'value_2'\n" + 88 | "\t\tFILE = credentials('fileCredentialId')\n" + 89 | "\t\tLOGIN = credentials('dummyGitRepo')\n" + 90 | "\t}\n" + 91 | "\tstages {\n" + 92 | "\t\tstage('satge1') {\n" + 93 | "\t\t\tsteps {\n" + 94 | "\t\t\t\tsh 'scripts/hello'\n" + 95 | "\t\t\t\tsh 'scripts/hello'\n" + 96 | "\t\t\t\tsleep 2\n" + 97 | "\t\t\t\tsleep 2\n" + 98 | "\t\t\t}\n" + 99 | "\t\t\tpost {\n" + 100 | "\t\t\t\tfailure {\n" + 101 | "\t\t\t\t\tsh 'scripts/hello'\n" + 102 | "\t\t\t\t}\n" + 103 | "\t\t\t}\n" + 104 | "\t\t}\n" + 105 | "\t\tstage('Publish reports & artifacts') {\n" + 106 | "\t\t\tsteps {\n" + 107 | "\t\t\t\tjunit 'location_of_report_1'\n" + 108 | "\t\t\t\tjunit 'location_of_report_2'\n" + 109 | "\t\t\t}\n" + 110 | "\t\t}\n" + 111 | "\t}\n" + 112 | "\tpost {\n" + 113 | "\t\talways {\n" + 114 | "\t\t\tsh 'scripts/hello'\n" + 115 | "\t\t}\n" + 116 | "\t}\n" + 117 | "}\n"; 118 | 119 | assertEquals(expectedPipeline, actualPipeline); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/YamlToPipelineTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp; 2 | 3 | import io.jenkins.plugins.sprp.exception.ConversionException; 4 | import io.jenkins.plugins.sprp.git.GitConfig; 5 | import org.apache.tools.ant.filters.StringInputStream; 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | import org.jvnet.hudson.test.JenkinsRule; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | public class YamlToPipelineTest { 13 | @Rule 14 | public JenkinsRule jenkinsRule = new JenkinsRule(); 15 | 16 | @Test 17 | public void yamlToPipelineTest() throws ConversionException { 18 | String yaml = "agent: any\n" + 19 | "\n" + 20 | "stages:\n" + 21 | " - name: stage1\n" + 22 | " agent: any\n" + 23 | " steps:\n" + 24 | " - sh: \"scripts/hello.sh\"\n" + 25 | " - sh:\n" + 26 | " script: \"scripts/hello.sh\"" + 27 | "\n" + 28 | "configuration:\n" + 29 | " archiveArtifacts:\n" + 30 | " - Jenkinsfile.yaml\n" + 31 | " - scripts/hello.sh\n" + 32 | "\n"; 33 | 34 | String pipelineScriptLinuxExpected = "pipeline {\n" + 35 | "\tagent any\n" + 36 | "\tstages {\n" + 37 | "\t\tstage('stage1') {\n" + 38 | "\t\t\tsteps {\n" + 39 | "\t\t\t\tsh 'scripts/hello.sh'\n" + 40 | "\t\t\t\tsh 'scripts/hello.sh'\n" + 41 | "\t\t\t}\n" + 42 | "\t\t}\n" + 43 | "\t\tstage('Archive artifacts') {\n" + 44 | "\t\t\tsteps {\n" + 45 | "\t\t\t\tarchiveArtifacts artifacts: 'Jenkinsfile.yaml'\n" + 46 | "\t\t\t\tarchiveArtifacts artifacts: 'scripts/hello.sh'\n" + 47 | "\t\t\t}\n" + 48 | "\t\t}\n" + 49 | "\t}\n" + 50 | "}\n"; 51 | 52 | StringInputStream yamlInputStream = new StringInputStream(yaml); 53 | String pipelineScriptActual = new YamlToPipeline().generatePipeline(yamlInputStream, 54 | new GitConfig(), jenkinsRule.createTaskListener()); 55 | 56 | assertEquals(pipelineScriptLinuxExpected, pipelineScriptActual); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/AgentGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.models.Agent; 5 | import org.junit.Before; 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | import org.jvnet.hudson.test.For; 9 | import org.jvnet.hudson.test.JenkinsRule; 10 | 11 | import java.util.ArrayList; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | 15 | @For(AgentGenerator.class) 16 | public class AgentGeneratorTest { 17 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 18 | @Rule 19 | public JenkinsRule jenkinsRule = new JenkinsRule(); 20 | 21 | private AgentGenerator generator; 22 | 23 | @Before 24 | public void setupGenerator() { 25 | generator = PipelineGenerator.lookupConverter(AgentGenerator.class); 26 | } 27 | @Test 28 | public void nodeGenerationLabelOnlyTest() { 29 | Agent agent = new Agent(); 30 | agent.setLabel("my-label"); 31 | 32 | String agentSnippetActual = 33 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 34 | 35 | String agentSnippetExpected = 36 | "agent {\n" + 37 | "\tnode {\n" + 38 | "\t\tlabel 'my-label'\n" + 39 | "\t}\n" + 40 | "}\n"; 41 | 42 | assertEquals(agentSnippetExpected, agentSnippetActual); 43 | } 44 | 45 | @Test 46 | public void nodeGenerationTest() { 47 | Agent agent = new Agent(); 48 | agent.setLabel("my-label"); 49 | agent.setCustomWorkspace("my-customWorkspace"); 50 | 51 | String agentSnippetActual = 52 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 53 | 54 | String agentSnippetExpected = 55 | "agent {\n" + 56 | "\tnode {\n" + 57 | "\t\tlabel 'my-label'\n" + 58 | "\t\tcustomWorkspace 'my-customWorkspace'\n" + 59 | "\t}\n" + 60 | "}\n"; 61 | 62 | assertEquals(agentSnippetExpected, agentSnippetActual); 63 | } 64 | 65 | @Test 66 | public void dockerGenerationTest() { 67 | Agent agent = new Agent(); 68 | agent.setDockerImage("my-docker-image"); 69 | agent.setArgs("-v temp:temp"); 70 | 71 | String agentSnippetActual = 72 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 73 | 74 | String agentSnippetExpected = 75 | "agent {\n" + 76 | "\tdocker {\n" + 77 | "\t\timage 'my-docker-image'\n" + 78 | "\t\targs '-v temp:temp'\n" + 79 | "\t\talwaysPull false\n" + 80 | "\t\treuseNode false\n" + 81 | "\t}\n" + 82 | "}\n"; 83 | 84 | assertEquals(agentSnippetExpected, agentSnippetActual); 85 | } 86 | 87 | @Test 88 | public void dockerGenerationTest1(){ 89 | Agent agent = new Agent(); 90 | agent.setDockerImage("my-docker-image"); 91 | agent.setArgs("-v temp:temp"); 92 | agent.setAlwaysPull(true); 93 | agent.setReuseNode(true); 94 | 95 | String agentSnippetActual = 96 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 97 | 98 | String agentSnippetExpected = 99 | "agent {\n" + 100 | "\tdocker {\n" + 101 | "\t\timage 'my-docker-image'\n" + 102 | "\t\targs '-v temp:temp'\n" + 103 | "\t\talwaysPull true\n" + 104 | "\t\treuseNode true\n" + 105 | "\t}\n" + 106 | "}\n"; 107 | 108 | assertEquals(agentSnippetExpected, agentSnippetActual); 109 | } 110 | 111 | @Test 112 | public void dockerGenerationTest2(){ 113 | Agent agent = new Agent(); 114 | agent.setDockerImage("my-docker-image"); 115 | agent.setArgs("-v temp:temp"); 116 | agent.setAlwaysPull(false); 117 | agent.setReuseNode(false); 118 | 119 | String agentSnippetActual = 120 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 121 | 122 | String agentSnippetExpected = 123 | "agent {\n" + 124 | "\tdocker {\n" + 125 | "\t\timage 'my-docker-image'\n" + 126 | "\t\targs '-v temp:temp'\n" + 127 | "\t\talwaysPull false\n" + 128 | "\t\treuseNode false\n" + 129 | "\t}\n" + 130 | "}\n"; 131 | 132 | assertEquals(agentSnippetExpected, agentSnippetActual); 133 | } 134 | 135 | @Test 136 | public void dockerfileGenerationTest() { 137 | Agent agent = new Agent(); 138 | agent.setDockerfile("my-dockerfile"); 139 | agent.setArgs("-v temp:temp"); 140 | 141 | String agentSnippetActual = 142 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 143 | 144 | String agentSnippetExpected = 145 | "agent {\n" + 146 | "\tdockerfile {\n" + 147 | "\t\tfilename 'my-dockerfile'\n" + 148 | "\t\tadditionalBuildArgs '-v temp:temp'\n" + 149 | "\t\treuseNode false\n" + 150 | "\t}\n" + 151 | "}\n"; 152 | 153 | assertEquals(agentSnippetExpected, agentSnippetActual); 154 | } 155 | 156 | @Test 157 | public void dockerfileGenerationTest2() { 158 | Agent agent = new Agent(); 159 | agent.setDockerfile("my-dockerfile"); 160 | agent.setArgs("-v temp:temp"); 161 | agent.setLabel("my-label"); 162 | agent.setCustomWorkspace("my-customWorkspace"); 163 | agent.setDir("dir-path"); 164 | agent.setReuseNode(true); 165 | 166 | String agentSnippetActual = 167 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 168 | 169 | String agentSnippetExpected = 170 | "agent {\n" + 171 | "\tdockerfile {\n" + 172 | "\t\tfilename 'my-dockerfile'\n" + 173 | "\t\tdir 'dir-path'\n" + 174 | "\t\tadditionalBuildArgs '-v temp:temp'\n" + 175 | "\t\tlabel 'my-label'\n" + 176 | "\t\tcustomWorkspace 'my-customWorkspace'\n" + 177 | "\t\treuseNode true\n" + 178 | "\t}\n" + 179 | "}\n"; 180 | 181 | assertEquals(agentSnippetExpected, agentSnippetActual); 182 | } 183 | 184 | @Test 185 | public void dockerfileGenerationTest3() { 186 | Agent agent = new Agent(); 187 | agent.setDockerfile("my-dockerfile"); 188 | agent.setArgs("-v temp:temp"); 189 | agent.setLabel("my-label"); 190 | agent.setCustomWorkspace("my-customWorkspace"); 191 | agent.setDir("dir-path"); 192 | agent.setReuseNode(false); 193 | 194 | String agentSnippetActual = 195 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(agent)); 196 | 197 | String agentSnippetExpected = 198 | "agent {\n" + 199 | "\tdockerfile {\n" + 200 | "\t\tfilename 'my-dockerfile'\n" + 201 | "\t\tdir 'dir-path'\n" + 202 | "\t\tadditionalBuildArgs '-v temp:temp'\n" + 203 | "\t\tlabel 'my-label'\n" + 204 | "\t\tcustomWorkspace 'my-customWorkspace'\n" + 205 | "\t\treuseNode false\n" + 206 | "\t}\n" + 207 | "}\n"; 208 | 209 | assertEquals(agentSnippetExpected, agentSnippetActual); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/ArchiveArtifactStageGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import org.junit.Before; 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.jvnet.hudson.test.For; 8 | import org.jvnet.hudson.test.JenkinsRule; 9 | 10 | import java.util.ArrayList; 11 | 12 | import static org.junit.Assert.assertEquals; 13 | 14 | @For(ArchiveArtifactStageGenerator.class) 15 | public class ArchiveArtifactStageGeneratorTest { 16 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 17 | @Rule 18 | public JenkinsRule jenkinsRule = new JenkinsRule(); 19 | 20 | private ArchiveArtifactStageGenerator generator; 21 | 22 | @Before 23 | public void setupGenerator() { 24 | generator = PipelineGenerator.lookupConverter(ArchiveArtifactStageGenerator.class); 25 | } 26 | 27 | @Test 28 | public void echo() { 29 | ArrayList archiveArtifacts = new ArrayList<>(); 30 | 31 | archiveArtifacts.add("path-to-archive-1"); 32 | archiveArtifacts.add("path-to-archive-2"); 33 | archiveArtifacts.add("path-to-archive-3"); 34 | 35 | String pipelineStepActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(archiveArtifacts)); 36 | String pipelineStepExpected = 37 | "stage('Archive artifacts') {\n" + 38 | "\tsteps {\n" + 39 | "\t\tarchiveArtifacts artifacts: 'path-to-archive-1'\n" + 40 | "\t\tarchiveArtifacts artifacts: 'path-to-archive-2'\n" + 41 | "\t\tarchiveArtifacts artifacts: 'path-to-archive-3'\n" + 42 | "\t}\n" + 43 | "}\n"; 44 | 45 | assertEquals(pipelineStepExpected, pipelineStepActual); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/CustomSectionGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.YamlToPipeline; 6 | import org.apache.tools.ant.filters.StringInputStream; 7 | import org.hamcrest.CoreMatchers; 8 | import org.jenkinsci.Symbol; 9 | import org.junit.Assert; 10 | import org.junit.Rule; 11 | import org.junit.Test; 12 | import org.jvnet.hudson.test.For; 13 | import org.jvnet.hudson.test.JenkinsRule; 14 | import org.jvnet.hudson.test.TestExtension; 15 | 16 | import javax.annotation.CheckForNull; 17 | import javax.annotation.Nonnull; 18 | import java.util.Collections; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | 22 | /** 23 | * @author Oleg Nenashev 24 | */ 25 | @For(CustomSectionGenerator.class) 26 | public class CustomSectionGeneratorTest { 27 | 28 | @Rule 29 | public JenkinsRule j = new JenkinsRule(); 30 | 31 | @Test 32 | public void checkCustomSection() throws Exception { 33 | String yaml = "agent: any\n" + 34 | "\n" + 35 | "stages:\n" + 36 | " - name: stage1\n" + 37 | " agent: any\n" + 38 | " steps:\n" + 39 | " - sh: \"scripts/hello.sh\"\n" + 40 | "\n" + 41 | "configuration:\n" + 42 | " sections:\n" + 43 | " - name: foo\n" + 44 | " data:\n" + 45 | " field1: hello\n" + 46 | " field2: world\n" + 47 | "\n"; 48 | 49 | StringInputStream yamlInputStream = new StringInputStream(yaml); 50 | String generatedPipeline = new YamlToPipeline().generatePipeline(yamlInputStream, null, 51 | j.createTaskListener()); 52 | Assert.assertThat(generatedPipeline, CoreMatchers.containsString("foo('hello','world')")); 53 | } 54 | 55 | @TestExtension 56 | @Symbol("foo") 57 | public static class FooGenerator extends PipelineGenerator { 58 | 59 | @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") 60 | @Nonnull 61 | @Override 62 | public List toPipeline(@CheckForNull Object object) throws ConversionException { 63 | if (object == null) { 64 | throw new ConversionException("No data"); 65 | } 66 | HashMap data = (HashMap)object; 67 | return Collections.singletonList("foo('" + data.get("field1") +"','" + data.get("field2") + "')"); 68 | } 69 | 70 | @Override 71 | public boolean canConvert(@Nonnull Object object) { 72 | return true; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/EnvironmentGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.models.Credential; 5 | import io.jenkins.plugins.sprp.models.Environment; 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.jvnet.hudson.test.For; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | 15 | import static org.junit.Assert.assertEquals; 16 | 17 | @For(EnvironmentGenerator.class) 18 | public class EnvironmentGeneratorTest { 19 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 20 | @Rule 21 | public JenkinsRule jenkinsRule = new JenkinsRule(); 22 | 23 | private EnvironmentGenerator generator; 24 | 25 | @Before 26 | public void setupGenerator() { 27 | generator = PipelineGenerator.lookupConverter(EnvironmentGenerator.class); 28 | } 29 | 30 | @Test 31 | public void env() { 32 | HashMap variables = new HashMap<>(); 33 | variables.put("JAVA_HOME", "/pathToJavaHome/dir1/dir2"); 34 | variables.put("MAVEN_HOME", "/pathToMavenHome/dir1/dir2"); 35 | 36 | ArrayList credentials = new ArrayList<>(); 37 | 38 | Credential credential1 = new Credential(); 39 | 40 | credential1.setCredentialId("fileCredentialId"); 41 | credential1.setVariable("FILE"); 42 | 43 | credentials.add(credential1); 44 | 45 | Credential credential2 = new Credential(); 46 | 47 | credential2.setCredentialId("usernameAndPasswordCredentialId"); 48 | credential2.setVariable("LOGIN"); 49 | 50 | credentials.add(credential2); 51 | 52 | Environment environment = new Environment(); 53 | environment.setVariables(variables); 54 | environment.setCredentials(credentials); 55 | 56 | String agentSnippetActual = 57 | PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(environment)); 58 | 59 | String agentSnippetExpected = 60 | "environment {\n" + 61 | "\tMAVEN_HOME = '/pathToMavenHome/dir1/dir2'\n" + 62 | "\tJAVA_HOME = '/pathToJavaHome/dir1/dir2'\n" + 63 | "\tFILE = credentials('fileCredentialId')\n" + 64 | "\tLOGIN = credentials('usernameAndPasswordCredentialId')\n" + 65 | "}\n"; 66 | 67 | assertEquals(agentSnippetExpected, agentSnippetActual); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/GitPushStageGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.git.GitConfig; 5 | import org.junit.Before; 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | import org.jvnet.hudson.test.For; 9 | import org.jvnet.hudson.test.JenkinsRule; 10 | 11 | import java.util.ArrayList; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | 15 | @For(GitPushStageGenerator.class) 16 | public class GitPushStageGeneratorTest { 17 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 18 | @Rule 19 | public JenkinsRule jenkinsRule = new JenkinsRule(); 20 | 21 | private GitPushStageGenerator generator; 22 | 23 | @Before 24 | public void setupGenerator() { 25 | generator = PipelineGenerator.lookupConverter(GitPushStageGenerator.class); 26 | } 27 | 28 | @Test 29 | public void gitPushStage() { 30 | GitConfig gitConfig = new GitConfig(); 31 | gitConfig.setGitBranch("branchName"); 32 | gitConfig.setCredentialsId("gitCredentialId"); 33 | gitConfig.setGitUrl("gitRepoUrl"); 34 | 35 | String pipelineStepActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(gitConfig)); 36 | String pipelineStepExpected = 37 | "stage('Git Push') {\n" + 38 | "\tsteps {\n" + 39 | "\t\tgitPush credentialId: \"gitCredentialId\",url: \"gitRepoUrl\",branch: \"branchName\"\n" + 40 | "\t}\n" + 41 | "}\n"; 42 | 43 | assertEquals(pipelineStepExpected, pipelineStepActual); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/PostGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.models.Post; 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.jvnet.hudson.test.For; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | import org.yaml.snakeyaml.Yaml; 12 | 13 | import java.util.ArrayList; 14 | 15 | import static org.junit.Assert.assertEquals; 16 | 17 | @For(PostGenerator.class) 18 | public class PostGeneratorTest { 19 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 20 | @Rule 21 | public JenkinsRule jenkinsRule = new JenkinsRule(); 22 | 23 | private PostGenerator generator; 24 | 25 | @Before 26 | public void setupGenerator() { 27 | generator = PipelineGenerator.lookupConverter(PostGenerator.class); 28 | } 29 | 30 | @Test 31 | public void echo() throws ConversionException { 32 | String postYaml = 33 | "always:\n" + 34 | " - sh: \"always.sh\"\n" + 35 | "changed:\n" + 36 | " - sh: \"changed.sh\"\n" + 37 | "fixed:\n" + 38 | " - sh: \"fixed.sh\"\n" + 39 | "regression:\n" + 40 | " - sh: \"regression.sh\"\n" + 41 | "aborted:\n" + 42 | " - sh: \"aborted.sh\"\n" + 43 | "failure:\n" + 44 | " - sh: \"failure.sh\"\n" + 45 | "success:\n" + 46 | " - sh: \"success.sh\"\n" + 47 | "unstable:\n" + 48 | " - sh: \"unstable.sh\"\n" + 49 | "cleanup:\n" + 50 | " - sh: \"cleanup.sh\"\n"; 51 | 52 | Yaml yaml = new Yaml(); 53 | Post postSection = yaml.loadAs(postYaml, Post.class); 54 | 55 | String pipelineStepActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(postSection)); 56 | String pipelineStepExpected = 57 | "post {\n" + 58 | "\talways {\n" + 59 | "\t\tsh 'always.sh'\n" + 60 | "\t}\n" + 61 | "\tchanged {\n" + 62 | "\t\tsh 'changed.sh'\n" + 63 | "\t}\n" + 64 | "\tfixed {\n" + 65 | "\t\tsh 'fixed.sh'\n" + 66 | "\t}\n" + 67 | "\tregression {\n" + 68 | "\t\tsh 'regression.sh'\n" + 69 | "\t}\n" + 70 | "\taborted {\n" + 71 | "\t\tsh 'aborted.sh'\n" + 72 | "\t}\n" + 73 | "\tfailure {\n" + 74 | "\t\tsh 'failure.sh'\n" + 75 | "\t}\n" + 76 | "\tsuccess {\n" + 77 | "\t\tsh 'success.sh'\n" + 78 | "\t}\n" + 79 | "\tunstable {\n" + 80 | "\t\tsh 'unstable.sh'\n" + 81 | "\t}\n" + 82 | "\tcleanup {\n" + 83 | "\t\tsh 'cleanup.sh'\n" + 84 | "\t}\n" + 85 | "}\n"; 86 | 87 | assertEquals(pipelineStepExpected, pipelineStepActual); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/PublishReportsAndArtifactsStageGenaratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.models.ArtifactPublishingConfig; 5 | import io.jenkins.plugins.sprp.models.ReportsAndArtifactsInfo; 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.jvnet.hudson.test.For; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | 15 | import static org.junit.Assert.assertEquals; 16 | 17 | @For(PublishReportsAndArtifactsStageGenerator.class) 18 | public class PublishReportsAndArtifactsStageGenaratorTest { 19 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 20 | @Rule 21 | public JenkinsRule jenkinsRule = new JenkinsRule(); 22 | 23 | private PublishReportsAndArtifactsStageGenerator generator; 24 | 25 | @Before 26 | public void setupGenerator() { 27 | generator = PipelineGenerator.lookupConverter(PublishReportsAndArtifactsStageGenerator.class); 28 | } 29 | 30 | @Test 31 | public void test1() { 32 | ReportsAndArtifactsInfo reportsAndArtifactsInfo = new ReportsAndArtifactsInfo(); 33 | 34 | ArrayList reports = new ArrayList<>(); 35 | reports.add("location-of-report-1"); 36 | reports.add("location-of-report-2"); 37 | 38 | ArtifactPublishingConfig artifactPublishingConfig = new ArtifactPublishingConfig(); 39 | artifactPublishingConfig.setCredentialId("credentialId"); 40 | artifactPublishingConfig.setHost("123.123.123.123"); 41 | artifactPublishingConfig.setUser("username"); 42 | 43 | ArrayList> artifactsToArchive = new ArrayList<>(); 44 | 45 | HashMap singleArtifactToArchive1 = new HashMap<>(); 46 | singleArtifactToArchive1.put("from", "from-path-1"); 47 | singleArtifactToArchive1.put("to", "to-path-1"); 48 | 49 | artifactsToArchive.add(singleArtifactToArchive1); 50 | 51 | HashMap singleArtifactToArchive2 = new HashMap<>(); 52 | singleArtifactToArchive2.put("from", "from-path-2"); 53 | singleArtifactToArchive2.put("to", "to-path-2"); 54 | artifactsToArchive.add(singleArtifactToArchive2); 55 | 56 | 57 | reportsAndArtifactsInfo.setReports(reports); 58 | reportsAndArtifactsInfo.setArtifactPublishingConfig(artifactPublishingConfig); 59 | reportsAndArtifactsInfo.setPublishArtifacts(artifactsToArchive); 60 | 61 | String pipelineStageActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(reportsAndArtifactsInfo)); 62 | String pipelineStageExpected = 63 | "stage('Publish reports & artifacts') {\n" + 64 | "\tsteps {\n" + 65 | "\t\tjunit 'location-of-report-1'\n" + 66 | "\t\tjunit 'location-of-report-2'\n" + 67 | "\t\twithCredentials([file(credentialsId: 'credentialId', variable: 'FILE')]) {\n" + 68 | "\t\t\tsh 'scp -i $FILE from-path-1 username@123.123.123.123:to-path-1'\n" + 69 | "\t\t\tsh 'scp -i $FILE from-path-2 username@123.123.123.123:to-path-2'\n" + 70 | "\t\t}\n" + 71 | "\t}\n" + 72 | "}\n"; 73 | 74 | assertEquals(pipelineStageExpected, pipelineStageActual); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/StageGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.models.Stage; 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.jvnet.hudson.test.For; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | import org.yaml.snakeyaml.Yaml; 12 | 13 | import java.util.ArrayList; 14 | 15 | import static org.junit.Assert.assertEquals; 16 | 17 | @For(StepGenerator.class) 18 | public class StageGeneratorTest { 19 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 20 | @Rule 21 | public JenkinsRule jenkinsRule = new JenkinsRule(); 22 | 23 | private StageGenerator generator; 24 | 25 | @Before 26 | public void setupGenerator() { 27 | generator = PipelineGenerator.lookupConverter(StageGenerator.class); 28 | } 29 | 30 | @Test 31 | public void stage() throws ConversionException { 32 | String stageYaml = 33 | "name: satge1\n" + 34 | "agent: any\n" + 35 | "steps:\n" + 36 | " - sh: \"scripts/hello\"\n" + 37 | " - sh: \"scripts/hello\"\n" + 38 | " - sh:\n" + 39 | " script: \"scripts/hello\"\n" + 40 | "post:\n" + 41 | " failure:\n" + 42 | " - sh: \"scripts/hello\""; 43 | 44 | Yaml yaml = new Yaml(); 45 | Stage stage = yaml.loadAs(stageYaml, Stage.class); 46 | 47 | String pipelineStageActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(stage)); 48 | String pipelineStageExpected = 49 | "stage('satge1') {\n" + 50 | "\tsteps {\n" + 51 | "\t\tsh 'scripts/hello'\n" + 52 | "\t\tsh 'scripts/hello'\n" + 53 | "\t\tsh 'scripts/hello'\n" + 54 | "\t}\n" + 55 | "\tpost {\n" + 56 | "\t\tfailure {\n" + 57 | "\t\t\tsh 'scripts/hello'\n" + 58 | "\t\t}\n" + 59 | "\t}\n" + 60 | "}\n"; 61 | 62 | assertEquals(pipelineStageExpected, pipelineStageActual); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/io/jenkins/plugins/sprp/generators/StepGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package io.jenkins.plugins.sprp.generators; 2 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 4 | import io.jenkins.plugins.sprp.exception.ConversionException; 5 | import io.jenkins.plugins.sprp.models.Step; 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.jvnet.hudson.test.For; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | 15 | import static org.junit.Assert.assertEquals; 16 | 17 | @For(StepGenerator.class) 18 | public class StepGeneratorTest { 19 | @SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 20 | @Rule 21 | public JenkinsRule jenkinsRule = new JenkinsRule(); 22 | 23 | private StepGenerator generator; 24 | 25 | @Before 26 | public void setupGenerator() { 27 | generator = PipelineGenerator.lookupConverter(StepGenerator.class); 28 | } 29 | 30 | @Test 31 | public void sh() throws ConversionException { 32 | Step step = new Step(); 33 | step.setStepName("sh"); 34 | step.setDefaultParameter("build.sh"); 35 | 36 | String pipelineStepActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(step)); 37 | String pipelineStepExpected = "sh 'build.sh'\n"; 38 | 39 | assertEquals(pipelineStepExpected, pipelineStepActual); 40 | } 41 | 42 | @Test 43 | public void sleep() throws ConversionException { 44 | Step step = new Step(); 45 | HashMap parameters = new HashMap<>(); 46 | 47 | step.setStepName("sleep"); 48 | 49 | parameters.put("time", 2); 50 | 51 | step.setParameters(parameters); 52 | 53 | 54 | String pipelineStepActual = PipelineGenerator.autoAddTabs((ArrayList) generator.toPipeline(step)); 55 | String pipelineStepExpected = "sleep 2\n"; 56 | 57 | assertEquals(pipelineStepExpected, pipelineStepActual); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /yamlExamples/AgentExamples.md: -------------------------------------------------------------------------------- 1 | ### Docker image example 1 2 | 3 | ```yaml 4 | agent: 5 | label: my_label 6 | customWorkspace: path_to_workspace 7 | dockerImage: maven:3-alpine 8 | args: -v /tmp:/tmp 9 | alwaysPull: false 10 | ``` 11 | 12 | ### Docker image example 2 13 | 14 | ```yaml 15 | agent: 16 | dockerImage: maven:3-alpine 17 | args: -v /tmp:/tmp 18 | alwaysPull: true 19 | ``` 20 | 21 | ### Docker file example 1 22 | 23 | ```yaml 24 | agent: 25 | label: my_label 26 | customWorkspace: path_to_workspace 27 | dockerfile: my_dockerfile 28 | args: dockerfile arguments 29 | dir: directory_location 30 | ``` 31 | 32 | ### Docker file example 2 33 | 34 | ```yaml 35 | agent: 36 | dockerfile: my_dockerfile 37 | args: dockerfile arguments 38 | ``` 39 | 40 | ### any agent example 41 | 42 | ```yaml 43 | agent: any 44 | ``` 45 | 46 | ### none agent example 47 | 48 | ```yaml 49 | agent: none 50 | ``` 51 | 52 | ### Agent with tools example 1 53 | 54 | ```yaml 55 | agent: 56 | label: my_label 57 | customWorkspace: path_to_workspace 58 | 59 | tools: 60 | maven : maven_3.0.1 61 | jdk : jdk8 62 | ``` 63 | 64 | ### Agent with tools example 2 65 | 66 | Here agent will be treated just like 'any agent example' 67 | 68 | ```yaml 69 | agent: 70 | tools: 71 | maven : maven_3.0.1 72 | jdk : jdk8 73 | ``` 74 | -------------------------------------------------------------------------------- /yamlExamples/ConfigurationExample.md: -------------------------------------------------------------------------------- 1 | ### configuration example 1 2 | 3 | ```yaml 4 | 5 | configuration: 6 | # Changes will be pushed to target branch if build and tests were successful 7 | pushPrOnSuccess: true 8 | 9 | # Trusted PR approvers 10 | prApprovers: 11 | - username1 12 | - username2 13 | - username3 14 | 15 | ``` 16 | ### configuration example 2 17 | 18 | ```yaml 19 | 20 | configuration: 21 | # Changes will not be pushed to target branch no matter what is the result of buld 22 | pushPrOnSuccess: false 23 | 24 | # Trusted PR approvers 25 | prApprovers: 26 | - username1 27 | - username2 28 | - username3 29 | 30 | ``` 31 | -------------------------------------------------------------------------------- /yamlExamples/EnvironmentExample.md: -------------------------------------------------------------------------------- 1 | ### environment example with only environment variables 2 | 3 | ```yaml 4 | environment: 5 | variables: 6 | variable_1: value_1 7 | variable_2: value_2 8 | ``` 9 | 10 | ### environment example with only credentials variables 11 | 12 | ```yaml 13 | environment: 14 | # Credentials contains only two fields. See pipeline file for how it will be used 15 | credentials: 16 | # If credentialId belongs to a secret text or secret file the the secret text or 17 | # contents of secret file will be available in $FILE environment variable 18 | - credentialId : fileCredentialId 19 | variable : FILE 20 | 21 | # If credentialId belongs to username and password type credential then 22 | # Username can be accessed by LOGIN_USR and Password can be accessed by LOGIN_PSW 23 | - credentialId : dummyGitRepo 24 | variable : LOGIN 25 | ``` 26 | 27 | ### environment example 28 | 29 | ```yaml 30 | environment: 31 | variables: 32 | variable_1: value_1 33 | variable_2: value_2 34 | 35 | # Credentials contains only two fields. See pipeline file for how it will be used 36 | credentials: 37 | - credentialId : fileCredentialId 38 | variable : FILE 39 | 40 | # Username will be accessed by LOGIN_USR and Password will be accessed by LOGIN_PSW 41 | - credentialId : dummyGitRepo 42 | variable : LOGIN 43 | ``` 44 | 45 | 46 | -------------------------------------------------------------------------------- /yamlExamples/Jenkinsfile.yaml: -------------------------------------------------------------------------------- 1 | agent: 2 | # Docket image agent example 3 | # label: my_label 4 | # customWorkspace: path_to_workspace 5 | # dockerImage: maven:3-alpine 6 | # args: -v /tmp:/tmp 7 | 8 | # tools needs to be defined in the tool configuration 9 | tools: 10 | maven : maven_3.0.1 11 | jdk : jdk8 12 | 13 | configuration: 14 | # Push PR changes to the target branch if the build will be success. 15 | # default value will be false 16 | pushPrOnSuccess: false 17 | 18 | prApprovers: 19 | - username1 20 | - username2 21 | - username3 22 | 23 | # Study about the reports type. Urgent 24 | reports: 25 | - location_of_report_1 26 | - location_of_report_2 27 | 28 | environment: 29 | variables: 30 | variable_1: value_1 31 | variable_2: value_2 32 | 33 | # Credentials contains only two fields. See pipeline file for how it will be used 34 | credentials: 35 | - credentialId : fileCredentialId 36 | variable : FILE 37 | 38 | # Username will be accessed by LOGIN_USR and Password will be accessed by LOGIN_PSW 39 | - credentialId : dummyGitRepo 40 | variable : LOGIN 41 | 42 | stages: 43 | - name: stage1 44 | agent: any 45 | steps: 46 | - sh: 47 | script: "scripts/hello" 48 | - sh: "scripts/hello" 49 | - sleep: 50 | time: 2 51 | # Configurator.lookup() in JCasc plugin returns null for java.util.concurrent.TimeUnit which is an Enum class 52 | # jira link: https://issues.jenkins-ci.org/browse/JENKINS-52443 53 | # unit: SECONDS 54 | - sleep: 2 55 | - junit: 56 | testResults: "target/**.xml" 57 | allowEmptyResults: true 58 | testDataPublishers: 59 | - AutomateTestDataPublisher 60 | - JunitResultPublisher: 61 | urlOverride: "urlOverride" 62 | # JCasc plugin having problem in configuring below class 63 | # jira link: https://issues.jenkins-ci.org/browse/JENKINS-52444 64 | 65 | # - JiraTestDataPublisher: 66 | # configs: 67 | # - SelectableFields: 68 | # fieldKey: "SelectableFields key" 69 | # value: "SelectableFields value" 70 | # 71 | # projectKey: "project key" 72 | # issueType: "issue type" 73 | # autoRaiseIssue: true 74 | 75 | 76 | post: 77 | failure: 78 | - sh: "scripts/hello" 79 | post: 80 | always: 81 | - sh: "scripts/hello" -------------------------------------------------------------------------------- /yamlExamples/MultipleStagesExample.md: -------------------------------------------------------------------------------- 1 | #### Jenkinsfile.yaml example with multiple stages 2 | 3 | ```yaml 4 | stages: 5 | - name: stage1 6 | agent: any 7 | 8 | steps: 9 | - sh: "scripts/hello" 10 | - sh: "scripts/hello" 11 | - sh: 12 | script: "scripts/hello" 13 | 14 | post: 15 | failure: 16 | - sh: "scripts/hello" 17 | 18 | 19 | - name: stage2 20 | agent: 21 | docketImage: maven:3-alpine 22 | customWorkspace: path_to_workspace 23 | 24 | steps: 25 | - echo: "Hello from stage2" 26 | 27 | post: 28 | success: 29 | echo: "stage2 was a success" 30 | post: 31 | always: 32 | - echo: "Pipeline completed" 33 | ``` 34 | 35 | We can define all other sections also 36 | 37 | ```yaml 38 | # same as defined in current version 39 | agent: 40 | label: my_label 41 | customWorkspace: path_to_workspace 42 | dockerImage: maven:3-alpine 43 | args: -v /tmp:/tmp 44 | 45 | tools: 46 | maven : maven_3.0.1 47 | jdk : jdk8 48 | 49 | configuration: 50 | pushPrOnSuccess: true 51 | 52 | prApprovers: 53 | - username1 54 | - username2 55 | 56 | reports: 57 | - location_of_report_1 58 | - location_of_report_2 59 | 60 | environment: 61 | variables: 62 | variable_1: value_1 63 | variable_2: value_2 64 | 65 | credentials: 66 | - credentialId : fileCredentialId 67 | variable : FILE 68 | 69 | - credentialId : dummyGitRepo 70 | variable : LOGIN 71 | 72 | stages: 73 | - name: stage1 74 | agent: any 75 | 76 | steps: 77 | - sh: "scripts/hello" 78 | - sh: "scripts/hello" 79 | - sh: 80 | script: "scripts/hello" 81 | 82 | post: 83 | failure: 84 | - sh: "scripts/hello" 85 | 86 | 87 | - name: stage2 88 | agent: 89 | docketImage: maven:3-alpine 90 | customWorkspace: path_to_workspace 91 | 92 | steps: 93 | - echo: "Hello from stage2" 94 | 95 | post: 96 | success: 97 | echo: "stage2 was a success" 98 | post: 99 | always: 100 | - echo: "Pipeline completed" 101 | ``` -------------------------------------------------------------------------------- /yamlExamples/Readme.md: -------------------------------------------------------------------------------- 1 | # YAML format documentation 2 | 3 | ## Sections of "Jenkinsfile.yaml" 4 | 5 | 0. agent 6 | 0. configuration 7 | 0. environment 8 | 0. steps 9 | 0. stages 10 | 0. post 11 | 12 | ## agent 13 | Agent in "Jenkinsfile.yaml" will be defined differently. We have below properties in agent 14 | 15 | 0. label 16 | 0. customWorkspace 17 | 0. dockerImage 18 | 0. alwaysPull 19 | 0. args 20 | 0. dockerfile 21 | 0. dir 22 | 0. reuseNode 23 | 0. tools 24 | 25 | All parameters are same as 26 | [Declarative pipeline agent](https://jenkins.io/doc/book/pipeline/syntax/#agent) and here we have 27 | one new parameters "dockerImage" and one parameter with different meaning "dockerfile". Also 28 | the function of "additionalBuildArgs" dockerfile agent type is served by "args" parameter only. 29 | 30 | [See agent examples](AgentExamples.md) 31 | 32 | Note: 33 | 1. dockerImage and dockerfile cannot be used simultaneously (obviously). 34 | 2. If you provide any extra parameter which will is not required like "reuseNode" without 35 | "dockerImage" or "dockerfile" parameter then it will have no effect. 36 | 37 | ## configuration 38 | This section has only two properties for now. They are: 39 | 0. **pushPrOnSuccess**: 40 | * **Type**: Boolean 41 | * **Description**: This is a boolean property with default value false. On true the plugin 42 | will push the changes to the target branch if the build is success and all tests 43 | passes else not. On the other hand on a false value no changes will not be pushed no matter what 44 | is the build result or all tests passes or not. 45 | 46 | 0. **prApprovers**: 47 | * **Type**: list of string 48 | * **Description**: This is a list of username of trusted approvers. If a user from this list approves 49 | a PR then only a build will be started else not. This function is not implemented yet. 50 | 51 | 0. **reports**: 52 | * **Type**: list of string 53 | * **Description**: List of location path can be specified here in the [Ant glob syntax](http://ant.apache.org/manual/Types/fileset.html). 54 | All these reports will be published at the end of build. 55 | * **Example** : "\*\*/build/test-reports/\*.xml" 56 | 57 | 0. **findbugs**: 58 | * **Type**: String 59 | * **Description**: Location of findbugs reports can be specified here in the 60 | [Ant glob syntax](http://ant.apache.org/manual/Types/fileset.html). 61 | These report(s) will be published at the end of build. 62 | 63 | 0. **artifactPublishingConfig**: 64 | * **Description**: This is a configuration section to publish / upload artifacts to a server. Following properties can 65 | be configured: 66 | 67 | 0. **host :** Host address to which artifacts needs to be uploaded. 68 | 0. **user :** username of the host machine. 69 | 0. **credentialId :** Credential Id of the credential having a secrete file or text that is needed 70 | to communicate with remote server. 71 | * **Example** : 72 | 73 | ```yaml 74 | artifactPublishingConfig: 75 | host: 192.32.52.12 76 | user: user53 77 | credentialId: SecretFileCredentialId 78 | ``` 79 | 80 | * **Note** : To indicate artifacts to be uploaded [publishArtifacts](#publishartifacts) is used. 81 | 82 | 0. **publishArtifacts**: 83 | * **Type**: List of HashMap with keys "*form*" and "*to*" 84 | * **Description**: This section enables us to specify which artifact needs to be uploaded where. 85 | * **Example** : 86 | 87 | ```yaml 88 | publishArtifacts: 89 | - from: location_artifact 90 | to: ~/upload_path_on_server 91 | 92 | - from: Jenkinsfile.yaml 93 | to: ~/archives 94 | ``` 95 | 96 | 0. **archiveArtifacts**: 97 | * **Type**: List of string 98 | * **Description**: This section enables us to provide a list of location of path in 99 | [Ant glob syntax](http://ant.apache.org/manual/Types/fileset.html) to archive them. 100 | * **Example** : 101 | 102 | ```yaml 103 | archiveArtifacts: 104 | - path_of_artifact_1 105 | - path_of_artifact_2 106 | ``` 107 | 108 | 0. **sections**: 109 | * **Type**: List of new sections implemented by different plugins. 110 | * **Description**: This plugin gives options to implement new sections for configuration to other 111 | developers as extensions. All the new sections which will be implemented 112 | by other plugins can be defined here. 113 | * **Example** : 114 | 115 | ```yaml 116 | configuration: 117 | sections: 118 | - name: foo 119 | data: 120 | field1: hello 121 | field2: world 122 | ``` 123 | 124 | Let's say foo is a new section implemented by some plugin having data as a hashmap. 125 | 126 | 127 | [See configuration examples](ConfigurationExample.md) 128 | 129 | ## environment 130 | This section has two properties: 131 | 1. **variables :** Any environment variable that user wants to use in his/her scripts can be 132 | defined here and it will be available to all the scripts at the time of build. 133 | 134 | 2. **credentials :** Any credentials (already configured in Jenkins instance) can be used in 135 | all user scripts by **credentials** property. 136 | 137 | [See environment example for more details](EnvironmentExample.md) 138 | 139 | ## stages 140 | This section is used to declare multiple stages for the pipeline. For now this section 141 | supports below properties. 142 | 143 | 0. **name :** This will be shown in pipeline dashboard as the name of stage. 144 | 0. **agent :** Separate agent can be defined for a stage. Rules to define stage level agent 145 | are same as [Declarative pipeline stage level agent](https://jenkins.io/doc/book/pipeline/syntax/#stage-level-agent-section). 146 | 0. **steps :** This enables us to write Jenkins supported steps. [See SimpleStageExample example for more details](SimpleStageExample.md) 147 | for information to how to define steps in "Jenkinsfile.yaml" 148 | 0. **post :** [Same as post](#post) 149 | 150 | ## steps 151 | If only a single stage is needs to be defined for a build the **steps** property can be used. 152 | A list of Jenkins supported steps needs to be defined in this section. 153 | 154 | 'Build' will be displayed as the name of this stage in the pipeline UI. 155 | 156 | [See SimpleStageExample example for more details](SimpleStageExample.md) 157 | 158 | ## post 159 | This section enables us to run some steps according to the result the whole build or a stage depending 160 | upon the location of the post section. This section supports all the conditions with same meaning 161 | like [here](https://jenkins.io/doc/book/pipeline/syntax/#post-conditions). 162 | 163 | #### Syntax 164 | post: 165 | : 166 | - list of steps 167 | : 168 | - list of steps 169 | 170 | #### Example of post 171 | ```yaml 172 | post: 173 | failure: 174 | - echo: "Build or stage is failed." 175 | success: 176 | - echo: "Build or stage was success." 177 | always: 178 | - echo: "I will run always." 179 | ``` -------------------------------------------------------------------------------- /yamlExamples/SimpleStageExample.md: -------------------------------------------------------------------------------- 1 | #### Jenkinsfile.yaml example with only a single simple stage 2 | 3 | If we want only a simple single stage then we can just place below code to Jenkinsfile.yaml 4 | and specify list of steps according to us. "Build" will be displayed as the name of this 5 | stage in Jenkins instance. 6 | 7 | ```yaml 8 | agent: any 9 | 10 | steps: 11 | - sh: "scripts/hello" 12 | - sh: "scripts/hello" 13 | - sh: 14 | script: "scripts/hello" 15 | 16 | ``` 17 | 18 | We still have option to define more sections like "configuration" 19 | "environment", "post", etc. 20 | 21 | ```yaml 22 | agent: any 23 | 24 | configuration: 25 | pushPrOnSuccess: true 26 | 27 | environment: 28 | variables: 29 | variable_1: value_1 30 | variable_2: value_2 31 | 32 | steps: 33 | - sh: "scripts/hello" 34 | - sh: "scripts/hello" 35 | - sh: 36 | script: "scripts/hello" 37 | ``` 38 | --------------------------------------------------------------------------------