name: Test on: push: branches: - main pull_request: branches: - main release: types: - published jobs: test-go: name: Test Go code runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set git slug envs uses: rlespinasse/github-slug-action@4.2.4 - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18.1 - name: Cache Go modules id: cache-go-modules uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-${{ env.GITHUB_REF_SLUG }}-go-modules-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-main-go-modules- - name: Fetch all Go modules if: steps.cache-go-modules.outputs.cache-hit != 'true' run: make download-deps-go - name: Mock web assets run: make mock-assets - name: Test Go code uses: nick-invision/retry@v2.7.0 with: timeout_minutes: 10 max_attempts: 5 command: make test-go - name: Report code coverage uses: codecov/codecov-action@v3.1.0 with: flags: backend files: ./coverage.txt lint-go: name: Lint Go code runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set git slug envs uses: rlespinasse/github-slug-action@4.2.4 - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18.1 - name: Cache Go modules id: cache-go-modules uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-${{ env.GITHUB_REF_SLUG }}-go-modules-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-main-go-modules- - name: Fetch all Go modules if: steps.cache-go-modules.outputs.cache-hit != 'true' run: make download-deps-go - name: Mock web assets run: make mock-assets - name: Lint Go code run: make make lint-go test-js: name: Test JS code runs-on: ubuntu-20.04 strategy: matrix: env: - "" - "env TZ=Pacific/Easter" steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Test Node JS code run: ${{ matrix.env }} make -C ui test-js env: NODE_ENV: test - name: Report code coverage uses: codecov/codecov-action@v3.1.0 with: flags: ui directory: ./ui/coverage lint-js: name: Lint JS code runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Lint Node JS code run: make -C ui lint-js format-go: name: Check Go code formatting runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18.1 - name: Format Go code run: make format-go - name: Check for local changes run: git diff --exit-code format-js: name: Check JS code formatting runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Lint Node JS code run: make -C ui format - name: Check for local changes run: git diff --exit-code deps-js: name: Check JS dependencies runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: depcheck uses: prymitive/depcheck-action@v1.4.3 with: workdir: "./ui" config: "./ui/.depcheckrc.yaml" package-lock: name: Check package-lock.json runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Run npm install run: cd ui && npm i - name: Check for local changes run: git diff --exit-code lint-versions: name: Lint Versions runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Lint Bootstrap Version run: make lint-bootstrap-version typescript: name: Check for non-typescript components runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Check for non-typescript UI components run: make -C ui lint-typescript git-commit: name: Lint git commit runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 with: fetch-depth: 0 - name: Lint git commit uses: wagoid/commitlint-github-action@v4.1.11 with: configFile: .commitlintrc.cjs docs: name: Lint documentation runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Run markdown-lint uses: avto-dev/markdown-lint@v1.5.0 with: config: .markdownlint.yml args: "*.md docs" stage-test-and-lint: name: "=== Test and lint stage ===" needs: - test-go - test-js - lint-go - lint-js - format-go - format-js - deps-js - package-lock - lint-versions - typescript - git-commit - docs runs-on: ubuntu-20.04 steps: - name: All linters passed run: "true" benchmark-go: name: Benchmark Go code compare if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name needs: stage-test-and-lint runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Set git slug envs uses: rlespinasse/github-slug-action@4.2.4 - name: Get modified files uses: dorny/paths-filter@v2.10.2 id: filter with: list-files: "shell" filters: | backend: - 'cmd/**/*' - 'internal/**/*' - 'go.mod' - 'go.sum' - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18.1 - name: Cache Go uses: actions/cache@v3 with: path: | ~/.cache/go-build ~/go/pkg/mod key: ${{ runner.os }}-go-benchmark-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go-benchmark- - name: Fetch all Go modules if: steps.cache-go-modules.outputs.cache-hit != 'true' run: make download-deps-go - name: Mock web assets if: steps.filter.outputs.backend == 'true' run: make mock-assets - name: Run benchmark if: steps.filter.outputs.backend == 'true' run: ./scripts/ci-diff-benchmark-go.sh env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PULL_REQUEST_NUMBER: ${{ github.event.number }} webpack-bundle-size: name: Webpack bundle size compare if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name needs: stage-test-and-lint runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Get modified files uses: dorny/paths-filter@v2.10.2 id: filter with: list-files: "shell" filters: | ui: - 'ui/**/*' - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Diff bundle size if: steps.filter.outputs.ui == 'true' run: ./scripts/ci-diff-webpack.sh env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PULL_REQUEST_NUMBER: ${{ github.event.number }} percy: name: Percy UI snapshots if: github.event_name != 'release' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name needs: stage-test-and-lint runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 - name: Get modified files uses: dorny/paths-filter@v2.10.2 id: filter with: list-files: "shell" filters: | percy: - 'ui/src/**/*' - 'ui/.storybook/*' - 'ui/package.json' - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Run Percy if: steps.filter.outputs.percy == 'true' run: make -C ui test-percy env: NODE_ENV: test PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} cross-compile: name: Cross compile binaries needs: stage-test-and-lint runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18.1 - name: Cache Go uses: actions/cache@v3 with: path: | ~/.cache/go-build ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/package-lock.json' - name: Cross compile binaries run: make crosscompile -j 2 - name: Compress binaries shell: bash run: | mkdir -p artifacts export SOURCE_DATE_EPOCH=$(git show -s --format=%ci ${GITHUB_SHA}) for i in karma-*; do tar --mtime="${SOURCE_DATE_EPOCH}" --owner=0 --group=0 --numeric-owner -c $i | gzip -n - > artifacts/$i.tar.gz; done (cd artifacts && shasum -a 512 karma-*.tar.gz | tee sha512sum.txt) - name: Get release if: github.event_name == 'release' id: get_release uses: bruceadams/get-release@v1.2.3 env: GITHUB_TOKEN: ${{ github.token }} - name: Upload binaries to GitHub release if: github.event_name == 'release' uses: AButler/upload-release-assets@v2.0 with: files: "artifacts/*" repo-token: ${{ secrets.GITHUB_TOKEN }} docker: name: Build docker image needs: stage-test-and-lint runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set git slug envs uses: rlespinasse/github-slug-action@4.2.4 - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to DockerHub if: github.event_name != 'pull_request' uses: docker/login-action@v2 with: username: lmierzwa password: ${{ secrets.DOCKER_HUB_PASSWORD }} - name: Login to GitHub Container Registry if: github.event_name != 'pull_request' uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GH_PKG_TOKEN }} - name: "Setup docker tags (latest + vX.Y)" if: github.event_name == 'release' run: | echo 'DOCKER_TAGS<> $GITHUB_ENV echo 'lmierzwa/karma:${{ env.GITHUB_REF_SLUG }}' >> $GITHUB_ENV echo 'lmierzwa/karma:latest' >> $GITHUB_ENV echo 'ghcr.io/prymitive/karma:${{ env.GITHUB_REF_SLUG }}' >> $GITHUB_ENV echo 'ghcr.io/prymitive/karma:latest' >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV - name: "Setup docker tags (latest)" if: github.event_name != 'release' run: | echo 'DOCKER_TAGS<> $GITHUB_ENV echo 'lmierzwa/karma:latest' >> $GITHUB_ENV echo 'ghcr.io/prymitive/karma:latest' >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV - name: "Setup docker plaforms (merge/release)" if: github.event_name != 'pull_request' run: | echo "DOCKER_PATFORMS=linux/amd64,linux/arm64" >> $GITHUB_ENV - name: "Setup docker plaforms (PR)" if: github.event_name == 'pull_request' run: | echo "DOCKER_PATFORMS=linux/amd64" >> $GITHUB_ENV - name: "Setup image version" run: | echo "VERSION=$(make show-version)" >> $GITHUB_ENV - name: Build and push id: docker_build uses: docker/build-push-action@v3 with: context: . file: ./Dockerfile platforms: ${{ env.DOCKER_PATFORMS }} push: ${{ github.event_name != 'pull_request' }} tags: ${{ env.DOCKER_TAGS }} build-args: | VERSION=${{ env.VERSION }} demo-deploy: name: Deploy demo app to Heroku if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name needs: stage-test-and-lint runs-on: ubuntu-20.04 steps: - name: Check out code uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up Node JS uses: actions/setup-node@v3 with: node-version: 18.1.0 cache: 'npm' cache-dependency-path: 'ui/e2e/package-lock.json' - name: Install Heroku CLI run: curl -s --connect-timeout 30 --fail https://cli-assets.heroku.com/install.sh | sh - name: Build Docker image run: docker build --build-arg VERSION=$(make show-version) -t registry.heroku.com/karma-demo/web -f demo/Dockerfile . shell: bash - name: Write .netrc run: | echo "machine api.heroku.com" >> $HOME/.netrc echo " login l.mierzwa@gmail.com" >> $HOME/.netrc echo " password ${HEROKU_API_KEY}" >> $HOME/.netrc env: HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }} - name: Login to Heroku run: echo "${HEROKU_API_KEY}" | docker login registry.heroku.com -u _ --password-stdin env: HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }} - name: Push docker image to Heroku run: docker push registry.heroku.com/karma-demo/web - name: Trigger Heroku release run: /usr/local/bin/heroku container:release web --app karma-demo - name: Run e2e test uses: nick-invision/retry@v2.7.0 with: timeout_minutes: 10 max_attempts: 3 command: make -C ui/e2e test - name: Rollback on failure if: failure() run: /usr/local/bin/heroku releases:rollback --app karma-demo