Giter Site home page Giter Site logo

gocd-json-config-plugin's Introduction

Google Groups GitHub Discussions

GoCD JSON configuration plugin

GoCD pipeline configuration as code

This is a GoCD server plugin which allows to keep pipelines and environments configuration in version control systems supported by GoCD (git, svn, mercurial, etc.). See this document to find out what GoCD's configuration repositories are.

Table of contents

  1. Setup
  2. File pattern
  3. Validation
  4. Format reference
  5. Format version
  6. Issues and questions
  7. Development
  8. License

Setup

Step 1: GoCD versions newer than 17.8.0 already have the plugin bundled. You don't need to install anything.

If you're using GoCD version older than 17.8.0, you need to install the plugin in the GoCD server. Download it from the releases page and place it on the GoCD server in plugins/external directory.

Step 2: Follow the GoCD documentation to add a new configuration repository.

You can use the example repository at: https://github.com/tomzo/gocd-json-config-example.git as a reference.

In your config repo (tomzo/gocd-json-config-example.git in this case), ensure that your GoCD json config is suffixed with .gopipeline.json for pipelines and .goenvironment.json for environments. Give it a minute or so for the polling to happen. Once that happens, you should see your pipeline(s) on your dashboard.

File pattern

Using this plugin you can store any number of pipeline or environment configurations in a versioned repository like git.

By default pipelines should be stored in *.gopipeline.json files and environments should be stored in *.goenvironment.json files.

The file name pattern can be changed on plugin configuration page.

Validation

You can validate if proposed GoCD JSON changes will be accepted by the server. Currently, 2 options are available:

Validation using CLI

You may find this introductory blog post useful.

There is an ongoing effort to allow in-depth validation of configuration before pushing configuration to the source control. This is provided by GoCD's preflight API and gocd-cli.

You have several options to configure validation tools on your workstation:

Either way you'll have gocd binary in your PATH or inside the docker container.

Syntax validation

This will check general validity of the yaml file, without talking to the GoCD server:

gocd configrepo --json syntax ci.gopipeline.json

Preflight validation

This command will parse and submit your json file to the configured GoCD server.

gocd configrepo preflight --json -r gocd-json-config-example *.gopipeline.json

Where -r is the configuration repository id, which you have earlier configured on GoCD server. You can check it on config repos page of your GoCD server, at /go/admin/config_repos. It is in the upper left corner of each config repo. config repo id

JSON Configuration reference

The pipeline configuration files should be stored in format similar to one exposed by GoCD API.

The format of environment configuration files is much simpler, you can find examples of correct environments below.

  1. Format version
  2. Environment
  3. Environment variables
  4. Pipeline
  5. Stage
  6. Job
  7. Tasks
  8. Materials

Format version

Please note that it is now recommended to declare the same format_version in each *.gopipeline.json or *.goenvironment.json file.

GoCD server version from 19.10.0 and beyond

Supports format_version value of 9. In this version, support of ignore_for_scheduling for dependency materials has been added. Setting this attribute will skip scheduling the pipeline when the dependency material has changed.

Using a newer format_version includes all the behavior of the previous versions too.

GoCD server version from 19.9.0 and beyond

Supports format_version value of 7 and 8. In version 7, support for properties has been removed. In version 8, support for mingle has been removed.

Using a newer format_version includes all the behavior of the previous versions too.

GoCD server version from 19.8.0 and beyond

Supports format_version value of 6. In this version, support of allow_only_on_success for approval on stage has been added. Setting this attribute will ensure that the manual trigger will be allowed only if the previous stage is successful.

Using a newer format_version includes all the behavior of the previous versions too.

GoCD server version from 19.4.0 to 19.7.0

Supports format_version value of 5. In this version, support of username and encrypted_password for git and hg material has been added. In addition to that, hg will also support branch attribute.

Using a newer format_version includes all the behavior of the previous versions too.

GoCD server version from 19.3.0 to 19.4.0

Supports format_version value of 4. In this version, support has been added to control the display order of pipelines.

This server version also supports format_version of 3 and 2. Using a newer format_version includes all the behavior of the previous versions too.

GoCD server version from 18.7.0 to 19.2.0

Supports format_version value of 3. In this version fetch artifact format was changed to include artifact_origin.

This server version also supports format_version of 2. Using a newer format_version includes all the behavior of the previous versions too.

GoCD server version up to 18.6.0

Supports format_version value of 2. In this version pipeline locking behavior was changed.

Environment

Configures a GoCD environment

{
  "name": "dev",
  "environment_variables": [
    {
      "name": "key1",
      "value": "value1"
    }
  ],
  "agents": [
    "123"
  ],
  "pipelines": [
    "mypipeline1"
  ]
}

Environment variables

Environment variables is a JSON array that can be declared in Environments, Pipelines, Stages and Jobs.

Any variable must contain name and value or encrypted_value.

{
  "environment_variables": [
    {
      "name": "key1",
      "value": "value1"
    },
    {
      "name": "keyd",
      "encrypted_value": "v12@SDfwez"
    }
  ]
}

Pipeline

