name: ci on: push: branches: - main pull_request: workflow_dispatch: permissions: actions: none checks: none contents: read deployments: none issues: none packages: none pull-requests: none repository-projects: none security-events: none statuses: none # Cancel in-progress runs for pull requests when developers push # additional changes concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: lint: runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || 'ubuntu-latest' }} steps: - name: Checkout uses: actions/checkout@v3 # Install Go! - uses: actions/setup-go@v3 with: go-version: "~1.20" # Check for any typos! - name: Check for typos uses: crate-ci/typos@v1.13.9 with: config: .github/workflows/typos.toml - name: Fix the typos if: ${{ failure() }} run: | echo "::notice:: you can automatically fix typos from your CLI: cargo install typos-cli typos -c .github/workflows/typos.toml -w" # Check for Go linting errors! - name: Lint Go uses: golangci/golangci-lint-action@v3.3.1 with: version: v1.51.0 - name: Lint shell scripts uses: ludeeus/action-shellcheck@2.0.0 env: SHELLCHECK_OPTS: --external-sources with: ignore: node_modules # Lint our dashboard! - name: Cache node_modules id: cache-node uses: actions/cache@v3 with: path: | **/node_modules .eslintcache key: js-${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }} restore-keys: | js-${{ runner.os }}- - name: Install node_modules run: ./scripts/yarn_install.sh - name: Lint TypeScript run: yarn lint working-directory: site # Make sure the Helm chart is linted! - name: Install helm uses: azure/setup-helm@v3 with: version: v3.9.2 - name: Lint Helm chart run: | cd helm make lint # Ensure AGPL and Enterprise are separated! - name: Check for AGPL code importing Enterprise... run: ./scripts/check_enterprise_imports.sh changes: runs-on: ubuntu-latest outputs: docs-only: ${{ steps.filter.outputs.docs_count == steps.filter.outputs.all_count }} sh: ${{ steps.filter.outputs.sh }} ts: ${{ steps.filter.outputs.ts }} k8s: ${{ steps.filter.outputs.k8s }} steps: - uses: actions/checkout@v3 # For pull requests it's not necessary to checkout the code - uses: dorny/paths-filter@v2 id: filter with: filters: | all: - '**' docs: - 'docs/**' # For testing: # - '.github/**' sh: - "**.sh" ts: - 'site/**' k8s: - 'helm/**' - Dockerfile - scripts/helm.sh - id: debug run: | echo "${{ toJSON(steps.filter )}}" gen: timeout-minutes: 8 runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || 'ubuntu-latest' }} needs: changes if: needs.changes.outputs.docs-only == 'false' steps: - uses: actions/checkout@v3 - name: Cache Node id: cache-node uses: actions/cache@v3 with: path: | **/node_modules .eslintcache key: js-${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }} restore-keys: | js-${{ runner.os }}- - name: Install node_modules run: ./scripts/yarn_install.sh - uses: actions/setup-go@v3 with: go-version: "~1.20" - name: Echo Go Cache Paths id: go-cache-paths run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_OUTPUT echo "GOMODCACHE=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT - name: Go Build Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOCACHE }} key: ${{ github.job }}-go-build-${{ hashFiles('**/go.sum', '**/**.go') }} - name: Go Mod Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOMODCACHE }} key: ${{ github.job }}-go-mod-${{ hashFiles('**/go.sum') }} - name: Install sqlc run: | curl -sSL https://github.com/kyleconroy/sqlc/releases/download/v1.16.0/sqlc_1.16.0_linux_amd64.tar.gz | sudo tar -C /usr/bin -xz sqlc - name: Install protoc-gen-go run: go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 - name: Install protoc-gen-go-drpc run: go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.26 - name: Install goimports run: go install golang.org/x/tools/cmd/goimports@latest - name: Install yq run: go run github.com/mikefarah/yq/v4@v4.30.6 - name: Install Protoc run: | # protoc must be in lockstep with our dogfood Dockerfile # or the version in the comments will differ. set -x cd dogfood DOCKER_BUILDKIT=1 docker build . --target proto -t protoc protoc_path=/usr/local/bin/protoc docker run --rm --entrypoint cat protoc /tmp/bin/protoc > $protoc_path chmod +x $protoc_path protoc --version - name: make gen run: "make --output-sync -j -B gen" - name: Check for unstaged files run: ./scripts/check_unstaged.sh fmt: runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 submodules: true - name: Cache Node id: cache-node uses: actions/cache@v3 with: path: | **/node_modules .eslintcache key: js-${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }} restore-keys: | js-${{ runner.os }}- - name: Install node_modules run: ./scripts/yarn_install.sh - name: Install shfmt run: go install mvdan.cc/sh/v3/cmd/shfmt@v3.5.0 - name: make fmt run: | export PATH=${PATH}:$(go env GOPATH)/bin make --output-sync -j -B fmt - name: Check for unstaged files run: ./scripts/check_unstaged.sh test-go: runs-on: ${{ matrix.os == 'ubuntu-latest' && github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || matrix.os == 'windows-2022' && github.repository_owner == 'coder' && 'windows-latest-8-cores'|| matrix.os }} timeout-minutes: 20 strategy: matrix: os: - ubuntu-latest - macos-latest - windows-2022 steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: go-version: "~1.20" # Sadly the new "set output" syntax (of writing env vars to # $GITHUB_OUTPUT) does not work on both powershell and bash so we use the # deprecated syntax here. - name: Echo Go Cache Paths id: go-cache-paths run: | echo "::set-output name=GOCACHE::$(go env GOCACHE)" echo "::set-output name=GOMODCACHE::$(go env GOMODCACHE)" - name: Go Build Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOCACHE }} key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.**', '**.go') }} - name: Go Mod Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOMODCACHE }} key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }} - name: Install gotestsum uses: jaxxstorm/action-install-gh-release@v1.9.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: repo: gotestyourself/gotestsum tag: v1.9.0 - uses: hashicorp/setup-terraform@v2 with: terraform_version: 1.1.9 terraform_wrapper: false - name: Test with Mock Database id: test shell: bash 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 "cover=true" >> $GITHUB_OUTPUT export COVERAGE_FLAGS='-covermode=atomic -coverprofile="gotests.coverage" -coverpkg=./...' else echo "cover=false" >> $GITHUB_OUTPUT fi gotestsum --junitfile="gotests.xml" --packages="./..." -- -parallel=8 -timeout=5m -short -failfast $COVERAGE_FLAGS - uses: actions/upload-artifact@v3 if: success() || failure() with: name: gotests-${{ matrix.os }}.xml path: ./gotests.xml retention-days: 30 - uses: codecov/codecov-action@v3 # This action has a tendency to error out unexpectedly, it has # the `fail_ci_if_error` option that defaults to `false`, but # that is no guarantee, see: # https://github.com/codecov/codecov-action/issues/788 continue-on-error: true if: steps.test.outputs.cover && github.actor != 'dependabot[bot]' && !github.event.pull_request.head.repo.fork with: token: ${{ secrets.CODECOV_TOKEN }} files: ./gotests.coverage flags: unittest-go-${{ matrix.os }} test-go-psql: runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || '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 # goroutines. Setting this to the timeout +5m should work quite well # even if some of the preceding steps are slow. timeout-minutes: 25 steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: go-version: "~1.20" - name: Echo Go Cache Paths id: go-cache-paths run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_OUTPUT echo "GOMODCACHE=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT - name: Go Build Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOCACHE }} key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum', '**/**.go') }} - name: Go Mod Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOMODCACHE }} key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }} - name: Install gotestsum uses: jaxxstorm/action-install-gh-release@v1.9.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: repo: gotestyourself/gotestsum tag: v1.9.0 - uses: hashicorp/setup-terraform@v2 with: terraform_version: 1.1.9 terraform_wrapper: false - name: Test with PostgreSQL Database run: | make test-postgres - uses: actions/upload-artifact@v3 if: success() || failure() with: name: gotests-postgres.xml path: ./gotests.xml retention-days: 30 - uses: codecov/codecov-action@v3 # This action has a tendency to error out unexpectedly, it has # the `fail_ci_if_error` option that defaults to `false`, but # 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 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./gotests.coverage flags: unittest-go-postgres-linux deploy: name: "deploy" runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || 'ubuntu-latest' }} timeout-minutes: 30 needs: changes if: | github.ref == 'refs/heads/main' && !github.event.pull_request.head.repo.fork && needs.changes.outputs.docs-only == 'false' permissions: contents: read id-token: write steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Authenticate to Google Cloud uses: google-github-actions/auth@v1 with: workload_identity_provider: projects/573722524737/locations/global/workloadIdentityPools/github/providers/github service_account: coder-ci@coder-dogfood.iam.gserviceaccount.com - name: Set up Google Cloud SDK uses: google-github-actions/setup-gcloud@v1 - uses: actions/setup-go@v3 with: go-version: "~1.20" - name: Echo Go Cache Paths id: go-cache-paths run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_OUTPUT echo "GOMODCACHE=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT - name: Go Build Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOCACHE }} key: ${{ runner.os }}-release-go-build-${{ hashFiles('**/go.sum') }} - name: Go Mod Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOMODCACHE }} key: ${{ runner.os }}-release-go-mod-${{ hashFiles('**/go.sum') }} - name: Cache Node id: cache-node uses: actions/cache@v3 with: path: | **/node_modules .eslintcache key: js-${{ runner.os }}-release-node-${{ hashFiles('**/yarn.lock') }} restore-keys: | js-${{ runner.os }}- - name: Install goimports run: go install golang.org/x/tools/cmd/goimports@latest - name: Install nfpm run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.16.0 - name: Install zstd run: sudo apt-get install -y zstd - name: Build Release run: | set -euo pipefail go mod download version="$(./scripts/version.sh)" make gen/mark-fresh make -j \ build/coder_"$version"_windows_amd64.zip \ build/coder_"$version"_linux_amd64.{tar.gz,deb} - name: Install Release run: | gcloud config set project coder-dogfood gcloud config set compute/zone us-central1-a gcloud compute scp ./build/coder_*_linux_amd64.deb coder:/tmp/coder.deb gcloud compute ssh coder -- sudo dpkg -i --force-confdef /tmp/coder.deb gcloud compute ssh coder -- sudo systemctl daemon-reload - name: Start run: gcloud compute ssh coder -- sudo service coder restart - uses: actions/upload-artifact@v3 with: name: coder path: | ./build/*.zip ./build/*.tar.gz ./build/*.deb retention-days: 7 test-js: runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || 'ubuntu-latest' }} timeout-minutes: 20 steps: - uses: actions/checkout@v3 - name: Cache Node id: cache-node uses: actions/cache@v3 with: path: | **/node_modules .eslintcache key: js-${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }} restore-keys: | js-${{ runner.os }}- - uses: actions/setup-node@v3 with: node-version: "14" - name: Install node_modules run: ./scripts/yarn_install.sh - run: yarn test:ci working-directory: site - uses: codecov/codecov-action@v3 # This action has a tendency to error out unexpectedly, it has # the `fail_ci_if_error` option that defaults to `false`, but # 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 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./site/coverage/lcov.info flags: unittest-js test-e2e: needs: - changes if: needs.changes.outputs.docs-only == 'false' runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-8-cores' || 'ubuntu-latest' }} timeout-minutes: 20 steps: - uses: actions/checkout@v3 - name: Cache Node id: cache-node uses: actions/cache@v3 with: path: | **/node_modules .eslintcache key: js-${{ runner.os }}-e2e-${{ hashFiles('**/yarn.lock') }} - uses: actions/setup-go@v3 with: go-version: "~1.20" - uses: hashicorp/setup-terraform@v2 with: terraform_version: 1.1.9 terraform_wrapper: false - uses: actions/setup-node@v3 with: node-version: "14" - name: Echo Go Cache Paths id: go-cache-paths run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_OUTPUT echo "GOMODCACHE=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT - name: Go Build Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOCACHE }} key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} - name: Go Mod Cache uses: actions/cache@v3 with: path: ${{ steps.go-cache-paths.outputs.GOMODCACHE }} key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }} - name: Build run: | sudo npm install -g prettier make -B site/out/index.html - run: yarn playwright:install working-directory: site - run: yarn playwright:install-deps working-directory: site - run: yarn playwright:test env: DEBUG: pw:api working-directory: site - name: Upload Playwright Failed Tests if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' && !github.event.pull_request.head.repo.fork uses: actions/upload-artifact@v3 with: name: failed-test-videos path: ./site/test-results/**/*.webm retention-days: 7 chromatic: # REMARK: this is only used to build storybook and deploy it to Chromatic. runs-on: ubuntu-latest needs: - changes if: needs.changes.outputs.ts == 'true' steps: - uses: actions/checkout@v3 with: # Required by Chromatic for build-over-build history, otherwise we # only get 1 commit on shallow checkout. fetch-depth: 0 - name: Install dependencies run: cd site && yarn # This step is not meant for mainline because any detected changes to # storybook snapshots will require manual approval/review in order for # the check to pass. This is desired in PRs, but not in mainline. - name: Publish to Chromatic (non-mainline) if: github.ref != 'refs/heads/main' && github.repository_owner == 'coder' uses: chromaui/action@v1 with: buildScriptName: "storybook:build" exitOnceUploaded: true # Chromatic states its fine to make this token public. See: # https://www.chromatic.com/docs/github-actions#forked-repositories projectToken: 695c25b6cb65 workingDir: "./site" # This is a separate step for mainline only that auto accepts and changes # instead of holding CI up. Since we squash/merge, this is defensive to # avoid the same changeset from requiring review once squashed into # main. Chromatic is supposed to be able to detect that we use squash # commits, but it's good to be defensive in case, otherwise CI remains # infinitely "in progress" in mainline unless we re-review each build. - name: Publish to Chromatic (mainline) if: github.ref == 'refs/heads/main' && github.repository_owner == 'coder' uses: chromaui/action@v1 with: autoAcceptChanges: true buildScriptName: "storybook:build" projectToken: 695c25b6cb65 workingDir: "./site"