From 3500616dcd7ba37c3b16a53a113241a26ebb508b Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Thu, 21 Dec 2017 13:51:59 -0800 Subject: [PATCH] Add support for `caches` attribute in concourse tasks See: https://www.pivotaltracker.com/story/show/153861788 --- .../vscode/concourse/PipelineYmlSchema.java | 4 ++ .../src/main/resources/desc/TaskCache/path.md | 5 ++ .../main/resources/desc/TaskConfig/caches.md | 36 ++++++++++++ .../vscode/concourse/ConcourseEditorTest.java | 55 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 headless-services/concourse-language-server/src/main/resources/desc/TaskCache/path.md create mode 100644 headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/caches.md diff --git a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java index 61d7a6c47..0b6da217c 100644 --- a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java +++ b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java @@ -249,12 +249,16 @@ public class PipelineYmlSchema implements YamlSchema { addProp(t_command, "dir", t_ne_string); addProp(t_command, "user", t_string); + YBeanType cache = f.ybean("TaskCache"); + addProp(cache, "path", t_ne_string).isRequired(true); + task = f.ybean("TaskConfig"); addProp(task, "platform", t_platform).isRequired(true); addProp(task, "image_resource", t_image_resource); addProp(task, "rootfs_uri", t_ne_string); addProp(task, "image", t_ne_string).isDeprecated("The 'image' property in 'TaskConfig' is renamed to 'rootfs_uri' in Concourse 3.0"); addProp(task, "inputs", f.yseq(t_input)); + addProp(task, "caches", f.yseq(cache)); addProp(task, "outputs", f.yseq(t_output)); addProp(task, "run", t_command).isRequired(true); addProp(task, "params", t_string_params); diff --git a/headless-services/concourse-language-server/src/main/resources/desc/TaskCache/path.md b/headless-services/concourse-language-server/src/main/resources/desc/TaskCache/path.md new file mode 100644 index 000000000..bd48b4f95 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/TaskCache/path.md @@ -0,0 +1,5 @@ +*Required.* The path to a directory to be cached. + +Paths are relative to the working directory of the task. Absolute paths are not respected. + +Note that this value must not overlap with any other caches in the same task. Each cache results in a new empty directory that your task can place artifacts in; if the path overlaps it'll clobber whatever files used to be there. \ No newline at end of file diff --git a/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/caches.md b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/caches.md new file mode 100644 index 000000000..788851c73 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/TaskConfig/caches.md @@ -0,0 +1,36 @@ +*Optional.* The cached directories shared between task runs. + +On the task's first run, all cache directories will be empty. It is the responsibility of the task to populate these directories with any artifacts to be cached. On subsequent runs, the cached directories will contain those artifacts. + +Caches are scoped to the worker the task is run on, so you will not get a cache hit when subsequent builds run on different workers. This also means that caching is not intended to share state between workers, and your task should be able to run whether or not the cache is warmed. + +Caches are also scoped to a particular task name inside of a pipeline's job. As a consequence, if the job name, step name or cache path are changed, the cache will not be used. This also means that caches do not exist for one-off builds. + +For example, the following task and script define a node project that takes advantage of task caches for its node modules: + + --- + platform: linux + + image_resource: # ... + + inputs: + - name: project-src + + caches: + - path: project-src/node_modules + + run: + path: project-src/ci/build + +...assuming project-src/ci/build looks something like: + + #!/bin/bash + + set -e -u -x + + cd project-src + npm install + + # ... + +...this task would cache the contents of project-src/node_modules between runs of this task on the same worker. \ No newline at end of file diff --git a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java index 9de8faadf..64fd83428 100644 --- a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java +++ b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java @@ -2875,6 +2875,9 @@ public class ConcourseEditorTest { , "<*>" , // ==> + "caches:\n" + + "- path: <*>" + , "image_resource:\n" + " type: <*>" , @@ -4141,6 +4144,58 @@ public class ConcourseEditorTest { ); } + @Test public void taskCachesReconcile() throws Exception { + //See: https://www.pivotaltracker.com/story/show/153861788 + Editor editor = harness.newEditor(LanguageId.CONCOURSE_TASK, + "platform: linux\n" + + "\n" + + "inputs:\n" + + "- name: project-src\n" + + "\n" + + "caches:\n" + + "- path: project-src/node_modules\n" + + " junk: bad\n" + + "\n" + + "run:\n" + + " path: project-src/ci/build" + ); + editor.assertProblems("junk|Unknown property"); + } + + @Test public void taskCachesCompletions() throws Exception { + //See: https://www.pivotaltracker.com/story/show/153861788 + Editor editor = harness.newEditor(LanguageId.CONCOURSE_TASK, + "platform: linux\n" + + "\n" + + "inputs:\n" + + "- name: project-src\n" + + "\n" + + "caches:\n" + + "- <*>\n" + + "run:\n" + + " path: project-src/ci/build" + ); + editor.assertContextualCompletions(PLAIN_COMPLETION, "<*>", "path: <*>"); + } + + @Test public void taskCachesHovers() throws Exception { + Editor editor = harness.newEditor(LanguageId.CONCOURSE_TASK, + "platform: linux\n" + + "\n" + + "inputs:\n" + + "- name: project-src\n" + + "\n" + + "caches:\n" + + "- path: project-src/node_modules\n" + + " junk: bad\n" + + "\n" + + "run:\n" + + " path: project-src/ci/build" + ); + editor.assertHoverContains("caches", "Caches are scoped to the worker the task is run on"); + editor.assertHoverContains("path", "The path to a directory to be cached"); + } + ////////////////////////////////////////////////////////////////////////////// private void assertContextualCompletions(String conText, String textBefore, String... textAfter) throws Exception {