Skip to content

Commit 82c8560

Browse files
authored
feat: add build secrets option (#75)
* feat: add build secrets option * make gen and fix tests
1 parent dabb7f3 commit 82c8560

File tree

4 files changed

+50
-12
lines changed

4 files changed

+50
-12
lines changed

docs/resources/cached_image.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The cached image resource can be used to retrieve a cached image produced by env
2525

2626
- `base_image_cache_dir` (String) (Envbuilder option) The path to a directory where the base image can be found. This should be a read-only directory solely mounted for the purpose of caching the base image.
2727
- `build_context_path` (String) (Envbuilder option) Can be specified when a DockerfilePath is specified outside the base WorkspaceFolder. This path MUST be relative to the WorkspaceFolder path into which the repo is cloned.
28+
- `build_secrets` (Map of String) The secrets to use for the build. This is a map of key-value pairs.
2829
- `cache_ttl_days` (Number) (Envbuilder option) The number of days to use cached layers before expiring them. Defaults to 7 days.
2930
- `devcontainer_dir` (String) (Envbuilder option) The path to the folder containing the devcontainer.json file that will be used to build the workspace and can either be an absolute path or a path relative to the workspace folder. If not provided, defaults to `.devcontainer`.
3031
- `devcontainer_json_path` (String) (Envbuilder option) The path to a devcontainer.json file that is either an absolute path or a path relative to DevcontainerDir. This can be used in cases where one wants to substitute an edited devcontainer.json file for the one that exists in the repo.

internal/provider/cached_image_resource.go

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type CachedImageResourceModel struct {
5151
// Optional "inputs".
5252
BaseImageCacheDir types.String `tfsdk:"base_image_cache_dir"`
5353
BuildContextPath types.String `tfsdk:"build_context_path"`
54+
BuildSecrets types.Map `tfsdk:"build_secrets"`
5455
CacheTTLDays types.Int64 `tfsdk:"cache_ttl_days"`
5556
DevcontainerDir types.String `tfsdk:"devcontainer_dir"`
5657
DevcontainerJSONPath types.String `tfsdk:"devcontainer_json_path"`
@@ -121,6 +122,11 @@ func (r *CachedImageResource) Schema(ctx context.Context, req resource.SchemaReq
121122
MarkdownDescription: "(Envbuilder option) Can be specified when a DockerfilePath is specified outside the base WorkspaceFolder. This path MUST be relative to the WorkspaceFolder path into which the repo is cloned.",
122123
Optional: true,
123124
},
125+
"build_secrets": schema.MapAttribute{
126+
MarkdownDescription: "The secrets to use for the build. This is a map of key-value pairs.",
127+
ElementType: types.StringType,
128+
Optional: true,
129+
},
124130
"cache_ttl_days": schema.Int64Attribute{
125131
MarkdownDescription: "(Envbuilder option) The number of days to use cached layers before expiring them. Defaults to 7 days.",
126132
Optional: true,

internal/provider/helpers.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package provider
22

33
import (
44
"fmt"
5+
"slices"
56
"strings"
67

78
eboptions "github.com/coder/envbuilder/options"
@@ -47,6 +48,22 @@ func optionsFromDataModel(data CachedImageResourceModel) (eboptions.Options, dia
4748
opts.BuildContextPath = data.BuildContextPath.ValueString()
4849
}
4950

51+
if !data.BuildSecrets.IsNull() {
52+
providerOpts["ENVBUILDER_BUILD_SECRETS"] = true
53+
54+
// Depending on use case, users might want to provide build secrets as a map or a list of strings.
55+
// The string list option is supported by extra_env, so we support the map option here. Envbuilder
56+
// expects a list of strings, so we convert the map to a list of strings here.
57+
buildSecretMap := tfutil.TFMapToStringMap(data.BuildSecrets)
58+
buildSecretSlice := make([]string, 0, len(buildSecretMap))
59+
for k, v := range buildSecretMap {
60+
buildSecretSlice = append(buildSecretSlice, fmt.Sprintf("%s=%s", k, v))
61+
}
62+
slices.Sort(buildSecretSlice)
63+
64+
opts.BuildSecrets = buildSecretSlice
65+
}
66+
5067
if !data.CacheTTLDays.IsNull() {
5168
providerOpts["ENVBUILDER_CACHE_TTL_DAYS"] = true
5269
opts.CacheTTLDays = data.CacheTTLDays.ValueInt64()
@@ -199,7 +216,7 @@ func overrideOptionsFromExtraEnv(opts *eboptions.Options, extraEnv map[string]st
199216

200217
// XXX: workaround for serpent behaviour where calling Set() on a
201218
// string slice will append instead of replace: set to empty first.
202-
if key == "ENVBUILDER_IGNORE_PATHS" {
219+
if _, ok := optsMap[key].(*serpent.StringArray); ok {
203220
_ = optsMap[key].Set("")
204221
}
205222

internal/provider/provider_internal_test.go

+25-11
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,15 @@ func Test_optionsFromDataModel(t *testing.T) {
3535
{
3636
name: "all options without extra_env",
3737
data: CachedImageResourceModel{
38-
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
39-
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
40-
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
41-
BaseImageCacheDir: basetypes.NewStringValue("/tmp/cache"),
42-
BuildContextPath: basetypes.NewStringValue("."),
38+
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
39+
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
40+
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
41+
BaseImageCacheDir: basetypes.NewStringValue("/tmp/cache"),
42+
BuildContextPath: basetypes.NewStringValue("."),
43+
BuildSecrets: basetypes.NewMapValueMust(basetypes.StringType{}, map[string]attr.Value{
44+
"FOO": basetypes.NewStringValue("bar"),
45+
"BAZ": basetypes.NewStringValue("qux"),
46+
}),
4347
CacheTTLDays: basetypes.NewInt64Value(7),
4448
DevcontainerDir: basetypes.NewStringValue(".devcontainer"),
4549
DevcontainerJSONPath: basetypes.NewStringValue(".devcontainer/devcontainer.json"),
@@ -66,6 +70,7 @@ func Test_optionsFromDataModel(t *testing.T) {
6670
GitURL: "[email protected]/devcontainer.git",
6771
BaseImageCacheDir: "/tmp/cache",
6872
BuildContextPath: ".",
73+
BuildSecrets: []string{"BAZ=qux", "FOO=bar"}, // Sorted
6974
CacheTTLDays: 7,
7075
DevcontainerDir: ".devcontainer",
7176
DevcontainerJSONPath: ".devcontainer/devcontainer.json",
@@ -97,9 +102,11 @@ func Test_optionsFromDataModel(t *testing.T) {
97102
"CODER_AGENT_TOKEN", "token",
98103
"CODER_AGENT_URL", "http://coder",
99104
"FOO", "bar",
105+
"ENVBUILDER_BUILD_SECRETS", "FOO=bar,BAZ=qux",
100106
),
101107
},
102108
expectOpts: eboptions.Options{
109+
BuildSecrets: []string{"FOO=bar", "BAZ=qux"},
103110
CacheRepo: "localhost:5000/cache",
104111
GitURL: "[email protected]/devcontainer.git",
105112
RemoteRepoBuildMode: true,
@@ -110,11 +117,14 @@ func Test_optionsFromDataModel(t *testing.T) {
110117
{
111118
name: "extra_env override warnings",
112119
data: CachedImageResourceModel{
113-
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
114-
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
115-
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
116-
BaseImageCacheDir: basetypes.NewStringValue("/tmp/cache"),
117-
BuildContextPath: basetypes.NewStringValue("."),
120+
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
121+
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
122+
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
123+
BaseImageCacheDir: basetypes.NewStringValue("/tmp/cache"),
124+
BuildContextPath: basetypes.NewStringValue("."),
125+
BuildSecrets: basetypes.NewMapValueMust(basetypes.StringType{}, map[string]attr.Value{
126+
"FOO": basetypes.NewStringValue("bar"),
127+
}),
118128
CacheTTLDays: basetypes.NewInt64Value(7),
119129
DevcontainerDir: basetypes.NewStringValue(".devcontainer"),
120130
DevcontainerJSONPath: basetypes.NewStringValue(".devcontainer/devcontainer.json"),
@@ -136,6 +146,7 @@ func Test_optionsFromDataModel(t *testing.T) {
136146
Verbose: basetypes.NewBoolValue(true),
137147
WorkspaceFolder: basetypes.NewStringValue("workspace"),
138148
ExtraEnv: extraEnvMap(t,
149+
"ENVBUILDER_BUILD_SECRETS", "FOO=bar,BAZ=qux",
139150
"ENVBUILDER_CACHE_REPO", "override",
140151
"ENVBUILDER_GIT_URL", "override",
141152
"ENVBUILDER_BASE_IMAGE_CACHE_DIR", "override",
@@ -169,6 +180,7 @@ func Test_optionsFromDataModel(t *testing.T) {
169180
// overridden
170181
BaseImageCacheDir: "override",
171182
BuildContextPath: "override",
183+
BuildSecrets: []string{"FOO=bar", "BAZ=qux"},
172184
CacheTTLDays: 8,
173185
DevcontainerDir: "override",
174186
DevcontainerJSONPath: "override",
@@ -189,7 +201,7 @@ func Test_optionsFromDataModel(t *testing.T) {
189201
Verbose: false,
190202
WorkspaceFolder: "override",
191203
},
192-
expectNumWarningDiags: 23,
204+
expectNumWarningDiags: 24,
193205
},
194206
{
195207
name: "extra_env override errors",
@@ -295,6 +307,7 @@ func Test_computeEnvFromOptions(t *testing.T) {
295307
BaseImageCacheDir: "string",
296308
BinaryPath: "string",
297309
BuildContextPath: "string",
310+
BuildSecrets: []string{"FOO=bar", "BAZ=qux"},
298311
CacheRepo: "string",
299312
CacheTTLDays: 1,
300313
CoderAgentSubsystem: []string{"one", "two"},
@@ -339,6 +352,7 @@ func Test_computeEnvFromOptions(t *testing.T) {
339352
"ENVBUILDER_BASE_IMAGE_CACHE_DIR": "string",
340353
"ENVBUILDER_BINARY_PATH": "string",
341354
"ENVBUILDER_BUILD_CONTEXT_PATH": "string",
355+
"ENVBUILDER_BUILD_SECRETS": "FOO=bar,BAZ=qux",
342356
"ENVBUILDER_CACHE_REPO": "string",
343357
"ENVBUILDER_CACHE_TTL_DAYS": "1",
344358
"ENVBUILDER_DEVCONTAINER_DIR": "string",

0 commit comments

Comments
 (0)