New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement YAML roundtripping, comment preserving edits #11456
Conversation
Changelog[uncommitted] (2022-12-12)Features
|
feb5cd6
to
c588409
Compare
692988e
to
194eebf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to piggyback an integration test for pulumi config set
for this change?
Looks good too me.
sdk/go/common/util/yamlutil/edit.go
Outdated
var b bytes.Buffer | ||
yamlEncoder := yaml.NewEncoder(&b) | ||
yamlEncoder.SetIndent(2) | ||
err = yamlEncoder.Encode(&newValue) | ||
if err != nil { | ||
return nil, fmt.Errorf("error editing value %#v: %w", newValue, err) | ||
} | ||
|
||
return b.Bytes(), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there was a way to avoid repeating this in sdk/go/common/encoding/marshal.go
, that would be great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exported a two space indendation YamlEncode
and refactored.
@iwahbe re: testing. Yeah I think so - we could modify an integration test to start with a file that has some config and comments. I'll do that. |
27c750e
to
166a652
Compare
@Frassle @justinvp @iwahbe Added tests here: https://github.com/pulumi/pulumi/blob/friel/yaml-roundtrip/tests/roundtrip_test.go I'd like the first test to use |
a5c3d75
to
39a108e
Compare
176cf85
to
12a8743
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 LGTM
bors merge |
11456: Implement YAML roundtripping, comment preserving edits r=AaronFriel a=AaronFriel By caching a copy of the raw bytes of the original loaded document - project, policy project, or stack - on save we: * Unmarshal the original bytes to a YAML AST * Recursively edit nodes of the document to match the values of the value we're saving, preserving trivia * Marshal the modified AST to []byte Closes #423, as we don't support comments in JSON presently (not using "JSON5") Closes #5235 Simplifies work done in #10797 and #10437 which used the previous `yamlutil` package to edit AST nodes directly. # Automation API Integration with automation API requires that operations either perform a "read-modify-write" in a single operation, or use a side channel to allow subsequent "read" (select stack?) and "write" operations to keep state of the original file. However I don't expect this to be needed. We don't have a reason to believe automation API users maintain comments in particular stack files, and doing so is already unsupported in automation scenarios. The Pulumi Service does not persist raw config files, thus `pulumi config refresh` and `CreateOrSelectStack` create config files without comments. n.b.: If you test this, due to the new behavior of this PR, `pulumi config refresh` will persist comments if there is an existing config file. I would expect automation API using local file workspaces to behave similarly. When using these tools to create a config file from the last deployment's definition, the file is created restored without comments. # Tradeoffs I believe that this closes #423 in spirit, but doesn't strictly implement round-tripping. There are a couple reasons for this. ## Marshaller interface and round-tripping simplification decisions We support unmarshaling "simplified" YAML, including allowing: ```yaml runtime: yaml # this unmarshals to a struct, not a scalar value config: someKey: "someScalar" # likewise ``` These simplifications make it much more difficult, the `Marshal` operation would _also_ need context of decisions made when unmarshaling to ensure a bijection. Otherwise we may save one of these as the other: ```yaml runtime: name: yaml ``` ```yaml runtime: yaml ``` This could be considered a feature, as it enforces a style guide - the decisions implemented in our custom `Marshaller` implementations become the style enforced on save. That said, I believe the new `Edit` API while not round-trippable, does reach a fixed point after one save through the new API. Once saved with this API, subsequent loads & saves without changes are idempotent. ## Indentation The YAML library uses a global indentation when marshaling values to YAML, as opposed to indentation being a property of AST nodes. This means we may lose other indentation. Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
Build failed: |
bors retry |
Build succeeded: |
By caching a copy of the raw bytes of the original loaded document - project, policy project, or stack - on save we:
Closes #423, as we don't support comments in JSON presently (not using "JSON5")
Closes #5235
Simplifies work done in #10797 and #10437 which used the previous
yamlutil
package to edit AST nodes directly.Automation API
Integration with automation API requires that operations either perform a "read-modify-write" in a single operation, or use a side channel to allow subsequent "read" (select stack?) and "write" operations to keep state of the original file.
However I don't expect this to be needed. We don't have a reason to believe automation API users maintain comments in particular stack files, and doing so is already unsupported in automation scenarios. The Pulumi Service does not persist raw config files, thus
pulumi config refresh
andCreateOrSelectStack
create config files without comments.n.b.: If you test this, due to the new behavior of this PR,
pulumi config refresh
will persist comments if there is an existing config file. I would expect automation API using local file workspaces to behave similarly. When using these tools to create a config file from the last deployment's definition, the file is created restored without comments.Tradeoffs
I believe that this closes #423 in spirit, but doesn't strictly implement round-tripping. There are a couple reasons for this.
Marshaller interface and round-tripping simplification decisions
We support unmarshaling "simplified" YAML, including allowing:
These simplifications make it much more difficult, the
Marshal
operation would also need context of decisions made when unmarshaling to ensure a bijection. Otherwise we may save one of these as the other:This could be considered a feature, as it enforces a style guide - the decisions implemented in our custom
Marshaller
implementations become the style enforced on save.That said, I believe the new
Edit
API while not round-trippable, does reach a fixed point after one save through the new API. Once saved with this API, subsequent loads & saves without changes are idempotent.Indentation
The YAML library uses a global indentation when marshaling values to YAML, as opposed to indentation being a property of AST nodes. This means we may lose other indentation.