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 d9e637ee6..7afb08926 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 @@ -367,10 +367,16 @@ public class PipelineYmlSchema implements YamlSchema { YBeanType setPipelineStep = f.ybean("SetPipelineStep"); addProp(setPipelineStep, "set_pipeline", t_ne_string); - addProp(setPipelineStep, "file", t_string).isRequired(true); + addProp(setPipelineStep, "file", t_ne_string).isRequired(true); addProp(setPipelineStep, "vars", t_params); addProp(setPipelineStep, "var_files", t_strings); + YBeanType loadVarStep = f.ybean("LoadVarStep"); + addProp(loadVarStep, "load_var", t_ne_string); //TODO: t_identifier: see https://concourse-ci.org/config-basics.html#schema.identifier + addProp(loadVarStep, "file", t_ne_string).isRequired(true); + addProp(loadVarStep, "format", f.yenum("LoadVarFormat", "json", "yaml", "yml", "trim", "raw")); + addProp(loadVarStep, "reveal", t_boolean); + YBeanType aggregateStep = f.ybean("AggregateStep"); YBeanType doStep = f.ybean("DoStep"); YBeanType tryStep = f.ybean("TryStep"); @@ -381,12 +387,14 @@ public class PipelineYmlSchema implements YamlSchema { putStep, taskStep, setPipelineStep, + loadVarStep, aggregateStep, inParallelStep, doStep, tryStep }; + YBeanUnionType step = f.yBeanUnion("Step", stepTypes); addProp(aggregateStep, "aggregate", f.yseq(step)).isDeprecated("Deprecated in favor of `in_parallel`"); diff --git a/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/file.md b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/file.md new file mode 100644 index 000000000..1f28dcfa4 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/file.md @@ -0,0 +1 @@ +*Required*. The path to a file whose content shall be read and used as the var's value. \ No newline at end of file diff --git a/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/format.md b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/format.md new file mode 100644 index 000000000..b6b9bfa7b --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/format.md @@ -0,0 +1,35 @@ +*Optional*. The format of the file's content. + +If unset, Concourse will try to detect the format from the file extension. If the file format cannot be determined, Concourse will fallback to `trim`. + +If set to `json`, `yaml`, or `yml`, the file content will be parsed accordingly and the resulting structure will be the value of the var. + +If set to `trim`, the var will be set to the content of the file with any trailing and leading whitespace removed. + +If set to `raw`, the var will be set to the content of the file without modification (i.e. with any existing whitespace). + +**Example**: Loading a var with multiple fields. + +Let's say we have a task, `generate-creds`, which produces a `generated-user` output containing a `user.json` file like so: + +``` +{ + "username": "some-user", + "password": "some-password" +} +``` + +We could pass these credentials to subsequent steps by loading it into a var with `load_var`, which will detect that it is in JSON format based on the file extension: + +``` +plan: +- task: generate-creds +- load_var: user + file: generated-user/user.json +- task: use-creds + params: + USERNAME: ((.:user.username)) + PASSWORD: ((.:user.password)) +``` + +If the `use-creds` task were to print these values, they would be automatically redacted unless `reveal: true` is set. \ No newline at end of file diff --git a/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/load_var.md b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/load_var.md new file mode 100644 index 000000000..45835b939 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/load_var.md @@ -0,0 +1,14 @@ +Note: The `load_var` step was introduced in Concourse v6.0.0. It is considered an experimental feature until its associated [RFC](https://github.com/concourse/rfcs/pull/27) is resolved. + +*Required* Load the value for a var at runtime, making it available to subsequent steps as a build-local var named after the given identifier. + +The following build plan uses a version produced by the semver resource as a tag: + +``` +plan: +- get: version +- load_var: version-tag + file: version/version +- put: image + params: {tag: ((.:version-tag))} +``` \ No newline at end of file diff --git a/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/reveal.md b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/reveal.md new file mode 100644 index 000000000..b20ef5b09 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/LoadVarStep/reveal.md @@ -0,0 +1 @@ +*Optional*. *Default: false*. If set to `true`, allow the var's content to be printed in the build output even with secret redaction enabled. \ 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 8d906ae64..8af1f35f1 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 @@ -371,6 +371,8 @@ public class ConcourseEditorTest { "in_parallel:\n" + " <*>" , // ============== + "load_var: <*>" + , // ============== "put: <*>" , // ============== "set_pipeline: <*>" @@ -400,7 +402,7 @@ public class ConcourseEditorTest { " - <*>" ); } - + @Test public void primaryStepHovers() throws Exception { Editor editor = harness.newEditor( @@ -417,7 +419,9 @@ public class ConcourseEditorTest { " - try:\n" + " put: test-logs\n" + " - set_pipeline: configure-the-pipeline\n" + - " file: my-repo/ci/pipeline.yml\n" + " file: my-repo/ci/pipeline.yml\n" + + " - load_var: some-var\n" + + " file: /path/to/var-file\n" ); editor.assertHoverContains("get", "Fetches a resource"); @@ -470,6 +474,50 @@ public class ConcourseEditorTest { editor.assertHoverContains("var_files", "files that will be passed to the pipeline config in the same manner as the --load-vars-from flag"); editor.assertHoverContains("vars", "A map of template variables to pass to the pipeline config."); } + + @Test + public void loadVarStepHovers() throws Exception { + Editor editor = harness.newEditor( + "jobs:\n" + + "- name: some-job\n" + + " plan:\n" + + " - get: my-repo\n" + + " - load_var: some-var\n" + + " file: path/to/varfile.json\n" + + " format: json\n" + + " reveal: true\n" + ); + + editor.assertHoverContains("load_var", "Load the value for a var at runtime"); + editor.assertHoverContains("file", "file whose content shall be read"); + editor.assertHoverContains("format", "The format of the file's content"); + editor.assertHoverContains("reveal", "allow the var's content to be printed"); + } + + @Test + public void loadVarStepReconcile() throws Exception { + Editor editor = harness.newEditor( + "jobs:\n" + + "- name: some-job\n" + + " plan:\n" + + " - load_var: some-var\n" + ); + editor.assertProblems("-^ load_var|'file' is required"); + + editor = harness.newEditor( + "jobs:\n" + + "- name: some-job\n" + + " plan:\n" + + " - load_var: some-var\n" + + " file: path/to/varfile.json\n" + + " format: a-format\n" + + " reveal: show-it\n" + ); + editor.assertProblems( + "a-format|Valid values are: [json, raw, trim, yaml, yml]", + "show-it|boolean" + ); + } @Test public void getStepHovers() throws Exception { @@ -4283,6 +4331,7 @@ public class ConcourseEditorTest { "- do", "- get", "- in_parallel", + "- load_var\n" + "- put", "- set_pipeline", "- task",