-
Notifications
You must be signed in to change notification settings - Fork 8
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
Improve ergonomics for Append/Prepend use cases in LayerEnv
API
#790
Comments
Thanks for the write-up! I'm worried when we strife too far from the CNB spec that it will lead to hard reason about where certain behaviour comes from. If someone runs into the issue with a missing delimiter, they can search for CNB in general and will get an answer that will point them to the solution they can also use with libcnb.rs since the API is very close to the spec.
That's another issue with the spec as it uses one file per environment variable. You can put multiple values in that file, but you'd need to concatenate with some delimiter before. There is no way to use the same delimiter mechanism from lifecycle implicitly. The whole idea of encoding the environment modifications as file system trees causes a lot of issues and makes it hard to work with. Using a TOML file would make it easy to enforce (in lifecycle) a delimiter with each append/prepend operation. One can argue that the current file system approach it's an easy interface for scripting languages, but buildpack authors have to write TOML in many cases anyway. Moving this feature to TOML as well would be more up- than downside, but that's a discussion for upstream. TL;DR: This is much more complicated to get right as it might seem. Playing it safe and keeping close the spec is my preferred solution mid-term. Working with upstream on the spec in that area sounds more fruitful to me. |
👍 Still wanted to capture it here. Improving the situation with the upstream spec is definitely the ideal so maybe Would a utility function in |
As for stopgap solutions I think upstream is again our best bet. Ideally Not sure how a helper in |
Just something simple that explicitly ties the two together like: // append a single value to the env while ensuring that there is a delimiter set
fn append_value_to_env<T>(name: T, value: T, delimiter: T, scope: Scope)
where
T: Into<OsString>;
// append multiple values to the env while ensuring that there is a delimiter set
// and each value is joined using that delimiter
fn append_values_to_env<I, T>(name: T, values: I, delimiter: T, scope: Scope)
where
I: IntoIterator<Item = T>,
T: Into<OsString>;
// prepend a single value to the env while ensuring that there is a delimiter set
fn prepend_value_to_env<T>(name: T, value: T, delimiter: T, scope: Scope)
where
T: Into<OsString>;
// prepend multiple values to the env while ensuring that there is a delimiter set
// and each value is joined using that delimiter
fn prepend_values_to_env<I, T>(name: T, values: I, delimiter: T, scope: Scope)
where
I: IntoIterator<Item = T>,
T: Into<OsString>; |
The API design of
LayerEnv
is meant to map directly to the environment variable modification rules of the CNB spec.For many cases this API is suitable. But, when it comes to environment variables that fall under the
Append
orPrepend
modification behavior, this API is less than ideal and can cause confusion for buildpack authors. Here are two such examples:A buildpack author wants to append to the
FOO
environment variable and callsWithout realizing they must also set a delimiter using or a default empty string will be used as a delimiter when the environment values are processed:
This is a known issue and Document the need to set an explicit delimiter when using
ModificationBehavior::{Append,Prepend}
#700 proposes better documentation to help. It seems that the API could also assist buildpack authors here by providing methods to ensure a delimiter is set at the same scope wheneverAppend
orPrepend
modification behaviors are used since these two concerns are linked.A buildpack author wants to prepend multiple values to the
BAR
environment variable and callsDue to the semantics of
Append
andPrepend
, I think it's easy to misinterpret whatenv.insert
is doing here and expect that it would modifyBAR
to insert each value using a prepend operation with the required delimiter. What it actually does is overwrite the value ofBAR
on each iteration so only the last value is persisted. This makes sense at a low-level but, like the required delimiter issue above, does no favors for the buildpack author. To get the correct result the delimiter needs to be used twice as can be seen in the following code:Since append and prepend semantics are typically associated with list operations, it would be preferable if the
LayerEnv
API matched those expectations whenModificationBehavior::{Append,Prepend}
operations are involved and would:The text was updated successfully, but these errors were encountered: