mirror of https://github.com/coder/coder.git
539 lines
17 KiB
YAML
539 lines
17 KiB
YAML
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' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v3
|
|
|
|
- uses: ./.github/actions/setup-go
|
|
|
|
# Check for any typos!
|
|
- name: Check for typos
|
|
uses: crate-ci/typos@v1.14.11
|
|
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.52.2
|
|
|
|
- name: Lint shell scripts
|
|
uses: ludeeus/action-shellcheck@2.0.0
|
|
env:
|
|
SHELLCHECK_OPTS: --external-sources
|
|
with:
|
|
ignore: node_modules
|
|
|
|
- uses: ./.github/actions/setup-node
|
|
- 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/**'
|
|
- scripts/Dockerfile
|
|
- scripts/Dockerfile.base
|
|
- scripts/helm.sh
|
|
- id: debug
|
|
run: |
|
|
echo "${{ toJSON(steps.filter )}}"
|
|
|
|
gen:
|
|
timeout-minutes: 8
|
|
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
|
needs: changes
|
|
if: needs.changes.outputs.docs-only == 'false'
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- uses: ./.github/actions/setup-node
|
|
- uses: ./.github/actions/setup-go
|
|
|
|
- name: Install sqlc
|
|
run: |
|
|
curl -sSL https://github.com/kyleconroy/sqlc/releases/download/v1.17.2/sqlc_1.17.2_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.30
|
|
- name: Install protoc-gen-go-drpc
|
|
run: go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.33
|
|
- 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 mockgen
|
|
run: go install github.com/golang/mock/mockgen@v1.6.0
|
|
|
|
- name: Install Protoc
|
|
run: |
|
|
# protoc must be in lockstep with our dogfood Dockerfile or the
|
|
# version in the comments will differ. This is also defined in
|
|
# security.yaml
|
|
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
|
|
|
|
- uses: ./.github/actions/setup-node
|
|
- uses: ./.github/actions/setup-go
|
|
|
|
- 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' && 'buildjet-4vcpu-ubuntu-2204' || matrix.os == 'windows-2019' && github.repository_owner == 'coder' && 'windows-latest-8-cores'|| matrix.os }}
|
|
timeout-minutes: 20
|
|
strategy:
|
|
matrix:
|
|
os:
|
|
- ubuntu-latest
|
|
- macos-latest
|
|
- windows-2019
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- uses: buildjet/setup-go@v4
|
|
with:
|
|
cache: false
|
|
go-version: ${{ env.CODER_GO_VERSION }}
|
|
|
|
- uses: ./.github/actions/setup-go
|
|
|
|
- name: Install gotestsum
|
|
uses: jaxxstorm/action-install-gh-release@v1.10.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
|
|
|
|
export TS_DEBUG_DISCO=true
|
|
gotestsum --junitfile="gotests.xml" --jsonfile="gotests.json" --packages="./..." -- -parallel=8 -timeout=7m -short -failfast $COVERAGE_FLAGS
|
|
|
|
- name: Print test stats
|
|
if: success() || failure()
|
|
run: |
|
|
# Artifacts are not available after rerunning a job,
|
|
# so we need to print the test stats to the log.
|
|
go run ./scripts/ci-report/main.go gotests.json | tee gotests_stats.json
|
|
|
|
- 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-pg:
|
|
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || '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: ./.github/actions/setup-go
|
|
|
|
- name: Install gotestsum
|
|
uses: jaxxstorm/action-install-gh-release@v1.10.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: |
|
|
export TS_DEBUG_DISCO=true
|
|
make test-postgres
|
|
|
|
- name: Print test stats
|
|
if: success() || failure()
|
|
run: |
|
|
# Artifacts are not available after rerunning a job,
|
|
# so we need to print the test stats to the log.
|
|
go run ./scripts/ci-report/main.go gotests.json | tee gotests_stats.json
|
|
|
|
- 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
|
|
|
|
test-go-race:
|
|
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
|
timeout-minutes: 25
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- uses: ./.github/actions/setup-go
|
|
|
|
- uses: hashicorp/setup-terraform@v2
|
|
with:
|
|
terraform_version: 1.1.9
|
|
terraform_wrapper: false
|
|
|
|
- name: Run Tests
|
|
run: |
|
|
go test -race ./...
|
|
|
|
deploy:
|
|
name: "deploy"
|
|
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || '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: buildjet/setup-go@v4
|
|
with:
|
|
cache: false
|
|
go-version: ${{ env.CODER_GO_VERSION }}
|
|
|
|
- uses: ./.github/actions/setup-go
|
|
- uses: ./.github/actions/setup-node
|
|
|
|
- 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: |
|
|
set -euo pipefail
|
|
|
|
regions=(
|
|
# gcp-region-id instance-name systemd-service-name
|
|
"us-central1-a coder coder"
|
|
"australia-southeast1-b coder-sydney coder-workspace-proxy"
|
|
"europe-west3-c coder-europe coder-workspace-proxy"
|
|
"southamerica-east1-b coder-brazil coder-workspace-proxy"
|
|
)
|
|
|
|
deb_pkg="./build/coder_$(./scripts/version.sh)_linux_amd64.deb"
|
|
if [ ! -f "$deb_pkg" ]; then
|
|
echo "deb package not found: $deb_pkg"
|
|
ls -l ./build
|
|
exit 1
|
|
fi
|
|
|
|
gcloud config set project coder-dogfood
|
|
for region in "${regions[@]}"; do
|
|
echo "::group::$region"
|
|
set -- $region
|
|
|
|
set -x
|
|
gcloud config set compute/zone "$1"
|
|
gcloud compute scp "$deb_pkg" "${2}:/tmp/coder.deb"
|
|
gcloud compute ssh "$2" -- /bin/sh -c "set -eux; sudo dpkg -i --force-confdef /tmp/coder.deb; sudo systemctl daemon-reload; sudo service '$3' restart"
|
|
set +x
|
|
|
|
echo "::endgroup::"
|
|
done
|
|
|
|
- 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' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
|
timeout-minutes: 20
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- uses: ./.github/actions/setup-node
|
|
|
|
- run: yarn test:ci --max-workers ${{ steps.cpu-cores.outputs.count }}
|
|
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' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
|
timeout-minutes: 20
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- uses: ./.github/actions/setup-node
|
|
- uses: ./.github/actions/setup-go
|
|
|
|
- uses: hashicorp/setup-terraform@v2
|
|
with:
|
|
terraform_version: 1.1.9
|
|
terraform_wrapper: false
|
|
|
|
- uses: buildjet/setup-node@v3
|
|
with:
|
|
node-version: "16.16.0"
|
|
|
|
- name: Build
|
|
run: |
|
|
sudo npm install -g prettier
|
|
make -B site/out/index.html
|
|
|
|
- run: yarn playwright:install
|
|
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
|
|
|
|
- uses: ./.github/actions/setup-node
|
|
|
|
# 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
|
|
env:
|
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
STORYBOOK: true
|
|
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
|
|
env:
|
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
STORYBOOK: true
|
|
with:
|
|
autoAcceptChanges: true
|
|
buildScriptName: "storybook:build"
|
|
projectToken: 695c25b6cb65
|
|
workingDir: "./site"
|