{
  "format_version" : 1,
  "group": "group1",
  "name": "pipe2",
  "label_template": "foo-1.0-${COUNT}",
  "enable_pipeline_locking" : false,
  "parameters": [
    {
      "name": "param",
      "value": "parameter"
    }
  ],
  "tracking_tool": null,
  "timer": {
    "spec": "0 15 10 * * ? *"
  },
  "environment_variables": [],
  "materials": [
    ...
  ],
  "stages": [
    ...
  ]
}

Referencing an existing template in a config repo:

{
  "format_version" : 1,
  "group": "group1",
  "name": "pipe-with-template",
  "label_template": "foo-1.0-${COUNT}",
  "enable_pipeline_locking" : false,
  "template": "template1",
  "parameters": [
    {
      "name": "param",
      "value": "parameter"
    }
  ],
  "materials": [
    ...
  ]
}

Please note:

  • Pipeline declares a group to which it belongs

Pipeline locking

Expected since GoCD v17.12, you need to use lock_behavior rather than enable_pipeline_locking.

"lock_behavior" : "none"

lock_behavior can be one of:

  • lockOnFailure - same as enable_pipeline_locking: true
  • unlockWhenFinished -
  • none - same enable_pipeline_locking: false

When format_version is 4 (see above), the order of display of pipelines on the GoCD dashboard can be influenced by setting the display_order_weight property.

  • This is an integer property and the pipelines in a pipeline group will be ordered by this value.
  • The default value for this property is -1.
  • Pipelines defined in GoCD's config XML will also default to -1.
  • If multiple pipelines have the same display_order_weight value, their order relative to each other will be indeterminate.
{
  "name": "pipeline1",
  "group": "pg1",
  "display_order_weight": 10
},
{
  "name": "pipeline2",
  "group": "pg1",
  "display_order_weight": -10
}

In the above example, since both pipelines are in the same group, pipeline2 will be shown ahead of pipeline1. If any pipelines are defined in the GoCD config XML, then they will appear in between these two pipelines.

Timer

{
    "spec": "0 0 22 ? * MON-FRI",
    "only_on_changes": true
}

Tracking tool

{
  "link": "http://your-trackingtool/yourproject/${ID}",
  "regex": "evo-(\\d+)"
}

Mingle

DEPRECATION NOTICE: Since GoCD version 19.9 and format_version 8, this is no longer supported

{
    "base_url": "https://mingle.example.com",
    "project_identifier": "foobar_widgets",
    "mql_grouping_conditions": "status > 'In Dev'"
}

Stage

{
  "name": "test",
  "fetch_materials": true,
  "never_cleanup_artifacts": false,
  "clean_working_directory": false,
  "approval" : null,
  "environment_variables": [
    {
      "name": "TEST_NUM",
      "value": "1"
    }
  ],
  "jobs": [
    ...
  ]
}

Approval

{
  "type": "manual",
  "allow_only_on_success": true,
  "users": [],
  "roles": [
    "manager"
  ]
}

Job

{
  "name": "test",
  "run_instance_count" : null,
  "environment_variables": [],
  "timeout": 180,
  "elastic_profile_id": "docker-big-image-1",
  "tabs": [
     {
       "name": "test",
       "path": "results.xml"
     }
   ],
   "resources": [
    "linux"
  ],
  "artifacts": [
    {
      "source": "src",
      "destination": "dest",
      "type": "test"
    },
    {
      "type": "external",
      "id": "docker-release-candidate",
      "store_id": "dockerhub",
      "configuration": [
        {
          "key": "Image",
          "value": "gocd/gocd-demo"
        },
        {
          "key": "Tag",
          "value": "${GO_PIPELINE_COUNTER}"
        },
        {
          "key": "some_secure_property",
          "encrypted_value": "!@ESsdD323#sdu"
        }
      ]
    }
  ],
  "tasks": [
    ...
  ]
}

Artifacts

There are 3 types of artifacts recognized by GoCD. Build and Test artifacts are stored on the GoCD server. The source and the destination of the artifact that should be stored on the GoCD server must be specified.

Build

{
  "source": "src",
  "destination": "dest",
  "type": "build"
}

Test

{
  "source": "src",
  "destination": "dest",
  "type": "test"
}

External

Artifacts of type external are stored in an artifact store outside of GoCD. The external artifact store's configuration must be created in the main GoCD config. Support for external artifact store config to be checked in as yaml is not available. The external artifact store is referenced by the store_id. The build specific artifact details that the artifact plugin needs to publish the artifact is provided as configuration.

{
  "type": "external",
  "id": "docker-release-candidate",
  "store_id": "dockerhub",
  "configuration": [
    {
      "key": "Image",
      "value": "gocd/gocd-demo"
    },
    {
      "key": "Tag",
      "value": "${GO_PIPELINE_COUNTER}"
    },
    {
      "key": "some_secure_property",
      "encrypted_value": "!@ESsdD323#sdu"
    }
  ]
}

Property

DEPRECATION NOTICE: Since GoCD version 19.9 and format_version 7, properties are no longer supported

