diff --git a/.github/workflows/trybot.yml b/.github/workflows/trybot.yml index 39018253f..f4217a4fa 100644 --- a/.github/workflows/trybot.yml +++ b/.github/workflows/trybot.yml @@ -184,7 +184,6 @@ jobs: Dispatch-Trailer: {"type":"')))) && (matrix.go-version == '1.22.x' && matrix.runner == 'ubuntu-22.04') name: End-to-end test env: - GITHUB_TOKEN: ${{ secrets.E2E_GITHUB_TOKEN }} CUE_LOGINS: ${{ secrets.E2E_CUE_LOGINS }} run: |- cd internal/e2e diff --git a/internal/ci/github/trybot.cue b/internal/ci/github/trybot.cue index 930002d2f..b95526e35 100644 --- a/internal/ci/github/trybot.cue +++ b/internal/ci/github/trybot.cue @@ -142,8 +142,7 @@ workflows: trybot: _repo.bashWorkflow & { // on the entire cue-labs-modules-testing org. Note that porcuepine is also an org admin, // since otherwise the repo admin access to create and delete repos does not work. env: { - GITHUB_TOKEN: "${{ secrets.E2E_GITHUB_TOKEN }}" - CUE_LOGINS: "${{ secrets.E2E_CUE_LOGINS }}" + CUE_LOGINS: "${{ secrets.E2E_CUE_LOGINS }}" } // Our regular tests run with both `go test ./...` and `go test -race ./...`. // The end-to-end tests should only be run once, given the slowness and API rate limits. diff --git a/internal/e2e/go.mod b/internal/e2e/go.mod index 3e9d33534..ae15c4bca 100644 --- a/internal/e2e/go.mod +++ b/internal/e2e/go.mod @@ -4,7 +4,6 @@ go 1.21 require ( cuelang.org/go v0.0.0-00010101000000-000000000000 - github.com/google/go-github/v56 v56.0.0 github.com/rogpeppe/go-internal v1.12.0 ) @@ -13,7 +12,6 @@ require ( github.com/cockroachdb/apd/v3 v3.2.1 // indirect github.com/emicklei/proto v1.10.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect diff --git a/internal/e2e/go.sum b/internal/e2e/go.sum index a5664aa4e..feeeaa4c8 100644 --- a/internal/e2e/go.sum +++ b/internal/e2e/go.sum @@ -11,14 +11,9 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v56 v56.0.0 h1:TysL7dMa/r7wsQi44BjqlwaHvwlFlqkK8CtBWCX3gb4= -github.com/google/go-github/v56 v56.0.0/go.mod h1:D8cdcX98YWJvi7TLo7zM4/h8ZTx6u6fwGEkCdisopo0= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= diff --git a/internal/e2e/script_test.go b/internal/e2e/script_test.go index 643eafc21..e3c22e1f1 100644 --- a/internal/e2e/script_test.go +++ b/internal/e2e/script_test.go @@ -16,18 +16,16 @@ package e2e_test import ( "bytes" - "context" cryptorand "crypto/rand" "fmt" "os" "os/exec" + "path" "path/filepath" - "strconv" "strings" "testing" "time" - "github.com/google/go-github/v56/github" "github.com/rogpeppe/go-internal/testscript" ) @@ -73,13 +71,15 @@ func TestMain(m *testing.M) { } var ( - // githubOrg is a GitHub organization where the "CUE Module Publisher" - // GitHub App has been installed on all repositories. - // This is necessary since we will create a new repository per test, - // and there's no way to easily install the app on each repo via the API. - githubOrg = envOr("GITHUB_ORG", "cue-labs-modules-testing") - // githubKeep leaves the newly created repo around when set to true. - githubKeep = envOr("GITHUB_KEEP", "false") + // githubPublicRepo is a GitHub public repository + // with the "cue.works authz" GitHub App installed. + // The repository can be entirely empty, as it's only needed for authz. + githubPublicRepo = envOr("GITHUB_PUBLIC_REPO", "github.com/cue-labs-modules-testing/e2e-public") + + // githubPublicRepo is a GitHub private repository + // with the "cue.works authz" GitHub App installed. + // The repository can be entirely empty, as it's only needed for authz. + githubPrivateRepo = envOr("GITHUB_PRIVATE_REPO", "github.com/cue-labs-modules-testing/e2e-private") // gcloudRegistry is an existing Google Cloud Artifact Registry repository // to publish module versions to via "cue mod publish", @@ -115,64 +115,24 @@ func TestScript(t *testing.T) { return nil }, Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){ - // create-github-repo creates a unique repository under githubOrg - // and sets $MODULE to its resulting module path. - // TODO(mvdan): once we support nested modules, - // such as github.com/owner/repo/subpath@v1.2.3, - // we could rely on an existing github.com/owner/repo repository on GitHub - // and use unique subpaths for each test run, - // meaning that the e2e tests would no longer need a GitHub token. - "create-github-repo": func(ts *testscript.TestScript, neg bool, args []string) { - if neg { - ts.Fatalf("usage: create-github-repo [field=value...]") - } - - // githubToken should have read and write access to repository - // administration and contents within githubOrg, - // to be able to create repositories under the org and git push to them. - // Not a global, since we only want to require GITHUB_TOKEN when needed. - githubToken := envMust(t, "GITHUB_TOKEN") - - repoName := testModuleName(ts) - client := github.NewClient(nil).WithAuthToken(githubToken) - ctx := context.TODO() - - repo := &github.Repository{ - Name: github.String(repoName), + // github-repo-module sets $MODULE to a unique nested module under the given repository path. + "github-repo-module": func(ts *testscript.TestScript, neg bool, args []string) { + if neg || len(args) != 1 { + ts.Fatalf("usage: with-github-repo ") } - for _, arg := range args { - field, value, ok := strings.Cut(arg, "=") - if !ok { - ts.Fatalf("invalid field=value arg: %q", arg) - } - switch field { - case "private": - b, err := strconv.ParseBool(value) - ts.Check(err) - repo.Private = addr(b) - default: - ts.Fatalf("unsupported field: %q", field) - } + moduleName := testModuleName(ts) + var repo string + switch args[0] { + case "public": + repo = githubPublicRepo + case "private": + repo = githubPrivateRepo + default: + ts.Fatalf("usage: with-github-repo ") } - _, _, err := client.Repositories.Create(ctx, githubOrg, repo) - ts.Check(err) - - // Unless GITHUB_KEEP=true is set, delete the repo when we finish. - // - // TODO: It might be useful to leave the repo around when the test fails. - // We would need testscript.TestScript to expose T.Failed for this. - ts.Defer(func() { - if githubKeep == "true" { - return - } - _, err := client.Repositories.Delete(ctx, githubOrg, repoName) - ts.Check(err) - }) - - module := fmt.Sprintf("github.com/%s/%s", githubOrg, repoName) + module := path.Join(repo, moduleName) ts.Setenv("MODULE", module) - ts.Setenv("GITHUB_TOKEN", githubToken) // needed for "git push" - ts.Logf("created github repo: https://%s", module) + ts.Logf("using module path %s", module) }, // env-fill rewrites its argument files to replace any environment variable // references with their values, using the same algorithm as cmpenv. @@ -252,6 +212,6 @@ func testModuleName(ts *testscript.TestScript) string { if _, err := cryptorand.Read(randomTrailer[:]); err != nil { panic(err) // should typically not happen } - return fmt.Sprintf("e2e-%s-%s-%x", ts.Name(), + return fmt.Sprintf("%s-%s-%x", ts.Name(), time.Now().UTC().Format("2006.01.02-15.04.05"), randomTrailer) } diff --git a/internal/e2e/testdata/script/gcloud_upload.txtar b/internal/e2e/testdata/script/gcloud_upload.txtar index d9d281105..cacea86fe 100644 --- a/internal/e2e/testdata/script/gcloud_upload.txtar +++ b/internal/e2e/testdata/script/gcloud_upload.txtar @@ -12,7 +12,6 @@ env MODVER=${MODULE}@v0 cd publish exec cue mod init ${MODVER} - exec cue mod publish ${VERSION} cd ../depend diff --git a/internal/e2e/testdata/script/github_app_private.txtar b/internal/e2e/testdata/script/github_app_private.txtar index 997a2b642..00ffd9c42 100644 --- a/internal/e2e/testdata/script/github_app_private.txtar +++ b/internal/e2e/testdata/script/github_app_private.txtar @@ -1,17 +1,15 @@ -# Create a private GitHub repository in an organization -# where the registry account owning $CUE_REGISTRY_TOKEN -# has read-write access to all GitHub repositories. +# Publish a CUE module under a private GitHub repository namespace +# where the $CUE_LOGINS tokens have full read-write access. # Publish a version for this new repository with `cue mod publish`, # and then fetch the module as a dependency via cmd/cue. -create-github-repo private=true +github-repo-module private env VERSION=v0.0.1 env MODVER=${MODULE}@v0 cd publish exec cue mod init ${MODVER} - exec cue mod publish ${VERSION} cd ../depend @@ -23,7 +21,7 @@ exec cue export cmp stdout export.golden # TODO(mvdan): Use another registry token without access to this private repo -# and check that they cannot list the module's versions or download any of them. +# and check that they cannot list, fetch, or publish any versions. -- publish/foo.cue -- package publish diff --git a/internal/e2e/testdata/script/github_app_public.txtar b/internal/e2e/testdata/script/github_app_public.txtar index 82954a93a..772547231 100644 --- a/internal/e2e/testdata/script/github_app_public.txtar +++ b/internal/e2e/testdata/script/github_app_public.txtar @@ -1,17 +1,15 @@ -# Create a public GitHub repository in an organization -# where the registry account owning $CUE_REGISTRY_TOKEN -# has read-write access to all GitHub repositories. +# Publish a CUE module under a public GitHub repository namespace +# where the $CUE_LOGINS tokens have full read-write access. # Publish a version for this new repository with `cue mod publish`, # and then fetch the module as a dependency via cmd/cue. -create-github-repo +github-repo-module public env VERSION=v0.0.1 env MODVER=${MODULE}@v0 cd publish exec cue mod init ${MODVER} - exec cue mod publish ${VERSION} cd ../depend @@ -22,6 +20,9 @@ exec cue mod tidy exec cue export cmp stdout export.golden +# TODO(mvdan): Use another registry token without access to this private repo +# and check that they can list and fetch, but not publish, any versions. + -- publish/foo.cue -- package publish