diff --git a/.github/workflows/coder.yaml b/.github/workflows/coder.yaml index 822545a285bb3..7afe95b2c892e 100644 --- a/.github/workflows/coder.yaml +++ b/.github/workflows/coder.yaml @@ -60,13 +60,31 @@ jobs: echo "${{ toJSON(steps.filter )}}" # Debug step - show-changes: - needs: changes + debug-inputs: + needs: + - changes + - pr-context runs-on: ubuntu-latest steps: - id: log run: | - echo "${{ toJSON(needs.changes) }}" + echo "${{ toJSON(needs) }}" + echo "${{ contains(needs.pr-context.outputs.skips, 'postgres') }} " + + pr-context: + runs-on: ubuntu-latest + outputs: + skips: ${{ steps.pr-context.outputs.skips }} + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v3 + with: + go-version: "~1.18" + - id: pr-context + env: + GITHUB_CONTEXT: ${{ toJSON(github) }} + run: | + go run github.com/coder/coder/.github/workflows/prcontext style-lint-golangci: name: style/lint/golangci @@ -157,6 +175,25 @@ jobs: - uses: actions/setup-go@v3 with: go-version: "~1.18" + + - name: Echo Go Cache Paths + id: go-cache-paths + run: | + echo "::set-output name=go-build::$(go env GOCACHE)" + echo "::set-output name=go-mod::$(go env GOMODCACHE)" + + - name: Go Build Cache + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-build }} + key: ${{ github.job }}-go-build-${{ hashFiles('**/go.sum', '**/**.go') }} + + - name: Go Mod Cache + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ github.job }}-go-mod-${{ hashFiles('**/go.sum') }} + - run: | curl -sSL https://github.com/kyleconroy/sqlc/releases/download/v1.13.0/sqlc_1.13.0_linux_amd64.tar.gz | sudo tar -C /usr/bin -xz sqlc @@ -229,7 +266,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.go-build }} - key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} + key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.**', '**.go') }} - name: Go Mod Cache uses: actions/cache@v3 @@ -251,14 +288,23 @@ jobs: terraform_wrapper: false - name: Test with Mock Database + id: test shell: bash - run: gotestsum --junitfile="gotests.xml" --packages="./..." -- - -covermode=atomic -coverprofile="gotests.coverage" - -coverpkg=./...,github.com/coder/coder/codersdk - -timeout=5m -short -failfast + run: | + # Code coverage is more computationally expensive and also + # prevents test caching, so we disable it on alternate operating + # systems. + if [ "${{ matrix.os }}" == "ubuntu-latest" ]; then + echo ::set-output name=cover::true + export COVERAGE_FLAGS='-covermode=atomic -coverprofile="gotests.coverage" -coverpkg=./...,github.com/coder/coder/codersdk' + else + echo ::set-output name=cover::false + fi + set -x + gotestsum --junitfile="gotests.xml" --packages="./..." -- -parallel=8 -timeout=5m -short -failfast $COVERAGE_FLAGS - name: Upload DataDog Trace - if: always() && github.actor != 'dependabot[bot]' && !github.event.pull_request.head.repo.fork + if: github.actor != 'dependabot[bot]' && !github.event.pull_request.head.repo.fork env: DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} DD_DATABASE: fake @@ -272,7 +318,7 @@ jobs: # that is no guarantee, see: # https://github.com/codecov/codecov-action/issues/788 continue-on-error: true - if: github.actor != 'dependabot[bot]' && !github.event.pull_request.head.repo.fork + if: steps.test.outputs.cover && github.actor != 'dependabot[bot]' && !github.event.pull_request.head.repo.fork with: token: ${{ secrets.CODECOV_TOKEN }} files: ./gotests.coverage @@ -280,8 +326,12 @@ jobs: test-go-postgres: name: "test/go/postgres" - needs: changes - if: needs.changes.outputs.docs-only == 'false' + needs: + - changes + - pr-context + if: > + needs.changes.outputs.docs-only == 'false' && + contains(needs.pr-context.outputs.skips, github.job) == 'false' runs-on: ubuntu-latest # This timeout must be greater than the timeout set by `go test` in # `make test-postgres` to ensure we receive a trace of running @@ -305,7 +355,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.go-build }} - key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} + key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum', '**/**.go') }} - name: Go Mod Cache uses: actions/cache@v3 @@ -517,8 +567,10 @@ jobs: test-e2e: name: "test/e2e/${{ matrix.os }}" - needs: changes - if: needs.changes.outputs.docs-only == 'false' + needs: + - changes + - pr-context + if: needs.changes.outputs.docs-only == 'false' && !contains(needs.pr-context.outputs.skips, 'test/e2e') runs-on: ${{ matrix.os }} timeout-minutes: 20 strategy: @@ -535,9 +587,7 @@ jobs: path: | **/node_modules .eslintcache - key: js-${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - js-${{ runner.os }}- + key: js-${{ runner.os }}-e2e-${{ hashFiles('**/yarn.lock') }} # Go is required for uploading the test results to datadog - uses: actions/setup-go@v3 @@ -573,6 +623,7 @@ jobs: - name: Build run: | + sudo npm install -g prettier make -B site/out/index.html - run: yarn playwright:install diff --git a/.github/workflows/prcontext/README.md b/.github/workflows/prcontext/README.md new file mode 100644 index 0000000000000..f3be624d1978e --- /dev/null +++ b/.github/workflows/prcontext/README.md @@ -0,0 +1,7 @@ +# prcontext + +`prcontext` is a simple Go program that extracts CI directives from PRs for a +more efficient merge cycle. + +Right now it only supports the `[ci-skip [job ...]]` directive. Since skips are +only possible within PRs, the full suite will still run on merge. diff --git a/.github/workflows/prcontext/main.go b/.github/workflows/prcontext/main.go new file mode 100644 index 0000000000000..f9c087c477b44 --- /dev/null +++ b/.github/workflows/prcontext/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/coder/flog" +) + +// githubContext is structured as documented here: +// https://docs.github.com/en/actions/learn-github-actions/contexts#github-context. +type githubContext struct { + EventName string `json:"event_name"` + Event struct { + PullRequest struct { + Body string `json:"body"` + } `json:"pull_request"` + } `json:"event"` +} + +func main() { + var c githubContext + err := json.Unmarshal([]byte(os.Getenv("GITHUB_CONTEXT")), &c) + if err != nil { + flog.Fatal("decode stdin: %+v", err) + } + flog.Info("detected event %q", c.EventName) + if c.EventName != "pull_request" { + flog.Info("aborting since not Pull Request") + return + } + + _, _ = fmt.Printf("::group::{PR Body}\n%s\n::endgroup::\n", c.Event.PullRequest.Body) + + skips := parseBody(c.Event.PullRequest.Body) + _, _ = fmt.Printf("::echo::on\n::set-output name=skips::[%s]\n", strings.Join(skips, " ")) +} diff --git a/.github/workflows/prcontext/parse.go b/.github/workflows/prcontext/parse.go new file mode 100644 index 0000000000000..4d4155772c32f --- /dev/null +++ b/.github/workflows/prcontext/parse.go @@ -0,0 +1,28 @@ +package main + +import ( + "regexp" + "strings" +) + +const ciSkipPrefix = "ci-skip" + +var skipDirective = regexp.MustCompile(`\[` + ciSkipPrefix + ` ([\w-\/ ]+)]`) + +func parseBody(body string) (skips []string) { + matches := skipDirective.FindAllStringSubmatch(body, -1) + // flog.Info("matches: %+v", matches) + + var skipMatches []string + for i := range matches { + for j := range matches[i] { + v := matches[i][j] + // flog.Info("%q", v) + if !strings.Contains(v, ciSkipPrefix) { + skipMatches = append(skipMatches, strings.Split(v, " ")...) + } + } + } + + return skipMatches +} diff --git a/.github/workflows/prcontext/parse_test.go b/.github/workflows/prcontext/parse_test.go new file mode 100644 index 0000000000000..3ef63163a4948 --- /dev/null +++ b/.github/workflows/prcontext/parse_test.go @@ -0,0 +1,38 @@ +package main + +import ( + "reflect" + "testing" +) + +func Test_parseBody_basic(t *testing.T) { + parseBody(` +This is a test PR. + +[ci-skip postgres windows] + `) +} + +func Test_parseBody(t *testing.T) { + type args struct { + body string + } + tests := []struct { + name string + args args + wantSkips []string + }{ + {"no directive", args{"test pr 123\n\n"}, nil}, + {"single dir single skip", args{"test pr [ci-skip dog] 123\n\n"}, []string{"dog"}}, + {"double dir double skip", args{"test pr [ci-skip dog] [ci-skip cat] 123\n\n"}, []string{"dog", "cat"}}, + {"single dir double skip", args{"test pr [ci-skip test/go/postgres cat] 123\n\n"}, []string{"test/go/postgres", "cat"}}, + {"confuse", args{"ci ci [ci-skip] dog [ci-skip test/go/postgres test/e2e/ubuntu-latest] 123\n\n"}, []string{"test/go/postgres", "test/e2e/ubuntu-latest"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotSkips := parseBody(tt.args.body); !reflect.DeepEqual(gotSkips, tt.wantSkips) { + t.Errorf("parseBody() = %v, want %v", gotSkips, tt.wantSkips) + } + }) + } +} diff --git a/go.mod b/go.mod index c33a634b4d002..b5ae58b368414 100644 --- a/go.mod +++ b/go.mod @@ -135,7 +135,10 @@ require ( tailscale.com v1.26.2 ) -require github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect +require ( + github.com/coder/flog v1.0.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect +) require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect diff --git a/go.sum b/go.sum index a686a4fd703ae..4e6a248e14e48 100644 --- a/go.sum +++ b/go.sum @@ -344,6 +344,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/coder/flog v1.0.0 h1:gqr4jYDQWYmsvFD0RV6Vs+SAj1Kbn0HGlV7UghfxP+8= +github.com/coder/flog v1.0.0/go.mod h1:UQlQvrkJBvnRGo69Le8E24Tcl5SJleAAR7gYEHzAmdQ= github.com/coder/glog v1.0.1-0.20220322161911-7365fe7f2cd1 h1:UqBrPWSYvRI2s5RtOul20JukUEpu4ip9u7biBL+ntgk= github.com/coder/glog v1.0.1-0.20220322161911-7365fe7f2cd1/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/coder/retry v1.3.0 h1:5lAAwt/2Cm6lVmnfBY7sOMXcBOwcwJhmV5QGSELIVWY= diff --git a/site/webpack.common.ts b/site/webpack.common.ts index 9fcd7a7ba2c00..ad7a758cca6c4 100644 --- a/site/webpack.common.ts +++ b/site/webpack.common.ts @@ -93,6 +93,10 @@ export const createCommonWebpackConfig = (options?: { skipTypecheck: boolean }): ], }, + cache: { + type: "filesystem", + }, + // resolve extend/modify how modules are resolved. // // REMARK: Do not add aliases here, unless they cannot be defined in a