{
  "name": "coverage.class",
  "source": "target/emma/coverage.xml",
  "xpath": "substring-before(//report/data/all/coverage[starts-with(@type,'class')]/@value, '%')"
}

Tab

{
      "name": "cobertura",
      "path": "target/site/cobertura/index.html"
}

Run many instances

Part of job object can be number of job to runs

"run_instance_count" : 6

Or to run on all agents

"run_instance_count" : "all"

Default is null which runs just one job.

Materials

All materials:

  • must have type - git, svn, hg, p4, tfs, dependency, package, plugin.
  • can have name and must have name when there is more than one material in pipeline

SCM-related materials have destination field.

Filter - blacklist and whitelist

All scm materials can have filter object:

  • for blacklisting:
"filter": {
  "ignore": [
    "externals",
    "tools"
  ]
}
  • for whitelisting (since Go >=16.7.0):
"filter": {
 "whitelist": [
   "moduleA"
 ]
}

Git

{
  "url": "http://my.git.repository.com",
  "branch": "feature12",
  "filter": {
    "ignore": [
      "externals",
      "tools"
    ]
  },
  "destination": "dir1",
  "auto_update": false,
  "name": "gitMaterial1",
  "type": "git",
  "shallow_clone": true,
  "username": "user1",
  "encrypted_password": "encrypted_value"
}

For GoCD >= 19.4.0 and format_version: 5 and above:

You are advised to utilize username and encrypted_password for passing in material credentials as:

{
  "url": "http://my.git.repository.com",
  "branch": "feature12",
  "username": "user1",
  "encrypted_password": "encrypted_value"
}
  • Instead of encrypted_password you may specify password but encrypted_password makes more sense considering that the value is stored in SCM.
  • Specifying credentials both in attributes and url will result in a validation error e.g.
      INVALID MERGED CONFIGURATION
      Number of errors: 1+
      1. Ambiguous credentials, must be provided either in URL or as attributes.;;
      - For Config Repo: https://your.config.repo.url at cbb047d78c239ab23b9565099e800c6fe4cc0anc
    
{
  "url": "http://svn",
  "username": "user1",
  "encrypted_password": "encrypted_value",
  "check_externals": true,
  "filter": {
    "ignore": [
      "tools",
      "lib"
    ]
  },
  "destination": "destDir1",
  "auto_update": false,
  "name": "svnMaterial1",
  "type": "svn"
}

Instead of encrypted_password you may specify password but encrypted_password makes more sense considering that the value is stored in SCM.

Hg

{
  "url": "repos/myhg",
  "filter": {
    "ignore": [
      "externals",
      "tools"
    ]
  },
  "destination": "dir1",
  "auto_update": false,
  "name": "hgMaterial1",
  "type": "hg",
  "username": "user1",
  "encrypted_password": "encrypted_value",
  "branch": "feature"
}

For GoCD >= 19.4.0 and format_version: 5 and above:

You are advised to utilize username and encrypted_password for passing in material credentials as:

{
  "url": "repos/myhg",
  "username": "user1",
  "encrypted_password": "encrypted_value"
}
  • Instead of encrypted_password you may specify password but encrypted_password makes more sense considering that the value is stored in SCM.
  • Specifying credentials both in attributes and url will result in a validation error e.g.
      INVALID MERGED CONFIGURATION
      Number of errors: 1+
      1. Ambiguous credentials, must be provided either in URL or as attributes.;;
      - For Config Repo: https://your.config.repo.url at cbb047d78c239ab23b9565099e800c6fe4cc0anc
    

In addition to that, you can also leverage branch attribute to specify the branch for material

{
  "branch": "feature"
}
{
  "port": "10.18.3.102:1666",
  "username": "user1",
  "encrypted_password": "encrypted_value",
  "use_tickets": false,
  "view": "//depot/dev/src...          //anything/src/...",
  "filter": {
    "ignore": [
      "lib",
      "tools"
    ]
  },
  "destination": "dir1",
  "auto_update": false,
  "name": "p4materialName",
  "type": "p4"
}

Instead of encrypted_password you may specify password but encrypted_password makes more sense considering that the value is stored in SCM.

Tfs

{
  "url": "url3",
  "username": "user4",
  "domain": "example.com",
  "encrypted_password": "encrypted_value",
  "project": "projectDir",
  "filter": {
    "ignore": [
      "tools",
      "externals"
    ]
  },
  "destination": "dir1",
  "auto_update": false,
  "name": "tfsMaterialName",
  "type": "tfs"
}

Instead of encrypted_password you may specify password but encrypted_password makes more sense considering that the value is stored in SCM.

Dependency

{
  "pipeline": "pipeline2",
  "stage": "build",
  "name": "pipe2",
  "type": "dependency",
  "ignore_for_scheduling": false
}

Package

{
  "package_id": "apt-repo-id",
  "name": "myapt",
  "type": "package"
}

Pluggable SCM

{
  "scm_id": "someScmGitRepositoryId",
  "destination": "destinationDir",
  "filter": {
    "ignore": [
      "dir1",
      "dir2"
    ]
  },
  "name": "myPluggableGit",
  "type": "plugin"
}

