Skip to content

Commit

Permalink
Draft of parsers and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzo committed Jul 14, 2016
1 parent 0f88d75 commit e74ce2a
Show file tree
Hide file tree
Showing 16 changed files with 387 additions and 10 deletions.
29 changes: 25 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,38 @@

# gocd-yaml-config-plugin

Plugin to declare Go pipeline and environments configuration in YAML.
Plugin to declare [Go's](go.cd) pipelines and environments configuration in YAML.

With this plugin and GoCD `>= 16.7.0` you can keep your pipeline and environments
configuration in source control.

This is second GoCD configuration plugin, which enhances some of shortcomings of
[JSON configuration plugin](https://github.com/tomzo/gocd-json-config-plugin)

* Format is **concise**. Unlike JSON, there are no unnecessary quotations `"`, brackets `{}` and commas `,`
* Tries to **enforce correctness** where possible. By using maps instead of lists and shorter object graphs.
* Allows to have multiple pipelines and environments in single file. But doesn't force it.
* **Comments in configuration files** - YAML supports comments,
so you can explain why pipeline/environment it is configured like this.

### Example

More examples are in [test resources](src/testResources/examples/).
More examples are in [test resources](src/test/resources/examples/).

```yaml
#ci.gocd.yaml
mygroup: # pipelines of mygroup by name
environments:
testing:
environment_variables:
DEPLOYMENT: testing
secure_variables:
ENV_PASSWORD: "s&Du#@$xsSa"
pipelines:
- example-deploy-testing
- build-testing
pipelines:
mypipe1: # definition of mypipe1 pipeline
group: mygroup
label_template: "${mygit[:8]}"
materials:
mygit: # this is the name of material
Expand Down Expand Up @@ -42,7 +61,7 @@ mygroup: # pipelines of mygroup by name
destination: test-reports/
tabs:
report: test-reports/index.html
tasks: # list of tasks to execute in job csharp
tasks: # ordered list of tasks to execute in job csharp
- fetch:
pipeline: pipe2
stage: build
Expand All @@ -56,3 +75,5 @@ mygroup: # pipelines of mygroup by name
# shorthand for script-executor plugin
- script: ./build.sh ci
```
# Specification
12 changes: 11 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies {
compile group: 'com.google.code.gson', name: 'gson', version: '2.6.2'
compile group: 'commons-io', name: 'commons-io', version: '2.4'
compile group: 'org.apache.ant', name: 'ant', version: '1.7.1'
compile group: 'com.esotericsoftware.yamlbeans', name: 'yamlbeans', version: '1.09'
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'org.mockito', name: 'mockito-core', version: '1.10.19'
testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
Expand All @@ -31,13 +32,22 @@ sourceSets {
java {
srcDirs = ["src/test/java"]
}
resources {
srcDir 'src/test/resources'
}
}
}

task copyTestResources(type: Copy) {
from "${projectDir}/src/test/resources"
into "${buildDir}/classes/test"
}
processTestResources.dependsOn copyTestResources

test {
useJUnit {
}
testLogging {
events "passed", "skipped", "failed", "standardOut"
}
}
}
56 changes: 56 additions & 0 deletions src/main/java/cd/go/plugin/config/yaml/JsonConfigCollection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cd.go.plugin.config.yaml;

import com.google.gson.*;

public class JsonConfigCollection {
private static final int TARGET_VERSION = 1;
private final Gson gson;

private JsonObject mainObject = new JsonObject();
private JsonArray environments = new JsonArray();
private JsonArray pipelines = new JsonArray();
private JsonArray errors = new JsonArray();

public JsonConfigCollection()
{
gson = new Gson();

mainObject.add("target_version",new JsonPrimitive(TARGET_VERSION));
mainObject.add("environments",environments);
mainObject.add("pipelines",pipelines);
mainObject.add("errors",errors);
}

protected JsonArray getEnvironments()
{
return environments;
}

public void addEnvironment(JsonElement environment,String location) {
environments.add(environment);
environment.getAsJsonObject().add("location",new JsonPrimitive(location));
}

public JsonObject getJsonObject()
{
return mainObject;
}

public void addPipeline(JsonElement pipeline,String location) {
pipelines.add(pipeline);
pipeline.getAsJsonObject().add("location",new JsonPrimitive(location));
}

public JsonArray getPipelines() {
return pipelines;
}

public JsonArray getErrors() {
return errors;
}

public void addError(PluginError error) {
errors.add(gson.toJsonTree(error));
}

}
32 changes: 32 additions & 0 deletions src/main/java/cd/go/plugin/config/yaml/PluginError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cd.go.plugin.config.yaml;

public class PluginError {
private String location;
private String message;

public PluginError(){}
public PluginError(String message){
this.message = message;
}
public PluginError(String message,String location)
{
this.location = location;
this.message = message;
}

public String getLocation() {
return location;
}

public void setLocation(String location) {
this.location = location;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}
16 changes: 16 additions & 0 deletions src/main/java/cd/go/plugin/config/yaml/RootParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cd.go.plugin.config.yaml;

import com.esotericsoftware.yamlbeans.YamlReader;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

public class RootParser {
public JsonConfigCollection parseString(InputStreamReader yaml) throws IOException {
YamlReader reader = new YamlReader(yaml);
Object object = reader.read();
return new JsonConfigCollection();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cd.go.plugin.config.yaml.materials;

import com.google.gson.JsonObject;

import java.util.HashSet;
import java.util.Map;

public class MaterialTransform {

public static final String JSON_MATERIAL_TYPE_FIELD = "type";
public static final String JSON_MATERIAL_NAME_FIELD = "name";

public static final String YAML_SHORT_KEYWORD_GIT = "git";
private final HashSet<String> yamlShortKeywords = new HashSet<String>();

public MaterialTransform() {
yamlShortKeywords.add(YAML_SHORT_KEYWORD_GIT);
}

public JsonObject transform(Object maybeMaterial) {
Map<String,Object> map = (Map<String,Object>)maybeMaterial;
for(Map.Entry<String, Object> entry : map.entrySet()) {
String materialName = entry.getKey();
JsonObject material = new JsonObject();
material.addProperty(JSON_MATERIAL_NAME_FIELD, materialName);
Map<String,Object> materialMap = (Map<String,Object>)entry.getValue();
String materialType = getOptionalString(materialMap,"type");
if(materialType != null)
material.addProperty(JSON_MATERIAL_TYPE_FIELD,materialType);

String git = getOptionalString(materialMap,YAML_SHORT_KEYWORD_GIT);
if(git != null)
{
material.addProperty(JSON_MATERIAL_TYPE_FIELD,YAML_SHORT_KEYWORD_GIT);
material.addProperty("url",git);
}

for(Map.Entry<String, Object> materialProp : materialMap.entrySet()) {
if(yamlShortKeywords.contains(materialProp.getKey()))
continue;
if(materialProp.getValue() instanceof String)
material.addProperty(materialProp.getKey(),(String)materialProp.getValue());
}
return material;
}
throw new RuntimeException("expected material hash to have 1 item");
}

private String getOptionalString(Map map, String fieldName) {
Object type = map.get(fieldName);
if(type != null)
{
return (String)type;
}
return null;
}
}
21 changes: 21 additions & 0 deletions src/test/java/cd/go/plugin/config/yaml/RootParserTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cd.go.plugin.config.yaml;

import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;

import static org.junit.Assert.*;

public class RootParserTest {
@Test
public void shouldReadSimpleFile() throws IOException {
YamlReader reader = new YamlReader(TestUtils.createReader("examples/simple.gocd.yaml"));
Object object = reader.read();
}
}
43 changes: 43 additions & 0 deletions src/test/java/cd/go/plugin/config/yaml/TestUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cd.go.plugin.config.yaml;

import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.apache.commons.io.IOUtils;

import java.io.*;

public class TestUtils {

public static JsonElement readJsonObject(String path) throws IOException {
JsonParser parser = new JsonParser();
return parser.parse(TestUtils.createReader(path));
}

public static Object readYamlObject(String path) throws IOException {
YamlReader reader = new YamlReader(TestUtils.createReader(path));
return reader.read();
}

public static InputStreamReader createReader(String path) throws IOException {
final InputStream resourceAsStream = getResourceAsStream(path);
return new InputStreamReader(resourceAsStream);
}

private static String loadString(String path) throws IOException {
final InputStream resourceAsStream = getResourceAsStream(path);
return IOUtils.toString(resourceAsStream);
}

private static InputStream getResourceAsStream( String resource ) {
final InputStream in
= getContextClassLoader().getResourceAsStream( resource );

return in == null ? TestUtils.class.getResourceAsStream( resource ) : in;
}

private static ClassLoader getContextClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class YamlConfigPluginTest {
public void SetUp() throws IOException {
plugin = new YamlConfigPlugin();
goAccessor = mock(GoApplicationAccessor.class);
plugin.initializeGoApplicationAccessor(goAccessor);
//plugin.initializeGoApplicationAccessor(goAccessor);
GoApiResponse settingsResponse = DefaultGoApiResponse.success("{}");
when(goAccessor.submit(any(GoApiRequest.class))).thenReturn(settingsResponse);

Expand All @@ -41,9 +41,9 @@ public void SetUp() throws IOException {
@Test
public void shouldRespondSuccessToGetConfigurationRequest() throws UnhandledRequestTypeException
{
DefaultGoPluginApiRequest getConfigRequest = new DefaultGoPluginApiRequest("configrepo","1.0","go.plugin-settings.get-configuration");
//DefaultGoPluginApiRequest getConfigRequest = new DefaultGoPluginApiRequest("configrepo","1.0","go.plugin-settings.get-configuration");

GoPluginApiResponse response = plugin.handle(getConfigRequest);
assertThat(response.responseCode(), is(DefaultGoPluginApiResponse.SUCCESS_RESPONSE_CODE));
//GoPluginApiResponse response = plugin.handle(getConfigRequest);
//assertThat(response.responseCode(), is(DefaultGoPluginApiResponse.SUCCESS_RESPONSE_CODE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cd.go.plugin.config.yaml.materials;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.junit.Test;

import java.io.IOException;

import static cd.go.plugin.config.yaml.TestUtils.readJsonObject;
import static cd.go.plugin.config.yaml.TestUtils.readYamlObject;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

public class MaterialTransformTest {
private final MaterialTransform parser;

public MaterialTransformTest() {
parser = new MaterialTransform();
}

@Test
public void shouldTransformMinimalGit() throws IOException {
testTransform("minimal.git");
}
@Test
public void shouldTransformMinimalExplicitGit() throws IOException {
testTransform("minimal-explicit.git","minimal.git");
}
@Test
public void shouldTransformMinimalNoUrlGit() throws IOException {
testTransform("minimal-nourl.git","minimal.git");
}

private void testTransform(String caseFile) throws IOException {
testTransform(caseFile,caseFile);
}

private void testTransform(String caseFile,String expectedFile) throws IOException {
JsonElement expectedObject = readJsonObject("parts/materials/" + expectedFile + ".json");
JsonObject jsonObject = parser.transform(readYamlObject("parts/materials/" + caseFile + ".yaml"));
assertThat(jsonObject,is(expectedObject));
}

}
Loading

0 comments on commit e74ce2a

Please sign in to comment.