├── .github ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── pr_workflow.yml │ ├── test_and_build.yml │ └── update-gradle-wrapper.yml ├── .gitignore ├── CHANGELOG.md ├── Dojofile ├── LICENSE ├── README.md ├── build.gradle ├── config_repo_id.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── src ├── main │ ├── java │ │ └── cd │ │ │ └── go │ │ │ └── plugin │ │ │ └── config │ │ │ └── yaml │ │ │ ├── AntDirectoryScanner.java │ │ │ ├── Capabilities.java │ │ │ ├── ConfigDirectoryScanner.java │ │ │ ├── ConfigRepoMessages.java │ │ │ ├── JSONUtils.java │ │ │ ├── JsonConfigCollection.java │ │ │ ├── ParsedRequest.java │ │ │ ├── PluginError.java │ │ │ ├── PluginSettings.java │ │ │ ├── YamlConfigException.java │ │ │ ├── YamlConfigParser.java │ │ │ ├── YamlConfigPlugin.java │ │ │ ├── YamlUtils.java │ │ │ ├── cli │ │ │ ├── RootCmd.java │ │ │ ├── SyntaxCmd.java │ │ │ └── YamlPluginCli.java │ │ │ └── transforms │ │ │ ├── ConfigurationTransform.java │ │ │ ├── EnvironmentVariablesTransform.java │ │ │ ├── EnvironmentsTransform.java │ │ │ ├── JobTransform.java │ │ │ ├── MaterialTransform.java │ │ │ ├── ParameterTransform.java │ │ │ ├── PipelineTransform.java │ │ │ ├── RootTransform.java │ │ │ ├── StageTransform.java │ │ │ └── TaskTransform.java │ └── resources │ │ ├── plugin-settings.template.html │ │ └── yaml.svg └── test │ ├── java │ └── cd │ │ └── go │ │ └── plugin │ │ └── config │ │ └── yaml │ │ ├── AntDirectoryScannerTest.java │ │ ├── JsonConfigCollectionTest.java │ │ ├── JsonObjectMatcher.java │ │ ├── PluginErrorTest.java │ │ ├── PluginSettingsTest.java │ │ ├── TestUtils.java │ │ ├── YamlConfigPluginIntegrationTest.java │ │ └── transforms │ │ ├── EnvironmentVariablesTransformTest.java │ │ ├── EnvironmentsTransformTest.java │ │ ├── JobTransformTest.java │ │ ├── MaterialTransformTest.java │ │ ├── ParameterTransformTest.java │ │ ├── PipelineTransformTest.java │ │ ├── RootTransformTest.java │ │ ├── StageTransformTest.java │ │ └── TaskTransformTest.java │ └── resources │ ├── examples.out │ ├── README.md │ ├── aliases.gocd.json │ ├── format-version-10.gocd.json │ ├── format-version-9.gocd.json │ ├── rich.gocd.json │ └── simple.gocd.json │ ├── examples │ ├── aliases.gocd.yaml │ ├── duplicate-materials.gocd.yaml │ ├── format-version-10.gocd.yaml │ ├── format-version-9.gocd.yaml │ ├── invalid-materials.gocd.yaml │ ├── rich.gocd.yaml │ ├── simple-invalid.gocd.yaml │ └── simple.gocd.yaml │ └── parts │ ├── display_order.pipe.json │ ├── display_order.pipe.yaml │ ├── env_vars │ ├── 1safe.json │ ├── 1safe.yaml │ ├── 2vars.json │ ├── 2vars.yaml │ ├── empty.json │ └── empty.yaml │ ├── environments │ ├── complete.json │ ├── complete.yaml │ ├── empty.json │ └── empty.yaml │ ├── export.pipe.json │ ├── export.pipe.yaml │ ├── jobs │ ├── complete.json │ ├── complete.yaml │ ├── elastic_profile.json │ ├── elastic_profile.yaml │ ├── external_artifacts.json │ ├── external_artifacts.yaml │ ├── list_of_lists_tasks.json │ ├── list_of_lists_tasks.yaml │ ├── minimal.json │ ├── minimal.yaml │ ├── minimal_defaults.json │ ├── minimal_defaults.yaml │ ├── runall.json │ └── runall.yaml │ ├── lock_behavior.pipe.json │ ├── lock_behavior.pipe.yaml │ ├── materials │ ├── auto_update.git.json │ ├── auto_update.git.yaml │ ├── branch.hg.json │ ├── branch.hg.yaml │ ├── complete10.cr.json │ ├── complete10.cr.yaml │ ├── complete10.git.json │ ├── complete10.git.yaml │ ├── complete10.hg.json │ ├── complete10.hg.yaml │ ├── complete10.p4.json │ ├── complete10.p4.yaml │ ├── complete10.pluggable.json │ ├── complete10.pluggable.yaml │ ├── complete10.scm.json │ ├── complete10.scm.yaml │ ├── complete10.svn.json │ ├── complete10.svn.yaml │ ├── complete10backwards.git.json │ ├── complete10backwards.git.yaml │ ├── complete9.git.json │ ├── complete9.git.yaml │ ├── ignore_for_scheduling.dependency.json │ ├── ignore_for_scheduling.dependency.yaml │ ├── material_without_name.git.json │ ├── minimal-explicit.git.yaml │ ├── minimal-nourl.git.yaml │ ├── minimal.cr.json │ ├── minimal.cr.yaml │ ├── minimal.git.json │ ├── minimal.git.yaml │ ├── package.json │ ├── package.yaml │ ├── password.git.json │ ├── password.git.yaml │ ├── password.hg.json │ ├── password.hg.yaml │ ├── simple.dependency.json │ └── simple.dependency.yaml │ ├── parameters │ ├── empty.json │ ├── empty.yaml │ ├── param.json │ └── param.yaml │ ├── pipeline_with_multiple_materials.json │ ├── rich.pipe.json │ ├── rich.pipe.yaml │ ├── roots │ ├── 2.yaml │ ├── common_section.yaml │ ├── duplicate.materials.pipe.yaml │ ├── empty.yaml │ ├── pipeline_order.yaml │ ├── version_1.yaml │ ├── version_2.yaml │ └── version_not_present.yaml │ ├── simple.pipe.json │ ├── simple.pipe.yaml │ ├── stage_nested_list.pipe.json │ ├── stage_nested_list.pipe.yaml │ ├── stages │ ├── complete.json │ ├── complete.yaml │ ├── complete_with_manual_approval.json │ ├── complete_with_manual_approval.yaml │ ├── short_approval.json │ ├── short_approval.yaml │ ├── stage-job.json │ └── stage-job.yaml │ ├── tasks │ ├── breakline.script.json │ ├── breakline.script.yaml │ ├── complete.fetch.json │ ├── complete.fetch.yaml │ ├── complete.plugin.json │ ├── complete.plugin.yaml │ ├── complete.rake.json │ ├── complete.rake.yaml │ ├── fetch_external_artifact.json │ ├── fetch_external_artifact.yaml │ ├── full.exec.json │ ├── full.exec.yaml │ ├── minimal.fetch.json │ ├── minimal.fetch.yaml │ ├── minimal.rake.json │ ├── minimal.rake.yaml │ ├── multiline.script.json │ ├── multiline.script.yaml │ ├── script.json │ └── script.yaml │ ├── template_ref.pipe.json │ └── template_ref.pipe.yaml └── yaml_file_pattern.png /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | PR should contain: 2 | - tests of new/changed behavior 3 | - documentation if adding new feature 4 | - added change summary in CHANGELOG.md 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: monthly 7 | groups: 8 | github-actions: 9 | patterns: 10 | - "*" 11 | - package-ecosystem: gradle 12 | directory: / 13 | schedule: 14 | interval: monthly 15 | groups: 16 | gradle-deps: 17 | patterns: 18 | - "*" 19 | 20 | -------------------------------------------------------------------------------- /.github/workflows/pr_workflow.yml: -------------------------------------------------------------------------------- 1 | name: Testing For PRs 2 | 3 | on: [ pull_request ] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | test: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Harden the runner (Audit all outbound calls) 13 | uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 14 | with: 15 | egress-policy: audit 16 | 17 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 18 | - name: Set up JDK 19 | uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 20 | with: 21 | java-version: 21 22 | distribution: temurin 23 | - name: Build with Gradle 24 | run: ./gradlew assemble check 25 | -------------------------------------------------------------------------------- /.github/workflows/test_and_build.yml: -------------------------------------------------------------------------------- 1 | name: Test and Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | workflow_dispatch: 7 | inputs: 8 | prerelease: 9 | description: 'The release should be an experimental release' 10 | default: 'NO' 11 | required: true 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Harden the runner (Audit all outbound calls) 18 | uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 19 | with: 20 | egress-policy: audit 21 | 22 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 23 | - name: Set up JDK 24 | uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 25 | with: 26 | java-version: 21 27 | distribution: temurin 28 | - name: Test with Gradle 29 | run: ./gradlew assemble check 30 | - name: Generate and submit dependency graph 31 | uses: gradle/actions/dependency-submission@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4 32 | if: github.ref == 'refs/heads/master' 33 | env: 34 | DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS: runtimeClasspath 35 | githubRelease: 36 | needs: test 37 | runs-on: ubuntu-latest 38 | env: 39 | GITHUB_USER: "tomzo" 40 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 41 | PRERELEASE: "${{ github.event.inputs.prerelease }}" 42 | steps: 43 | - name: Harden the runner (Audit all outbound calls) 44 | uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 45 | with: 46 | egress-policy: audit 47 | 48 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 49 | with: 50 | fetch-depth: 0 51 | - name: Set up JDK 52 | uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 53 | with: 54 | java-version: 21 55 | distribution: temurin 56 | - name: Build and release with Gradle 57 | run: ./gradlew githubRelease 58 | -------------------------------------------------------------------------------- /.github/workflows/update-gradle-wrapper.yml: -------------------------------------------------------------------------------- 1 | name: Update Gradle Wrapper 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 1 * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | update-gradle-wrapper: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Harden the runner (Audit all outbound calls) 14 | uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 15 | with: 16 | egress-policy: audit 17 | 18 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 19 | 20 | - name: Update Gradle Wrapper 21 | uses: gradle-update/update-gradle-wrapper-action@512b1875f3b6270828abfe77b247d5895a2da1e5 # v2.1.0 22 | with: 23 | labels: dependencies 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /token.sh 2 | /linux-amd64-github-release.tar.bz2 3 | /bin/linux/amd64/github-release 4 | /richCase/rich.gocd.yaml 5 | /simpleInvalidCase/simple-invalid.gocd.yaml 6 | /simpleCase/simple.gocd.yaml 7 | *.class 8 | 9 | # Mobile Tools for Java (J2ME) 10 | .mtj.tmp/ 11 | 12 | # Package Files # 13 | *.jar 14 | *.war 15 | *.ear 16 | 17 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 18 | hs_err_pid* 19 | /.gradle/ 20 | /.idea/ 21 | /build/ 22 | /out/ 23 | /buildSrc/build/ 24 | /buildSrc/.gradle/ 25 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 26 | !gradle-wrapper.jar 27 | 28 | docker/libs/ 29 | /docker/imagerc* 30 | /Idefile.to_be_tested 31 | /test/integration/test_ide_work/yaml-example/ 32 | src/main/resources-generated/ 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 0.14.2+ 2 | 3 | Please see the [releases page](https://github.com/tomzo/gocd-yaml-config-plugin/releases) for changelogs. 4 | 5 | ### 0.14.1 (2022-Sep-25) 6 | * Updated snakeyaml to a secure version 7 | 8 | ### 0.14.0 (2022-Jul-31) 9 | * Upgrade all dependencies to latest, patched versions 10 | 11 | ### 0.13.2 (2020-Dec-09) 12 | 13 | * use newer openjdk Dojo image kudulab/openjdk-dojo:1.4.1 14 | 15 | ### 0.13.0 (2020-Sep-11) 16 | 17 | * whitelist to includes rename, blacklist to ignore 18 | * V3 capabilities API implementation 19 | * Support `includes` in the JSON input for pipeline export. Related to: https://github.com/gocd/gocd/pull/8266 20 | * Fix for pipeline export with multiple materials without name, \#144 21 | 22 | ### 0.12.0 (2019-Oct-02) 23 | 24 | * Added support for `ignore_for_scheduling` to dependency materials. Updated README with changes in new Format Versions. 25 | * Updated library dependencies 26 | 27 | ### 0.11.2 (2019-Aug-22) 28 | 29 | * updated README documenting `allow_only_on_success` attribute for approval in stages 30 | 31 | ### 0.11.1 (2019-Aug-21) 32 | 33 | Release deleted. 34 | 35 | ### 0.11.0 (2019-Aug-02) 36 | 37 | * Adding endpoint that lists config files for the given directory 38 | 39 | ### 0.10.2 (2019-May-22) 40 | 41 | * updated README and tests to support credentials attributes in materials 42 | 43 | ### 0.10.1 (2019-May-01) 44 | 45 | * switch build system to use open source openjdk-dojo image \#17574 46 | * remove docker image from this repo, use [new image](https://github.com/gocd-contrib/docker-gocd-cli-dojo) with gocd-cli 47 | 48 | ### 0.10.0 (2019-Apr-05) 49 | 50 | * Add support for `display_order` at pipeline level \#114 51 | 52 | ### 0.9.1 (2019-Apr-05) 53 | 54 | * fixes export of external artifacts 55 | 56 | ### 0.9.0 (2019-Feb-12) 57 | 58 | * automate releases and version bump 59 | * support nested lists of stages \#95 60 | * added syntax to configure new scms \#109 61 | 62 | ### 0.8.6 (2019-Jan-21) 63 | 64 | * Changed JSON keys returned by `get-capabilities` call 65 | * Changed JSON structure returned by `parse-content` call 66 | * Implemented a new `get-icon` call that will return the icon for this plugin 67 | 68 | ### 0.8.5 (2019-Jan-15) 69 | 70 | * return json from CLI command 71 | 72 | ### 0.8.4 (2019-Jan-09) 73 | 74 | * Add export content metadata 75 | * Fix plugin settings request and implement handler for plugin config change notification 76 | 77 | ### 0.8.3 (2019-Jan-03) 78 | 79 | * Added support for `parse-content`. 80 | 81 | ### 0.8.2 (2018-Dec-12) 82 | 83 | * accept stdin input in cli tool 84 | 85 | ### 0.8.1 (2018-Nov-30) 86 | 87 | * adds CLI for syntax checking 88 | * adds docker image with the CLI to releases 89 | 90 | ### 0.8.0 (2018-Nov-09) 91 | 92 | * added inverse transforms and config-repo 2.0 API support 93 | * updated to gradle 4.10.2 94 | 95 | ### 0.7.0 (2018-Jul-09) 96 | 97 | * introduces `format_version: 3` and external fetch task 98 | 99 | ### 0.6.2 (2018-Mar-13) 100 | 101 | * fix ability to set custom file pattern per configuration repository 102 | 103 | ### 0.6.1 (2018-Feb-23) 104 | 105 | * switch to EsotericSoftware's yamlbeans 106 | 107 | ### 0.6.0 (2017-Oct-26) 108 | 109 | * adds support for referencing templates and specifying parameters 110 | * adds better support for YAML aliases 111 | * introduces format_version field, with future work for v2 format 112 | 113 | ### 0.5.0 (2017-Sep-15) 114 | 115 | * new release build tasks 116 | * added configrepo material type 117 | * added p4 material type support 118 | 119 | ### 0.4.0 (2016-Dec-16) 120 | 121 | * fixed IO error reporting 122 | * added elastic_profile_id in job 123 | 124 | ### 0.3.0 (2016-Nov-07) 125 | 126 | * added validation of duplicate keys 127 | 128 | ### 0.2.0 (2016-Oct-21) 129 | 130 | * added optional `timeout` field to job 131 | 132 | ### 0.1.0 (2016-Jul-16) 133 | 134 | Initial release. 135 | -------------------------------------------------------------------------------- /Dojofile: -------------------------------------------------------------------------------- 1 | DOJO_DOCKER_IMAGE=kudulab/openjdk-dojo:1.4.1 2 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | apply from: "https://raw.githubusercontent.com/gocd/gocd-plugin-gradle-task-helpers/master/helper.gradle?_=${(int) (new Date().toInstant().epochSecond / 60)}" 5 | 6 | gocdPlugin { 7 | id = 'yaml.config.plugin' 8 | pluginVersion = '1.0.0' 9 | goCdVersion = '22.1.0' 10 | name = 'YAML Configuration Plugin' 11 | description = 'GoCD pipelines and environments configuration in YAML' 12 | vendorName = 'Tomasz Setkowski' 13 | vendorUrl = 'https://github.com/tomzo/gocd-yaml-config-plugin' 14 | 15 | githubRepo { 16 | owner = System.getenv('GITHUB_USER') ?: 'bob' 17 | repo = 'gocd-yaml-config-plugin' 18 | token = System.getenv('GITHUB_TOKEN') ?: 'bad-token' 19 | } 20 | 21 | pluginProject = project 22 | 23 | prerelease = !"No".equalsIgnoreCase(System.getenv('PRERELEASE')) 24 | prereleaseDryrun = !"Yes".equalsIgnoreCase(System.getenv('PRERELEASE')) 25 | assetsToRelease = [project.tasks.jar] 26 | } 27 | 28 | group = 'cd.go.plugin.config.yaml' 29 | version = gocdPlugin.fullVersion(project) 30 | 31 | repositories { 32 | mavenCentral() 33 | } 34 | 35 | java { 36 | sourceCompatibility = JavaVersion.VERSION_17 37 | targetCompatibility = JavaVersion.VERSION_17 38 | } 39 | 40 | tasks.withType(JavaCompile).configureEach { 41 | options.release = 17 42 | } 43 | 44 | ext { 45 | pluginApiVersion = '25.3.0' 46 | } 47 | 48 | dependencies { 49 | implementation 'com.google.code.gson:gson:2.13.2' 50 | implementation 'org.apache.ant:ant:1.10.15' 51 | implementation 'com.beust:jcommander:1.82' 52 | implementation 'com.contrastsecurity:yamlbeans:1.17' 53 | implementation 'org.yaml:snakeyaml:2.5' 54 | 55 | compileOnly "cd.go.plugin:go-plugin-api:$pluginApiVersion" 56 | testImplementation "cd.go.plugin:go-plugin-api:$pluginApiVersion" 57 | 58 | testImplementation platform('org.junit:junit-bom:6.0.0') 59 | testImplementation 'org.junit.jupiter:junit-jupiter-api' 60 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' 61 | testRuntimeOnly 'org.junit.platform:junit-platform-launcher' 62 | testImplementation 'org.mockito:mockito-core:5.20.0' 63 | testImplementation 'org.hamcrest:hamcrest:3.0' 64 | } 65 | 66 | test { 67 | useJUnitPlatform() 68 | testLogging { 69 | events "passed", "skipped", "failed", "standardOut" 70 | } 71 | } 72 | 73 | // create a fat jar with all dependencies 74 | jar { 75 | archiveBaseName = project.name 76 | preserveFileTimestamps = false 77 | reproducibleFileOrder = true 78 | duplicatesStrategy = DuplicatesStrategy.INCLUDE 79 | 80 | manifest { 81 | attributes 'Main-Class': 'cd.go.plugin.config.yaml.cli.YamlPluginCli' 82 | } 83 | 84 | from { 85 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } 86 | } 87 | 88 | exclude "allow.class" // Noise from Ant 89 | exclude "META-INF/*.txt" 90 | exclude "META-INF/*.LIST" 91 | exclude "META-INF/versions/**" 92 | } 93 | -------------------------------------------------------------------------------- /config_repo_id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomzo/gocd-yaml-config-plugin/9e3f9e0f4f36870e0c6f42e1b40af70e37225dc9/config_repo_id.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomzo/gocd-yaml-config-plugin/9e3f9e0f4f36870e0c6f42e1b40af70e37225dc9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | 118 | 119 | # Determine the Java command to use to start the JVM. 120 | if [ -n "$JAVA_HOME" ] ; then 121 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 122 | # IBM's JDK on AIX uses strange locations for the executables 123 | JAVACMD=$JAVA_HOME/jre/sh/java 124 | else 125 | JAVACMD=$JAVA_HOME/bin/java 126 | fi 127 | if [ ! -x "$JAVACMD" ] ; then 128 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 129 | 130 | Please set the JAVA_HOME variable in your environment to match the 131 | location of your Java installation." 132 | fi 133 | else 134 | JAVACMD=java 135 | if ! command -v java >/dev/null 2>&1 136 | then 137 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 138 | 139 | Please set the JAVA_HOME variable in your environment to match the 140 | location of your Java installation." 141 | fi 142 | fi 143 | 144 | # Increase the maximum file descriptors if we can. 145 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 146 | case $MAX_FD in #( 147 | max*) 148 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 149 | # shellcheck disable=SC2039,SC3045 150 | MAX_FD=$( ulimit -H -n ) || 151 | warn "Could not query maximum file descriptor limit" 152 | esac 153 | case $MAX_FD in #( 154 | '' | soft) :;; #( 155 | *) 156 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 157 | # shellcheck disable=SC2039,SC3045 158 | ulimit -n "$MAX_FD" || 159 | warn "Could not set maximum file descriptor limit to $MAX_FD" 160 | esac 161 | fi 162 | 163 | # Collect all arguments for the java command, stacking in reverse order: 164 | # * args from the command line 165 | # * the main class name 166 | # * -classpath 167 | # * -D...appname settings 168 | # * --module-path (only if needed) 169 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 170 | 171 | # For Cygwin or MSYS, switch paths to Windows format before running java 172 | if "$cygwin" || "$msys" ; then 173 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ 214 | "$@" 215 | 216 | # Stop when "xargs" is not available. 217 | if ! command -v xargs >/dev/null 2>&1 218 | then 219 | die "xargs is not available" 220 | fi 221 | 222 | # Use "xargs" to parse quoted args. 223 | # 224 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 225 | # 226 | # In Bash we could simply go: 227 | # 228 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 229 | # set -- "${ARGS[@]}" "$@" 230 | # 231 | # but POSIX shell has neither arrays nor command substitution, so instead we 232 | # post-process each arg (as a line of input to sed) to backslash-escape any 233 | # character that might be a shell metacharacter, then use eval to reverse 234 | # that process (while maintaining the separation between arguments), and wrap 235 | # the whole thing up as a single "set" statement. 236 | # 237 | # This will of course break if any of these variables contains a newline or 238 | # an unmatched quote. 239 | # 240 | 241 | eval "set -- $( 242 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 243 | xargs -n1 | 244 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 245 | tr '\n' ' ' 246 | )" '"$@"' 247 | 248 | exec "$JAVACMD" "$@" 249 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | 74 | 75 | @rem Execute Gradle 76 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 77 | 78 | :end 79 | @rem End local scope for the variables with windows NT shell 80 | if %ERRORLEVEL% equ 0 goto mainEnd 81 | 82 | :fail 83 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 84 | rem the _cmd.exe /c_ return code! 85 | set EXIT_CODE=%ERRORLEVEL% 86 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 87 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 88 | exit /b %EXIT_CODE% 89 | 90 | :mainEnd 91 | if "%OS%"=="Windows_NT" endlocal 92 | 93 | :omega 94 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'yaml-config-plugin' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/AntDirectoryScanner.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import org.apache.tools.ant.DirectoryScanner; 4 | 5 | import java.io.File; 6 | 7 | public class AntDirectoryScanner implements ConfigDirectoryScanner { 8 | 9 | @Override 10 | public String[] getFilesMatchingPattern(File directory, String pattern) { 11 | DirectoryScanner scanner = new DirectoryScanner(); 12 | scanner.setBasedir(directory); 13 | scanner.setIncludes(pattern.trim().split(" *, *")); 14 | scanner.scan(); 15 | return scanner.getIncludedFiles(); 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/Capabilities.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.annotations.Expose; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | public class Capabilities { 7 | @Expose 8 | @SerializedName("supports_pipeline_export") 9 | private boolean supportsPipelineExport; 10 | 11 | @Expose 12 | @SerializedName("supports_parse_content") 13 | private boolean supportsParseContent; 14 | 15 | @Expose 16 | @SerializedName("supports_list_config_files") 17 | private boolean supportsListConfigFiles; 18 | 19 | @Expose 20 | @SerializedName("supports_user_defined_properties") 21 | private boolean supportsUserDefinedProperties; 22 | 23 | public Capabilities() { 24 | this.supportsPipelineExport = true; 25 | this.supportsParseContent = true; 26 | this.supportsListConfigFiles = true; 27 | this.supportsUserDefinedProperties = false; 28 | } 29 | 30 | public boolean isSupportsPipelineExport() { 31 | return supportsPipelineExport; 32 | } 33 | 34 | public void setSupportsPipelineExport(boolean supportsPipelineExport) { 35 | this.supportsPipelineExport = supportsPipelineExport; 36 | } 37 | 38 | public boolean isSupportsParseContent() { 39 | return supportsParseContent; 40 | } 41 | 42 | public void setSupportsParseContent(boolean supportsParseContent) { 43 | this.supportsParseContent = supportsParseContent; 44 | } 45 | 46 | public boolean isSupportsListConfigFiles() { 47 | return supportsListConfigFiles; 48 | } 49 | 50 | public void setSupportsListConfigFiles(boolean supportsListConfigFiles) { 51 | this.supportsListConfigFiles = supportsListConfigFiles; 52 | } 53 | 54 | public boolean isSupportsUserDefinedProperties() { 55 | return supportsUserDefinedProperties; 56 | } 57 | 58 | public void setSupportsUserDefinedProperties(boolean supportsUserDefinedProperties) { 59 | this.supportsUserDefinedProperties = supportsUserDefinedProperties; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/ConfigDirectoryScanner.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import java.io.File; 4 | 5 | public interface ConfigDirectoryScanner { 6 | String[] getFilesMatchingPattern(File directory, String pattern); 7 | } -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/ConfigRepoMessages.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | public interface ConfigRepoMessages { 4 | String REQ_GET_PLUGIN_SETTINGS = "go.processor.plugin-settings.get"; 5 | String REQ_GET_CAPABILITIES = "get-capabilities"; 6 | String REQ_PLUGIN_SETTINGS_CHANGED = "go.plugin-settings.plugin-settings-changed"; 7 | String REQ_PLUGIN_SETTINGS_GET_CONFIGURATION = "go.plugin-settings.get-configuration"; 8 | String REQ_PLUGIN_SETTINGS_GET_VIEW = "go.plugin-settings.get-view"; 9 | String REQ_PLUGIN_SETTINGS_VALIDATE_CONFIGURATION = "go.plugin-settings.validate-configuration"; 10 | String REQ_PARSE_DIRECTORY = "parse-directory"; 11 | String REQ_PARSE_CONTENT = "parse-content"; 12 | String REQ_PIPELINE_EXPORT = "pipeline-export"; 13 | String REQ_CONFIG_FILES = "config-files"; 14 | String REQ_GET_ICON = "get-icon"; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/JSONUtils.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class JSONUtils { 11 | 12 | private static final Gson GSON = new GsonBuilder().create(); 13 | 14 | static Map fromJSON(String json) { 15 | return GSON.fromJson(json, new TypeToken>() {}.getType()); 16 | } 17 | 18 | static String toJSON(Object object) { 19 | return GSON.toJson(object); 20 | } 21 | 22 | public static void addOptionalValue(Map dest, Map src, String jsonField, String yamlFieldName) { 23 | if (src.containsKey(jsonField)) { 24 | dest.put(yamlFieldName, src.get(jsonField)); 25 | } 26 | } 27 | 28 | public static void addOptionalList(Map dest, Map src, String jsonField, String yamlFieldName) { 29 | List value = (List) src.get(jsonField); 30 | if (value != null && !value.isEmpty()) { 31 | dest.put(yamlFieldName, value); 32 | } 33 | } 34 | 35 | public static void addOptionalInt(Map dest, Map src, String jsonField, String yamlFieldName) { 36 | Object n = src.get(jsonField); 37 | if (n == null) 38 | return; 39 | if (n instanceof Double) { 40 | dest.put(yamlFieldName, ((Double) n).intValue()); 41 | } else { 42 | dest.put(yamlFieldName, n); 43 | } 44 | } 45 | 46 | public static void addRequiredValue(Map dest, Map src, String jsonField, String yamlFieldName) { 47 | Object value = src.get(jsonField); 48 | if (value == null) 49 | throw new YamlConfigException("field " + yamlFieldName + ": is required"); 50 | 51 | dest.put(yamlFieldName, value); 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/JsonConfigCollection.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.*; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | public class JsonConfigCollection { 9 | private static final int DEFAULT_VERSION = 1; 10 | private final Gson gson; 11 | 12 | private Set uniqueVersions = new HashSet<>(); 13 | private JsonObject mainObject = new JsonObject(); 14 | private JsonArray environments = new JsonArray(); 15 | private JsonArray pipelines = new JsonArray(); 16 | private JsonArray errors = new JsonArray(); 17 | 18 | public JsonConfigCollection() { 19 | gson = new Gson(); 20 | 21 | updateTargetVersionTo(DEFAULT_VERSION); 22 | mainObject.add("environments", environments); 23 | mainObject.add("pipelines", pipelines); 24 | mainObject.add("errors", errors); 25 | } 26 | 27 | protected JsonArray getEnvironments() { 28 | return environments; 29 | } 30 | 31 | public void addEnvironment(JsonElement environment, String location) { 32 | environments.add(environment); 33 | environment.getAsJsonObject().add("location", new JsonPrimitive(location)); 34 | } 35 | 36 | public JsonObject getJsonObject() { 37 | return mainObject; 38 | } 39 | 40 | public void addPipeline(JsonElement pipeline, String location) { 41 | pipelines.add(pipeline); 42 | pipeline.getAsJsonObject().add("location", new JsonPrimitive(location)); 43 | } 44 | 45 | public JsonArray getPipelines() { 46 | return pipelines; 47 | } 48 | 49 | public JsonArray getErrors() { 50 | return errors; 51 | } 52 | 53 | public void addError(String message, String location) { 54 | this.addError(new PluginError(message, location)); 55 | } 56 | 57 | public void addError(PluginError error) { 58 | errors.add(gson.toJsonTree(error)); 59 | } 60 | 61 | public void append(JsonConfigCollection other) { 62 | this.environments.addAll(other.environments); 63 | this.pipelines.addAll(other.pipelines); 64 | this.errors.addAll(other.errors); 65 | this.uniqueVersions.addAll(other.uniqueVersions); 66 | } 67 | 68 | public void updateFormatVersionFound(int version) { 69 | uniqueVersions.add(version); 70 | updateTargetVersionTo(version); 71 | } 72 | 73 | public void updateTargetVersionFromFiles() { 74 | if (uniqueVersions.size() > 1) { 75 | throw new RuntimeException("Versions across files are not unique. Found versions: " + uniqueVersions + ". There can only be one version across the whole repository."); 76 | } 77 | updateTargetVersionTo(uniqueVersions.iterator().hasNext() ? uniqueVersions.iterator().next() : DEFAULT_VERSION); 78 | } 79 | 80 | private void updateTargetVersionTo(int targetVersion) { 81 | mainObject.remove("target_version"); 82 | mainObject.add("target_version", new JsonPrimitive(targetVersion)); 83 | } 84 | } -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/ParsedRequest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.*; 4 | import com.google.gson.reflect.TypeToken; 5 | import com.thoughtworks.go.plugin.api.request.GoPluginApiRequest; 6 | 7 | import java.util.Map; 8 | 9 | import static java.lang.String.format; 10 | 11 | class ParsedRequest { 12 | private static final Gson GSON = new Gson(); 13 | private static final String EMPTY_REQUEST_BODY_MESSAGE = "Request body cannot be null or empty"; 14 | private static final String INVALID_JSON = "Request body must be valid JSON string"; 15 | private static final String MISSING_PARAM_MESSAGE = "`%s` property is missing in `%s` request"; 16 | private static final String PARAM_NOT_A_STRING_MESSAGE = "Expected `%s` param in request type `%s` to be a string"; 17 | private static final String PARAM_FAILED_TO_PARSE_TO_TYPE = "Failed to parse parameter `%s` for request type `%s`: %s"; 18 | private static final String PARAM_CONFIGURATIONS = "configurations"; 19 | private final String requestName; 20 | private final JsonObject params; 21 | 22 | private ParsedRequest(String requestName, JsonObject params) { 23 | this.requestName = requestName; 24 | this.params = params; 25 | } 26 | 27 | static ParsedRequest parse(GoPluginApiRequest req) { 28 | String requestBody = req.requestBody(); 29 | 30 | if (null == requestBody || requestBody.trim().isEmpty()) { 31 | throw new RequestParseException(EMPTY_REQUEST_BODY_MESSAGE); 32 | } 33 | 34 | JsonElement parsed; 35 | try { 36 | parsed = JsonParser.parseString(requestBody); 37 | } catch (JsonParseException e) { 38 | throw new RequestParseException(INVALID_JSON, e); 39 | } 40 | 41 | if (parsed.equals(new JsonObject())) { 42 | throw new RequestParseException(EMPTY_REQUEST_BODY_MESSAGE); 43 | } 44 | 45 | try { 46 | return new ParsedRequest(req.requestName(), parsed.getAsJsonObject()); 47 | } catch (Exception e) { 48 | throw new ParsedRequest.RequestParseException(e); 49 | } 50 | } 51 | 52 | String getStringParam(String paramName) { 53 | params.getAsJsonPrimitive(paramName); 54 | 55 | JsonPrimitive paramValue; 56 | try { 57 | paramValue = params.getAsJsonPrimitive(paramName); 58 | } catch (Exception e) { 59 | throw new RequestParseException(e); 60 | } 61 | 62 | if (null == paramValue) { 63 | throw new RequestParseException(format(MISSING_PARAM_MESSAGE, paramName, requestName)); 64 | } 65 | 66 | try { 67 | return paramValue.getAsString(); 68 | } catch (Exception e) { 69 | throw new RequestParseException(format(PARAM_NOT_A_STRING_MESSAGE, paramName, requestName)); 70 | } 71 | } 72 | 73 | Map getParam(String paramName, Class valueType) { 74 | try { 75 | JsonElement json = params.get(paramName); 76 | 77 | if (null == json || json.isJsonNull()) { 78 | throw new RequestParseException(format(MISSING_PARAM_MESSAGE, paramName, requestName)); 79 | } 80 | 81 | return GSON.fromJson(json, TypeToken.getParameterized(Map.class, String.class, valueType).getType()); 82 | } catch (Exception e) { 83 | throw new RequestParseException(format(PARAM_FAILED_TO_PARSE_TO_TYPE, paramName, requestName, e.getMessage())); 84 | } 85 | } 86 | 87 | String getConfigurationKey(String keyName) { 88 | String value = null; 89 | 90 | try { 91 | JsonArray perRepoConfig = params.getAsJsonArray(PARAM_CONFIGURATIONS); 92 | 93 | if (perRepoConfig != null) { 94 | for (JsonElement config : perRepoConfig) { 95 | JsonObject configObj = config.getAsJsonObject(); 96 | String key = configObj.getAsJsonPrimitive("key").getAsString(); 97 | 98 | if (key.equals(keyName)) { 99 | value = configObj.getAsJsonPrimitive("value").getAsString(); 100 | } 101 | } 102 | } 103 | } catch (Exception e) { 104 | throw new RequestParseException(e); 105 | } 106 | 107 | return value; 108 | } 109 | 110 | static class RequestParseException extends RuntimeException { 111 | RequestParseException(String message) { 112 | super(message); 113 | } 114 | 115 | RequestParseException(Throwable cause) { 116 | super(cause); 117 | } 118 | 119 | RequestParseException(String message, Throwable cause) { 120 | super(message, cause); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/PluginError.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | public class PluginError { 4 | private String location; 5 | private String message; 6 | 7 | public PluginError(String message, String location) { 8 | this.location = location; 9 | this.message = message; 10 | } 11 | 12 | public String getLocation() { 13 | return location; 14 | } 15 | 16 | public String getMessage() { 17 | return message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/PluginSettings.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import java.util.Map; 4 | 5 | class PluginSettings { 6 | static final String PLUGIN_SETTINGS_FILE_PATTERN = "file_pattern"; 7 | static final String DEFAULT_FILE_PATTERN = "**/*.gocd.yaml,**/*.gocd.yml"; 8 | 9 | private String filePattern; 10 | 11 | PluginSettings() { 12 | } 13 | 14 | PluginSettings(String filePattern) { 15 | this.filePattern = filePattern; 16 | } 17 | 18 | static PluginSettings fromJson(String json) { 19 | Map raw = JSONUtils.fromJSON(json); 20 | return new PluginSettings(raw.get(PLUGIN_SETTINGS_FILE_PATTERN)); 21 | } 22 | 23 | String getFilePattern() { 24 | return filePattern; 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/YamlConfigException.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | public class YamlConfigException extends RuntimeException { 4 | public YamlConfigException(String message) { 5 | super(message); 6 | } 7 | 8 | public YamlConfigException(String message, Throwable e) { 9 | super(message, e); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/YamlConfigParser.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import cd.go.plugin.config.yaml.transforms.RootTransform; 4 | import com.esotericsoftware.yamlbeans.UnsafeYamlConfig; 5 | import com.esotericsoftware.yamlbeans.YamlConfig; 6 | import com.esotericsoftware.yamlbeans.YamlReader; 7 | 8 | import java.io.*; 9 | 10 | public class YamlConfigParser { 11 | private RootTransform rootTransform; 12 | 13 | public YamlConfigParser() { 14 | this(new RootTransform()); 15 | } 16 | 17 | public YamlConfigParser(RootTransform rootTransform) { 18 | this.rootTransform = rootTransform; 19 | } 20 | 21 | public JsonConfigCollection parseFiles(File baseDir, String[] files) { 22 | JsonConfigCollection collection = new JsonConfigCollection(); 23 | 24 | for (String file : files) { 25 | try { 26 | parseStream(collection, new FileInputStream(new File(baseDir, file)), file); 27 | } catch (FileNotFoundException ex) { 28 | collection.addError("File matching GoCD YAML pattern disappeared", file); 29 | } 30 | } 31 | 32 | return collection; 33 | } 34 | 35 | public void parseStream(JsonConfigCollection result, InputStream input, String location) { 36 | try (InputStreamReader contentReader = new InputStreamReader(input)) { 37 | if (input.available() < 1) { 38 | result.addError("File is empty", location); 39 | return; 40 | } 41 | 42 | try (YamlReader reader = new YamlReader(contentReader, newYamlConfig())) { 43 | JsonConfigCollection filePart = rootTransform.transform(reader.read(), location); 44 | result.append(filePart); 45 | } catch (YamlReader.YamlReaderException e) { 46 | result.addError(e.getMessage(), location); 47 | } 48 | } catch (IOException e) { 49 | result.addError(e.getMessage() + " : " + e.getCause().getMessage() + " : ", location); 50 | } 51 | } 52 | 53 | public static YamlConfig newYamlConfig() { 54 | YamlConfig config = new UnsafeYamlConfig(); 55 | config.readConfig.setClassTags(false); 56 | config.setAllowDuplicates(false); 57 | return config; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/YamlUtils.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonObject; 6 | import org.yaml.snakeyaml.DumperOptions; 7 | import org.yaml.snakeyaml.Yaml; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.regex.Pattern; 12 | 13 | import static java.lang.Integer.parseInt; 14 | 15 | public class YamlUtils { 16 | // http://yaml.org/type/bool.html 17 | private static final Pattern PATTERN_TRUE = Pattern.compile( 18 | "y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON"); 19 | private static final Pattern PATTERN_FALSE = Pattern.compile( 20 | "n|N|no|No|NO|false|False|FALSE|off|Off|OFF"); 21 | 22 | public static String dump(Object o) { 23 | DumperOptions options = new DumperOptions(); 24 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 25 | options.setPrettyFlow(true); 26 | return new Yaml(options).dump(o); 27 | } 28 | 29 | public static void addOptionalObject(JsonObject jsonObject, Map yamlSource, String jsonField, String yamlFieldName) { 30 | Object obj = getOptionalObject(yamlSource, yamlFieldName); 31 | if (obj != null) 32 | jsonObject.add(jsonField, new Gson().toJsonTree(obj)); 33 | } 34 | 35 | public static void addOptionalBoolean(JsonObject material, Map map, String jsonFieldName, String yamlFieldName) { 36 | Boolean autoUpdate = getOptionalBoolean(map, yamlFieldName); 37 | if (autoUpdate != null) { 38 | material.addProperty(jsonFieldName, autoUpdate); 39 | } 40 | } 41 | 42 | public static void addOptionalString(JsonObject jsonObject, Map yamlSource, String jsonField, String yamlFieldName) { 43 | String value = getOptionalString(yamlSource, yamlFieldName); 44 | if (value != null) 45 | jsonObject.addProperty(jsonField, value); 46 | } 47 | 48 | public static void addOptionalInteger(JsonObject jsonObject, Map yamlSource, String jsonField, String yamlFieldName) { 49 | Integer value = getOptionalInteger(yamlSource, yamlFieldName); 50 | if (value != null) 51 | jsonObject.addProperty(jsonField, value); 52 | } 53 | 54 | public static void addOptionalStringList(JsonObject jsonObject, Map yamlSource, String jsonField, String yamlFieldName) { 55 | JsonArray value = getOptionalStringList(yamlSource, yamlFieldName); 56 | if (value != null) 57 | jsonObject.add(jsonField, value); 58 | } 59 | 60 | private static JsonArray getOptionalStringList(Map map, String fieldName) { 61 | JsonArray jsonArray = new JsonArray(); 62 | Object value = map.get(fieldName); 63 | if (value != null) { 64 | @SuppressWarnings("unchecked") List list = (List) value; 65 | if (list.isEmpty()) 66 | return null; 67 | for (String item : list) { 68 | jsonArray.add(item); 69 | } 70 | return jsonArray; 71 | } 72 | return null; 73 | } 74 | 75 | public static void addRequiredString(JsonObject jsonObject, Map yamlSource, String jsonField, String yamlFieldName) { 76 | String value = getOptionalString(yamlSource, yamlFieldName); 77 | if (value == null) 78 | throw new YamlConfigException("String field " + yamlFieldName + ": is required"); 79 | 80 | jsonObject.addProperty(jsonField, value); 81 | } 82 | 83 | public static Boolean getOptionalBoolean(Map map, String fieldName) { 84 | Object value = map.get(fieldName); 85 | if (value != null) { 86 | if (value instanceof Boolean) 87 | return (Boolean) value; 88 | String boolText = (String) value; 89 | if (PATTERN_TRUE.matcher(boolText).matches()) 90 | return true; 91 | else if (PATTERN_FALSE.matcher(boolText).matches()) 92 | return false; 93 | throw new YamlConfigException("Expected boolean value in field " + fieldName + ", got " + boolText); 94 | } 95 | return null; 96 | } 97 | 98 | public static String getOptionalString(Map map, String fieldName) { 99 | Object value = map.get(fieldName); 100 | if (value != null) { 101 | return (String) value; 102 | } 103 | return null; 104 | } 105 | 106 | public static Integer getOptionalInteger(Map map, String fieldName) { 107 | Object value = map.get(fieldName); 108 | if (value != null) { 109 | if (value instanceof Integer) 110 | return (Integer) value; 111 | else if (value instanceof String) { 112 | return parseInt((String) value); 113 | } 114 | } 115 | return null; 116 | } 117 | 118 | public static Object getOptionalObject(Map map, String fieldName) { 119 | return map.get(fieldName); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/cli/RootCmd.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.cli; 2 | 3 | import com.beust.jcommander.Parameter; 4 | 5 | class RootCmd { 6 | @Parameter(names = {"--help", "-h"}, help = true, description = "Print this help message") 7 | boolean help; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/cli/SyntaxCmd.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.cli; 2 | 3 | import com.beust.jcommander.Parameter; 4 | 5 | class SyntaxCmd { 6 | @Parameter(names = {"--help", "-h"}, help = true, description = "Print this help message") 7 | boolean help; 8 | 9 | @Parameter(description = "file", required = true) 10 | String file; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/cli/YamlPluginCli.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.cli; 2 | 3 | import cd.go.plugin.config.yaml.JsonConfigCollection; 4 | import cd.go.plugin.config.yaml.YamlConfigParser; 5 | import com.beust.jcommander.JCommander; 6 | import com.beust.jcommander.ParameterException; 7 | import com.google.gson.JsonObject; 8 | 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.InputStream; 12 | 13 | public class YamlPluginCli { 14 | public static void main(String[] args) { 15 | RootCmd root = new RootCmd(); 16 | SyntaxCmd syntax = new SyntaxCmd(); 17 | 18 | JCommander cmd = JCommander.newBuilder(). 19 | programName("yaml-cli"). 20 | addObject(root). 21 | addCommand("syntax", syntax). 22 | build(); 23 | 24 | try { 25 | cmd.parse(args); 26 | 27 | if (root.help) { 28 | printUsageAndExit(0, cmd, cmd.getParsedCommand()); 29 | } 30 | 31 | if (syntax.help) { 32 | printUsageAndExit(0, cmd, cmd.getParsedCommand()); 33 | } 34 | 35 | if (null == syntax.file) { 36 | printUsageAndExit(1, cmd, cmd.getParsedCommand()); 37 | } 38 | } catch (ParameterException e) { 39 | error(e.getMessage()); 40 | printUsageAndExit(1, cmd, cmd.getParsedCommand()); 41 | } 42 | 43 | YamlConfigParser parser = new YamlConfigParser(); 44 | JsonConfigCollection collection = new JsonConfigCollection(); 45 | parser.parseStream(collection, getFileAsStream(syntax.file), getLocation(syntax.file)); 46 | 47 | if (collection.getErrors().size() > 0) { 48 | JsonObject result = collection.getJsonObject(); 49 | result.remove("environments"); 50 | result.remove("pipelines"); 51 | result.addProperty("valid", false); 52 | die(1, result.toString()); 53 | } else { 54 | die(0, "{\"valid\":true}"); 55 | } 56 | } 57 | 58 | private static String getLocation(String file) { 59 | return "-".equals(file) ? "" : file; 60 | } 61 | 62 | private static InputStream getFileAsStream(String file) { 63 | InputStream s = null; 64 | try { 65 | s = "-".equals(file) ? System.in : new FileInputStream(file); 66 | } catch (FileNotFoundException e) { 67 | die(1, e.getMessage()); 68 | } 69 | return s; 70 | } 71 | 72 | private static void echo(String message, Object... items) { 73 | System.out.printf(message + "%n", items); 74 | } 75 | 76 | private static void error(String message, Object... items) { 77 | System.err.printf(message + "%n", items); 78 | } 79 | 80 | private static void die(int exitCode, String message, Object... items) { 81 | if (exitCode != 0) { 82 | error(message, items); 83 | } else { 84 | echo(message, items); 85 | } 86 | System.exit(exitCode); 87 | } 88 | 89 | private static void printUsageAndExit(int exitCode, JCommander cmd, String command) { 90 | StringBuilder out = new StringBuilder(); 91 | if (null == command) { 92 | cmd.getUsageFormatter().usage(out); 93 | } else { 94 | cmd.getUsageFormatter().usage(command, out); 95 | } 96 | die(exitCode, out.toString()); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/ConfigurationTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.internal.LinkedTreeMap; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class ConfigurationTransform { 11 | 12 | static final String YAML_PLUGIN_STD_CONFIG_FIELD = "options"; 13 | static final String YAML_PLUGIN_SEC_CONFIG_FIELD = "secure_options"; 14 | static final String JSON_PLUGIN_CONFIG_KEY_FIELD = "key"; 15 | static final String JSON_PLUGIN_CONFIG_VALUE_FIELD = "value"; 16 | static final String JSON_PLUGIN_CONFIG_ENCRYPTED_VALUE_FIELD = "encrypted_value"; 17 | static final String JSON_PLUGIN_CONFIGURATION_FIELD = "configuration"; 18 | 19 | void addConfiguration(JsonObject json, Map configurationMap) { 20 | if (configurationMap == null) { 21 | return; 22 | } 23 | JsonArray configuration = new JsonArray(); 24 | Object options = configurationMap.get(YAML_PLUGIN_STD_CONFIG_FIELD); 25 | Object optionsSecure = configurationMap.get(YAML_PLUGIN_SEC_CONFIG_FIELD); 26 | transformPlainAndSecureOptions(configuration, options, optionsSecure, JSON_PLUGIN_CONFIG_KEY_FIELD); 27 | if (configuration.size() > 0) 28 | json.add(JSON_PLUGIN_CONFIGURATION_FIELD, configuration); 29 | } 30 | 31 | void addInverseConfiguration(Map taskData, Map task) { 32 | List> jsonOptions = (List>) task.get(JSON_PLUGIN_CONFIGURATION_FIELD); 33 | if (jsonOptions == null) 34 | return; 35 | 36 | Map options = new LinkedTreeMap<>(); 37 | Map secureOptions = new LinkedTreeMap<>(); 38 | 39 | for (Map option : jsonOptions) { 40 | if (option.containsKey(JSON_PLUGIN_CONFIG_ENCRYPTED_VALUE_FIELD)) { 41 | secureOptions.put((String) option.get(JSON_PLUGIN_CONFIG_KEY_FIELD), option.get(JSON_PLUGIN_CONFIG_ENCRYPTED_VALUE_FIELD)); 42 | } else { 43 | options.put((String) option.get(JSON_PLUGIN_CONFIG_KEY_FIELD), option.get(JSON_PLUGIN_CONFIG_VALUE_FIELD)); 44 | } 45 | } 46 | 47 | if (options.size() > 0) 48 | taskData.put(YAML_PLUGIN_STD_CONFIG_FIELD, options); 49 | if (secureOptions.size() > 0) 50 | taskData.put(YAML_PLUGIN_SEC_CONFIG_FIELD, secureOptions); 51 | } 52 | 53 | void transformPlainAndSecureOptions(JsonArray configuration, Object options, Object secureOptions, String keyField) { 54 | if (options != null && options != "") { 55 | transformValues(configuration, (Map) options, JSON_PLUGIN_CONFIG_VALUE_FIELD, keyField); 56 | } 57 | if (secureOptions != null && secureOptions != "") { 58 | transformValues(configuration, (Map) secureOptions, JSON_PLUGIN_CONFIG_ENCRYPTED_VALUE_FIELD, keyField); 59 | } 60 | } 61 | 62 | public Map inverseTransformPlainAndSecureOptions(List> vars, String plainField, String secureField) { 63 | if (vars == null) 64 | return null; 65 | Map result = new LinkedTreeMap<>(); 66 | Map variables = new LinkedTreeMap<>(); 67 | Map secureVariables = new LinkedTreeMap<>(); 68 | for (Map var : vars) { 69 | if (var.containsKey(JSON_PLUGIN_CONFIG_ENCRYPTED_VALUE_FIELD)) { 70 | secureVariables.put((String) var.get("name"), var.get(JSON_PLUGIN_CONFIG_ENCRYPTED_VALUE_FIELD)); 71 | } else { 72 | variables.put((String) var.get("name"), var.get(JSON_PLUGIN_CONFIG_VALUE_FIELD)); 73 | } 74 | } 75 | 76 | if (variables.size() > 0) 77 | result.put(plainField, variables); 78 | if (secureVariables.size() > 0) 79 | result.put(secureField, secureVariables); 80 | return result; 81 | } 82 | 83 | private void transformValues(JsonArray configuration, Map plainOrSecureOptions, String valueOrEncryptedValue, String keyField) { 84 | for (Map.Entry env : plainOrSecureOptions.entrySet()) { 85 | JsonObject kv = new JsonObject(); 86 | kv.addProperty(keyField, env.getKey()); 87 | kv.addProperty(valueOrEncryptedValue, env.getValue()); 88 | configuration.add(kv); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/EnvironmentVariablesTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import com.google.gson.JsonArray; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class EnvironmentVariablesTransform extends ConfigurationTransform { 9 | public static final String JSON_ENV_VAR_FIELD = "environment_variables"; 10 | 11 | public static final String JSON_ENV_NAME_FIELD = "name"; 12 | 13 | public static final String YAML_ENV_VAR_FIELD = "environment_variables"; 14 | public static final String YAML_SEC_VAR_FIELD = "secure_variables"; 15 | 16 | public JsonArray transform(Object variables, Object secureVariables) { 17 | JsonArray array = new JsonArray(); 18 | transformPlainAndSecureOptions(array, variables, secureVariables, JSON_ENV_NAME_FIELD); 19 | return array; 20 | } 21 | 22 | public Map inverseTransform(List> vars) { 23 | if (vars == null) 24 | return null; 25 | return inverseTransformPlainAndSecureOptions(vars, YAML_ENV_VAR_FIELD, YAML_SEC_VAR_FIELD); 26 | } 27 | 28 | public JsonArray transform(Object all) { 29 | Map map = (Map) all; 30 | return transform(map.get(YAML_ENV_VAR_FIELD), map.get(YAML_SEC_VAR_FIELD)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/EnvironmentsTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.YamlConfigException; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonObject; 6 | 7 | import java.util.Map; 8 | 9 | import static cd.go.plugin.config.yaml.YamlUtils.addOptionalStringList; 10 | import static cd.go.plugin.config.yaml.transforms.EnvironmentVariablesTransform.JSON_ENV_VAR_FIELD; 11 | 12 | public class EnvironmentsTransform { 13 | private static final String JSON_ENV_NAME_FIELD = "name"; 14 | private EnvironmentVariablesTransform environmentVariablesTransform; 15 | 16 | public EnvironmentsTransform(EnvironmentVariablesTransform environmentVariablesTransform) { 17 | this.environmentVariablesTransform = environmentVariablesTransform; 18 | } 19 | 20 | public JsonObject transform(Object yamlObject) { 21 | Map map = (Map) yamlObject; 22 | for (Map.Entry entry : map.entrySet()) { 23 | return transform(entry); 24 | } 25 | throw new RuntimeException("expected environments hash to have 1 item"); 26 | } 27 | 28 | public JsonObject transform(Map.Entry env) { 29 | String envName = env.getKey(); 30 | JsonObject envJson = new JsonObject(); 31 | envJson.addProperty(JSON_ENV_NAME_FIELD, envName); 32 | Object envObj = env.getValue(); 33 | if (envObj == null) 34 | return envJson; 35 | if (!(envObj instanceof Map)) 36 | throw new YamlConfigException("Expected environment to be a hash"); 37 | Map envMap = (Map) envObj; 38 | addOptionalStringList(envJson, envMap, "agents", "agents"); 39 | addOptionalStringList(envJson, envMap, "pipelines", "pipelines"); 40 | JsonArray jsonEnvVariables = environmentVariablesTransform.transform(envMap); 41 | if (jsonEnvVariables != null && jsonEnvVariables.size() > 0) 42 | envJson.add(JSON_ENV_VAR_FIELD, jsonEnvVariables); 43 | return envJson; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/ParameterTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.internal.LinkedTreeMap; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class ParameterTransform { 11 | 12 | public static final String YAML_PIPELINE_PARAMETERS_FIELD = "parameters"; 13 | public static final String JSON_PARAM_NAME_FIELD = "name"; 14 | public static final String JSON_PARAM_VALUE_FIELD = "value"; 15 | 16 | 17 | public JsonArray transform(Object all) { 18 | Map map = (Map) all; 19 | Object parameters = map.get(YAML_PIPELINE_PARAMETERS_FIELD); 20 | JsonArray paramArray = new JsonArray(); 21 | if (parameters != null && parameters != "") { 22 | for (Map.Entry param : ((Map) parameters).entrySet()) { 23 | JsonObject paramJson = new JsonObject(); 24 | paramJson.addProperty(JSON_PARAM_NAME_FIELD, param.getKey()); 25 | paramJson.addProperty(JSON_PARAM_VALUE_FIELD, param.getValue()); 26 | paramArray.add(paramJson); 27 | } 28 | 29 | } 30 | return paramArray; 31 | } 32 | 33 | public Map inverseTransform(List> params) { 34 | if (params == null || params.isEmpty()) 35 | return null; 36 | Map result = new LinkedTreeMap<>(); 37 | Map inverseParams = new LinkedTreeMap<>(); 38 | for (Map param : params) { 39 | inverseParams.putAll(inverseTransformParam(param)); 40 | } 41 | result.put(YAML_PIPELINE_PARAMETERS_FIELD, inverseParams); 42 | return result; 43 | } 44 | 45 | public Map inverseTransformParam(Map param) { 46 | String name = (String) param.get(JSON_PARAM_NAME_FIELD); 47 | Map inverseParam = new LinkedTreeMap<>(); 48 | inverseParam.put(name, param.get(JSON_PARAM_VALUE_FIELD)); 49 | return inverseParam; 50 | } 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/PipelineTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.YamlConfigException; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.internal.LinkedTreeMap; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import static cd.go.plugin.config.yaml.JSONUtils.addOptionalInt; 13 | import static cd.go.plugin.config.yaml.JSONUtils.addOptionalValue; 14 | import static cd.go.plugin.config.yaml.YamlUtils.*; 15 | import static cd.go.plugin.config.yaml.transforms.EnvironmentVariablesTransform.JSON_ENV_VAR_FIELD; 16 | import static cd.go.plugin.config.yaml.transforms.ParameterTransform.YAML_PIPELINE_PARAMETERS_FIELD; 17 | 18 | public class PipelineTransform { 19 | private static final String JSON_PIPELINE_NAME_FIELD = "name"; 20 | private static final String JSON_PIPELINE_GROUP_FIELD = "group"; 21 | private static final String JSON_PIPELINE_TEMPLATE_FIELD = "template"; 22 | private static final String JSON_PIPELINE_LABEL_TEMPLATE_FIELD = "label_template"; 23 | private static final String JSON_PIPELINE_PIPE_LOCKING_FIELD = "enable_pipeline_locking"; 24 | private static final String JSON_PIPELINE_LOCK_BEHAVIOR_FIELD = "lock_behavior"; 25 | private static final String JSON_PIPELINE_TRACKING_TOOL_FIELD = "tracking_tool"; 26 | private static final String JSON_PIPELINE_TIMER_FIELD = "timer"; 27 | private static final String JSON_PIPELINE_MATERIALS_FIELD = "materials"; 28 | private static final String JSON_PIPELINE_STAGES_FIELD = "stages"; 29 | private static final String JSON_PIPELINE_DISPLAY_ORDER_FIELD = "display_order_weight"; 30 | 31 | private static final String YAML_PIPELINE_GROUP_FIELD = "group"; 32 | private static final String YAML_PIPELINE_TEMPLATE_FIELD = "template"; 33 | private static final String YAML_PIPELINE_LABEL_TEMPLATE_FIELD = "label_template"; 34 | private static final String YAML_PIPELINE_PIPE_LOCKING_FIELD = "locking"; 35 | private static final String YAML_PIPELINE_LOCK_BEHAVIOR_FIELD = "lock_behavior"; 36 | private static final String YAML_PIPELINE_TRACKING_TOOL_FIELD = "tracking_tool"; 37 | private static final String YAML_PIPELINE_TIMER_FIELD = "timer"; 38 | private static final String YAML_PIPELINE_MATERIALS_FIELD = "materials"; 39 | private static final String YAML_PIPELINE_STAGES_FIELD = "stages"; 40 | private static final String YAML_PIPELINE_DISPLAY_ORDER_FIELD = "display_order"; 41 | 42 | private final MaterialTransform materialTransform; 43 | private final StageTransform stageTransform; 44 | private final EnvironmentVariablesTransform variablesTransform; 45 | private ParameterTransform parameterTransform; 46 | 47 | public PipelineTransform(MaterialTransform materialTransform, StageTransform stageTransform, EnvironmentVariablesTransform variablesTransform, ParameterTransform parameterTransform) { 48 | this.materialTransform = materialTransform; 49 | this.stageTransform = stageTransform; 50 | this.variablesTransform = variablesTransform; 51 | this.parameterTransform = parameterTransform; 52 | } 53 | 54 | public JsonObject transform(Object maybePipe, int formatVersion) { 55 | Map map = (Map) maybePipe; 56 | for (Map.Entry entry : map.entrySet()) { 57 | return transform(entry, formatVersion); 58 | } 59 | throw new RuntimeException("expected pipeline hash to have 1 item"); 60 | } 61 | 62 | public JsonObject transform(Map.Entry entry, int formatVersion) { 63 | String pipelineName = entry.getKey(); 64 | JsonObject pipeline = new JsonObject(); 65 | pipeline.addProperty(JSON_PIPELINE_NAME_FIELD, pipelineName); 66 | Map pipeMap = (Map) entry.getValue(); 67 | 68 | addOptionalString(pipeline, pipeMap, JSON_PIPELINE_GROUP_FIELD, YAML_PIPELINE_GROUP_FIELD); 69 | addOptionalInteger(pipeline, pipeMap, JSON_PIPELINE_DISPLAY_ORDER_FIELD, YAML_PIPELINE_DISPLAY_ORDER_FIELD); 70 | addOptionalString(pipeline, pipeMap, JSON_PIPELINE_TEMPLATE_FIELD, YAML_PIPELINE_TEMPLATE_FIELD); 71 | addOptionalString(pipeline, pipeMap, JSON_PIPELINE_LABEL_TEMPLATE_FIELD, YAML_PIPELINE_LABEL_TEMPLATE_FIELD); 72 | addOptionalBoolean(pipeline, pipeMap, JSON_PIPELINE_PIPE_LOCKING_FIELD, YAML_PIPELINE_PIPE_LOCKING_FIELD); 73 | addOptionalString(pipeline, pipeMap, JSON_PIPELINE_LOCK_BEHAVIOR_FIELD, YAML_PIPELINE_LOCK_BEHAVIOR_FIELD); 74 | 75 | addOptionalObject(pipeline, pipeMap, JSON_PIPELINE_TRACKING_TOOL_FIELD, YAML_PIPELINE_TRACKING_TOOL_FIELD); 76 | addTimer(pipeline, pipeMap); 77 | 78 | JsonArray jsonEnvVariables = variablesTransform.transform(pipeMap); 79 | if (jsonEnvVariables != null && jsonEnvVariables.size() > 0) 80 | pipeline.add(JSON_ENV_VAR_FIELD, jsonEnvVariables); 81 | 82 | addMaterials(pipeline, pipeMap, formatVersion); 83 | if (!pipeline.has(JSON_PIPELINE_TEMPLATE_FIELD)) { 84 | addStages(pipeline, pipeMap); 85 | } 86 | 87 | JsonArray params = parameterTransform.transform(pipeMap); 88 | if (params != null && params.size() > 0) { 89 | pipeline.add(YAML_PIPELINE_PARAMETERS_FIELD, params); 90 | } 91 | 92 | return pipeline; 93 | } 94 | 95 | public Map inverseTransform(Object pipeline) { 96 | return inverseTransform((Map) pipeline); 97 | } 98 | 99 | public Map inverseTransform(Map pipeline) { 100 | Map result = new LinkedTreeMap<>(); 101 | Map pipelineMap = new LinkedTreeMap<>(); 102 | String name = (String) pipeline.get(JSON_PIPELINE_NAME_FIELD); 103 | 104 | pipelineMap.put(YAML_PIPELINE_GROUP_FIELD, pipeline.get(JSON_PIPELINE_GROUP_FIELD)); 105 | addOptionalValue(pipelineMap, pipeline, JSON_PIPELINE_TEMPLATE_FIELD, YAML_PIPELINE_TEMPLATE_FIELD); 106 | addOptionalValue(pipelineMap, pipeline, JSON_PIPELINE_LABEL_TEMPLATE_FIELD, YAML_PIPELINE_LABEL_TEMPLATE_FIELD); 107 | addOptionalValue(pipelineMap, pipeline, JSON_PIPELINE_PIPE_LOCKING_FIELD, YAML_PIPELINE_PIPE_LOCKING_FIELD); 108 | addOptionalValue(pipelineMap, pipeline, JSON_PIPELINE_LOCK_BEHAVIOR_FIELD, YAML_PIPELINE_LOCK_BEHAVIOR_FIELD); 109 | addOptionalValue(pipelineMap, pipeline, JSON_PIPELINE_TRACKING_TOOL_FIELD, YAML_PIPELINE_TRACKING_TOOL_FIELD); 110 | addOptionalInt(pipelineMap, pipeline, JSON_PIPELINE_DISPLAY_ORDER_FIELD, YAML_PIPELINE_DISPLAY_ORDER_FIELD); 111 | 112 | addInverseTimer(pipelineMap, pipeline); 113 | 114 | Map yamlEnvVariables = variablesTransform.inverseTransform((List>) pipeline.get(JSON_ENV_VAR_FIELD)); 115 | if (yamlEnvVariables != null && yamlEnvVariables.size() > 0) 116 | pipelineMap.putAll(yamlEnvVariables); 117 | 118 | addInverseMaterials(pipelineMap, (List>) pipeline.get(JSON_PIPELINE_MATERIALS_FIELD)); 119 | if (!pipelineMap.containsKey(YAML_PIPELINE_TEMPLATE_FIELD)) { 120 | addInverseStages(pipelineMap, (List>) pipeline.get(JSON_PIPELINE_STAGES_FIELD)); 121 | } 122 | 123 | Map params = parameterTransform.inverseTransform((List>) pipeline.get("parameters")); 124 | if (params != null && !params.isEmpty()) { 125 | pipelineMap.putAll(params); 126 | } 127 | 128 | result.put(name, pipelineMap); 129 | return result; 130 | 131 | } 132 | 133 | private void addInverseMaterials(Map pipelineMap, List> materials) { 134 | Map inverseMaterials = new LinkedTreeMap<>(); 135 | for (Map material : materials) { 136 | inverseMaterials.putAll(materialTransform.inverseTransform(material)); 137 | } 138 | pipelineMap.put(YAML_PIPELINE_MATERIALS_FIELD, inverseMaterials); 139 | } 140 | 141 | private void addInverseStages(Map pipelineMap, List> stages) { 142 | List> inverseStages = new ArrayList<>(); 143 | for (Map stage : stages) { 144 | inverseStages.add(null == stage ? null : stageTransform.inverseTransform(stage)); 145 | } 146 | pipelineMap.put(YAML_PIPELINE_STAGES_FIELD, inverseStages); 147 | } 148 | 149 | private void addInverseTimer(Map pipelineMap, Map pipeline) { 150 | Object timer = pipeline.get(JSON_PIPELINE_TIMER_FIELD); 151 | if (timer == null) 152 | return; 153 | Map timerMap = (Map) timer; 154 | pipelineMap.put(YAML_PIPELINE_TIMER_FIELD, timerMap); 155 | } 156 | 157 | private void addTimer(JsonObject pipeline, Map pipeMap) { 158 | Object timer = pipeMap.get(YAML_PIPELINE_TIMER_FIELD); 159 | if (timer == null) 160 | return; 161 | JsonObject timerJson = new JsonObject(); 162 | Map timerMap = (Map) timer; 163 | addRequiredString(timerJson, timerMap, "spec", "spec"); 164 | addOptionalBoolean(timerJson, timerMap, "only_on_changes", "only_on_changes"); 165 | pipeline.add(JSON_PIPELINE_TIMER_FIELD, timerJson); 166 | } 167 | 168 | private void addStages(JsonObject pipeline, Map pipeMap) { 169 | Object stages = pipeMap.get(YAML_PIPELINE_STAGES_FIELD); 170 | if (!(stages instanceof List)) 171 | throw new YamlConfigException("expected a list of pipeline stages or a template reference"); 172 | List stagesList = (List) stages; 173 | JsonArray stagesArray = transformStages(stagesList); 174 | pipeline.add(JSON_PIPELINE_STAGES_FIELD, stagesArray); 175 | } 176 | 177 | private JsonArray transformStages(List stagesList) { 178 | JsonArray stagesArray = new JsonArray(); 179 | for (Object stage : stagesList) { 180 | if (stage instanceof List) { 181 | List stageNestedList = (List) stage; 182 | for(Object s : stageNestedList) { 183 | stagesArray.add(stageTransform.transform(s)); 184 | } 185 | } 186 | else 187 | stagesArray.add(stageTransform.transform(stage)); 188 | } 189 | return stagesArray; 190 | } 191 | 192 | private void addMaterials(JsonObject pipeline, Map pipeMap, int formatVersion) { 193 | Object materials = pipeMap.get(YAML_PIPELINE_MATERIALS_FIELD); 194 | if (!(materials instanceof Map)) 195 | throw new YamlConfigException("expected a hash of pipeline materials"); 196 | Map materialsMap = (Map) materials; 197 | JsonArray materialsArray = transformMaterials(materialsMap, formatVersion); 198 | pipeline.add(JSON_PIPELINE_MATERIALS_FIELD, materialsArray); 199 | } 200 | 201 | private JsonArray transformMaterials(Map materialsMap, int formatVersion) { 202 | JsonArray materialsArray = new JsonArray(); 203 | for (Map.Entry entry : materialsMap.entrySet()) { 204 | materialsArray.add(materialTransform.transform(entry, formatVersion)); 205 | } 206 | return materialsArray; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/RootTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonConfigCollection; 4 | import cd.go.plugin.config.yaml.PluginError; 5 | import cd.go.plugin.config.yaml.YamlConfigException; 6 | import cd.go.plugin.config.yaml.YamlUtils; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.internal.LinkedTreeMap; 9 | 10 | import java.util.Map; 11 | 12 | public class RootTransform { 13 | private final PipelineTransform pipelineTransform; 14 | private final EnvironmentsTransform environmentsTransform; 15 | 16 | public RootTransform() { 17 | EnvironmentVariablesTransform environmentVarsTransform = new EnvironmentVariablesTransform(); 18 | MaterialTransform material = new MaterialTransform(); 19 | ParameterTransform parameterTransform = new ParameterTransform(); 20 | JobTransform job = new JobTransform(environmentVarsTransform, new TaskTransform()); 21 | StageTransform stage = new StageTransform(environmentVarsTransform, job); 22 | this.pipelineTransform = new PipelineTransform(material, stage, environmentVarsTransform, parameterTransform); 23 | this.environmentsTransform = new EnvironmentsTransform(environmentVarsTransform); 24 | } 25 | 26 | public RootTransform(PipelineTransform pipelineTransform, EnvironmentsTransform environmentsTransform) { 27 | this.pipelineTransform = pipelineTransform; 28 | this.environmentsTransform = environmentsTransform; 29 | } 30 | 31 | public String inverseTransformPipeline(Map pipeline) { 32 | Map result = new LinkedTreeMap<>(); 33 | result.put("format_version", 10); 34 | result.put("pipelines", pipelineTransform.inverseTransform(pipeline)); 35 | return YamlUtils.dump(result); 36 | } 37 | 38 | public JsonConfigCollection transform(Object rootObj, String location) { 39 | JsonConfigCollection partialConfig = new JsonConfigCollection(); 40 | @SuppressWarnings("unchecked") Map rootMap = (Map) rootObj; 41 | // must obtain format_version first 42 | int formatVersion = 1; 43 | for (Map.Entry pe : rootMap.entrySet()) { 44 | if ("format_version".equalsIgnoreCase(pe.getKey())) { 45 | formatVersion = Integer.parseInt((String) pe.getValue()); 46 | partialConfig.updateFormatVersionFound(formatVersion); 47 | } 48 | } 49 | for (Map.Entry pe : rootMap.entrySet()) { 50 | if ("pipelines".equalsIgnoreCase(pe.getKey())) { 51 | if (pe.getValue() == null) 52 | continue; 53 | Map pipelines = (Map) pe.getValue(); 54 | for (Map.Entry pipe : pipelines.entrySet()) { 55 | try { 56 | JsonElement jsonPipeline = pipelineTransform.transform(pipe, formatVersion); 57 | partialConfig.addPipeline(jsonPipeline, location); 58 | } catch (Exception ex) { 59 | partialConfig.addError(new PluginError( 60 | String.format("Failed to parse pipeline %s; %s", pipe.getKey(), ex.getMessage()), location)); 61 | } 62 | } 63 | } else if ("environments".equalsIgnoreCase(pe.getKey())) { 64 | if (pe.getValue() == null) 65 | continue; 66 | @SuppressWarnings("unchecked") Map environments = (Map) pe.getValue(); 67 | for (Map.Entry env : environments.entrySet()) { 68 | try { 69 | JsonElement jsonEnvironment = environmentsTransform.transform(env); 70 | partialConfig.addEnvironment(jsonEnvironment, location); 71 | } catch (Exception ex) { 72 | partialConfig.addError(new PluginError( 73 | String.format("Failed to parse environment %s; %s", env.getKey(), ex.getMessage()), location)); 74 | } 75 | } 76 | } else if (!"common".equalsIgnoreCase(pe.getKey()) && !"format_version".equalsIgnoreCase(pe.getKey())) 77 | throw new YamlConfigException(pe.getKey() + " is invalid, expected format_version, pipelines, environments, or common"); 78 | } 79 | return partialConfig; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/StageTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.YamlConfigException; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.internal.LinkedTreeMap; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import static cd.go.plugin.config.yaml.JSONUtils.*; 12 | import static cd.go.plugin.config.yaml.YamlUtils.*; 13 | import static cd.go.plugin.config.yaml.transforms.EnvironmentVariablesTransform.JSON_ENV_VAR_FIELD; 14 | 15 | public class StageTransform { 16 | private static final String JSON_STAGE_NAME_FIELD = "name"; 17 | private static final String JSON_STAGE_FETCH_FIELD = "fetch_materials"; 18 | private static final String YAML_STAGE_FETCH_FIELD = "fetch_materials"; 19 | private static final String JSON_STAGE_NEVER_CLEAN_FIELD = "never_cleanup_artifacts"; 20 | private static final String YAML_STAGE_KEEP_ARTIFACTS_FIELD = "keep_artifacts"; 21 | private static final String JSON_STAGE_CLEAN_WORK_FIELD = "clean_working_directory"; 22 | private static final String YAML_STAGE_CLEAN_WORK_FIELD = "clean_workspace"; 23 | private static final String YAML_STAGE_APPROVAL_FIELD = "approval"; 24 | private static final String JSON_STAGE_APPROVAL_FIELD = "approval"; 25 | private static final String JSON_STAGE_APPROVAL_TYPE_FIELD = "type"; 26 | private static final String YAML_STAGE_APPROVAL_TYPE_FIELD = "type"; 27 | private static final String JSON_STAGE_JOBS_FIELD = "jobs"; 28 | private static final String JSON_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD = "allow_only_on_success"; 29 | private static final String YAML_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD = "allow_only_on_success"; 30 | private static final String JSON_STAGE_APPROVAL_USERS_FIELD = "users"; 31 | private static final String YAML_STAGE_APPROVAL_USERS_FIELD = "users"; 32 | private static final String JSON_STAGE_APPROVAL_ROLES_FIELD = "roles"; 33 | private static final String YAML_STAGE_APPROVAL_ROLES_FIELD = "roles"; 34 | 35 | private EnvironmentVariablesTransform environmentTransform; 36 | private JobTransform jobTransform; 37 | 38 | public StageTransform(EnvironmentVariablesTransform environmentTransform, JobTransform jobTransform) { 39 | this.environmentTransform = environmentTransform; 40 | this.jobTransform = jobTransform; 41 | } 42 | 43 | public JsonObject transform(Object maybeStage) { 44 | Map map = (Map) maybeStage; 45 | for (Map.Entry entry : map.entrySet()) { 46 | return transform(entry); 47 | } 48 | throw new RuntimeException("expected stage hash to have 1 item"); 49 | } 50 | 51 | public JsonObject transform(Map.Entry entry) { 52 | String stageName = entry.getKey(); 53 | JsonObject stage = new JsonObject(); 54 | stage.addProperty(JSON_STAGE_NAME_FIELD, stageName); 55 | Map stageMap = (Map) entry.getValue(); 56 | 57 | addOptionalBoolean(stage, stageMap, JSON_STAGE_FETCH_FIELD, YAML_STAGE_FETCH_FIELD); 58 | addOptionalBoolean(stage, stageMap, JSON_STAGE_NEVER_CLEAN_FIELD, YAML_STAGE_KEEP_ARTIFACTS_FIELD); 59 | addOptionalBoolean(stage, stageMap, JSON_STAGE_CLEAN_WORK_FIELD, YAML_STAGE_CLEAN_WORK_FIELD); 60 | 61 | addApproval(stage, stageMap); 62 | 63 | JsonArray jsonEnvVariables = environmentTransform.transform(stageMap); 64 | if (jsonEnvVariables != null && jsonEnvVariables.size() > 0) 65 | stage.add(JSON_ENV_VAR_FIELD, jsonEnvVariables); 66 | 67 | addJobs(stage, stageMap); 68 | 69 | return stage; 70 | } 71 | 72 | public Map inverseTransform(Map stage) { 73 | if (stage == null) { 74 | return null; 75 | } 76 | String stageName = (String) stage.get(JSON_STAGE_NAME_FIELD); 77 | Map inverseStage = new LinkedTreeMap<>(); 78 | Map stageData = new LinkedTreeMap<>(); 79 | 80 | addOptionalValue(stageData, stage, JSON_STAGE_FETCH_FIELD, YAML_STAGE_FETCH_FIELD); 81 | addOptionalValue(stageData, stage, JSON_STAGE_NEVER_CLEAN_FIELD, YAML_STAGE_KEEP_ARTIFACTS_FIELD); 82 | addOptionalValue(stageData, stage, JSON_STAGE_CLEAN_WORK_FIELD, YAML_STAGE_CLEAN_WORK_FIELD); 83 | addOptionalValue(stageData, stage, JSON_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD, YAML_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD); 84 | 85 | addInverseApproval(stageData, stage); 86 | 87 | Map yamlEnvVariables = environmentTransform.inverseTransform((List>) stage.get(JSON_ENV_VAR_FIELD)); 88 | if (yamlEnvVariables != null && yamlEnvVariables.size() > 0) 89 | stageData.putAll(yamlEnvVariables); 90 | 91 | addInverseJobs(stageData, (List>) stage.get(JSON_STAGE_JOBS_FIELD)); 92 | 93 | inverseStage.put(stageName, stageData); 94 | return inverseStage; 95 | } 96 | 97 | private void addInverseJobs(Map stageData, List> jobs) { 98 | Map inverseJobs = new LinkedTreeMap<>(); 99 | for (Map job : jobs) { 100 | Map inverseJob = jobTransform.inverseTransform(job); 101 | if (inverseJob != null) 102 | inverseJobs.putAll(inverseJob); 103 | } 104 | 105 | stageData.put("jobs", inverseJobs); 106 | } 107 | 108 | private void addInverseApproval(Map stageData, Map stage) { 109 | Map approval = (Map) stage.get(JSON_STAGE_APPROVAL_FIELD); 110 | Map inverseApproval = new LinkedTreeMap<>(); 111 | if (approval == null) 112 | return; 113 | 114 | addRequiredValue(inverseApproval, approval, JSON_STAGE_APPROVAL_TYPE_FIELD, YAML_STAGE_APPROVAL_TYPE_FIELD); 115 | addOptionalValue(inverseApproval, approval, JSON_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD, YAML_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD); 116 | addOptionalList(inverseApproval, approval, JSON_STAGE_APPROVAL_ROLES_FIELD, YAML_STAGE_APPROVAL_ROLES_FIELD); 117 | addOptionalList(inverseApproval, approval, JSON_STAGE_APPROVAL_USERS_FIELD, YAML_STAGE_APPROVAL_USERS_FIELD); 118 | 119 | stageData.put(YAML_STAGE_APPROVAL_FIELD, inverseApproval); 120 | } 121 | 122 | private void addApproval(JsonObject stage, Map stageMap) { 123 | Object approval = stageMap.get(YAML_STAGE_APPROVAL_FIELD); 124 | if (approval == null) 125 | return; 126 | JsonObject approvalJson = new JsonObject(); 127 | if (approval instanceof String) { 128 | // shorthand 129 | if ("auto".equals(approval) || "success".equals(approval)) 130 | approvalJson.addProperty(JSON_STAGE_APPROVAL_TYPE_FIELD, "success"); 131 | else if ("manual".equals(approval)) 132 | approvalJson.addProperty(JSON_STAGE_APPROVAL_TYPE_FIELD, "manual"); 133 | else 134 | throw new YamlConfigException("Approval should be a hash or string [auto or manual]"); 135 | } else { 136 | Map approvalMap = (Map) approval; 137 | addRequiredString(approvalJson, approvalMap, JSON_STAGE_APPROVAL_TYPE_FIELD, YAML_STAGE_APPROVAL_TYPE_FIELD); 138 | addOptionalBoolean(approvalJson, approvalMap, JSON_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD, YAML_STAGE_APPROVAL_ALLOW_ONLY_ON_SUCCESS_FIELD); 139 | addOptionalStringList(approvalJson, approvalMap, JSON_STAGE_APPROVAL_USERS_FIELD, YAML_STAGE_APPROVAL_USERS_FIELD); 140 | addOptionalStringList(approvalJson, approvalMap, JSON_STAGE_APPROVAL_ROLES_FIELD, YAML_STAGE_APPROVAL_ROLES_FIELD); 141 | } 142 | 143 | stage.add(JSON_STAGE_APPROVAL_FIELD, approvalJson); 144 | } 145 | 146 | private void addJobs(JsonObject stage, Map stageMap) { 147 | JsonArray jsonJobs = new JsonArray(); 148 | Object jobsObj = stageMap.get("jobs"); 149 | if (jobsObj == null) { 150 | //there are no jobs, then it might be a single-job stage 151 | Object tasks = stageMap.get("tasks"); 152 | if (tasks == null) 153 | throw new YamlConfigException("Stage must have jobs defined, or tasks if only one job should exist"); 154 | // single-job stage - expect to find job definition in the stage definition 155 | JsonObject job = jobTransform.transform(stage.get(JSON_STAGE_NAME_FIELD).getAsString(), stageMap); 156 | jsonJobs.add(job); 157 | } else { 158 | // standard definition 159 | Map jobsMap = (Map) jobsObj; 160 | for (Map.Entry entry : jobsMap.entrySet()) { 161 | JsonObject job = jobTransform.transform(entry); 162 | jsonJobs.add(job); 163 | } 164 | } 165 | stage.add(JSON_STAGE_JOBS_FIELD, jsonJobs); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/cd/go/plugin/config/yaml/transforms/TaskTransform.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.YamlConfigException; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.internal.LinkedTreeMap; 7 | 8 | import java.util.HashSet; 9 | import java.util.Map; 10 | 11 | import static cd.go.plugin.config.yaml.JSONUtils.addOptionalList; 12 | import static cd.go.plugin.config.yaml.JSONUtils.addOptionalValue; 13 | import static cd.go.plugin.config.yaml.YamlUtils.*; 14 | 15 | public class TaskTransform extends ConfigurationTransform { 16 | public static final String YAML_TASK_CANCEL_FIELD = "on_cancel"; 17 | public static final String JSON_TASK_CANCEL_FIELD = "on_cancel"; 18 | public static final String JSON_TASK_IS_FILE_FIELD = "is_source_a_file"; 19 | public static final String YAML_TASK_IS_FILE_FIELD = "is_file"; 20 | public static final String JSON_TASK_EXEC_ARGS_FIELD = "arguments"; 21 | public static final String YAML_TASK_EXEC_ARGS_FIELD = "arguments"; 22 | public static final String YAML_PLUGIN_STD_CONFIG_FIELD = "options"; 23 | public static final String YAML_PLUGIN_SEC_CONFIG_FIELD = "secure_options"; 24 | public static final String YAML_PLUGIN_CONFIGURATION_FIELD = "configuration"; 25 | public static final String JSON_TASK_PLUGIN_CONFIGURATION_FIELD = "plugin_configuration"; 26 | private static final String JSON_TASK_TYPE_FIELD = "type"; 27 | private static final String JSON_PLUGIN_CONFIGURATION_FIELD = "configuration"; 28 | private HashSet yamlSpecialKeywords = new HashSet<>(); 29 | 30 | public TaskTransform() { 31 | yamlSpecialKeywords.add("type"); 32 | yamlSpecialKeywords.add("is_file"); 33 | yamlSpecialKeywords.add("on_cancel"); 34 | yamlSpecialKeywords.add("arguments"); 35 | yamlSpecialKeywords.add(YAML_PLUGIN_STD_CONFIG_FIELD); 36 | yamlSpecialKeywords.add(YAML_PLUGIN_SEC_CONFIG_FIELD); 37 | yamlSpecialKeywords.add(YAML_PLUGIN_CONFIGURATION_FIELD); 38 | } 39 | 40 | public JsonObject transform(Object maybeTask) { 41 | Map map = (Map) maybeTask; 42 | for (Map.Entry entry : map.entrySet()) { 43 | return transform(entry); 44 | } 45 | throw new RuntimeException("expected task hash to have 1 item"); 46 | } 47 | 48 | public JsonObject transform(Map.Entry taskEntry) { 49 | JsonObject taskJson = new JsonObject(); 50 | 51 | String taskType = taskEntry.getKey(); 52 | if (taskEntry.getValue() == null) { 53 | taskJson.addProperty(JSON_TASK_TYPE_FIELD, taskType); 54 | return taskJson; 55 | } 56 | if (taskEntry.getValue() instanceof String) { 57 | if (taskType.equalsIgnoreCase("script")) { 58 | taskJson.addProperty(JSON_TASK_TYPE_FIELD, "plugin"); 59 | JsonArray config = new JsonArray(); 60 | JsonObject scriptKv = new JsonObject(); 61 | scriptKv.addProperty("key", "script"); 62 | scriptKv.addProperty("value", (String) taskEntry.getValue()); 63 | config.add(scriptKv); 64 | JsonObject pluginConfig = new JsonObject(); 65 | pluginConfig.addProperty("id", "script-executor"); 66 | pluginConfig.addProperty("version", "1"); 67 | taskJson.add(JSON_PLUGIN_CONFIGURATION_FIELD, config); 68 | taskJson.add(JSON_TASK_PLUGIN_CONFIGURATION_FIELD, pluginConfig); 69 | return taskJson; 70 | } 71 | } 72 | taskJson.addProperty(JSON_TASK_TYPE_FIELD, taskType); 73 | if (!(taskEntry.getValue() instanceof Map)) 74 | throw new YamlConfigException("expected task " + taskType + " to be a hash"); 75 | Map taskMap = (Map) taskEntry.getValue(); 76 | addOnCancel(taskJson, taskMap); 77 | 78 | if ("fetch".equals(taskType)) { 79 | addOptionalObject(taskJson, taskMap, JSON_PLUGIN_CONFIGURATION_FIELD, YAML_PLUGIN_CONFIGURATION_FIELD); 80 | super.addConfiguration(taskJson, (Map) taskMap.get(JSON_PLUGIN_CONFIGURATION_FIELD)); 81 | } else { 82 | addOptionalObject(taskJson, taskMap, JSON_TASK_PLUGIN_CONFIGURATION_FIELD, YAML_PLUGIN_CONFIGURATION_FIELD); 83 | super.addConfiguration(taskJson, taskMap); 84 | } 85 | 86 | 87 | addOptionalBoolean(taskJson, taskMap, JSON_TASK_IS_FILE_FIELD, YAML_TASK_IS_FILE_FIELD); 88 | addOptionalStringList(taskJson, taskMap, JSON_TASK_EXEC_ARGS_FIELD, YAML_TASK_EXEC_ARGS_FIELD); 89 | // copy all other members 90 | for (Map.Entry taskProp : taskMap.entrySet()) { 91 | if (yamlSpecialKeywords.contains(taskProp.getKey())) 92 | continue; 93 | if (taskProp.getValue() instanceof String) 94 | taskJson.addProperty(taskProp.getKey(), (String) taskProp.getValue()); 95 | } 96 | return taskJson; 97 | } 98 | 99 | public Map inverseTransform(Map task) { 100 | String type = (String) task.get(JSON_TASK_TYPE_FIELD); 101 | Map inverseTask = new LinkedTreeMap<>(); 102 | Map taskData = new LinkedTreeMap<>(); 103 | 104 | addInverseOnCancel(taskData, task); 105 | 106 | addOptionalValue(taskData, task, JSON_TASK_PLUGIN_CONFIGURATION_FIELD, YAML_PLUGIN_CONFIGURATION_FIELD); 107 | addInverseConfiguration(taskData, task); 108 | 109 | addOptionalValue(taskData, task, JSON_TASK_IS_FILE_FIELD, YAML_TASK_IS_FILE_FIELD); 110 | addOptionalList(taskData, task, JSON_TASK_EXEC_ARGS_FIELD, YAML_TASK_EXEC_ARGS_FIELD); 111 | 112 | for (Map.Entry taskProp : task.entrySet()) { 113 | if (yamlSpecialKeywords.contains(taskProp.getKey())) 114 | continue; 115 | if (taskProp.getValue() instanceof String) 116 | taskData.put(taskProp.getKey(), taskProp.getValue()); 117 | } 118 | 119 | inverseTask.put(type, taskData); 120 | return inverseTask; 121 | } 122 | 123 | private void addInverseOnCancel(Map taskData, Map task) { 124 | Object on_cancel = task.get(JSON_TASK_CANCEL_FIELD); 125 | if (on_cancel != null) { 126 | if (!(on_cancel instanceof LinkedTreeMap)) 127 | throw new YamlConfigException("expected on_cancel task to be a hash"); 128 | taskData.put(YAML_TASK_CANCEL_FIELD, inverseTransform((Map) on_cancel)); 129 | } 130 | } 131 | 132 | private void addOnCancel(JsonObject taskJson, Map taskMap) { 133 | Object on_cancel = taskMap.get(YAML_TASK_CANCEL_FIELD); 134 | if (on_cancel != null) { 135 | if (!(on_cancel instanceof Map)) 136 | throw new YamlConfigException("expected on_cancel task to be a hash"); 137 | JsonObject onCancelJson = transform(on_cancel); 138 | taskJson.add(JSON_TASK_CANCEL_FIELD, onCancelJson); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/resources/plugin-settings.template.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | {{ GOINPUTNAME[file_pattern].$error.server }} 5 |
6 | -------------------------------------------------------------------------------- /src/main/resources/yaml.svg: -------------------------------------------------------------------------------- 1 | file_type_light_yaml 2 | -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/AntDirectoryScannerTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.junit.jupiter.api.Test; 5 | import org.junit.jupiter.api.io.TempDir; 6 | 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | 10 | import static java.util.Arrays.asList; 11 | import static org.hamcrest.CoreMatchers.hasItems; 12 | import static org.hamcrest.CoreMatchers.is; 13 | import static org.hamcrest.MatcherAssert.assertThat; 14 | 15 | public class AntDirectoryScannerTest { 16 | @TempDir 17 | public Path tempDir; 18 | 19 | private AntDirectoryScanner scanner; 20 | 21 | @BeforeEach 22 | public void setUp() throws Exception { 23 | scanner = new AntDirectoryScanner(); 24 | } 25 | 26 | @Test 27 | public void shouldMatchSimplePattern() throws Exception { 28 | Files.createFile(tempDir.resolve("abc.xml")); 29 | Files.createFile(tempDir.resolve("def.xml")); 30 | Files.createFile(tempDir.resolve("ghi.txt")); 31 | 32 | String[] xmlFilesOnly = scanner.getFilesMatchingPattern(tempDir.toFile(), "*.xml"); 33 | 34 | assertThat(xmlFilesOnly.length, is(2)); 35 | assertThat(asList(xmlFilesOnly), hasItems("abc.xml", "def.xml")); 36 | } 37 | 38 | @Test 39 | public void shouldMatchPatternInDirectory() throws Exception { 40 | Files.createDirectories(tempDir.resolve("1").resolve("a")); 41 | Files.createDirectories(tempDir.resolve("2").resolve("d")); 42 | Files.createDirectories(tempDir.resolve("3")); 43 | Files.createDirectories(tempDir.resolve("4")); 44 | 45 | Files.createFile(tempDir.resolve("1/a/abc.xml")); 46 | Files.createFile(tempDir.resolve("2/d/def.xml")); 47 | Files.createFile(tempDir.resolve("3/ghi.xml")); 48 | Files.createFile(tempDir.resolve("4/jkl.txt")); 49 | Files.createFile(tempDir.resolve("mno.txt")); 50 | Files.createFile(tempDir.resolve("pqr.xml")); 51 | 52 | String[] xmlFilesOnly = scanner.getFilesMatchingPattern(tempDir.toFile(), "**/*.xml"); 53 | 54 | assertThat(xmlFilesOnly.length, is(4)); 55 | assertThat(asList(xmlFilesOnly), hasItems("1/a/abc.xml", "2/d/def.xml", "3/ghi.xml", "pqr.xml")); 56 | } 57 | 58 | @Test 59 | public void shouldIgnoreSpacesAroundThePattern() throws Exception { 60 | Files.createFile(tempDir.resolve("def.xml")); 61 | Files.createFile(tempDir.resolve("ghi.txt")); 62 | 63 | String[] xmlFilesOnly = scanner.getFilesMatchingPattern(tempDir.toFile(), " *.xml "); 64 | 65 | assertThat(xmlFilesOnly.length, is(1)); 66 | assertThat(asList(xmlFilesOnly), hasItems("def.xml")); 67 | } 68 | 69 | @Test 70 | public void shouldAcceptMultiplePatternsSeparatedByComma() throws Exception { 71 | Files.createDirectories(tempDir.resolve("1").resolve("a")); 72 | Files.createDirectories(tempDir.resolve("2").resolve("d")); 73 | Files.createDirectories(tempDir.resolve("3")); 74 | Files.createDirectories(tempDir.resolve("4")); 75 | 76 | 77 | Files.createFile(tempDir.resolve("1/a/abc.xml")); 78 | Files.createFile(tempDir.resolve("2/d/def.gif")); 79 | Files.createFile(tempDir.resolve("3/ghi.xml")); 80 | Files.createFile(tempDir.resolve("4/jkl.txt")); 81 | Files.createFile(tempDir.resolve("mno.jpg")); 82 | Files.createFile(tempDir.resolve("4/pqr.jpg")); 83 | Files.createFile(tempDir.resolve("stu.xml")); 84 | 85 | String[] xmlFilesOnly = scanner.getFilesMatchingPattern(tempDir.toFile(), "**/*.xml, **/*.gif, *.jpg"); 86 | 87 | assertThat(xmlFilesOnly.length, is(5)); 88 | assertThat(asList(xmlFilesOnly), hasItems("1/a/abc.xml", "2/d/def.gif", "3/ghi.xml", "mno.jpg", "stu.xml")); 89 | } 90 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/JsonConfigCollectionTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonPrimitive; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.hamcrest.CoreMatchers.is; 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | 12 | public class JsonConfigCollectionTest { 13 | 14 | private JsonConfigCollection jsonCollection; 15 | private JsonObject pipe1; 16 | private JsonObject pipe2; 17 | private JsonObject devEnv; 18 | 19 | @BeforeEach 20 | public void setUp() { 21 | jsonCollection = new JsonConfigCollection(); 22 | 23 | pipe1 = new JsonObject(); 24 | pipe1.addProperty("name", "pipe1"); 25 | 26 | pipe2 = new JsonObject(); 27 | pipe2.addProperty("name", "pipe2"); 28 | 29 | devEnv = new JsonObject(); 30 | devEnv.addProperty("name", "dev"); 31 | } 32 | 33 | @Test 34 | public void shouldReturnTargetVersion() { 35 | JsonObject jsonObject = jsonCollection.getJsonObject(); 36 | assertThat(jsonObject.get("target_version") instanceof JsonPrimitive, is(true)); 37 | assertThat(jsonObject.getAsJsonPrimitive("target_version").getAsInt(), is(1)); 38 | } 39 | 40 | @Test 41 | public void shouldReturnEnvironmentsArrayInJsonObjectWhenEmpty() { 42 | JsonObject jsonObject = jsonCollection.getJsonObject(); 43 | assertThat(jsonObject.get("environments") instanceof JsonArray, is(true)); 44 | assertThat(jsonObject.getAsJsonArray("environments"), is(new JsonArray())); 45 | } 46 | 47 | @Test 48 | public void shouldAppendPipelinesToPipelinesCollection() { 49 | jsonCollection.addPipeline(pipe1, "pipe1.json"); 50 | jsonCollection.addPipeline(pipe2, "pipe2.json"); 51 | JsonObject jsonObject = jsonCollection.getJsonObject(); 52 | assertThat(jsonObject.getAsJsonArray("pipelines").size(), is(2)); 53 | } 54 | 55 | 56 | @Test 57 | public void shouldReturnEnvironmentsInJsonObject() { 58 | jsonCollection.addEnvironment(devEnv, "dev.json"); 59 | JsonObject jsonObject = jsonCollection.getJsonObject(); 60 | assertThat(jsonObject.getAsJsonArray("environments").size(), is(1)); 61 | } 62 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/JsonObjectMatcher.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import org.hamcrest.Description; 7 | import org.hamcrest.TypeSafeMatcher; 8 | 9 | import java.util.Map; 10 | 11 | public class JsonObjectMatcher extends TypeSafeMatcher { 12 | private final JsonObject expected; 13 | 14 | public JsonObjectMatcher(JsonObject expected) { 15 | this.expected = expected; 16 | } 17 | 18 | @Override 19 | protected boolean matchesSafely(JsonObject actual) { 20 | if (actual == null) 21 | return false; 22 | for (Map.Entry field : this.expected.entrySet()) { 23 | if (!actual.has(field.getKey())) 24 | return false; 25 | if (field.getValue().isJsonObject()) { 26 | JsonObjectMatcher inner = new JsonObjectMatcher(field.getValue().getAsJsonObject()); 27 | JsonObject otherObj = actual.get(field.getKey()).getAsJsonObject(); 28 | if (!inner.matchesSafely(otherObj)) 29 | return false; 30 | } else if (field.getValue().isJsonArray()) { 31 | JsonArray thisArray = field.getValue().getAsJsonArray(); 32 | JsonArray otherArray = actual.get(field.getKey()).getAsJsonArray(); 33 | if (otherArray == null) 34 | return false; 35 | if (thisArray.size() != otherArray.size()) 36 | return false; 37 | for (int i = 0; i < thisArray.size(); i++) { 38 | JsonElement thisItem = thisArray.get(i); 39 | if (!equalToAnyOther(thisItem, otherArray)) 40 | return false; 41 | } 42 | } else if (!field.getValue().equals(actual.get(field.getKey()))) 43 | return false; 44 | } 45 | return true; 46 | } 47 | 48 | private boolean equalToAnyOther(JsonElement thisItem, JsonArray otherArray) { 49 | for (int i = 0; i < otherArray.size(); i++) { 50 | JsonElement otherItem = otherArray.get(i); 51 | if (thisItem.isJsonObject()) { 52 | if (!otherItem.isJsonObject()) 53 | continue; 54 | if (new JsonObjectMatcher(thisItem.getAsJsonObject()).matchesSafely(otherItem.getAsJsonObject())) 55 | return true; 56 | } else if (thisItem.equals(otherItem)) 57 | return true; 58 | } 59 | return false; 60 | } 61 | 62 | @Override 63 | public void describeTo(Description description) { 64 | description.appendText(expected.toString()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/PluginErrorTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static org.hamcrest.CoreMatchers.equalTo; 7 | import static org.hamcrest.CoreMatchers.is; 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | 10 | public class PluginErrorTest { 11 | 12 | @Test 13 | public void shouldGetLocation() { 14 | PluginError pluginError = new PluginError(null, "location"); 15 | assertThat(pluginError.getLocation(), is(equalTo("location"))); 16 | } 17 | 18 | @Test 19 | public void shouldGetMessage() { 20 | PluginError pluginError = new PluginError("message", null); 21 | assertThat(pluginError.getMessage(), is(equalTo("message"))); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/PluginSettingsTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.hamcrest.CoreMatchers.is; 6 | import static org.hamcrest.MatcherAssert.assertThat; 7 | 8 | public class PluginSettingsTest { 9 | @Test 10 | public void shouldGetFilePattern() { 11 | PluginSettings pluginSettings = new PluginSettings("file-pattern"); 12 | 13 | assertThat(pluginSettings.getFilePattern(), is("file-pattern")); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/TestUtils.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml; 2 | 3 | import com.esotericsoftware.yamlbeans.YamlReader; 4 | import com.google.gson.Gson; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonParser; 7 | import com.google.gson.reflect.TypeToken; 8 | import org.yaml.snakeyaml.Yaml; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.InputStreamReader; 13 | import java.nio.charset.StandardCharsets; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | import static org.junit.jupiter.api.Assertions.assertEquals; 18 | 19 | public class TestUtils { 20 | private static final Gson GSON = new Gson(); 21 | 22 | public static JsonElement readJsonObject(String path) { 23 | return JsonParser.parseReader(createReader(path)); 24 | } 25 | 26 | public static List> readJsonArrayGson(String path) { 27 | return GSON.fromJson(createReader(path), new TypeToken>>() {}.getType()); 28 | } 29 | 30 | public static Map readJsonGson(String path) { 31 | return GSON.fromJson(createReader(path), new TypeToken>() {}.getType()); 32 | } 33 | 34 | public static Object readYamlObject(String path) throws IOException { 35 | try (YamlReader reader = new YamlReader(createReader(path), YamlConfigParser.newYamlConfig())) { 36 | return reader.read(); 37 | } 38 | } 39 | 40 | private static InputStreamReader createReader(String path) { 41 | return new InputStreamReader(getResourceAsStream(path)); 42 | } 43 | 44 | public static String loadString(String path) throws IOException { 45 | try (InputStream resourceAsStream = getResourceAsStream(path)) { 46 | return new String(resourceAsStream.readAllBytes(), StandardCharsets.UTF_8); 47 | } 48 | } 49 | 50 | @SuppressWarnings("resource") 51 | static InputStream getResourceAsStream(String resource) { 52 | final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource); 53 | 54 | return in == null ? TestUtils.class.getResourceAsStream(resource) : in; 55 | } 56 | 57 | public static void assertYamlEquivalent(String expected, String actual) { 58 | Yaml yaml = new Yaml(); 59 | Object expectedParse = yaml.load(expected); 60 | Object actualParse = yaml.load(actual); 61 | assertEquals(expectedParse, actualParse); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/EnvironmentVariablesTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.YamlUtils; 4 | import com.google.gson.JsonArray; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.IOException; 8 | import java.util.Map; 9 | 10 | import static cd.go.plugin.config.yaml.TestUtils.*; 11 | import static org.hamcrest.CoreMatchers.is; 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | 14 | public class EnvironmentVariablesTransformTest { 15 | private final EnvironmentVariablesTransform parser; 16 | 17 | public EnvironmentVariablesTransformTest() { 18 | parser = new EnvironmentVariablesTransform(); 19 | } 20 | 21 | @Test 22 | public void shouldTransformEmpty() throws IOException { 23 | testTransform("empty"); 24 | } 25 | 26 | @Test 27 | public void shouldTransform1SecureVariable() throws IOException { 28 | testTransform("1safe"); 29 | } 30 | 31 | @Test 32 | public void shouldTransform2Variables() throws IOException { 33 | testTransform("2vars"); 34 | } 35 | 36 | @Test 37 | public void shouldInverseTransform1SecureVariable() throws IOException { 38 | testInverseTransform("1safe"); 39 | } 40 | 41 | @Test 42 | public void shouldInverseTransform2Variable() throws IOException { 43 | testInverseTransform("2vars"); 44 | } 45 | 46 | private void testTransform(String caseFile) throws IOException { 47 | testTransform(caseFile, caseFile); 48 | } 49 | 50 | private void testTransform(String caseFile, String expectedFile) throws IOException { 51 | JsonArray expected = (JsonArray) readJsonObject("parts/env_vars/" + expectedFile + ".json"); 52 | JsonArray actual = parser.transform(readYamlObject("parts/env_vars/" + caseFile + ".yaml")); 53 | assertThat(actual, is(expected)); 54 | } 55 | 56 | private void testInverseTransform(String caseFile) throws IOException { 57 | testInverseTransform(caseFile, caseFile); 58 | } 59 | 60 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 61 | String expectedObject = loadString("parts/env_vars/" + expectedFile + ".yaml"); 62 | Map actual = parser.inverseTransform(readJsonArrayGson("parts/env_vars/" + caseFile + ".json")); 63 | assertYamlEquivalent(expectedObject, YamlUtils.dump(actual)); 64 | } 65 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/EnvironmentsTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonObjectMatcher; 4 | import com.google.gson.JsonObject; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.IOException; 8 | 9 | import static cd.go.plugin.config.yaml.TestUtils.readJsonObject; 10 | import static cd.go.plugin.config.yaml.TestUtils.readYamlObject; 11 | import static org.hamcrest.CoreMatchers.is; 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | 14 | public class EnvironmentsTransformTest { 15 | private final EnvironmentsTransform parser; 16 | 17 | public EnvironmentsTransformTest() { 18 | parser = new EnvironmentsTransform(new EnvironmentVariablesTransform()); 19 | } 20 | 21 | @Test 22 | public void shouldTransformCompleteEnvironment() throws IOException { 23 | testTransform("complete"); 24 | } 25 | 26 | @Test 27 | public void shouldTransformEmptyEnvironment() throws IOException { 28 | testTransform("empty"); 29 | } 30 | 31 | private JsonObject testTransform(String caseFile) throws IOException { 32 | return testTransform(caseFile, caseFile); 33 | } 34 | 35 | private JsonObject testTransform(String caseFile, String expectedFile) throws IOException { 36 | JsonObject expectedObject = (JsonObject) readJsonObject("parts/environments/" + expectedFile + ".json"); 37 | JsonObject jsonObject = parser.transform(readYamlObject("parts/environments/" + caseFile + ".yaml")); 38 | assertThat(jsonObject, is(new JsonObjectMatcher(expectedObject))); 39 | return jsonObject; 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/JobTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonObjectMatcher; 4 | import cd.go.plugin.config.yaml.YamlUtils; 5 | import com.google.gson.JsonObject; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.util.Map; 11 | 12 | import static cd.go.plugin.config.yaml.TestUtils.*; 13 | import static org.hamcrest.CoreMatchers.is; 14 | import static org.hamcrest.MatcherAssert.assertThat; 15 | import static org.mockito.Mockito.mock; 16 | 17 | public class JobTransformTest { 18 | private EnvironmentVariablesTransform environmentTransform; 19 | private TaskTransform taskTransform; 20 | private JobTransform parser; 21 | 22 | @BeforeEach 23 | public void SetUp() { 24 | environmentTransform = new EnvironmentVariablesTransform(); 25 | taskTransform = mock(TaskTransform.class); 26 | parser = new JobTransform(environmentTransform, taskTransform); 27 | } 28 | 29 | @Test 30 | public void shouldTransformMinimalJob() throws IOException { 31 | testTransform("minimal"); 32 | } 33 | 34 | @Test 35 | public void shouldTransformRunAllJob() throws IOException { 36 | JsonObject job = testTransform("runall"); 37 | assertThat(job.get("run_instance_count").getAsJsonPrimitive().isString(), is(true)); 38 | assertThat(job.get("run_instance_count").getAsString(), is("all")); 39 | } 40 | 41 | @Test 42 | public void shouldTransformCompleteJob() throws IOException { 43 | testTransform("complete"); 44 | } 45 | 46 | @Test 47 | public void shouldTransformElasticProfileJob() throws IOException { 48 | testTransform("elastic_profile"); 49 | } 50 | 51 | @Test 52 | public void shouldTransformExternalArtifactConfig() throws IOException { 53 | useParserWithoutMocks(); 54 | 55 | testTransform("external_artifacts"); 56 | } 57 | 58 | @Test 59 | public void shouldTransformJobWithListOfListsTasks() throws IOException { 60 | useParserWithoutMocks(); 61 | 62 | testTransform("list_of_lists_tasks"); 63 | } 64 | 65 | @Test 66 | public void shouldInverseTransformMinimalJob() throws IOException { 67 | testInverseTransform("minimal"); 68 | } 69 | 70 | @Test 71 | public void shouldInverseTransformMinimalWithDefaultsJob() throws IOException { 72 | testInverseTransform("minimal_defaults"); 73 | } 74 | 75 | @Test 76 | public void shouldInverseTransformRunAllJob() throws IOException { 77 | testInverseTransform("runall"); 78 | } 79 | 80 | @Test 81 | public void shouldInverseTransformCompleteJob() throws IOException { 82 | testInverseTransform("complete"); 83 | } 84 | 85 | @Test 86 | public void shouldInverseTransformElasticProfileJob() throws IOException { 87 | testInverseTransform("elastic_profile"); 88 | } 89 | 90 | @Test 91 | public void shouldInverseTransformExternalArtifactConfig() throws IOException { 92 | useParserWithoutMocks(); 93 | 94 | testInverseTransform("external_artifacts"); 95 | } 96 | 97 | private void useParserWithoutMocks() { 98 | environmentTransform = new EnvironmentVariablesTransform(); 99 | taskTransform = new TaskTransform(); 100 | parser = new JobTransform(environmentTransform, taskTransform); 101 | } 102 | 103 | private JsonObject testTransform(String caseFile) throws IOException { 104 | return testTransform(caseFile, caseFile); 105 | } 106 | 107 | private JsonObject testTransform(String caseFile, String expectedFile) throws IOException { 108 | JsonObject expectedObject = (JsonObject) readJsonObject("parts/jobs/" + expectedFile + ".json"); 109 | JsonObject jsonObject = parser.transform(readYamlObject("parts/jobs/" + caseFile + ".yaml")); 110 | assertThat(jsonObject, is(new JsonObjectMatcher(expectedObject))); 111 | return jsonObject; 112 | } 113 | 114 | private void testInverseTransform(String caseFile) throws IOException { 115 | testInverseTransform(caseFile, caseFile); 116 | } 117 | 118 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 119 | Map inverse = parser.inverseTransform(readJsonGson("parts/jobs/" + caseFile + ".json")); 120 | assertYamlEquivalent(loadString("parts/jobs/" + expectedFile + ".yaml"), YamlUtils.dump(inverse)); 121 | } 122 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/MaterialTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonObjectMatcher; 4 | import cd.go.plugin.config.yaml.YamlUtils; 5 | import com.google.gson.JsonObject; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.util.Map; 10 | 11 | import static cd.go.plugin.config.yaml.TestUtils.*; 12 | import static org.hamcrest.CoreMatchers.containsString; 13 | import static org.hamcrest.CoreMatchers.is; 14 | import static org.hamcrest.MatcherAssert.assertThat; 15 | 16 | public class MaterialTransformTest { 17 | private final MaterialTransform parser; 18 | // Becomes relevant only when testing whitelist/includes migration 19 | private final int defaultVersionForContext = 10; 20 | 21 | public MaterialTransformTest() { 22 | parser = new MaterialTransform(); 23 | } 24 | 25 | @Test 26 | public void shouldTransformMinimalGit() throws IOException { 27 | testTransform("minimal.git", defaultVersionForContext); 28 | } 29 | 30 | @Test 31 | public void shouldTransformMinimalExplicitGit() throws IOException { 32 | testTransform("minimal-explicit.git", "minimal.git", defaultVersionForContext); 33 | } 34 | 35 | @Test 36 | public void shouldTransformMinimalNoUrlGit() throws IOException { 37 | testTransform("minimal-nourl.git", "minimal.git", defaultVersionForContext); 38 | } 39 | 40 | @Test 41 | public void shouldTransformGitWhenAutoUpdateIsFalse() throws IOException { 42 | testTransform("auto_update.git", defaultVersionForContext); 43 | } 44 | 45 | @Test 46 | public void shouldTransformGitWhenPlainPassword() throws IOException { 47 | testTransform("password.git", defaultVersionForContext); 48 | } 49 | 50 | @Test 51 | public void shouldTransformCompleteGitWhenFormat9() throws IOException { 52 | testTransform("complete9.git", 9); 53 | } 54 | 55 | @Test 56 | public void shouldTransformCompleteGitWhenFormat10() throws IOException { 57 | testTransform("complete10.git", defaultVersionForContext); 58 | } 59 | 60 | @Test 61 | public void shouldTransformCompleteGitWhenFormat10BackwardsComp() throws IOException { 62 | testTransform("complete10backwards.git", defaultVersionForContext); 63 | } 64 | 65 | @Test 66 | public void shouldTransformMinimalConfigRepo() throws IOException { 67 | testTransform("minimal.cr", defaultVersionForContext); 68 | } 69 | 70 | @Test 71 | public void shouldTransformCompleteConfigRepo() throws IOException { 72 | testTransform("complete10.cr", defaultVersionForContext); 73 | } 74 | 75 | @Test 76 | public void shouldTransformCompleteSvn() throws IOException { 77 | testTransform("complete10.svn", defaultVersionForContext); 78 | } 79 | 80 | @Test 81 | public void shouldTransformCompleteHg() throws IOException { 82 | testTransform("complete10.hg", defaultVersionForContext); 83 | } 84 | 85 | @Test 86 | public void shouldTransformHgWhenPlainPassword() throws IOException { 87 | testTransform("password.hg", defaultVersionForContext); 88 | } 89 | 90 | @Test 91 | public void shouldTransformHgWhenBranchIsPresent() throws IOException { 92 | testTransform("branch.hg", defaultVersionForContext); 93 | } 94 | 95 | @Test 96 | public void shouldTransformSimpleDependency() throws IOException { 97 | testTransform("simple.dependency", defaultVersionForContext); 98 | } 99 | 100 | @Test 101 | public void shouldTransformDependencyWithIgnoreForSchedulingFlag() throws IOException { 102 | testTransform("ignore_for_scheduling.dependency", defaultVersionForContext); 103 | } 104 | 105 | @Test 106 | public void shouldTransformCompletePluggable() throws IOException { 107 | testTransform("complete10.pluggable", defaultVersionForContext); 108 | } 109 | 110 | @Test 111 | public void shouldTransformCompleteSCM() throws IOException { 112 | testTransform("complete10.scm", defaultVersionForContext); 113 | } 114 | 115 | @Test 116 | public void shouldInverseTransformCompleteSCM() throws IOException { 117 | testInverseTransform("complete10.scm"); 118 | } 119 | 120 | @Test 121 | public void shouldTransformPackage() throws IOException { 122 | testTransform("package", defaultVersionForContext); 123 | } 124 | 125 | @Test 126 | public void shouldTransformCompleteP4() throws IOException { 127 | testTransform("complete10.p4", defaultVersionForContext); 128 | } 129 | 130 | 131 | @Test 132 | public void shouldInverseTransformMinimalGit() throws IOException { 133 | testInverseTransform("minimal.git"); 134 | } 135 | 136 | @Test 137 | public void shouldInverseTransformGitWhenAutoUpdateIsFalse() throws IOException { 138 | testInverseTransform("auto_update.git"); 139 | } 140 | 141 | @Test 142 | public void shouldInverseTransformCompleteCr() throws IOException { 143 | testInverseTransform("complete10.cr"); 144 | } 145 | 146 | @Test 147 | public void shouldInverseTransformCompleteSvn() throws IOException { 148 | testInverseTransform("complete10.svn"); 149 | } 150 | 151 | @Test 152 | public void shouldInverseTransformCompleteGit() throws IOException { 153 | testInverseTransform("complete10.git"); 154 | } 155 | 156 | @Test 157 | public void shouldInverseTransformCompleteHg() throws IOException { 158 | testInverseTransform("complete10.hg"); 159 | } 160 | 161 | @Test 162 | public void shouldInverseTransformSimpleDependency() throws IOException { 163 | testInverseTransform("simple.dependency"); 164 | } 165 | 166 | @Test 167 | public void shouldInverseTransformDependencyWithIgnoreForSchedulingFlag() throws IOException { 168 | testInverseTransform("ignore_for_scheduling.dependency"); 169 | } 170 | 171 | @Test 172 | public void shouldInverseTransformCompleteP4() throws IOException { 173 | testInverseTransform("complete10.p4"); 174 | } 175 | 176 | @Test 177 | public void shouldInverseTransformPackage() throws IOException { 178 | testInverseTransform("package"); 179 | } 180 | 181 | @Test 182 | public void shouldInverseTRansformCompletePluggable() throws IOException { 183 | testInverseTransform("complete10.pluggable"); 184 | } 185 | 186 | @Test 187 | public void inverseTransform_shouldGenerateARandomMaterialNameInAbsenceOfName() { 188 | Map material = parser.inverseTransform(readJsonGson("parts/materials/material_without_name.git.json")); 189 | 190 | String materialName = material.keySet().stream().findFirst().orElseThrow(); 191 | assertThat(materialName, containsString("git-")); 192 | } 193 | 194 | private void testTransform(String caseFile, int formatVersion) throws IOException { 195 | testTransform(caseFile, caseFile, formatVersion); 196 | } 197 | 198 | private void testTransform(String caseFile, String expectedFile, int formatVersion) throws IOException { 199 | JsonObject expectedObject = (JsonObject) readJsonObject("parts/materials/" + expectedFile + ".json"); 200 | JsonObject jsonObject = parser.transform(readYamlObject("parts/materials/" + caseFile + ".yaml"), formatVersion); 201 | assertThat(jsonObject, is(new JsonObjectMatcher(expectedObject))); 202 | } 203 | 204 | private void testInverseTransform(String caseFile) throws IOException { 205 | testInverseTransform(caseFile, caseFile); 206 | } 207 | 208 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 209 | String expectedObject = loadString("parts/materials/" + expectedFile + ".yaml"); 210 | Map actual = parser.inverseTransform(readJsonGson("parts/materials/" + caseFile + ".json")); 211 | assertYamlEquivalent(expectedObject, YamlUtils.dump(actual)); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/ParameterTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import com.google.gson.JsonArray; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.util.Map; 8 | 9 | import static cd.go.plugin.config.yaml.TestUtils.*; 10 | import static org.hamcrest.CoreMatchers.is; 11 | import static org.hamcrest.MatcherAssert.assertThat; 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | public class ParameterTransformTest { 15 | 16 | private final ParameterTransform paramterTransform; 17 | 18 | public ParameterTransformTest() { 19 | paramterTransform = new ParameterTransform(); 20 | } 21 | 22 | @Test 23 | public void shouldTransformEmpty() throws IOException { 24 | testTransform("empty"); 25 | } 26 | 27 | @Test 28 | public void shouldTransformAParameter() throws IOException { 29 | testTransform("param"); 30 | } 31 | 32 | @Test 33 | public void shouldInverseTransformAParameter() throws IOException { 34 | testInverseTransform("param"); 35 | } 36 | 37 | private void testTransform(String caseFile) throws IOException { 38 | testTransform(caseFile, caseFile); 39 | } 40 | 41 | private void testTransform(String caseFile, String expectedFile) throws IOException { 42 | JsonArray expected = (JsonArray) readJsonObject("parts/parameters/" + expectedFile + ".json"); 43 | JsonArray actual = paramterTransform.transform(readYamlObject("parts/parameters/" + caseFile + ".yaml")); 44 | assertThat(actual, is(expected)); 45 | } 46 | 47 | private void testInverseTransform(String caseFile) throws IOException { 48 | testInverseTransform(caseFile, caseFile); 49 | } 50 | 51 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 52 | Map inverse = paramterTransform.inverseTransform(readJsonArrayGson("parts/parameters/" + caseFile + ".json")); 53 | JsonArray actual = paramterTransform.transform(inverse); 54 | assertEquals((readJsonObject("parts/parameters/" + expectedFile + ".json")), actual); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/PipelineTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonObjectMatcher; 4 | import cd.go.plugin.config.yaml.YamlUtils; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.internal.LinkedTreeMap; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.io.IOException; 11 | import java.util.Map; 12 | 13 | import static cd.go.plugin.config.yaml.TestUtils.*; 14 | import static org.hamcrest.CoreMatchers.is; 15 | import static org.hamcrest.MatcherAssert.assertThat; 16 | import static org.mockito.Mockito.*; 17 | 18 | public class PipelineTransformTest { 19 | 20 | private PipelineTransform parser; 21 | private MaterialTransform materialTransform; 22 | private StageTransform stageTransform; 23 | private EnvironmentVariablesTransform environmentTransform; 24 | private ParameterTransform parameterTransform; 25 | 26 | @BeforeEach 27 | public void SetUp() { 28 | materialTransform = mock(MaterialTransform.class); 29 | stageTransform = mock(StageTransform.class); 30 | environmentTransform = mock(EnvironmentVariablesTransform.class); 31 | parameterTransform = mock(ParameterTransform.class); 32 | 33 | parser = new PipelineTransform(materialTransform, stageTransform, environmentTransform, parameterTransform); 34 | } 35 | 36 | @Test 37 | public void shouldTransformSimplePipeline() throws IOException { 38 | testTransform("simple.pipe"); 39 | } 40 | @Test 41 | public void shouldTransformPipelineWithNestedStagesList() throws IOException { 42 | testTransform("stage_nested_list.pipe"); 43 | } 44 | 45 | @Test 46 | public void shouldTransformRichPipeline() throws IOException { 47 | testTransform("rich.pipe"); 48 | } 49 | 50 | @Test 51 | public void shouldTransformRichPipeline2() throws IOException { 52 | testTransform("lock_behavior.pipe"); 53 | } 54 | 55 | @Test 56 | public void shouldTransformAPipelineReferencingATemplate() throws IOException { 57 | testTransform("template_ref.pipe"); 58 | } 59 | 60 | @Test 61 | public void shouldTransformAPipelineWhichHasADisplayOrderWeight() throws IOException { 62 | testTransform("display_order.pipe"); 63 | } 64 | 65 | @Test 66 | public void shouldInverseTransformPipeline() throws IOException { 67 | Map materials = new LinkedTreeMap<>(); 68 | materials.put("foo", new LinkedTreeMap<>()); 69 | when(materialTransform.inverseTransform(any())).thenReturn(materials); 70 | 71 | testInverseTransform("export.pipe"); 72 | } 73 | 74 | @Test 75 | public void shouldInverseTransformAPipelineWhichHasADisplayOrderWeight() throws IOException { 76 | Map materials = new LinkedTreeMap<>(); 77 | materials.put("foo", new LinkedTreeMap<>()); 78 | when(materialTransform.inverseTransform(any())).thenReturn(materials); 79 | 80 | testInverseTransform("display_order.pipe"); 81 | } 82 | 83 | @Test 84 | public void inverseTransform_shouldHandleMultipleMaterialsWithoutNames() { 85 | parser = new PipelineTransform(new MaterialTransform(), stageTransform, environmentTransform, parameterTransform); 86 | 87 | Map pipeline = parser.inverseTransform(readJsonGson("parts/pipeline_with_multiple_materials.json")); 88 | 89 | assertThat(((Map)((Map)pipeline.get("pipe1")).get("materials")).size(), is(2)); 90 | } 91 | 92 | private void testTransform(String caseFile) throws IOException { 93 | testTransform(caseFile, caseFile); 94 | } 95 | 96 | private void testInverseTransform(String caseFile) throws IOException { 97 | testInverseTransform(caseFile, caseFile); 98 | } 99 | 100 | private void testTransform(String caseFile, String expectedFile) throws IOException { 101 | JsonObject expectedObject = (JsonObject) readJsonObject("parts/" + expectedFile + ".json"); 102 | JsonObject jsonObject = parser.transform(readYamlObject("parts/" + caseFile + ".yaml"), 9); 103 | assertThat(jsonObject, is(new JsonObjectMatcher(expectedObject))); 104 | } 105 | 106 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 107 | String expectedObject = loadString("parts/" + expectedFile + ".yaml"); 108 | Map actual = parser.inverseTransform(readJsonGson("parts/" + caseFile + ".json")); 109 | assertYamlEquivalent(expectedObject, YamlUtils.dump(actual)); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/RootTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonConfigCollection; 4 | import com.esotericsoftware.yamlbeans.YamlReader; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonObject; 7 | import com.google.gson.JsonPrimitive; 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import java.io.IOException; 12 | 13 | import static cd.go.plugin.config.yaml.TestUtils.readYamlObject; 14 | import static org.hamcrest.CoreMatchers.is; 15 | import static org.hamcrest.MatcherAssert.assertThat; 16 | import static org.junit.jupiter.api.Assertions.assertThrows; 17 | import static org.mockito.Mockito.mock; 18 | 19 | public class RootTransformTest { 20 | private RootTransform rootTransform; 21 | private PipelineTransform pipelineTransform; 22 | private EnvironmentsTransform environmentsTransform; 23 | 24 | @BeforeEach 25 | public void Setup() { 26 | pipelineTransform = mock(PipelineTransform.class); 27 | environmentsTransform = mock(EnvironmentsTransform.class); 28 | rootTransform = new RootTransform(pipelineTransform, environmentsTransform); 29 | } 30 | 31 | @Test 32 | public void shouldTransformEmptyRoot() throws IOException { 33 | JsonConfigCollection empty = readRootYaml("empty"); 34 | assertThat(empty.getJsonObject().isJsonObject(), is(true)); 35 | assertThat(empty.getJsonObject().get("environments").isJsonArray(), is(true)); 36 | assertThat(empty.getJsonObject().get("pipelines").isJsonArray(), is(true)); 37 | assertThat(empty.getJsonObject().get("environments").getAsJsonArray().size(), is(0)); 38 | assertThat(empty.getJsonObject().get("pipelines").getAsJsonArray().size(), is(0)); 39 | } 40 | 41 | @Test 42 | public void shouldTransformRootWhen2PipelinesAnd2Environments() throws IOException { 43 | JsonConfigCollection collection = readRootYaml("2"); 44 | assertThat(collection.getJsonObject().get("environments").getAsJsonArray().size(), is(2)); 45 | assertThat(collection.getJsonObject().get("pipelines").getAsJsonArray().size(), is(2)); 46 | } 47 | 48 | @Test 49 | public void shouldTransformRootWithCommonSection() throws IOException { 50 | JsonConfigCollection collection = readRootYaml("common_section"); 51 | assertThat(collection.getJsonObject().get("environments").getAsJsonArray().size(), is(1)); 52 | assertThat(collection.getJsonObject().get("pipelines").getAsJsonArray().size(), is(1)); 53 | } 54 | 55 | @Test 56 | public void shouldRecognizeAndUpdateVersion() throws Exception { 57 | assertTargetVersion(readRootYaml("version_not_present").getJsonObject(), 1); 58 | assertTargetVersion(readRootYaml("version_1").getJsonObject(), 1); 59 | assertTargetVersion(readRootYaml("version_2").getJsonObject(), 2); 60 | } 61 | 62 | @Test 63 | public void shouldPreserveOrderOfPipelines() throws IOException { 64 | MaterialTransform materialTransform = mock(MaterialTransform.class); 65 | StageTransform stageTransform = mock(StageTransform.class); 66 | EnvironmentVariablesTransform environmentTransform = mock(EnvironmentVariablesTransform.class); 67 | ParameterTransform parameterTransform = mock(ParameterTransform.class); 68 | pipelineTransform = new PipelineTransform(materialTransform, stageTransform, environmentTransform, parameterTransform); 69 | rootTransform = new RootTransform(pipelineTransform, environmentsTransform); 70 | 71 | JsonConfigCollection collection = readRootYaml("pipeline_order"); 72 | JsonArray pipelines = collection.getJsonObject().get("pipelines").getAsJsonArray(); 73 | assertThat(pipelines.get(0).getAsJsonObject().get("name").getAsString(), is("pipe1")); 74 | assertThat(pipelines.get(1).getAsJsonObject().get("name").getAsString(), is("pipe2")); 75 | assertThat(pipelines.get(2).getAsJsonObject().get("name").getAsString(), is("pipe3")); 76 | } 77 | 78 | @Test 79 | public void shouldNotTransformRootWhenYAMLHasDuplicateKeys() { 80 | assertThrows(YamlReader.YamlReaderException.class, () -> readRootYaml("duplicate.materials.pipe")); 81 | } 82 | 83 | private JsonConfigCollection readRootYaml(String caseFile) throws IOException { 84 | return rootTransform.transform(readYamlObject("parts/roots/" + caseFile + ".yaml"), "test code"); 85 | } 86 | 87 | private void assertTargetVersion(JsonObject jsonObject, int expectedVersion) { 88 | assertThat(jsonObject.get("target_version") instanceof JsonPrimitive, is(true)); 89 | assertThat(jsonObject.getAsJsonPrimitive("target_version").getAsInt(), is(expectedVersion)); 90 | } 91 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/StageTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonObjectMatcher; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.internal.LinkedTreeMap; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.util.Map; 11 | 12 | import static cd.go.plugin.config.yaml.TestUtils.*; 13 | import static org.hamcrest.CoreMatchers.is; 14 | import static org.hamcrest.MatcherAssert.assertThat; 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | import static org.mockito.Mockito.*; 17 | 18 | public class StageTransformTest { 19 | private StageTransform parser; 20 | private EnvironmentVariablesTransform environmentTransform; 21 | private JobTransform jobTransform; 22 | 23 | @BeforeEach 24 | public void SetUp() { 25 | environmentTransform = new EnvironmentVariablesTransform(); 26 | jobTransform = mock(JobTransform.class); 27 | parser = new StageTransform(environmentTransform, jobTransform); 28 | } 29 | 30 | @Test 31 | public void shouldTransformCompleteStage() throws IOException { 32 | testTransform("complete"); 33 | } 34 | 35 | @Test 36 | public void shouldTransformCompleteStageWithManualApproval() throws IOException { 37 | testTransform("complete_with_manual_approval"); 38 | } 39 | 40 | @Test 41 | public void shouldTransformShortApprovalStage() throws IOException { 42 | testTransform("short_approval"); 43 | } 44 | 45 | @Test 46 | public void shouldTransformSingleJobStage() throws IOException { 47 | parser = new StageTransform(environmentTransform, new JobTransform(environmentTransform, mock(TaskTransform.class))); 48 | testTransform("stage-job"); 49 | } 50 | 51 | @Test 52 | public void shouldInverseTransformCompleteStage() throws IOException { 53 | Map jobs = new LinkedTreeMap<>(); 54 | jobs.put("one", null); 55 | jobs.put("two", null); 56 | when(jobTransform.inverseTransform(any())).thenReturn(jobs); 57 | testInverseTransform("complete"); 58 | } 59 | 60 | @Test 61 | public void shouldInverseTransformSingleJobStage() throws IOException { 62 | parser = new StageTransform(environmentTransform, new JobTransform(environmentTransform, mock(TaskTransform.class))); 63 | testTransform("stage-job"); 64 | } 65 | 66 | private void testTransform(String caseFile) throws IOException { 67 | testTransform(caseFile, caseFile); 68 | } 69 | 70 | private void testTransform(String caseFile, String expectedFile) throws IOException { 71 | JsonObject expectedObject = (JsonObject) readJsonObject("parts/stages/" + expectedFile + ".json"); 72 | JsonObject jsonObject = parser.transform(readYamlObject("parts/stages/" + caseFile + ".yaml")); 73 | assertThat(jsonObject, is(new JsonObjectMatcher(expectedObject))); 74 | } 75 | 76 | private void testInverseTransform(String caseFile) throws IOException { 77 | testInverseTransform(caseFile, caseFile); 78 | } 79 | 80 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 81 | Map inverse = parser.inverseTransform(readJsonGson("parts/stages/" + caseFile + ".json")); 82 | JsonObject actual = parser.transform(inverse); 83 | assertEquals((readJsonObject("parts/stages/" + expectedFile + ".json")), actual); 84 | } 85 | } -------------------------------------------------------------------------------- /src/test/java/cd/go/plugin/config/yaml/transforms/TaskTransformTest.java: -------------------------------------------------------------------------------- 1 | package cd.go.plugin.config.yaml.transforms; 2 | 3 | import cd.go.plugin.config.yaml.JsonObjectMatcher; 4 | import com.google.gson.JsonObject; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.IOException; 8 | import java.util.Map; 9 | 10 | import static cd.go.plugin.config.yaml.TestUtils.*; 11 | import static org.hamcrest.CoreMatchers.is; 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | import static org.junit.jupiter.api.Assertions.assertEquals; 14 | 15 | public class TaskTransformTest { 16 | private final TaskTransform parser; 17 | 18 | public TaskTransformTest() { 19 | parser = new TaskTransform(); 20 | } 21 | 22 | @Test 23 | public void shouldTransformMinimalFetch() throws IOException { 24 | testTransform("minimal.fetch"); 25 | } 26 | 27 | @Test 28 | public void shouldTransformCompleteFetch() throws IOException { 29 | testTransform("complete.fetch"); 30 | } 31 | 32 | @Test 33 | public void shouldTransformFetchExternalArtifactTask() throws IOException { 34 | testTransform("fetch_external_artifact"); 35 | } 36 | 37 | @Test 38 | public void shouldTransformCompleteRake() throws IOException { 39 | testTransform("complete.rake"); 40 | } 41 | 42 | @Test 43 | public void shouldTransformCompletePlugin() throws IOException { 44 | testTransform("complete.plugin"); 45 | } 46 | 47 | @Test 48 | public void shouldTransformMinimalRake() throws IOException { 49 | testTransform("minimal.rake"); 50 | } 51 | 52 | @Test 53 | public void shouldTransformFullExec() throws IOException { 54 | testTransform("full.exec"); 55 | } 56 | 57 | @Test 58 | public void shouldTransformScript() throws IOException { 59 | testTransform("script"); 60 | } 61 | 62 | @Test 63 | public void shouldTransformMultilineScript() throws IOException { 64 | JsonObject plugin = testTransform("multiline.script"); 65 | assertThat(plugin.getAsJsonArray("configuration").get(0).getAsJsonObject().get("value").getAsString(), is("./build.sh compile\nmake test")); 66 | } 67 | 68 | @Test 69 | public void shouldTransformBreaklineScript() throws IOException { 70 | JsonObject plugin = testTransform("breakline.script"); 71 | assertThat(plugin.getAsJsonArray("configuration").get(0).getAsJsonObject().get("value").getAsString(), is("./build.sh compile && make test")); 72 | } 73 | 74 | @Test 75 | public void shouldInverseTransformFullExec() throws IOException { 76 | testInverseTransform("full.exec"); 77 | } 78 | 79 | @Test 80 | public void shouldInverseTransformMinimalFetch() throws IOException { 81 | testInverseTransform("minimal.fetch"); 82 | } 83 | 84 | @Test 85 | public void shouldInverseTransformCompleteFetch() throws IOException { 86 | testInverseTransform("complete.fetch"); 87 | } 88 | 89 | @Test 90 | public void shouldInverseTransformCompleteRake() throws IOException { 91 | testInverseTransform("complete.rake"); 92 | } 93 | 94 | @Test 95 | public void shouldInverseTransformCompletePlugin() throws IOException { 96 | testInverseTransform("complete.plugin"); 97 | } 98 | 99 | @Test 100 | public void shouldInverseTransformMinimalRake() throws IOException { 101 | testInverseTransform("minimal.rake"); 102 | } 103 | 104 | @Test 105 | public void shouldInverseTransformScript() throws IOException { 106 | testInverseTransform("script"); 107 | } 108 | 109 | @Test 110 | public void shouldInverseTransformMultilineScript() throws IOException { 111 | testInverseTransform("multiline.script"); 112 | } 113 | 114 | @Test 115 | public void shouldInverseTransformBreaklineScript() throws IOException { 116 | testInverseTransform("breakline.script"); 117 | } 118 | 119 | private JsonObject testTransform(String caseFile) throws IOException { 120 | return testTransform(caseFile, caseFile); 121 | } 122 | 123 | private JsonObject testTransform(String caseFile, String expectedFile) throws IOException { 124 | JsonObject expectedObject = (JsonObject) readJsonObject("parts/tasks/" + expectedFile + ".json"); 125 | JsonObject jsonObject = parser.transform(readYamlObject("parts/tasks/" + caseFile + ".yaml")); 126 | assertThat(jsonObject, is(new JsonObjectMatcher(expectedObject))); 127 | return jsonObject; 128 | } 129 | 130 | private void testInverseTransform(String caseFile) throws IOException { 131 | testInverseTransform(caseFile, caseFile); 132 | } 133 | 134 | private void testInverseTransform(String caseFile, String expectedFile) throws IOException { 135 | Map inverse = parser.inverseTransform(readJsonGson("parts/tasks/" + caseFile + ".json")); 136 | JsonObject actual = parser.transform(inverse); 137 | assertEquals((readJsonObject("parts/tasks/" + expectedFile + ".json")), actual); 138 | } 139 | } -------------------------------------------------------------------------------- /src/test/resources/examples.out/README.md: -------------------------------------------------------------------------------- 1 | This directory contains JSON responses that would be sent to GoCD server after parsing 2 | contents of files in [examples](../examples). 3 | -------------------------------------------------------------------------------- /src/test/resources/examples.out/aliases.gocd.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_version": 1, 3 | "environments": [], 4 | "pipelines": [{ 5 | "name": "pipe1", 6 | "group": "aliases", 7 | "materials": [{ 8 | "name": "mygit", 9 | "type": "git", 10 | "url": "https://my.example.org/mygit.git", 11 | "branch": "ci" 12 | }], 13 | "stages": [{ 14 | "name": "prepare", 15 | "jobs": [{ 16 | "name": "prepare", 17 | "tasks": [{ 18 | "type": "exec", 19 | "arguments": ["hello world"], 20 | "command": "prepare" 21 | }] 22 | }] 23 | }, { 24 | "name": "build", 25 | "jobs": [{ 26 | "name": "build", 27 | "tasks": [{ 28 | "type": "exec", 29 | "command": "init" 30 | }, { 31 | "type": "exec", 32 | "arguments": ["VERBOSE=true"], 33 | "command": "make" 34 | }] 35 | }] 36 | }, { 37 | "name": "test", 38 | "jobs": [{ 39 | "name": "test", 40 | "tasks": [{ 41 | "type": "exec", 42 | "command": "init" 43 | }, { 44 | "type": "exec", 45 | "arguments": ["VERBOSE=true"], 46 | "command": "make" 47 | }, { 48 | "type": "exec", 49 | "command": "test_unit" 50 | }, { 51 | "type": "exec", 52 | "command": "test_integration" 53 | }] 54 | }] 55 | }], 56 | "location": "aliases.gocd.yaml" 57 | }], 58 | "errors": [] 59 | } -------------------------------------------------------------------------------- /src/test/resources/examples.out/format-version-10.gocd.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_version": 10, 3 | "errors": [], 4 | "environments": [], 5 | "pipelines": [ 6 | { 7 | "location": "format-version-10.gocd.yaml", 8 | "name": "pipe1", 9 | "group": "simple", 10 | "materials": [ 11 | { 12 | "name": "mygit", 13 | "type": "git", 14 | "url": "https://my.example.org/mygit.git", 15 | "filter": { 16 | "includes": [ 17 | "externals", 18 | "tools" 19 | ] 20 | } 21 | } 22 | ], 23 | "stages": [ 24 | { 25 | "name": "build", 26 | "jobs": [ 27 | { 28 | "name": "build", 29 | "tasks": [ 30 | { 31 | "type": "exec", 32 | "command": "make" 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | }, 40 | { 41 | "location": "format-version-10.gocd.yaml", 42 | "name": "pipe2", 43 | "group": "simple", 44 | "materials": [ 45 | { 46 | "name": "mygit", 47 | "type": "git", 48 | "url": "https://my.example.org/mygit.git", 49 | "filter": { 50 | "includes": [ 51 | "externals", 52 | "tools" 53 | ] 54 | } 55 | } 56 | ], 57 | "stages": [ 58 | { 59 | "name": "build", 60 | "jobs": [ 61 | { 62 | "name": "build", 63 | "tasks": [ 64 | { 65 | "type": "exec", 66 | "command": "make" 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /src/test/resources/examples.out/format-version-9.gocd.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_version": 9, 3 | "errors": [], 4 | "environments": [], 5 | "pipelines": [ 6 | { 7 | "location": "format-version-9.gocd.yaml", 8 | "name": "pipe1", 9 | "group": "simple", 10 | "materials": [ 11 | { 12 | "name": "mygit", 13 | "type": "git", 14 | "url": "https://my.example.org/mygit.git", 15 | "filter": { 16 | "whitelist": [ 17 | "externals", 18 | "tools" 19 | ] 20 | } 21 | } 22 | ], 23 | "stages": [ 24 | { 25 | "name": "build", 26 | "jobs": [ 27 | { 28 | "name": "build", 29 | "tasks": [ 30 | { 31 | "type": "exec", 32 | "command": "make" 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | }, 40 | { 41 | "location": "format-version-9.gocd.yaml", 42 | "name": "pipe2", 43 | "group": "simple", 44 | "materials": [ 45 | { 46 | "name": "mygit", 47 | "type": "git", 48 | "url": "https://my.example.org/mygit.git", 49 | "filter" : { 50 | "whitelist": [ 51 | "externals", 52 | "tools" 53 | ] 54 | } 55 | } 56 | ], 57 | "stages": [ 58 | { 59 | "name": "build", 60 | "jobs": [ 61 | { 62 | "name": "build", 63 | "tasks": [ 64 | { 65 | "type": "exec", 66 | "command": "make" 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /src/test/resources/examples.out/rich.gocd.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_version": 1, 3 | "errors": [], 4 | "environments": [], 5 | "pipelines": [ 6 | { 7 | "location": "rich.gocd.yaml", 8 | "name": "pipe2", 9 | "group": "rich", 10 | "label_template": "${mygit[:8]}", 11 | "enable_pipeline_locking": true, 12 | "tracking_tool": { 13 | "link": "http://your-trackingtool/yourproject/${ID}", 14 | "regex": "evo-(\\d+)" 15 | }, 16 | "timer": { 17 | "spec": "0 0 22 ? * MON-FRI", 18 | "only_on_changes": true 19 | }, 20 | "materials": [ 21 | { 22 | "name": "mygit", 23 | "type": "git", 24 | "url": "https://my.example.org/mygit.git", 25 | "branch": "ci" 26 | }, 27 | { 28 | "name": "upstream", 29 | "type": "dependency", 30 | "pipeline": "pipe2", 31 | "stage": "test" 32 | } 33 | ], 34 | "stages": [ 35 | { 36 | "name": "build", 37 | "clean_working_directory": true, 38 | "approval": { 39 | "type": "manual", 40 | "roles": [ 41 | "manager" 42 | ] 43 | }, 44 | "jobs": [ 45 | { 46 | "name": "csharp", 47 | "run_instance_count": 3, 48 | "resources": [ 49 | "net45" 50 | ], 51 | "artifacts": [ 52 | { 53 | "type": "build", 54 | "source": "bin/", 55 | "destination": "build" 56 | }, 57 | { 58 | "type": "test", 59 | "source": "tests/", 60 | "destination": "test-reports/" 61 | } 62 | ], 63 | "tabs": [ 64 | { 65 | "name": "report", 66 | "path": "test-reports/index.html" 67 | } 68 | ], 69 | "environment_variables": [ 70 | { 71 | "name": "MONO_PATH", 72 | "value": "/usr/bin/local/mono" 73 | }, 74 | { 75 | "name": "PASSWORD", 76 | "encrypted_value": "s&Du#@$xsSa" 77 | } 78 | ], 79 | "properties": [ 80 | { 81 | "name": "perf", 82 | "source": "test.xml", 83 | "xpath": "substring-before(//report/data/all/coverage[starts-with(@type,\u0027class\u0027)]/@value, \u0027%\u0027)" 84 | } 85 | ], 86 | "tasks": [ 87 | { 88 | "type": "fetch", 89 | "pipeline": "pipe2", 90 | "stage": "build", 91 | "job": "test", 92 | "source": "test-bin/", 93 | "destination": "bin/" 94 | }, 95 | { 96 | "type": "exec", 97 | "command": "make", 98 | "arguments": [ 99 | "VERBOSE=true" 100 | ] 101 | }, 102 | { 103 | "type": "plugin", 104 | "configuration": [ 105 | { 106 | "key": "script", 107 | "value": "./build.sh ci" 108 | } 109 | ], 110 | "plugin_configuration": { 111 | "id": "script-executor", 112 | "version": "1" 113 | } 114 | } 115 | ] 116 | } 117 | ] 118 | } 119 | ] 120 | } 121 | ] 122 | } 123 | -------------------------------------------------------------------------------- /src/test/resources/examples.out/simple.gocd.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_version": 1, 3 | "errors": [], 4 | "environments": [], 5 | "pipelines": [ 6 | { 7 | "location": "simple.gocd.yaml", 8 | "name": "pipe1", 9 | "group": "simple", 10 | "materials": [ 11 | { 12 | "name": "mygit", 13 | "type": "git", 14 | "url": "https://my.example.org/mygit.git" 15 | } 16 | ], 17 | "stages": [ 18 | { 19 | "name": "build", 20 | "jobs": [ 21 | { 22 | "name": "build", 23 | "tasks": [ 24 | { 25 | "type": "exec", 26 | "command": "make" 27 | } 28 | ] 29 | } 30 | ] 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /src/test/resources/examples/aliases.gocd.yaml: -------------------------------------------------------------------------------- 1 | # aliases.gocd.yaml 2 | common: # aliases section 3 | scalar_alias: &scalar_alias "hello world" 4 | task_list_alias: &task_list_alias 5 | - exec: 6 | command: init 7 | - exec: 8 | command: make 9 | arguments: 10 | - "VERBOSE=true" 11 | pipelines: 12 | pipe1: 13 | group: aliases 14 | materials: 15 | mygit: 16 | git: https://my.example.org/mygit.git 17 | branch: ci 18 | stages: 19 | - prepare: 20 | jobs: 21 | prepare: 22 | tasks: 23 | - exec: 24 | command: prepare 25 | arguments: # use of scalar alias 26 | - *scalar_alias 27 | - build: 28 | jobs: 29 | build: 30 | tasks: *task_list_alias # use of task list alias as the full list 31 | - test: 32 | jobs: 33 | test: 34 | tasks: 35 | - *task_list_alias # use of task list alias as a partial list with more added 36 | - exec: 37 | command: test_unit 38 | - exec: 39 | command: test_integration -------------------------------------------------------------------------------- /src/test/resources/examples/duplicate-materials.gocd.yaml: -------------------------------------------------------------------------------- 1 | pipelines: 2 | pipe1: 3 | group: group 4 | materials: 5 | upstream: 6 | pipeline: upstream-pipeline-1 7 | stage: test1 8 | upstream: 9 | pipeline: upstream-pipeline-2 10 | stage: test2 -------------------------------------------------------------------------------- /src/test/resources/examples/format-version-10.gocd.yaml: -------------------------------------------------------------------------------- 1 | # format-version-10.gocd.yaml 2 | # This test resource is for whitelist/includes migration cases 3 | format_version: 10 4 | pipelines: 5 | pipe1: 6 | group: simple 7 | materials: 8 | mygit: 9 | git: https://my.example.org/mygit.git 10 | # whitelist is still allowed (backwards compatibility) and transforms to includes because format_version is 10 11 | whitelist: 12 | - externals 13 | - tools 14 | stages: 15 | - build: 16 | jobs: 17 | build: 18 | tasks: 19 | - exec: 20 | command: make 21 | pipe2: 22 | group: simple 23 | materials: 24 | mygit: 25 | git: https://my.example.org/mygit.git 26 | # includes is allowed and transforms to includes because format_version is 10 27 | includes: 28 | - externals 29 | - tools 30 | stages: 31 | - build: 32 | jobs: 33 | build: 34 | tasks: 35 | - exec: 36 | command: make -------------------------------------------------------------------------------- /src/test/resources/examples/format-version-9.gocd.yaml: -------------------------------------------------------------------------------- 1 | # format-version-9.gocd.yaml 2 | # This test resource is for whitelist/includes migration cases 3 | format_version: 9 4 | pipelines: 5 | pipe1: 6 | group: simple 7 | materials: 8 | mygit: 9 | git: https://my.example.org/mygit.git 10 | # whitelist is still allowed and transforms to whitelist because format_version is 9 11 | whitelist: 12 | - externals 13 | - tools 14 | stages: 15 | - build: 16 | jobs: 17 | build: 18 | tasks: 19 | - exec: 20 | command: make 21 | pipe2: 22 | group: simple 23 | materials: 24 | mygit: 25 | git: https://my.example.org/mygit.git 26 | # includes is allowed and transforms to whitelist because format_version is 9 27 | includes: 28 | - externals 29 | - tools 30 | stages: 31 | - build: 32 | jobs: 33 | build: 34 | tasks: 35 | - exec: 36 | command: make -------------------------------------------------------------------------------- /src/test/resources/examples/invalid-materials.gocd.yaml: -------------------------------------------------------------------------------- 1 | pipelines: 2 | pipe1: 3 | group: group 4 | materials: 5 | upstream: 6 | pipeline: upstream-pipeline-1 7 | stage: test1 8 | stages: # list of stages in order 9 | - build-image: # name of stage 10 | clean_workspace: true 11 | jobs: 12 | build-image: # name of the job 13 | artifacts: 14 | - build: 15 | source: image_ref 16 | tasks: 17 | - exec: # indicates type of task 18 | command: bash 19 | arguments:` 20 | - "-c" 21 | - "docker build" 22 | -------------------------------------------------------------------------------- /src/test/resources/examples/rich.gocd.yaml: -------------------------------------------------------------------------------- 1 | # rich.gocd.yaml 2 | pipelines: # tells plugin that here are pipelines by name 3 | pipe2: 4 | group: rich 5 | label_template: "${mygit[:8]}" 6 | locking: on 7 | tracking_tool: 8 | link: "http://your-trackingtool/yourproject/${ID}" 9 | regex: "evo-(\\d+)" 10 | timer: 11 | spec: "0 0 22 ? * MON-FRI" 12 | only_on_changes: true 13 | materials: 14 | mygit: # this is the name of material 15 | # says about type of material and url at once 16 | git: https://my.example.org/mygit.git 17 | branch: ci 18 | upstream: 19 | # type is optional here, material type is implied based on pipeline and stage fields 20 | type: dependency 21 | pipeline: pipe2 22 | stage: test 23 | stages: 24 | - build: # name of stage 25 | clean_workspace: true 26 | approval: 27 | type: manual 28 | allow_only_on_success: true 29 | roles: 30 | - manager 31 | jobs: 32 | csharp: # name of the job 33 | run_instances: 3 34 | resources: 35 | - net45 36 | artifacts: 37 | - build: 38 | source: bin/ 39 | destination: build 40 | - test: 41 | source: tests/ 42 | destination: test-reports/ 43 | tabs: 44 | report: test-reports/index.html 45 | environment_variables: 46 | MONO_PATH: /usr/bin/local/mono 47 | secure_variables: 48 | PASSWORD: "s&Du#@$xsSa" 49 | properties: 50 | perf: 51 | source: test.xml 52 | xpath: "substring-before(//report/data/all/coverage[starts-with(@type,\u0027class\u0027)]/@value, \u0027%\u0027)" 53 | tasks: 54 | - fetch: 55 | pipeline: pipe2 56 | stage: build 57 | job: test 58 | source: test-bin/ 59 | destination: bin/ 60 | - exec: # indicates type of task 61 | command: make 62 | arguments: 63 | - "VERBOSE=true" 64 | # shorthand for script-executor plugin 65 | - script: ./build.sh ci 66 | -------------------------------------------------------------------------------- /src/test/resources/examples/simple-invalid.gocd.yaml: -------------------------------------------------------------------------------- 1 | # simple.gocd.yaml 2 | pipelines: 3 | pipe1: 4 | group: simple 5 | materials: 6 | # materials should be a hash - bogus ! 7 | - mygit: 8 | git: https://my.example.org/mygit.git 9 | stages: 10 | - build: # name of stage 11 | jobs: 12 | build: # name of the job 13 | tasks: 14 | - exec: # indicates type of task 15 | command: make 16 | -------------------------------------------------------------------------------- /src/test/resources/examples/simple.gocd.yaml: -------------------------------------------------------------------------------- 1 | # simple.gocd.yaml 2 | pipelines: 3 | pipe1: 4 | group: simple 5 | materials: 6 | mygit: # this is the name of material 7 | # says about type of material and url at once 8 | git: https://my.example.org/mygit.git 9 | stages: 10 | - build: # name of stage 11 | jobs: 12 | build: # name of the job 13 | tasks: 14 | - exec: # indicates type of task 15 | command: make 16 | -------------------------------------------------------------------------------- /src/test/resources/parts/display_order.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pipe1", 3 | "group": "group1", 4 | "display_order_weight": 10, 5 | "materials": [ 6 | null 7 | ], 8 | "stages": [ 9 | null, 10 | null 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/parts/display_order.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe1: 2 | group: group1 3 | display_order: 10 4 | materials: 5 | foo: {} 6 | stages: 7 | - null 8 | - null -------------------------------------------------------------------------------- /src/test/resources/parts/env_vars/1safe.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "ENV_PASSWORD", 4 | "encrypted_value": "s&Du#@$xsSa" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/env_vars/1safe.yaml: -------------------------------------------------------------------------------- 1 | secure_variables: 2 | ENV_PASSWORD: "s&Du#@$xsSa" 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/env_vars/2vars.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "DEPLOYMENT", 4 | "value": "testing" 5 | }, 6 | { 7 | "name": "ENV_PASSWORD", 8 | "encrypted_value": "s&Du#@$xsSa" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /src/test/resources/parts/env_vars/2vars.yaml: -------------------------------------------------------------------------------- 1 | environment_variables: 2 | DEPLOYMENT: testing 3 | secure_variables: 4 | ENV_PASSWORD: "s&Du#@$xsSa" 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/env_vars/empty.json: -------------------------------------------------------------------------------- 1 | [ 2 | ] 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/env_vars/empty.yaml: -------------------------------------------------------------------------------- 1 | environment_variables: 2 | secure_variables: 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/environments/complete.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testing", 3 | "environment_variables": [ 4 | { 5 | "name": "DEPLOYMENT", 6 | "value": "testing" 7 | }, 8 | { 9 | "name": "ENV_PASSWORD", 10 | "encrypted_value": "s&Du#@$xsSa" 11 | } 12 | ], 13 | "pipelines": [ 14 | "example-deploy-testing", 15 | "build-testing" 16 | ], 17 | "agents": [ 18 | "123" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/parts/environments/complete.yaml: -------------------------------------------------------------------------------- 1 | testing: 2 | environment_variables: 3 | DEPLOYMENT: testing 4 | secure_variables: 5 | ENV_PASSWORD: "s&Du#@$xsSa" 6 | pipelines: 7 | - example-deploy-testing 8 | - build-testing 9 | agents: 10 | - 123 11 | -------------------------------------------------------------------------------- /src/test/resources/parts/environments/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dev" 3 | } 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/environments/empty.yaml: -------------------------------------------------------------------------------- 1 | dev: 2 | -------------------------------------------------------------------------------- /src/test/resources/parts/export.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": "group1", 3 | "name": "pipe2", 4 | "label_template": "foo-1.0-${COUNT}", 5 | "enable_pipeline_locking": true, 6 | "tracking_tool": { 7 | "link": "http://your-trackingtool/yourproject/${ID}", 8 | "regex": "evo-(\\d+)" 9 | }, 10 | "timer": { 11 | "spec": "0 15 10 * * ? *", 12 | "only_on_changes": true 13 | }, 14 | "materials": [ 15 | { 16 | "name": "foo" 17 | } 18 | ], 19 | "stages": [ 20 | null, 21 | null 22 | ] 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/test/resources/parts/export.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe2: 2 | group: group1 3 | label_template: "foo-1.0-${COUNT}" 4 | locking: on 5 | tracking_tool: 6 | link: "http://your-trackingtool/yourproject/${ID}" 7 | regex: "evo-(\\d+)" 8 | timer: 9 | spec: "0 15 10 * * ? *" 10 | only_on_changes: yes 11 | materials: 12 | foo: {} 13 | stages: 14 | - null 15 | - null 16 | 17 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/complete.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "timeout" : 5, 4 | "run_instance_count": 7, 5 | "environment_variables": [ 6 | { 7 | "name": "LD_LIBRARY_PATH", 8 | "value": "." 9 | } 10 | ], 11 | "tabs": [ 12 | { 13 | "name": "test", 14 | "path": "results.xml" 15 | } 16 | ], 17 | "resources": [ 18 | "linux" 19 | ], 20 | "artifacts": [ 21 | { 22 | "source": "src", 23 | "destination": "dest", 24 | "type": "test" 25 | }, 26 | { 27 | "source": "bin", 28 | "type": "build" 29 | } 30 | ], 31 | "properties": [ 32 | { 33 | "name": "perf", 34 | "source": "test.xml", 35 | "xpath": "substring-before(//report/data/all/coverage[starts-with(@type,\u0027class\u0027)]/@value, \u0027%\u0027)" 36 | } 37 | ], 38 | "tasks": [ 39 | null 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/complete.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | timeout: 5 3 | run_instances: 7 4 | environment_variables: 5 | LD_LIBRARY_PATH: . 6 | tabs: 7 | test: results.xml 8 | resources: 9 | - linux 10 | artifacts: 11 | - test: 12 | source: src 13 | destination: dest 14 | - build: 15 | source: bin 16 | properties: 17 | perf: 18 | source: test.xml 19 | xpath: "substring-before(//report/data/all/coverage[starts-with(@type,\u0027class\u0027)]/@value, \u0027%\u0027)" 20 | tasks: 21 | - null 22 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/elastic_profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "elastic_profile_id" : "profile-id", 4 | "tasks": [ 5 | null 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/elastic_profile.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | elastic_profile_id: "profile-id" 3 | tasks: 4 | - null 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/external_artifacts.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "artifacts": [ 4 | { 5 | "type": "build", 6 | "source": "src1", 7 | "destination": "dest1" 8 | }, 9 | { 10 | "type": "test", 11 | "source": "src2", 12 | "destination": "dest2" 13 | }, 14 | { 15 | "type": "external", 16 | "id": "blinky", 17 | "store_id": "shadow", 18 | "configuration": [ 19 | { 20 | "key": "white_russian", 21 | "value": "cocktail" 22 | }, 23 | { 24 | "key": "fermented_coffee", 25 | "encrypted_value": "sfsggge124#" 26 | } 27 | ] 28 | } 29 | ], 30 | "tasks": [ 31 | { 32 | "type": "exec", 33 | "command": "make" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/external_artifacts.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | artifacts: 3 | - build: 4 | source: src1 5 | destination: dest1 6 | - test: 7 | source: src2 8 | destination: dest2 9 | - external: 10 | id: blinky 11 | store_id: shadow 12 | configuration: 13 | options: 14 | white_russian: "cocktail" 15 | secure_options: 16 | fermented_coffee: "sfsggge124#" 17 | tasks: 18 | - exec: 19 | command: make 20 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/list_of_lists_tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "tasks": [ 4 | { 5 | "type": "exec", 6 | "arguments": ["clean"], 7 | "command": "./gradlew" 8 | }, 9 | { 10 | "type": "exec", 11 | "arguments": ["assemble"], 12 | "command": "./gradlew" 13 | }, 14 | { 15 | "type": "exec", 16 | "arguments": ["test"], 17 | "command": "./gradlew" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/list_of_lists_tasks.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | tasks: 3 | - 4 | - exec: 5 | command: ./gradlew 6 | arguments: 7 | - clean 8 | - exec: 9 | command: ./gradlew 10 | arguments: 11 | - assemble 12 | - exec: 13 | command: ./gradlew 14 | arguments: 15 | - test -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "tasks": [ 4 | null 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/minimal.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | tasks: 3 | - null 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/minimal_defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "run_instance_count": 0, 4 | "tasks": [ 5 | null 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/minimal_defaults.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | tasks: 3 | - null 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/runall.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "run_instance_count": "all", 4 | "tasks": [ 5 | null 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/parts/jobs/runall.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | run_instances: all 3 | tasks: 4 | - null 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/lock_behavior.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": "group1", 3 | "name": "pipe2", 4 | "lock_behavior": "lockOnFailure", 5 | "materials": [ 6 | null, 7 | null 8 | ], 9 | "stages": [ 10 | null, 11 | null 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/parts/lock_behavior.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe2: 2 | group: group1 3 | lock_behavior: "lockOnFailure" 4 | environment_variables: null 5 | materials: 6 | foo: 7 | bar: 8 | stages: 9 | - null 10 | - null 11 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/auto_update.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mygit", 3 | "type": "git", 4 | "auto_update": false, 5 | "url": "http://example.com/mygit.git" 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/auto_update.git.yaml: -------------------------------------------------------------------------------- 1 | mygit: 2 | git: http://example.com/mygit.git 3 | auto_update: false 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/branch.hg.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "repos/myhg", 3 | "branch": "feature" 4 | } -------------------------------------------------------------------------------- /src/test/resources/parts/materials/branch.hg.yaml: -------------------------------------------------------------------------------- 1 | hgMaterial1: 2 | hg: repos/myhg 3 | branch: feature -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.cr.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crMaterial", 3 | "type": "configrepo", 4 | "filter": { 5 | "ignore": [ 6 | "externals", 7 | "tools" 8 | ] 9 | }, 10 | "destination": "dir1" 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.cr.yaml: -------------------------------------------------------------------------------- 1 | crMaterial: 2 | type: configrepo 3 | ignore: 4 | - externals 5 | - tools 6 | destination: dir1 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitMaterial1", 3 | "type": "git", 4 | "url": "https://my.git.repository.com", 5 | "branch": "feature12", 6 | "username": "username", 7 | "encrypted_password": "some encrypted value", 8 | "filter": { 9 | "includes": [ 10 | "externals", 11 | "tools" 12 | ] 13 | }, 14 | "destination": "dir1", 15 | "auto_update": false, 16 | "shallow_clone": true 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.git.yaml: -------------------------------------------------------------------------------- 1 | gitMaterial1: 2 | git: "https://my.git.repository.com" 3 | username: "username" 4 | encrypted_password: "some encrypted value" 5 | branch: "feature12" 6 | includes: 7 | - externals 8 | - tools 9 | destination: dir1 10 | auto_update: false 11 | shallow_clone: true 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.hg.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "repos/myhg", 3 | "username": "username", 4 | "encrypted_password": "some encrypted value", 5 | "filter": { 6 | "ignore": [ 7 | "externals", 8 | "tools" 9 | ] 10 | }, 11 | "destination": "dir1", 12 | "auto_update": false, 13 | "name": "hgMaterial1", 14 | "type": "hg" 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.hg.yaml: -------------------------------------------------------------------------------- 1 | hgMaterial1: 2 | hg: repos/myhg 3 | username: username 4 | encrypted_password: some encrypted value 5 | ignore: 6 | - externals 7 | - tools 8 | destination: dir1 9 | auto_update: false 10 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.p4.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "p4Material1", 3 | "type": "p4", 4 | "port": "host.domain.com:12345", 5 | "username": "johndoe", 6 | "password": "pass", 7 | "use_tickets": false, 8 | "view": "//depot/external... //ws/external...\n//depot/tools... //ws/external...", 9 | "filter": { 10 | "ignore": [ 11 | "externals", 12 | "tools" 13 | ] 14 | }, 15 | "auto_update": false 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.p4.yaml: -------------------------------------------------------------------------------- 1 | p4Material1: 2 | p4: "host.domain.com:12345" 3 | username: johndoe 4 | password: pass 5 | use_tickets: false 6 | view: |- 7 | //depot/external... //ws/external... 8 | //depot/tools... //ws/external... 9 | ignore: 10 | - externals 11 | - tools 12 | auto_update: false 13 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.pluggable.json: -------------------------------------------------------------------------------- 1 | { 2 | "scm_id": "someScmGitRepositoryId", 3 | "destination": "destinationDir", 4 | "filter": { 5 | "ignore": [ 6 | "dir1", 7 | "dir2" 8 | ] 9 | }, 10 | "name": "myPluggableGit", 11 | "type": "plugin" 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.pluggable.yaml: -------------------------------------------------------------------------------- 1 | myPluggableGit: 2 | scm: someScmGitRepositoryId 3 | destination: destinationDir 4 | ignore: 5 | - dir1 6 | - dir2 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.scm.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugin_configuration": { 3 | "id": "plugin_id", 4 | "version": "1" 5 | }, 6 | "configuration": [{ 7 | "key": "url", 8 | "value": "url" 9 | }], 10 | "destination": "destinationDir", 11 | "filter": { 12 | "ignore": [ 13 | "dir1", 14 | "dir2" 15 | ] 16 | }, 17 | "name": "myPluggableGit", 18 | "type": "plugin", 19 | "scm_id": "myScmId" 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.scm.yaml: -------------------------------------------------------------------------------- 1 | myPluggableGit: 2 | scm: myScmId 3 | plugin_configuration: 4 | id: plugin_id 5 | version: "1" 6 | options: 7 | url: url 8 | ignore: 9 | - dir1 10 | - dir2 11 | destination: destinationDir 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.svn.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "http://svn", 3 | "username": "user1", 4 | "password": "pass1", 5 | "check_externals": true, 6 | "filter": { 7 | "ignore": [ 8 | "tools", 9 | "lib" 10 | ] 11 | }, 12 | "destination": "destDir1", 13 | "auto_update": false, 14 | "name": "svnMaterial1", 15 | "type": "svn" 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10.svn.yaml: -------------------------------------------------------------------------------- 1 | svnMaterial1: 2 | svn: "http://svn" 3 | username: "user1" 4 | password: "pass1" 5 | check_externals: true 6 | ignore: 7 | - tools 8 | - lib 9 | destination: destDir1 10 | auto_update: false 11 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10backwards.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitMaterial1", 3 | "type": "git", 4 | "url": "https://my.git.repository.com", 5 | "branch": "feature12", 6 | "username": "username", 7 | "encrypted_password": "some encrypted value", 8 | "filter": { 9 | "includes": [ 10 | "externals", 11 | "tools" 12 | ] 13 | }, 14 | "destination": "dir1", 15 | "auto_update": false, 16 | "shallow_clone": true 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete10backwards.git.yaml: -------------------------------------------------------------------------------- 1 | gitMaterial1: 2 | git: "https://my.git.repository.com" 3 | username: "username" 4 | encrypted_password: "some encrypted value" 5 | branch: "feature12" 6 | whitelist: 7 | - externals 8 | - tools 9 | destination: dir1 10 | auto_update: false 11 | shallow_clone: true 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete9.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitMaterial1", 3 | "type": "git", 4 | "url": "https://my.git.repository.com", 5 | "branch": "feature12", 6 | "username": "username", 7 | "encrypted_password": "some encrypted value", 8 | "filter": { 9 | "whitelist": [ 10 | "externals", 11 | "tools" 12 | ] 13 | }, 14 | "destination": "dir1", 15 | "auto_update": false, 16 | "shallow_clone": true 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/complete9.git.yaml: -------------------------------------------------------------------------------- 1 | gitMaterial1: 2 | git: "https://my.git.repository.com" 3 | username: "username" 4 | encrypted_password: "some encrypted value" 5 | branch: "feature12" 6 | whitelist: 7 | - externals 8 | - tools 9 | destination: dir1 10 | auto_update: false 11 | shallow_clone: true 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/ignore_for_scheduling.dependency.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "dependency", 3 | "name": "upstream", 4 | "pipeline": "upstream-pipeline-1", 5 | "stage": "test", 6 | "ignore_for_scheduling": true 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/ignore_for_scheduling.dependency.yaml: -------------------------------------------------------------------------------- 1 | upstream: 2 | pipeline: upstream-pipeline-1 3 | stage: test 4 | ignore_for_scheduling: true 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/material_without_name.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "git", 3 | "url": "http://example.com/mygit.git" 4 | } 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/minimal-explicit.git.yaml: -------------------------------------------------------------------------------- 1 | mygit: 2 | type: git 3 | url: http://example.com/mygit.git 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/minimal-nourl.git.yaml: -------------------------------------------------------------------------------- 1 | mygit: 2 | type: git 3 | git: http://example.com/mygit.git 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/minimal.cr.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crMaterial", 3 | "type": "configrepo" 4 | } 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/minimal.cr.yaml: -------------------------------------------------------------------------------- 1 | crMaterial: 2 | type: configrepo -------------------------------------------------------------------------------- /src/test/resources/parts/materials/minimal.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mygit", 3 | "type": "git", 4 | "url": "http://example.com/mygit.git" 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/minimal.git.yaml: -------------------------------------------------------------------------------- 1 | mygit: 2 | git: http://example.com/mygit.git 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "package_id": "apt-repo-id", 3 | "name": "myapt", 4 | "type": "package" 5 | } 6 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/package.yaml: -------------------------------------------------------------------------------- 1 | myapt: 2 | package: apt-repo-id 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/password.git.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitMaterial1", 3 | "type": "git", 4 | "url": "https://my.git.repository.com", 5 | "branch": "feature12", 6 | "username": "some username", 7 | "password": "some password" 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/password.git.yaml: -------------------------------------------------------------------------------- 1 | gitMaterial1: 2 | git: "https://my.git.repository.com" 3 | username: "some username" 4 | password: "some password" 5 | branch: "feature12" 6 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/password.hg.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "repos/myhg", 3 | "username": "some username", 4 | "password": "some password" 5 | } -------------------------------------------------------------------------------- /src/test/resources/parts/materials/password.hg.yaml: -------------------------------------------------------------------------------- 1 | hgMaterial1: 2 | hg: repos/myhg 3 | username: some username 4 | password: some password 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/simple.dependency.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "dependency", 3 | "name": "upstream", 4 | "pipeline": "upstream-pipeline-1", 5 | "stage": "test" 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/materials/simple.dependency.yaml: -------------------------------------------------------------------------------- 1 | upstream: 2 | pipeline: upstream-pipeline-1 3 | stage: test 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/parameters/empty.json: -------------------------------------------------------------------------------- 1 | [ 2 | ] 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/parameters/empty.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | -------------------------------------------------------------------------------- /src/test/resources/parts/parameters/param.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "param1", 4 | "value": "value1" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/parameters/param.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | param1: value1 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/pipeline_with_multiple_materials.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": "group1", 3 | "name": "pipe1", 4 | "label_template": "foo-1.0-${COUNT}", 5 | "enable_pipeline_locking": true, 6 | "tracking_tool": { 7 | "link": "http://your-trackingtool/yourproject/${ID}", 8 | "regex": "evo-(\\d+)" 9 | }, 10 | "timer": { 11 | "spec": "0 15 10 * * ? *", 12 | "only_on_changes": true 13 | }, 14 | "materials": [ 15 | { 16 | "type": "git", 17 | "url": "http://example.com/mygit.git" 18 | }, 19 | { 20 | "type": "git", 21 | "url": "http://other.com/mygit.git" 22 | } 23 | ], 24 | "stages": [ 25 | null, 26 | null 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/test/resources/parts/rich.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": "group1", 3 | "name": "pipe2", 4 | "label_template": "foo-1.0-${COUNT}", 5 | "enable_pipeline_locking": true, 6 | "tracking_tool": { 7 | "link": "http://your-trackingtool/yourproject/${ID}", 8 | "regex": "evo-(\\d+)" 9 | }, 10 | "timer": { 11 | "spec": "0 15 10 * * ? *", 12 | "only_on_changes": true 13 | }, 14 | "materials": [ 15 | null, 16 | null 17 | ], 18 | "stages": [ 19 | null, 20 | null 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/test/resources/parts/rich.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe2: 2 | group: group1 3 | label_template: "foo-1.0-${COUNT}" 4 | locking: on 5 | tracking_tool: 6 | link: "http://your-trackingtool/yourproject/${ID}" 7 | regex: "evo-(\\d+)" 8 | timer: 9 | spec: "0 15 10 * * ? *" 10 | only_on_changes: yes 11 | environment_variables: null 12 | parameters: null 13 | materials: 14 | foo: 15 | bar: 16 | stages: 17 | - null 18 | - null 19 | -------------------------------------------------------------------------------- /src/test/resources/parts/roots/2.yaml: -------------------------------------------------------------------------------- 1 | environments: 2 | first: 3 | second: 4 | pipelines: 5 | pipe1: 6 | pipe2: 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/roots/common_section.yaml: -------------------------------------------------------------------------------- 1 | common: 2 | some_string: &alias1 hello world 3 | environments: 4 | first: 5 | pipelines: 6 | pipe1: 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/roots/duplicate.materials.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipelines: 2 | pipe1: 3 | group: group 4 | materials: 5 | upstream: 6 | pipeline: upstream-pipeline-1 7 | stage: test1 8 | upstream: 9 | pipeline: upstream-pipeline-2 10 | stage: test2 -------------------------------------------------------------------------------- /src/test/resources/parts/roots/empty.yaml: -------------------------------------------------------------------------------- 1 | environments: 2 | pipelines: 3 | -------------------------------------------------------------------------------- /src/test/resources/parts/roots/pipeline_order.yaml: -------------------------------------------------------------------------------- 1 | environments: 2 | env1: 3 | pipelines: 4 | - pipe1 5 | 6 | pipelines: 7 | pipe1: 8 | group: simple 9 | materials: 10 | mygit: 11 | stages: 12 | - null 13 | pipe2: 14 | group: simple 15 | materials: 16 | mygit: 17 | stages: 18 | - null 19 | pipe3: 20 | group: simple 21 | materials: 22 | mygit: 23 | stages: 24 | - null 25 | -------------------------------------------------------------------------------- /src/test/resources/parts/roots/version_1.yaml: -------------------------------------------------------------------------------- 1 | format_version: 1 2 | environments: 3 | first: 4 | pipelines: 5 | - pipe1 6 | pipelines: 7 | pipe1: 8 | group: simple 9 | materials: 10 | mygit: 11 | git: http://test.example.git 12 | stages: 13 | - build: 14 | jobs: 15 | job1: 16 | tasks: 17 | - exec: 18 | command: make 19 | arguments: 20 | - "abc" -------------------------------------------------------------------------------- /src/test/resources/parts/roots/version_2.yaml: -------------------------------------------------------------------------------- 1 | format_version: 2 2 | environments: 3 | first: 4 | pipelines: 5 | - pipe1 6 | pipelines: 7 | pipe1: 8 | group: simple 9 | materials: 10 | mygit: 11 | git: http://test.example.git 12 | stages: 13 | - build: 14 | jobs: 15 | job1: 16 | tasks: 17 | - exec: 18 | command: make 19 | arguments: 20 | - "abc" -------------------------------------------------------------------------------- /src/test/resources/parts/roots/version_not_present.yaml: -------------------------------------------------------------------------------- 1 | environments: 2 | first: 3 | pipelines: 4 | - pipe1 5 | pipelines: 6 | pipe1: 7 | group: simple 8 | materials: 9 | mygit: 10 | git: http://test.example.git 11 | stages: 12 | - build: 13 | jobs: 14 | job1: 15 | tasks: 16 | - exec: 17 | command: make 18 | arguments: 19 | - "abc" -------------------------------------------------------------------------------- /src/test/resources/parts/simple.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pipe1", 3 | "group": "simple", 4 | "materials": [ 5 | null 6 | ], 7 | "stages": [ 8 | null 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/parts/simple.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe1: 2 | group: simple 3 | materials: 4 | mygit: 5 | stages: 6 | - null 7 | -------------------------------------------------------------------------------- /src/test/resources/parts/stage_nested_list.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pipe1", 3 | "group": "simple", 4 | "materials": [ 5 | null 6 | ], 7 | "stages": [ 8 | null, 9 | null, 10 | null, 11 | null, 12 | null 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/parts/stage_nested_list.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe1: 2 | group: simple 3 | materials: 4 | mygit: 5 | stages: 6 | - 7 | - null 8 | - null 9 | - null 10 | - 11 | - null 12 | - null 13 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/complete.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "fetch_materials": true, 4 | "never_cleanup_artifacts": true, 5 | "clean_working_directory": true, 6 | "approval": { 7 | "type": "success", 8 | "roles": [ 9 | "manager" 10 | ], 11 | "users": [ 12 | "john" 13 | ] 14 | }, 15 | "environment_variables": [ 16 | { 17 | "name": "TEST_NUM", 18 | "value": "1" 19 | }, 20 | { 21 | "name": "PASSWORD", 22 | "encrypted_value": "!@ESsdD323#sdu" 23 | } 24 | ], 25 | "jobs": [ 26 | null, 27 | null 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/complete.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | fetch_materials: yes 3 | keep_artifacts: yes 4 | clean_workspace: yes 5 | approval: 6 | type: success 7 | roles: 8 | - manager 9 | users: 10 | - john 11 | environment_variables: 12 | TEST_NUM: 1 13 | secure_variables: 14 | PASSWORD: "!@ESsdD323#sdu" 15 | jobs: 16 | one: 17 | two: 18 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/complete_with_manual_approval.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "fetch_materials": true, 4 | "never_cleanup_artifacts": true, 5 | "clean_working_directory": true, 6 | "approval": { 7 | "type": "manual", 8 | "allow_only_on_success": true, 9 | "roles": [ 10 | "manager" 11 | ], 12 | "users": [ 13 | "john" 14 | ] 15 | }, 16 | "environment_variables": [ 17 | { 18 | "name": "TEST_NUM", 19 | "value": "1" 20 | }, 21 | { 22 | "name": "PASSWORD", 23 | "encrypted_value": "!@ESsdD323#sdu" 24 | } 25 | ], 26 | "jobs": [ 27 | null, 28 | null 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/complete_with_manual_approval.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | fetch_materials: yes 3 | keep_artifacts: yes 4 | clean_workspace: yes 5 | approval: 6 | type: manual 7 | allow_only_on_success: true 8 | roles: 9 | - manager 10 | users: 11 | - john 12 | environment_variables: 13 | TEST_NUM: 1 14 | secure_variables: 15 | PASSWORD: "!@ESsdD323#sdu" 16 | jobs: 17 | one: 18 | two: 19 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/short_approval.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "approval": { 4 | "type": "manual" 5 | }, 6 | "jobs": [ 7 | null 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/short_approval.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | approval: manual 3 | jobs: 4 | one: 5 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/stage-job.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "build", 3 | "approval": { 4 | "type": "manual" 5 | }, 6 | "jobs": [ 7 | { 8 | "name": "build", 9 | "resources": [ 10 | "cpp" 11 | ], 12 | "tasks": [ 13 | null 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/parts/stages/stage-job.yaml: -------------------------------------------------------------------------------- 1 | build: 2 | approval: manual 3 | resources: 4 | - cpp 5 | tasks: 6 | - exec: 7 | command: make 8 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/breakline.script.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "plugin", 3 | "configuration": [ 4 | { 5 | "key": "script", 6 | "value": "./build.sh compile && make test" 7 | } 8 | ], 9 | "plugin_configuration": { 10 | "id": "script-executor", 11 | "version": "1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/breakline.script.yaml: -------------------------------------------------------------------------------- 1 | script: >- 2 | ./build.sh compile && 3 | make test 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/complete.fetch.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "fetch", 3 | "artifact_origin": "gocd", 4 | "run_if": "any", 5 | "pipeline": "upstream", 6 | "stage": "upstream_stage", 7 | "job": "upstream_job", 8 | "is_source_a_file": true, 9 | "source": "result", 10 | "destination": "test" 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/complete.fetch.yaml: -------------------------------------------------------------------------------- 1 | fetch: 2 | run_if: any 3 | artifact_origin: gocd 4 | pipeline: upstream 5 | stage: upstream_stage 6 | job: upstream_job 7 | is_file: yes 8 | source: result 9 | destination: test 10 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/complete.plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "plugin", 3 | "configuration": [ 4 | { 5 | "key": "ConverterType", 6 | "value": "jsunit" 7 | }, 8 | { 9 | "key": "password", 10 | "encrypted_value": "ssd#%fFS*!Esx" 11 | } 12 | ], 13 | "run_if": "failed", 14 | "plugin_configuration": { 15 | "id": "xunit.converter.task.plugin", 16 | "version": "1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/complete.plugin.yaml: -------------------------------------------------------------------------------- 1 | plugin: 2 | options: 3 | ConverterType: jsunit 4 | secure_options: 5 | password: "ssd#%fFS*!Esx" 6 | run_if: failed 7 | configuration: 8 | id: xunit.converter.task.plugin 9 | version: 1 10 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/complete.rake.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "rake", 3 | "run_if": "passed", 4 | "working_directory": "sample-project", 5 | "build_file": "SomeRakefile", 6 | "target": "build", 7 | "on_cancel": { 8 | "type": "rake", 9 | "working_directory": "sample-project", 10 | "build_file": "CancelRakefile", 11 | "target": "cancel" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/complete.rake.yaml: -------------------------------------------------------------------------------- 1 | rake: 2 | run_if: passed 3 | working_directory: sample-project 4 | build_file: SomeRakefile 5 | target: build 6 | on_cancel: 7 | rake: 8 | working_directory: sample-project 9 | build_file: CancelRakefile 10 | target: cancel 11 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/fetch_external_artifact.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "fetch", 3 | "run_if": "any", 4 | "artifact_origin": "external", 5 | "pipeline": "upstream", 6 | "stage": "upstream_stage", 7 | "job": "upstream_job", 8 | "artifact_id": "upstream_artifact_id", 9 | "configuration": [ 10 | { 11 | "key": "Foo", 12 | "value": "bar" 13 | }, 14 | { 15 | "key": "secure_property", 16 | "encrypted_value": "ssd#%fFS*!Esx" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/fetch_external_artifact.yaml: -------------------------------------------------------------------------------- 1 | fetch: 2 | run_if: any 3 | artifact_origin: external 4 | pipeline: upstream 5 | stage: upstream_stage 6 | job: upstream_job 7 | artifact_id: upstream_artifact_id 8 | configuration: 9 | options: 10 | Foo: bar 11 | secure_options: 12 | secure_property: ssd#%fFS*!Esx -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/full.exec.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "exec", 3 | "run_if": "any", 4 | "command": "make", 5 | "arguments": [ 6 | "-j3", 7 | "docs", 8 | "install" 9 | ], 10 | "working_directory": "dir" 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/full.exec.yaml: -------------------------------------------------------------------------------- 1 | exec: 2 | run_if: any 3 | command: make 4 | arguments: 5 | - -j3 6 | - docs 7 | - install 8 | working_directory: dir 9 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/minimal.fetch.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "fetch", 3 | "artifact_origin": "gocd", 4 | "stage": "build", 5 | "job": "test", 6 | "source": "test-bin/" 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/minimal.fetch.yaml: -------------------------------------------------------------------------------- 1 | fetch: 2 | stage: build 3 | artifact_origin: gocd 4 | job: test 5 | source: test-bin/ 6 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/minimal.rake.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "rake" 3 | } 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/minimal.rake.yaml: -------------------------------------------------------------------------------- 1 | rake: 2 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/multiline.script.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "plugin", 3 | "configuration": [ 4 | { 5 | "key": "script", 6 | "value": "./build.sh compile\nmake test" 7 | } 8 | ], 9 | "plugin_configuration": { 10 | "id": "script-executor", 11 | "version": "1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/multiline.script.yaml: -------------------------------------------------------------------------------- 1 | script: |- 2 | ./build.sh compile 3 | make test 4 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/script.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "plugin", 3 | "configuration": [ 4 | { 5 | "key": "script", 6 | "value": "./build.sh compile" 7 | } 8 | ], 9 | "plugin_configuration": { 10 | "id": "script-executor", 11 | "version": "1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/parts/tasks/script.yaml: -------------------------------------------------------------------------------- 1 | script: ./build.sh compile 2 | -------------------------------------------------------------------------------- /src/test/resources/parts/template_ref.pipe.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": "group1", 3 | "name": "pipe2", 4 | "label_template": "foo-1.0-${COUNT}", 5 | "enable_pipeline_locking": true, 6 | "tracking_tool": { 7 | "link": "http://your-trackingtool/yourproject/${ID}", 8 | "regex": "evo-(\\d+)" 9 | }, 10 | "timer": { 11 | "spec": "0 15 10 * * ? *", 12 | "only_on_changes": true 13 | }, 14 | "materials": [ 15 | null, 16 | null 17 | ], 18 | "template": "template" 19 | } 20 | -------------------------------------------------------------------------------- /src/test/resources/parts/template_ref.pipe.yaml: -------------------------------------------------------------------------------- 1 | pipe2: 2 | group: group1 3 | label_template: "foo-1.0-${COUNT}" 4 | locking: on 5 | tracking_tool: 6 | link: "http://your-trackingtool/yourproject/${ID}" 7 | regex: "evo-(\\d+)" 8 | timer: 9 | spec: "0 15 10 * * ? *" 10 | only_on_changes: yes 11 | environment_variables: null 12 | materials: 13 | foo: 14 | bar: 15 | template: template -------------------------------------------------------------------------------- /yaml_file_pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomzo/gocd-yaml-config-plugin/9e3f9e0f4f36870e0c6f42e1b40af70e37225dc9/yaml_file_pattern.png --------------------------------------------------------------------------------