Since GoCD >= 19.2.0 defining new pluggable materials that are not defined in the GoCD server is supported.

{
  "plugin_configuration": {
    "id": "plugin_id",
    "version": "1"
  },
  "configuration": [
    {
      "key": "url",
      "value": "[email protected]:tomzo/gocd-json-config-plugin.git"
    }
  ],
  "destination": "destinationDir",
  "filter": {
    "ignore": [
      "dir1",
      "dir2"
    ]
  },
  "name": "myPluggableGit",
  "type": "plugin"
}

Configrepo

This is a convenience for shorter and more consistent material declaration. When configuration repository is the same as one of pipeline materials, then you usually need to repeat definitions in XML and in JSON, for example:

...
  "materials": [
    {
      "url": "https://github.com/tomzo/gocd-json-config-example.git",
      "branch" : "ci",
      "type": "git",
      "name" : "mygit"
    }
  ],
...

And in server XML:

<config-repos>
   <config-repo pluginId="json.config.plugin" id="repo1">
     <git url="https://github.com/tomzo/gocd-json-config-example.git" branch="ci" />
   </config-repo>
</config-repos>

Notice that url and branch is repeated. This is inconvenient in case when you move repository, because it requires 2 updates, in code and in server XML.

Using configrepo material type, above repetition can be avoided, last example can be refactored into:

...
  "materials": [
    {
      "type": "configrepo",
      "name" : "mygit"
    }
  ],
...

Server interprets configrepo material in this way:

Clone the material configuration of the repository we are parsing as is in XML and replace name, destination and filters (whitelist/blacklist), then use the modified clone in place of configrepo material.

Tasks

Every task object must have type field. Which can be exec, ant, nant, rake, fetch, plugin

Optionally any task can have run_if and on_cancel.

  • run_if is a string. Valid values are passed, failed, any
  • on_cancel is a task object. Same rules apply as to tasks described on this page.

Exec

{
    "type": "exec",
    "run_if": "passed",
    "on_cancel" : null,
    "command": "make",
    "arguments": [
      "-j3",
      "docs",
      "install"
    ],
    "working_directory": null
}

Ant

{
  "build_file": "mybuild.xml",
  "target": "compile",
  "type": "ant",
  "run_if": "any",
  "on_cancel" : null,
}

Nant

{
  "type": "nant",
  "run_if": "passed",
  "working_directory": "script/build/123",
  "build_file": null,
  "target": null,
  "nant_path": null
}

Rake

{
  "type": "rake",
  "run_if": "passed",
  "working_directory": "sample-project",
  "build_file": null,
  "target": null
}

Fetch

Fetch artifact from the GoCD server

{
   "type": "fetch",
   "artifact_origin": "gocd",
   "run_if": "any",
   "pipeline": "upstream",
   "stage": "upstream_stage",
   "job": "upstream_job",
   "is_source_a_file": false,
   "source": "result",
   "destination": "test"
 }

Fetch artifact from an external artifact store

{
   "type": "fetch",
   "artifact_origin": "external",
   "run_if": "any",
   "pipeline": "upstream",
   "stage": "upstream_stage",
   "job": "upstream_job",
   "artifact_id": "upstream_external_artifactid",
   "configuration": [
     {
       "key": "DestOnAgent",
       "value": "foo"
     },
     {
       "key": "some_secure_property",
       "encrypted_value": "ssd#%fFS*!Esx"
     }
   ]
 }

Plugin

{
  "type": "plugin",
  "configuration": [
    {
      "key": "ConverterType",
      "value": "jsunit"
    },
    {
      "key": "password",
      "encrypted_value": "ssd#%fFS*!Esx"
    }
  ],
  "run_if": "passed",
  "plugin_configuration": {
    "id": "xunit.converter.task.plugin",
    "version": "1"
  },
  "on_cancel": null
}

Development

Environment setup

To build and test this plugin, you'll need java jdk >= 8.

If you have local java environment, then you may run all tests and create a ready to use jar with:

./gradlew test jar

Building with docker and dojo

You don't need to setup java on your host, if you are fine with using docker and Dojo. This is actually how our GoCD builds the plugin:

dojo "gradle test jar"

Assuming you already have a working docker, On OSX, you can install with homebrew:

brew install kudulab/homebrew-dojo-osx/dojo

A manual install is another option:

version="0.9.0"
# on Linux:
wget -O /tmp/dojo https://github.com/kudulab/dojo/releases/download/${version}/dojo_linux_amd64
# or on Darwin:
# wget -O /tmp/dojo https://github.com/kudulab/dojo/releases/download/${version}/dojo_darwin_amd64
chmod +x /tmp/dojo
mv /tmp/dojo /usr/bin/dojo

Then enter a docker container with java and gradle pre-installed, by running following command at the root of the project:

dojo

Issues and questions

  • If you have questions on usage, please ask them on the GoCD Google Groups forum or GitHub Discussions.

  • If you think there is a bug, or you have an idea for a feature and you are not sure if it's plugin's or GoCD fault/responsibity, please ask on the chat first too.

