-
Notifications
You must be signed in to change notification settings - Fork 71
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
RFC: Execution Environments #274
base: main
Are you sure you want to change the base?
Conversation
Maintainers, As you review this RFC please queue up issues to be created using the following commands:
Issues(none) |
Signed-off-by: Terence Lee <[email protected]>
50f431b
to
2e9e00d
Compare
|
||
In order to support additional execution environments an `exec-env` key will be added to various TOML tables in the project. The value can be any string with `all` having special meaning. `all` will apply to all execution environments and will be the default if not specified. This should make it backwards compatible and optional. When `exec-env` is not set to `all`, the table settings will only be applied to that execution environment. | ||
|
||
### Project Descriptor - `project.toml` (App Developers) |
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.
Can you add an example of a full project.toml that is used for producing a test image and a production image?
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.
Just for Project Descriptor?
I'm having a difficulty trying to grasp how environment is being used by different toml files. @hone could you please provide examples of places where you imagine it being used and how that information will be leveraged by buildpacks/platform? |
Signed-off-by: Terence Lee <[email protected]>
Signed-off-by: Terence Lee <[email protected]>
* test | ||
* development | ||
|
||
### Buildpack API |
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.
Can we perhaps get a conceptual example of what a buildpack author might do with this new execution environment information?
I have in my head a language buildpack author may...
- install test group dependencies
- create
ruby-tests
process /ruby-tests-verbose
process - Skip cleaning up things they might clean up otherwise for production images
- Set env vars to test mode operation (RAILS_ENV or similar)
Frankly, I don't get this proposal aligned with my mental model of what buildpacks do and how they help. For me, container images are just another software artefact nowadays produced to ship software. Like a while back one was to produce JAR and/or WAR files that got delivered and finally deployed into some execution environment. From my POV buildpacks should focus on that task, creating the container image, and leave the other CI tasks to specialized tools. Please help me to adjust my mental model, why's this added complexity in the buildpack spec worth it? |
I'm not the author but I can speak for my own mental model. One use case is from the app developer side. Today they can If we imagine the resulting image is ruby + nodejs, the developer has to setup both of those environments locally to develop and AGAIN on say GitHub Actions. The way those installations happen can differ. The GitHub action may install a different minor version of node or ruby to run the tests for instance. Setting up CI with buildpacks could make this experience easier. Another future-proofing thing here may be around future ARM support. Building and running an ARM test image via |
# Unresolved Questions | ||
[unresolved-questions]: #unresolved-questions | ||
|
||
- "env" is overloaded as a word since we also use it for environment variables. Is there a better word here? |
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.
How about "mode"?
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.
I like "context", but that's just as overloaded. How about "purpose = test" or "intent = test"?
|
||
### `builder.toml` (Builder Authors) | ||
|
||
The only table that `exec-env` will be added to is `[[order.group.env]]`. |
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.
Do you mean [[order.group]]
?
With the test OCI Image, a platform can execute the tests in the pipeline as they see fit. This means a bulk of the responsibilities are platform concerns: | ||
|
||
- Set which environment to build for | ||
- Decide which buildpacks to execute |
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.
Isn't this a lifecycle concern? i.e., when processing a group within an order, should it skip buildpacks that do not declare exec-env
matching the desired env?
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.
When talking to @jabrown85, I thought the Platform/Builder provide the order.toml
to lifecycle
?
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.
From WG, lifecycle
will decide which buildpacks to run based on the execution environment being passed along by the platform.
- How to execute the tests | ||
- What is the test result format like [TAP](https://en.wikipedia.org/wiki/Test_Anything_Protocol)? | ||
- How to process the test results | ||
- What to do with the results |
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.
Is this ever something we would want to spec? Having a consistent way for buildpacks to e.g., dump test output could help ensure portability across platforms.
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.
I could see us wanting to do that, but I wasn't sure how much we wanted to impose standards there.
- Should the execution environments be an enum or flexible as a string? | ||
- enums will help encourage standardization across buildpacks and platforms. | ||
- strings can help account for use cases we haven't thought of yet. | ||
- Should buildpacks be allowed specify allowlist execution environments? |
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.
Are there any downsides to doing this? It would be more flexible and possibly avoid some duplication within orders (we could keep all
as a special value)
## Development Environments | ||
The specifics of creating development enviroments are out of scope of this RFC, but it's not hard to extrapolate how these kind of changes can assist in creating Buildpacks for development environments. | ||
|
||
# How it Works |
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.
It would be nice to see the pack flow as well
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.
Should we add anything to the app image to designate it as being built for a particular environment? To avoid users accidentally deploying a test image in production...
I could see folks wanting to use the same tag when re-building a test image for production, in order to use previously cached dependencies.
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.
@natalieparellano that's a good question. Do you think cached dependencies should be shared b/t different execution environments?
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.
Is a label the best place to designate the execution environment?
I have a use-case for this. |
Really excited for this proposal, and I think there's a lot of interesting ways to make use of it. In the context of a self-hosted PaaS On the developer side, most folks don't ever see production-like environments, so being able to debug their applications in production-like environments becomes incredibly difficult. In the past, I've seen some of these per-environment configurations being managed through GitOps and config files. This gives the user some control over managing the movement of the workload through the system, but even still they may not be able to build that container and interact with it directly Moving the environment configuration opens up a lot of possibilities in this use case. I could image an operator encoding their per-environment configurations into the builder, and giving the developer the ability to simulate how their application will change in behavior across configurations. For CI/CD Changing what "prod-like" means |
|
||
There were some flaws in this design. Though it's clean to separate production and test code paths, they end up sharing a lot of code. Many of the bash based Heroku buildpacks would just [call `bin/compile`](https://github.com/heroku/heroku-buildpack-nodejs/blob/main/bin/test-compile#L24) with different parameters/env vars. | ||
|
||
## [GOOGLE_DEVMODE](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_devmode) |
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.
Similar to devmode, I just ran across live reloading in the Paketo python buildpacks https://paketo.io/docs/howto/python/#using-bp_live_reload_enabled
|
||
## `exec-env` key in TOML | ||
|
||
In order to support additional execution environments an `exec-env` key will be added to various TOML tables in the project. The value can be any string with `all` having special meaning. `all` will apply to all execution environments and will be the default if not specified. This should make it backwards compatible and optional. When `exec-env` is not set to `all`, the table settings will only be applied to that execution environment. |
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.
What would consume this new key? If a platform or user ran pack build -e CNB_EXEC_ENV=test my-app:test
, a buildpack might contribute new launch entries flagged for test, but how would a platform or user determine which of the launch entries were all
or test
? My guess is at the very least, we'd want this key to show up in the io.buildpacks.build.metadata
process-types
label data?
Co-authored-by: Natalie Arellano <[email protected]> Signed-off-by: Terence Lee <[email protected]>
Co-authored-by: Josh W Lewis <[email protected]> Signed-off-by: Terence Lee <[email protected]>
Two questions:
|
This RFC aims to only produce a test image artifact. A test platform would then execute the image and collect the results (TAP/json/etc).
There would be no such guarantee. Production images vary quite a bit from stack to stack and there is no one size fits all solution for testing. For a practical example, a ruby or node app will often have test environment specific dependencies that should not make their way into the final production images. Another example is a simple go app on a scratch/tiny stack. The go tooling itself, Thinking out loud, a test pipeline could grab the SBOM/digests/shasum of the things it cares about and compare them to the production image that was built. |
Right, so right now the image produced is a self-executing app built, whether it's npm, or go or whatever. The test image would not execute anything but would contain the app with all of the, keeping to the npm example, dev dependencies. Maybe it's even built. And the pipeline would use that image, run its tools on top of that (static analysis, test, etc.), grab the produced outputs, and publish them. |
The way I understand this is the produced image would have A golang buildpack would create a layer that contains go testing tools and maybe even run a |
Hi, I wanted to comment the concept with a use-case. So, I don't see the point in creating a production images in environment X, while testing in environment Y. That's not consistent way of doing CD pipelines (current behavior) 🙂 I give buildpacks to teams, they set e.g. BP_NODE_VERSION 16.1 and it will execute with Node 16.1, while in tests it will still execute with hardcoded Node 16.0 because I have to maintain additional images. Using buildpacks in this scenario is loosing sense for me 🙂 More consistent way is to just use the Dockerfile with base image used in tests, because it has consistent Maven and Java version inside. Due to nature of buildpacks - preparing the environment (by installing required tooling, setting up those tools) - I think the test phase is even a neccesary scenario to implement a valid CD pipeline in order to gain reproducible environment everytime. The tests needs to be running on something that is CLOSE TO PRODUCTION 🙂 So I see that The case is similar to the principle, where we should not build artifact twice if promoting to next environment e.g. dev -> prod, but just reuse the artifact. There we should use the same build parameters, same tooling. Its difficult to maitain e.g. Node 14, Node 15, Java 8, Java 11, and 15 other base images just for tests, while giving teams a possibility to set a Node or Java version in buildpacks. A
|
|
||
## `exec-env` key in TOML | ||
|
||
In order to support additional execution environments an `exec-env` key will be added to various TOML tables in the project. The value can be any string with `all` having special meaning. `all` will apply to all execution environments and will be the default if not specified. This should make it backwards compatible and optional. When `exec-env` is not set to `all`, the table settings will only be applied to that execution environment. |
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.
We should consider wanting multiple values. This might make []
mean all
, which is kind of odd.
exec-env: ["staging", "production"] # but not uat
Readable