this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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í <mvdan@mvdan.cc>
Change-Id: I2e45865bf86788c42ba3ef2d7422fd21b9af221a
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1171911
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+94 -4
+43 -3
internal/e2e/script_test.go
··· 15 15 package e2e_test 16 16 17 17 import ( 18 + "bytes" 18 19 "context" 19 20 "fmt" 20 21 "net/http" 21 22 "os" 22 23 "os/exec" 23 24 "path/filepath" 25 + "strings" 24 26 "testing" 25 27 "time" 26 28 ··· 78 80 githubOrg = envOr("GITHUB_ORG", "cue-labs-modules-testing") 79 81 // githubKeep leaves the newly created repo around when set to true. 80 82 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") 81 88 ) 82 89 83 90 func TestScript(t *testing.T) { ··· 104 111 // Not a global, since 105 112 githubToken := envMust(t, "GITHUB_TOKEN") 106 113 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) 110 115 client := github.NewClient(nil).WithAuthToken(githubToken) 111 116 ctx := context.TODO() 112 117 ··· 165 170 } 166 171 ts.Fatalf("timed out waiting for module") 167 172 }, 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 + }, 168 198 }, 169 199 } 170 200 testscript.Run(t, p) ··· 190 220 return ts.Getenv(key) 191 221 }) 192 222 } 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 + }
+50
internal/e2e/testdata/script/gcloud_upload.txtar
··· 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 + }
+1 -1
internal/e2e/testdata/script/github_app_public.txtar
··· 9 9 10 10 cd publish 11 11 12 - # TODO: replace by "cue mod init" once it's available. 12 + # TODO: replace by "cue mod init" once it supports versioned module names. 13 13 # cue mod init ${MODVER} 14 14 env-fill cue.mod/module.cue 15 15