Please note this brief overview of what is done by the plugin:

  • parsing files into json when GoCD server asks for it.

And this is done by the GoCD server:

  • complex logic merging multiple config repo sources and XML
  • validation of pipelines/stages/jobs/tasks domain
  • any UI rendering

Versioning

We use semantic versioning.

If you are submitting a new feature or patch, please bump the version in build.gradle.

License

Copyright 2019 Tomasz Sฤ™tkowski

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

gocd-json-config-plugin's People

Contributors

aerostitch avatar arvindsv avatar bdpiprava avatar chadlwilson avatar dependabot-preview[bot] avatar dependabot[bot] avatar ganeshspatil avatar gradle-update-robot avatar hveiga avatar ibnc avatar ketan avatar kritika-singh3 avatar marques-work avatar nelsu avatar tomzo avatar varshavaradarajan avatar vrushaliwaykole avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gocd-json-config-plugin's Issues

Improve docs

The readme isn't enough. There are many properties that show single examples but not any reference values or what is expected. forexample, for auto deleting artifacts there's a single example shows but this page shows various options: https://docs.gocd.org/current/configuration/delete_artifacts.html . the README for this plugin does not specify all these options for even the json properties are.

How do I find out such json properties and expected values?

Failed to run git clone command, fatal: could not read Username

When defining a git material in my pipeline JSON I am not able to use the "username" and "encrypted_password" attributes without getting a "Failed to run git clone command" and "fatal: could not read Username" error.

If I include the credentials directly in the "url" attribute it works great, but then the password is not encrypted.

Is there a solution to this problem? Our version of GoCD is 19.1.0.

Modification check failed for material: URL: http://git.mycompany.com:8080/scm/my/myrepo.git, Branch: master30 Oct, 2019 at 18:04:56 Local Time
Failed to run git clone command STDERR: Cloning into '/var/lib/go-server/pipelines/flyweight/3cca5759-a3c5-4f71-a6c2-b86e0ac12802'...
STDERR: fatal: could not read Username for 'http://git.mycompany.com:8080': No such device or address

Not clear what attribute "id" means. Getting error 'Repository not found'

Hi,
We're using this plugin very actively. Currently, we are using 17.10.0 gocd version, and it's not clear from the README what to add to the XML for the "id" attribute.
Example https://github.com/tomzo/gocd-json-config-example seems not updated too.

   <config-repo pluginId="json.config.plugin" id="repo1">
     <git url="https://github.com/tomzo/gocd-json-config-example.git" />
   </config-repo>
</config-repos>
...
<pipelines />

Becuase in some cases we are getting error
: ERROR: Repository not found. STDERR: fatal: Could not read from remote repository. STDERR: STDERR: Please make sure you have the correct access rights STDERR: and the repository exists. but git repo exists and working

Thank you

Config-repo level file pattern configuration not working

Issue Type: Bug

It looks like the config-repo level file pattern is broken. It is not picking the config-repo level changes or overriding the plugin level global file pattern.

For example, below doesn't work and shows only pipelines from default file pattern **/*.gopipeline.json.

  <config-repo pluginId="json.config.plugin" id="sample">
     <git url="https://github.com/ankitsri11/gocd-json-config-example.git" />
     <configuration>
       <property>
         <key>pipeline_pattern</key>
         <value>**/*.goprodpipeline.json</value>
       </property>
       <property>
         <key>environment_pattern</key>
         <value>**/*.goprodenvironment.json</value>
       </property>
     </configuration>
   </config-repo>

Note: Plugin level global file pattern is working fine.

NullPointerException when material type is missing

When a material has no type attribute, the GoCD Config repo admin screen reports:

runtime;
1. Unexpected error when handling plugin response
java.lang.NullPointerException

I would have expected an error message along the lines of "Material No. 1 of pipeline dummy has no attribute 'type'" or something like that.

This is a sample material I've used to reproduce this behavior:

