mirror of
https://github.com/hanzoai/pack.git
synced 2026-09-30 23:43:13 +00:00
feat(buildkit): add RAILPACK_BUILT_AT environment variable (#669)
- Add `RAILPACK_BUILT_AT` to runtime image environment containing Unix epoch seconds - Document runtime Railpack environment variables and precedence rules - Add unit tests verifying environment generation and cache isolation for deploy variables Generated-by: aiautocommit
This commit is contained in:
+5
-4
@@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/moby/buildkit/client/llb"
|
||||
"github.com/moby/buildkit/util/system"
|
||||
@@ -32,9 +34,7 @@ type ConvertPlanOptions struct {
|
||||
NoCache bool
|
||||
}
|
||||
|
||||
const (
|
||||
WorkingDir = "/app"
|
||||
)
|
||||
const WorkingDir = "/app"
|
||||
|
||||
func ConvertPlanToLLB(plan *p.BuildPlan, opts ConvertPlanOptions) (*llb.State, *Image, error) {
|
||||
platform := opts.BuildPlatform
|
||||
@@ -107,11 +107,12 @@ func getImageEnv(graphOutput *build_llb.BuildGraphOutput, plan *p.BuildPlan) []s
|
||||
slices.Sort(paths)
|
||||
pathString := strings.Join(paths, ":")
|
||||
|
||||
envMap := make(map[string]string, len(graphOutput.GraphEnv.EnvVars)+len(plan.Deploy.Variables)+1)
|
||||
envMap := make(map[string]string, len(graphOutput.GraphEnv.EnvVars)+len(plan.Deploy.Variables)+2)
|
||||
maps.Copy(envMap, graphOutput.GraphEnv.EnvVars)
|
||||
maps.Copy(envMap, plan.Deploy.Variables)
|
||||
|
||||
envMap["PATH"] = pathString
|
||||
envMap["RAILPACK_BUILT_AT"] = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
envVars := make([]string, 0, len(envMap))
|
||||
for _, k := range slices.Sorted(maps.Keys(envMap)) {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package buildkit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/railwayapp/railpack/buildkit/build_llb"
|
||||
"github.com/railwayapp/railpack/core/plan"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetImageEnvIncludesBuiltAt(t *testing.T) {
|
||||
graphOutput := &build_llb.BuildGraphOutput{
|
||||
GraphEnv: build_llb.NewGraphEnvironment(),
|
||||
}
|
||||
buildPlan := plan.NewBuildPlan()
|
||||
buildPlan.Deploy.Variables = map[string]string{
|
||||
"RAILPACK_BUILT_AT": "custom",
|
||||
}
|
||||
before := time.Now().Unix()
|
||||
|
||||
env := getImageEnv(graphOutput, buildPlan)
|
||||
after := time.Now().Unix()
|
||||
|
||||
builtAt := ""
|
||||
for _, variable := range env {
|
||||
if value, ok := strings.CutPrefix(variable, "RAILPACK_BUILT_AT="); ok {
|
||||
builtAt = value
|
||||
}
|
||||
}
|
||||
timestamp, err := strconv.ParseInt(builtAt, 10, 64)
|
||||
require.NoError(t, err)
|
||||
require.GreaterOrEqual(t, timestamp, before)
|
||||
require.LessOrEqual(t, timestamp, after)
|
||||
require.True(t, slices.IsSorted(env))
|
||||
}
|
||||
|
||||
func TestDeployVariablesDoNotAffectLLB(t *testing.T) {
|
||||
firstPlan := plan.NewBuildPlan()
|
||||
firstPlan.Deploy.Base = plan.NewImageLayer("alpine:latest")
|
||||
firstPlan.Deploy.Variables = map[string]string{"VALUE": "one"}
|
||||
secondPlan := plan.NewBuildPlan()
|
||||
secondPlan.Deploy.Base = plan.NewImageLayer("alpine:latest")
|
||||
secondPlan.Deploy.Variables = map[string]string{"VALUE": "two"}
|
||||
opts := ConvertPlanOptions{
|
||||
BuildPlatform: specs.Platform{
|
||||
OS: "linux",
|
||||
Architecture: "amd64",
|
||||
},
|
||||
}
|
||||
|
||||
firstState, firstImage, err := ConvertPlanToLLB(firstPlan, opts)
|
||||
require.NoError(t, err)
|
||||
secondState, secondImage, err := ConvertPlanToLLB(secondPlan, opts)
|
||||
require.NoError(t, err)
|
||||
|
||||
firstDefinition, err := firstState.Marshal(context.Background())
|
||||
require.NoError(t, err)
|
||||
secondDefinition, err := secondState.Marshal(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, firstDefinition.ToPB(), secondDefinition.ToPB())
|
||||
require.NotEqual(t, firstImage.Config.Env, secondImage.Config.Env)
|
||||
}
|
||||
@@ -42,8 +42,20 @@ Environment variables can be set in two ways:
|
||||
}
|
||||
```
|
||||
|
||||
Railpack always sets `RAILPACK_VERSION` on the final runtime image to the
|
||||
Railpack version that produced the image (for example `0.12.3`).
|
||||
## Runtime Railpack Variables
|
||||
|
||||
The final image includes runtime metadata that is not available to build
|
||||
commands:
|
||||
|
||||
| Name | Description |
|
||||
| :------------------ | :--------------------------------------- |
|
||||
| `RAILPACK_VERSION` | Version used to produce the image |
|
||||
| `RAILPACK_BUILT_AT` | Build time as Unix epoch seconds (UTC) |
|
||||
|
||||
Runtime metadata is added after generating the build graph, so it does not
|
||||
invalidate application layer caches. The `RAILPACK_` namespace in the final
|
||||
image is reserved for generated runtime metadata, which takes precedence over
|
||||
deploy variables with the same name.
|
||||
|
||||
## Secrets
|
||||
|
||||
|
||||
Reference in New Issue
Block a user