Skip to content

Commit a060f85

Browse files
committed
internal/e2e: add a "cue mod upload" end-to-end test with gcloud
Now that we have the first experimental version of "cue mod upload", and we support authenticating with cloud provider registries via docker credential helpers such as gcloud, we can write an end-to-end test with Google Cloud Artifact Registry. This test does the same as our existing GitHub App test at a high level, publishing one module version and then using it as a dependency. However, instead of creating a GitHub repo and pushing a git tag, we use "cue mod upload" with gcloud as a credential helper, making sure that gcloud shares the same configuration as the host. The test script is named after "gcloud" since all the auth bits are particular to Google Cloud right now. We can later add another script, or make this script more generic, if we want to test against other common OCI/Docker registry providers. Note that the test is skipped for now for the sake of our CI, since we don't have a service account set up with a key on it yet. The next commit will do that bit of setup in our CI script. Signed-off-by: Daniel Martí <[email protected]> Change-Id: I2e45865bf86788c42ba3ef2d7422fd21b9af221a Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1171911 Reviewed-by: Roger Peppe <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 4dba8dd commit a060f85

File tree

3 files changed

+94
-4
lines changed

3 files changed

+94
-4
lines changed

internal/e2e/script_test.go

+43-3
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
package e2e_test
1616

1717
import (
18+
"bytes"
1819
"context"
1920
"fmt"
2021
"net/http"
2122
"os"
2223
"os/exec"
2324
"path/filepath"
25+
"strings"
2426
"testing"
2527
"time"
2628

@@ -78,6 +80,11 @@ var (
7880
githubOrg = envOr("GITHUB_ORG", "cue-labs-modules-testing")
7981
// githubKeep leaves the newly created repo around when set to true.
8082
githubKeep = envOr("GITHUB_KEEP", "false")
83+
84+
// gcloudRegistry is an existing Google Cloud Artifact Registry repository
85+
// to upload module versions to via "cue mod upload",
86+
// and authenticated via gcloud's configuration in the host environment.
87+
gcloudRegistry = envOr("GCLOUD_REGISTRY", "europe-west1-docker.pkg.dev/project-unity-377819/modules-e2e-registry")
8188
)
8289

8390
func TestScript(t *testing.T) {
@@ -104,9 +111,7 @@ func TestScript(t *testing.T) {
104111
// Not a global, since
105112
githubToken := envMust(t, "GITHUB_TOKEN")
106113

107-
// TODO: name the repo after ts.Name once the API lands
108-
// TODO: add a short random suffix to prevent time collisions
109-
repoName := time.Now().UTC().Format("2006-01-02.15-04-05")
114+
repoName := testModuleName(ts)
110115
client := github.NewClient(nil).WithAuthToken(githubToken)
111116
ctx := context.TODO()
112117

@@ -165,6 +170,31 @@ func TestScript(t *testing.T) {
165170
}
166171
ts.Fatalf("timed out waiting for module")
167172
},
173+
// gcloud-auth-docker configures gcloud so that it uses the host's existing configuration,
174+
// and sets CUE_REGISTRY and CUE_REGISTRY_HOST according to gcloudRegistry.
175+
"gcloud-auth-docker": func(ts *testscript.TestScript, neg bool, args []string) {
176+
if neg || len(args) > 0 {
177+
ts.Fatalf("usage: gcloud-auth-docker")
178+
}
179+
// The test script needs to be able to run gcloud as a docker credential helper.
180+
// gcloud will be accessible via $PATH without issue, but it needs to use its host config,
181+
// so we pass it along as $CLOUDSDK_CONFIG to not share the host's entire $HOME.
182+
//
183+
// We assume that the host already has gcloud authorized to upload OCI artifacts,
184+
// via either a user account (gcloud auth login) or a service account key (gcloud auth activate-service-account).
185+
gcloudConfigPath, err := exec.Command("gcloud", "info", "--format=value(config.paths.global_config_dir)").Output()
186+
ts.Check(err)
187+
ts.Setenv("CLOUDSDK_CONFIG", string(bytes.TrimSpace(gcloudConfigPath)))
188+
189+
// The module path can be anything we want in this case,
190+
// but we might as well make it unique and realistic.
191+
ts.Setenv("MODULE", "domain.test/"+testModuleName(ts))
192+
193+
ts.Setenv("CUE_REGISTRY", gcloudRegistry)
194+
// TODO: reuse internal/mod/modresolve.parseRegistry, returning a Location with Host.
195+
gcloudRegistryHost, _, _ := strings.Cut(gcloudRegistry, "/")
196+
ts.Setenv("CUE_REGISTRY_HOST", gcloudRegistryHost)
197+
},
168198
},
169199
}
170200
testscript.Run(t, p)
@@ -190,3 +220,13 @@ func tsExpand(ts *testscript.TestScript, s string) string {
190220
return ts.Getenv(key)
191221
})
192222
}
223+
224+
// testModuleName creates a unique string without any slashes
225+
// which can be used as the base name for a module path to publish,
226+
// so that test runs don't conflict with one another
227+
// and can be easily attributed to a point in time.
228+
func testModuleName(ts *testscript.TestScript) string {
229+
// TODO: name the repo after ts.Name once the API lands
230+
// TODO: add a short random suffix to prevent time collisions
231+
return time.Now().UTC().Format("2006-01-02.15-04-05")
232+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Publish a version for a simple CUE module via "cue mod upload"
2+
# to an off-the-shelf OCI registry which requires authentication.
3+
# Then fetch that module as a dependency via cmd/cue.
4+
5+
skip 'TODO(mvdan): set up a service account key on GitHub Actions'
6+
7+
gcloud-auth-docker # sets: MODULE, CUE_REGISTRY, CUE_REGISTRY_HOST, CLOUDSDK_CONFIG
8+
env DOCKER_CONFIG=$WORK/docker-config
9+
env-fill docker-config/config.json
10+
11+
env VERSION=v0.0.1
12+
env MODVER=${MODULE}@v0
13+
14+
cd publish
15+
16+
# TODO: replace by "cue mod init" once it supports versioned module names.
17+
# cue mod init ${MODVER}
18+
env-fill cue.mod/module.cue
19+
20+
exec cue mod upload ${VERSION}
21+
22+
cd ../depend
23+
24+
env-fill cue.mod/module.cue out_foo.cue
25+
exec cue export
26+
cmp stdout export.golden
27+
28+
-- docker-config/config.json --
29+
{"credHelpers": {"${CUE_REGISTRY_HOST}": "gcloud"}}
30+
-- publish/cue.mod/module.cue --
31+
module: "${MODVER}"
32+
-- publish/foo.cue --
33+
package publish
34+
35+
foo: "foo value"
36+
37+
-- depend/cue.mod/module.cue --
38+
module: "depend.localhost"
39+
40+
deps: "${MODVER}": v: "${VERSION}"
41+
-- depend/out_foo.cue --
42+
package depend
43+
44+
import mt "${MODVER}:publish"
45+
46+
out: mt.foo
47+
-- depend/export.golden --
48+
{
49+
"out": "foo value"
50+
}

internal/e2e/testdata/script/github_app_public.txtar

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ env MODVER=${MODULE}@v0
99

1010
cd publish
1111

12-
# TODO: replace by "cue mod init" once it's available.
12+
# TODO: replace by "cue mod init" once it supports versioned module names.
1313
# cue mod init ${MODVER}
1414
env-fill cue.mod/module.cue
1515

0 commit comments

Comments
 (0)