"materials": [
    {
      "auto_update": false,
      "branch": "master",
      "destination": "dummy",
      "filter": {
        "ignore": [],
        "whitelist": []
      },
      "name": "dummy",
      "shallow_clone": false,
      "url": "https://github.com/gocd/build_map.git"
    }

This bug happens with GoCD Version: 19.3.0 (8959-259d1f79e361875995072e5c1fcc9cbda7ccc600).

In case it makes the reproduction of this bug easier, here is the full JSON of the the pipeline:

{
  "environment_variables": [],
  "group": "misc",
  "label_template": "${COUNT}",
  "lock_behavior": "none",
  "materials": [
    {
      "auto_update": false,
      "branch": "master",
      "destination": "dummy",
      "filter": {
        "ignore": [],
        "whitelist": []
      },
      "name": "dummy",
      "shallow_clone": false,
      "url": "https://github.com/gocd/build_map.git"
    }
  ],
  "name": "dummy",
  "stages": [
    {
      "approval": {
        "roles": [],
        "type": "success",
        "users": []
      },
      "clean_working_directory": true,
      "environment_variables": [],
      "fetch_materials": true,
      "jobs": [
        {
          "artifacts": [],
          "environment_variables": [],
          "name": "dummy",
          "properties": [],
          "resources": [
            "stretch"
          ],
          "run_instance_count": "0",
          "tabs": [],
          "tasks": [
            {
              "arguments": [
                "test"
              ],
              "command": "echo",
              "run_if": "passed",
              "timeout": -1,
              "type": "exec",
              "working_directory": "dummy"
            }
          ],
          "timeout": 10
        }
      ],
      "name": "dummy",
      "never_cleanup_artifacts": false
    }
  ]
}

Cannot define artifacts

I've been trying to configure some jobs to save artifacts but it's doesn't seem to be working:

I've added the following snippet to one of the jobs:

          "artifacts": [
            {
              "artifact": {
                "src": "manifest.json",
                "dst": "manifests"
              }
            }
          ]

But the plugin breaks with the following error:
runtime; - Unexpected error when handling plugin response java.lang.NullPointerException

If I check the logs I can see this:

2018-08-17 17:05:43,035 ERROR [100@MessageListener for ConfigMaterialUpdater] GoRepoConfigDataSource:148 - Failed to parse configuration material https://**********@github.com/*************** by Plugin json.config.plugin
com.thoughtworks.go.plugin.access.configrepo.InvalidPartialConfigException:
runtime;
	- Unexpected error when handling plugin response
java.lang.NullPointerException
	at com.thoughtworks.go.config.ConfigRepoPlugin.parseDirectory(ConfigRepoPlugin.java:58)
	at com.thoughtworks.go.config.ConfigRepoPlugin.load(ConfigRepoPlugin.java:46)
	at com.thoughtworks.go.config.GoRepoConfigDataSource.onCheckoutComplete(GoRepoConfigDataSource.java:136)
	at com.thoughtworks.go.server.materials.ConfigMaterialUpdater.updateConfigurationFromCheckout(ConfigMaterialUpdater.java:106)
	at com.thoughtworks.go.server.materials.ConfigMaterialUpdater.onMessage(ConfigMaterialUpdater.java:91)
	at com.thoughtworks.go.server.materials.ConfigMaterialUpdater.onMessage(ConfigMaterialUpdater.java:38)
	at com.thoughtworks.go.server.messaging.activemq.JMSMessageListenerAdapter.runImpl(JMSMessageListenerAdapter.java:73)
	at com.thoughtworks.go.server.messaging.activemq.JMSMessageListenerAdapter.run(JMSMessageListenerAdapter.java:53)
	at java.lang.Thread.run(Thread.java:748)

Can anyone shed some light on how to use this?

Change "plugin" to "pluginId"

Type:

  • Bug Report

Description

config-repo tag under config-xml has changed to contain "pluginId" attribute instead of "plugin"

Current Result

<config-repos>
   <config-repo plugin="json.config.plugin">
     <git url="https://github.com/tomzo/gocd-json-config-example.git" />
   </config-repo>
</config-repos>

Expected Result

<config-repos>
   <config-repo pluginId="json.config.plugin" id="repo1">
     <git url="https://github.com/tomzo/gocd-json-config-example.git" />
   </config-repo>
</config-repos>

More information

Plugin doesn't work wit exciting env and new pipeline

I've installed the plugin, created the *.gopipeline.json and was trying to add the plugin to our goCd server. But it seems not working for our case.
The reason is we're using environments, and there is no way of specifying the exciting (default) environment for a newly created pipeline using the current plugin.

I tried to add pipeline name to the cruise-config.xml file but got an error that pipeline doesn't exist which make sense.
Can any workaround be suggested, please?

docs issue

install docs refer to <atifactStores/>

that should be <artifactStores/> (missing first "r")

Inconsistent download URL for releases

Version 0.2.0 has a download URL of https://github.com/tomzo/gocd-json-config-plugin/releases/download/0.2.0/json-config-plugin-0.2.jar. For future releases, it would be nice if the final .0 was included on the jar name so that scripts can make use of variables like the following example:

$GOCD_PLUGINS=/var/lib/go-server/plugins/external
$VERSION=0.2.0

sudo curl -sL -o $GOCD_PLUGINS/json-config-plugin-$VERSION.jar \
  https://github.com/tomzo/gocd-json-config-plugin/releases/download/$VERSION/json-config-plugin-$VERSION.jar

environments config not working correctly

configured the environment as below, if I look at the agents tab the agent is showing the correct environment next to it but if I look on the environments page, the environment has no agents assigned to it. If I check the config xml, no agents are showing under the environment. We have multiple agents on a single server. Specifying the agent name complains about not having uuid.

goenvironment.json

{
"name": "my_new_env",
"environment_variables": [],
"agents": [
"243c8698-54ac-4b1e-86d7-609572390ebe"
],
"pipelines": []
}

gocd 18.12
json config plugin 0.2.1

Feature: ability to use current branch as material

I would like to request a feature.

Background

When creating a feature branch, I would like to setup additional pipelines to build this feature branch before it is merged. This way changes can be previewed by other developers for larger changes.

Implementation

A material is defined like this in build.pipeline.json:

    {
      "url": "[email protected]:company/my-repo.git",
      "branch": "develop",
      "type": "git"
    }

I would like to be able to insert the current branch here so this build works for any branch I specify in the config:

    {
      "url": "[email protected]:company/my-repo.git",
      "branch": "{{CURRENT_BRANCH}}",
      "type": "git"
    }

The placeholder {{CURRENT_BRANCH}} would be replaced with the value in the config xml when the plugin is loading the config into GoCD.

    <config-repo pluginId="json.config.plugin" id="my-repo">
      <git url="[email protected]:company/my-repo.git" branch="my-feature-branch" />
    </config-repo>

In this case:

{{CURRENT_BRANCH}} => my-feature-branch

encrypt_value instead of encrypted_value

Hi there,

I ran into an issue where I had the most simple tasks (custom command of originally extracting a tar down to a straightforward echo during debug) failing. Long story short: I had one of the secure variables down with encrypt_value as key in the JSON config plugin rather than encrypted_value...

There was no obvious error showing up, however (in hindsight) I spotted that the specific secure variable was also omitted upon the "Start to update materials" step (setting environment variables) on the console tab.

Not sure whether something could be done to flag something like this more clearly. At the very least it's something to be aware of as it can send a whole schoal of red herrings in someone's direction :-)

