cuelang.org/go@v0.13.0/internal/ci/github/trybot.cue (about) 1 // Copyright 2022 The CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package github 16 17 import ( 18 "list" 19 "cue.dev/x/githubactions" 20 ) 21 22 // The trybot workflow. 23 workflows: trybot: _repo.bashWorkflow & { 24 name: _repo.trybot.name 25 26 on: { 27 push: { 28 branches: list.Concat([[_repo.testDefaultBranch], _repo.protectedBranchPatterns]) // do not run PR branches 29 "tags-ignore": [_repo.releaseTagPattern] 30 } 31 // Note that pull_request_target gives PR CI jobs full access to our secrets, 32 // which is necessary to fetch dependencies from the registry via NOTCUECKOO_CUE_TOKEN. 33 // Giving access to secrets is OK given that we must approve PR jobs to run on CI, 34 // which mirrors the approval workflow for CI on Gerrit. 35 pull_request_target: {} 36 } 37 38 jobs: { 39 test: { 40 strategy: _testStrategy 41 "runs-on": "${{ matrix.runner }}" 42 43 let _setupGoActionsCaches = _repo.setupGoActionsCaches & { 44 #goVersion: goVersionVal 45 #os: runnerOSVal 46 _ 47 } 48 49 let installGo = _repo.installGo & { 50 #setupGo: with: "go-version": goVersionVal 51 _ 52 } 53 54 // Only run the trybot workflow if we have the trybot trailer, or 55 // if we have no special trailers. Note this condition applies 56 // after and in addition to the "on" condition above. 57 if: "\(_repo.containsTrybotTrailer) || ! \(_repo.containsDispatchTrailer)" 58 59 steps: [ 60 for v in _repo.checkoutCode {v}, 61 62 for v in installGo {v}, 63 64 // cachePre must come after installing Node and Go, because the cache locations 65 // are established by running each tool. 66 for v in _setupGoActionsCaches {v}, 67 68 _repo.loginCentralRegistry, 69 70 _repo.earlyChecks & { 71 // These checks don't vary based on the Go version or OS, 72 // so we only need to run them on one of the matrix jobs. 73 if: _isLatestLinux 74 }, 75 _goTest & { 76 if: "\(_repo.isProtectedBranch) || !\(_isLatestLinux)" 77 }, 78 _goTestRace, 79 _goTest32bit, 80 _goTestWasm, 81 for v in _e2eTestSteps {v}, 82 for v in _goChecks {v}, 83 _checkTags, 84 // Run code generation towards the very end, to ensure it succeeds and makes no changes. 85 // Note that doing this before any Go tests or checks may lead to test cache misses, 86 // as Go uses modtimes to approximate whether files have been modified. 87 // Moveover, Go test failures on CI due to changed generated code are very confusing 88 // as the user might not notice that checkGitClean is also failing towards the end. 89 _goGenerate, 90 _repo.checkGitClean, 91 ] 92 } 93 } 94 95 let runnerOS = "runner.os" 96 let runnerOSVal = "${{ \(runnerOS) }}" 97 let matrixRunner = "matrix.runner" 98 let goVersion = "matrix.go-version" 99 let goVersionVal = "${{ \(goVersion) }}" 100 101 _testStrategy: { 102 "fail-fast": false 103 matrix: { 104 "go-version": _repo.matrixGo 105 runner: [_repo.linuxMachine, _repo.macosMachine, _repo.windowsMachine] 106 } 107 } 108 109 // _isLatestLinux returns a GitHub expression that evaluates to true if the job 110 // is running on Linux with the latest version of Go. This expression is often 111 // used to run certain steps just once per CI workflow, to avoid duplicated 112 // work. 113 _isLatestLinux: "(\(goVersion) == '\(_repo.latestGo)' && \(matrixRunner) == '\(_repo.linuxMachine)')" 114 115 _goGenerate: githubactions.#Step & { 116 name: "Generate" 117 run: "go generate ./..." 118 // The Go version corresponds to the precise version specified in 119 // the matrix. Skip windows for now until we work out why re-gen is flaky 120 if: _isLatestLinux 121 } 122 123 _goTest: githubactions.#Step & { 124 name: "Test" 125 run: "go test ./..." 126 } 127 128 _e2eTestSteps: [... githubactions.#Step & { 129 // The end-to-end tests require a github token secret and are a bit slow, 130 // so we only run them on pushes to protected branches and on one 131 // environment in the source repo. 132 if: "github.repository == '\(_repo.githubRepositoryPath)' && (\(_repo.isProtectedBranch) || \(_repo.isTestDefaultBranch)) && \(_isLatestLinux)" 133 }] & [ 134 // Two setup steps per the upstream docs: 135 // https://github.com/google-github-actions/setup-gcloud#service-account-key-json 136 { 137 name: "gcloud auth for end-to-end tests" 138 id: "auth" 139 uses: "google-github-actions/auth@v2" 140 // E2E_GCLOUD_KEY is a key for the service account cue-e2e-ci, 141 // which has the Artifact Registry Repository Administrator role. 142 with: credentials_json: "${{ secrets.E2E_GCLOUD_KEY }}" 143 }, 144 { 145 name: "gcloud setup for end-to-end tests" 146 uses: "google-github-actions/setup-gcloud@v2" 147 }, 148 { 149 name: "End-to-end test" 150 env: { 151 // E2E_PORCUEPINE_CUE_TOKEN is a token generated on registry.cue.works 152 // as the GitHub porcuepine user, with description "e2e cue repo". 153 CUE_TEST_TOKEN: "${{ secrets.E2E_PORCUEPINE_CUE_TOKEN }}" 154 } 155 // Our regular tests run with both `go test ./...` and `go test -race ./...`. 156 // The end-to-end tests should only be run once, given the slowness and API rate limits. 157 // We want to catch any data races they spot as soon as possible, and they aren't CPU-bound, 158 // so running them only with -race seems reasonable. 159 run: """ 160 cd internal/_e2e 161 go test -race 162 """ 163 }, 164 ] 165 166 _goChecks: [...githubactions.#Step & { 167 // These checks can vary between platforms, as different code can be built 168 // based on GOOS and GOARCH build tags. 169 // However, CUE does not have any such build tags yet, and we don't use 170 // dependencies that vary wildly between platforms. 171 // For now, to save CI resources, just run the checks on one matrix job. 172 if: _isLatestLinux 173 }] & [ 174 { 175 name: "Go checks" 176 // Also ensure that the end-to-end tests in ./internal/_e2e, which are only run 177 // on pushes to protected branches, still build correctly before merging. 178 // 179 // TODO: consider adding more checks as per https://github.com/golang/go/issues/42119. 180 run: """ 181 go vet ./... 182 go mod tidy 183 (cd internal/_e2e && go test -run=-) 184 """ 185 }, { 186 name: "staticcheck" 187 // TODO(mvdan): once we can do 'go tool staticcheck' with Go 1.24+, 188 // then using this action is probably no longer worthwhile. 189 // Note that we should then persist staticcheck's cache too. 190 uses: "dominikh/staticcheck-action@v1" 191 with: { 192 version: "2025.1" // Pin a version for determinism. 193 "install-go": false // We install Go ourselves. 194 } 195 }, 196 ] 197 198 _checkTags: githubactions.#Step & { 199 // Ensure that GitHub and Gerrit agree on the full list of available tags. 200 // This way, if there is any discrepancy, we will get a useful go-cmp diff. 201 // 202 // We use `git ls-remote` to list all tags from each remote git repository 203 // because it does not depend on custom REST API endpoints and is very fast. 204 // Note that it sorts tag names as strings, which is not the best, but works OK. 205 if: _isLatestLinux 206 name: "Check all git tags are available" 207 run: """ 208 cd $(mktemp -d) 209 210 git ls-remote --tags https://github.com/cue-lang/cue >github.txt 211 echo "GitHub tags:" 212 sed 's/^/ /' github.txt 213 214 git ls-remote --tags https://review.gerrithub.io/cue-lang/cue >gerrit.txt 215 216 if ! diff -u github.txt gerrit.txt; then 217 echo "GitHub and Gerrit do not agree on the list of tags!" 218 echo "Did you forget about refs/attic branches? https://github.com/cue-lang/cue/wiki/Notes-for-project-maintainers" 219 exit 1 220 fi 221 """ 222 } 223 224 _goTestRace: githubactions.#Step & { 225 // Windows and Mac on CI are slower than Linux, and most data races are not specific 226 // to any OS or Go version in particular, so only run all tests with -race on Linux 227 // to not slow down CI unnecessarily. 228 if: _isLatestLinux 229 name: "Test with -race" 230 env: GORACE: "atexit_sleep_ms=10" // Otherwise every Go package being tested sleeps for 1s; see https://go.dev/issues/20364. 231 run: "go test -race ./..." 232 } 233 234 _goTest32bit: githubactions.#Step & { 235 // Ensure that the entire build and all tests succeed on a 32-bit platform as well. 236 // This should catch if any of the code or test cases rely on bit sizes, 237 // such as int being 64 bits, which could cause portability bugs for 32-bit platforms. 238 // While GOARCH=386 isn't particularly popular anymore, it can run on an amd64 machine, 239 // and the Linux runners on GitHub Actions use amd64. 240 // 241 // Running just the short tests is enough for now. 242 if: _isLatestLinux 243 name: "Test on 32 bits" 244 env: GOARCH: "386" 245 run: "go test -short ./..." 246 } 247 248 _goTestWasm: githubactions.#Step & { 249 name: "Test with -tags=cuewasm" 250 // The wasm interpreter is only bundled into cmd/cue with the cuewasm build tag. 251 // Test the related packages with the build tag enabled as well. 252 run: "go test -tags cuewasm ./cmd/cue/cmd ./cue/interpreter/wasm" 253 } 254 }