Thanks!
David

P.S. Great work on this plugin - this quickly became an essential plugin for my GoCD setup!

Request to support 'parameters' on the pipeline

In my pipelines manually configured through the GoCD UI, I have a parameter called DEPLOY_ENV:

     <params>
       <param name="DEPLOY_ENV">acc</param>
     </params>

This allows me to define tasks in a more generic way by passing in the #{DEPLOY_ENV} as a parameter to my task definitions.

In an effort to move to using JSON to define my configuration as code, it would be nice if I could continue this model.

What's the chance of adding support for parameters?

Tasks not killed when cancelled

When configuring an exec task within a pipeline, the task is not terminated if the build is cancelled.

What should the on_cancel task be set to for an exec task to ensure it is cancelled?

Is it related to: gocd/gocd#3375 ?

Thanks in advance!

"500 Internal Server Error" when calling GET /go/api/admin/pipelines/:pipeline_name

Issue Type
  • Bug Report
Summary

Getting "500 Internal Server Error" when calling pipelines API for pipelines backed by config repo with YAML config. Seems to be because of missing destination K/V in YAML and JSON.

Environment
Basic environment details
  • Go Version: 18.10.0 (7703-42d1cbe661161b5400289ead86c0447c84af8c0a)
  • JAVA Version: 1.8.0_171
  • OS: Linux 3.10.0-693.2.2.el7.x86_64
  • Browser vendor and version (if relevant): curl and node
Additional Environment Details
Steps to Reproduce
  1. curl API without destination key, will get HTTP 500 error.
  2. Add destination to ci.gocd.yaml file.
  3. curl API with destination: "" key works fine.

See config in code snippet below.
curl: (22) The requested URL returned error: 500 Server Error

format_version: 3
pipelines:
  TestGoPipelineAPI:
    group: DevOps
    materials:
      mygit:
        git: https://github.com/gocd-contrib/getting-started-repo.git
    stages:
    - Build:
        jobs:
          build:
            elastic_profile_id: "rhel7"
            tasks:
            - exec:
                command: mkdir
                arguments:
                - "surefire-reports"
            artifacts:
            - test:
                source: surefire-reports

Adding destination: "" makes it work fine.

format_version: 3
pipelines:
  TestGoPipelineAPI:
    group: DevOps
    materials:
      mygit:
        git: https://github.com/gocd-contrib/getting-started-repo.git
    stages:
    - Build:
        jobs:
          build:
            elastic_profile_id: "rhel7"
            tasks:
            - exec:
                command: mkdir
                arguments:
                - "surefire-reports"
            artifacts:
            - test:
                source: surefire-reports
                destination: ""
Expected Results
curl --fail --user user:pwd https://gocd-server.example.com/go/api/admin/pipelines/TestGoPipelineAPI -H 'Accept: application/vnd.go.cd.v6+json'
{
  "_links" : {
    "self" : {
...
      "artifacts" : [ {
        "type" : "test",
        "source" : "surefire-reports",
        "destination" : "testoutput"
      } ],
      "properties" : null
    } ]
  } ],
  "tracking_tool" : null,
  "timer" : null
}
Actual Results
curl --fail --user user:pwd https://gocd-server.example.com/go/api/admin/pipelines/TestGoPipelineAPI -H 'Accept: application/vnd.go.cd.v6+json'
curl: (22) The requested URL returned error: 500 Server Error
Possible Fix

Work around is to add: destination: "" key

Log snippets
java.lang.RuntimeException: Try to write null value into configuration! [com.thoughtworks.go.config.BuiltinArtifactConfig.destination]
	at com.thoughtworks.go.util.ExceptionUtils.bomb(ExceptionUtils.java:30)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter$AttributeXmlFieldWithValue.populate(MagicalGoConfigXmlWriter.java:278)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter.write(MagicalGoConfigXmlWriter.java:146)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter.access$200(MagicalGoConfigXmlWriter.java:43)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter$CollectionXmlFieldWithValue.populate(MagicalGoConfigXmlWriter.java:342)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter$ExplicitCollectionXmlFieldWithValue.populate(MagicalGoConfigXmlWriter.java:363)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter.write(MagicalGoConfigXmlWriter.java:146)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter.access$200(MagicalGoConfigXmlWriter.java:43)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter$CollectionXmlFieldWithValue.populate(MagicalGoConfigXmlWriter.java:342)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter$ExplicitCollectionXmlFieldWithValue.populate(MagicalGoConfigXmlWriter.java:363)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter.write(MagicalGoConfigXmlWriter.java:146)
	at com.thoughtworks.go.config.MagicalGoConfigXmlWriter.toXmlPartial(MagicalGoConfigXmlWriter.java:120)
	at com.thoughtworks.go.server.service.EntityHashingService.computeMd5For(EntityHashingService.java:203)
	at com.thoughtworks.go.server.service.EntityHashingService.getFromCache(EntityHashingService.java:180)
	at com.thoughtworks.go.server.service.EntityHashingService.md5ForEntity(EntityHashingService.java:110)
	at com.thoughtworks.go.apiv6.admin.pipelineconfig.PipelineConfigControllerV6.etagFor(PipelineConfigControllerV6.java:74)
	at com.thoughtworks.go.apiv6.admin.pipelineconfig.PipelineConfigControllerV6.etagFor(PipelineConfigControllerV6.java:53)
	at com.thoughtworks.go.api.CrudController.isGetOrHeadRequestFresh(CrudController.java:32)
	at com.thoughtworks.go.apiv6.admin.pipelineconfig.PipelineConfigControllerV6.show(PipelineConfigControllerV6.java:172)
	at spark.RouteImpl$1.handle(RouteImpl.java:72)
	at spark.http.matching.Routes.execute(Routes.java:61)
	at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
	at spark.servlet.SparkFilter.doFilter(SparkFilter.java:173)
	at com.thoughtworks.go.spark.SparkPreFilter.doFilter(SparkPreFilter.java:53)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:420)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:203)
	at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:73)
	at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:213)
	at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:171)
	at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
	at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
	at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at com.thoughtworks.go.server.web.FlashLoadingFilter.doFilterInternal(FlashLoadingFilter.java:39)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at com.thoughtworks.go.server.newsecurity.filters.DenyIfRefererIsNotFilesFilter.doFilterInternal(DenyIfRefererIsNotFilesFilter.java:53)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at com.thoughtworks.go.server.newsecurity.filters.VerifyAuthorityFilter.doFilterInternal(VerifyAuthorityFilter.java:58)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at com.thoughtworks.go.server.newsecurity.filters.AbstractUserEnabledCheckFilter.doFilterInternal(AbstractUserEnabledCheckFilter.java:67)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at com.thoughtworks.go.server.newsecurity.filters.ThreadLocalUserFilter.doFilterInternal(ThreadLocalUserFilter.java:42)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at com.thoughtworks.go.server.newsecurity.filters.AbstractBasicAuthenticationFilter.filterWhenSecurityEnabled(AbstractBasicAuthenticationFilter.java:99)
	at com.thoughtworks.go.server.newsecurity.filters.AbstractBasicAuthenticationFilter.doFilterInternal(AbstractBasicAuthenticationFilter.java:68)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at com.thoughtworks.go.server.newsecurity.filters.AssumeAnonymousUserFilter.doFilterInternal(AssumeAnonymousUserFilter.java:65)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at com.thoughtworks.go.server.newsecurity.filters.AbstractReAuthenticationFilter.doFilterInternal(AbstractReAuthenticationFilter.java:75)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at com.thoughtworks.go.server.newsecurity.filters.InvalidateAuthenticationOnSecurityConfigChangeFilter.doFilterInternal(InvalidateAuthenticationOnSecurityConfigChangeFilter.java:84)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at com.thoughtworks.go.server.newsecurity.filters.AlwaysCreateSessionFilter.doFilterInternal(AlwaysCreateSessionFilter.java:41)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at com.thoughtworks.go.server.newsecurity.filters.AbstractSessionReduceIdleTimeoutFilter.doFilterInternal(AbstractSessionReduceIdleTimeoutFilter.java:45)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:185)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at com.thoughtworks.go.server.newsecurity.filters.ModeAwareFilter.doFilter(ModeAwareFilter.java:53)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
	at com.thoughtworks.go.server.newsecurity.filterchains.MainFilterChain.doFilter(MainFilterChain.java:76)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
	at com.thoughtworks.go.server.web.BackupFilter.doFilter(BackupFilter.java:88)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
	at com.thoughtworks.go.server.web.DefaultHeadersFilter.doFilter(DefaultHeadersFilter.java:36)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1629)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:527)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:530)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
	at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:289)
	at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:149)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
	at java.lang.Thread.run(Thread.java:748)
Code snippets/Screenshots
Any other info

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.