name: Build on: push: branches: - main pull_request: branches: - main # Note: if: success() is used in several jobs - # this ensures that it only executes if all previous jobs succeeded. # if: steps.cache-yarn.outputs.cache-hit != 'true' # will skip running `yarn install` if it successfully fetched from cache jobs: prebuild: name: Pre-build checks runs-on: ubuntu-latest timeout-minutes: 15 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} steps: - name: Checkout repo uses: actions/checkout@v2 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Install helm uses: azure/setup-helm@v1.1 - name: Fetch dependencies from cache id: cache-yarn uses: actions/cache@v2 with: path: "**/node_modules" key: yarn-build-${{ hashFiles('**/yarn.lock') }} restore-keys: | yarn-build- - name: Install dependencies if: steps.cache-yarn.outputs.cache-hit != 'true' run: yarn --frozen-lockfile - name: Run yarn fmt run: yarn fmt if: success() - name: Run yarn lint run: yarn lint if: success() - name: Run code-server unit tests run: yarn test:unit if: success() - name: Upload coverage report to Codecov run: yarn coverage if: success() audit-ci: name: Run audit-ci needs: prebuild runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: Checkout repo uses: actions/checkout@v2 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Fetch dependencies from cache id: cache-yarn uses: actions/cache@v2 with: path: "**/node_modules" key: yarn-build-${{ hashFiles('**/yarn.lock') }} restore-keys: | yarn-build- - name: Install dependencies if: steps.cache-yarn.outputs.cache-hit != 'true' run: yarn --frozen-lockfile - name: Audit for vulnerabilities run: yarn _audit if: success() build: name: Build needs: prebuild runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Fetch dependencies from cache id: cache-yarn uses: actions/cache@v2 with: path: "**/node_modules" key: yarn-build-${{ hashFiles('**/yarn.lock') }} restore-keys: | yarn-build- - name: Install dependencies if: steps.cache-yarn.outputs.cache-hit != 'true' run: yarn --frozen-lockfile - name: Build code-server run: yarn build # Parse the hash of the latest commit inside lib/vscode # use this to avoid rebuilding it if nothing changed # How it works: the `git log` command fetches the hash of the last commit # that changed a file inside `lib/vscode`. If a commit changes any file in there, # the hash returned will change, and we rebuild vscode. If the hash did not change, # (for example, a change to `src/` or `docs/`), we reuse the same build as last time. # This saves a lot of time in CI, as compiling VSCode can take anywhere from 5-10 minutes. - name: Get latest lib/vscode rev id: vscode-rev run: echo "::set-output name=rev::$(git log -1 --format='%H' ./lib/vscode)" - name: Attempt to fetch vscode build from cache id: cache-vscode uses: actions/cache@v2 with: path: | lib/vscode/.build lib/vscode/out-build lib/vscode/out-vscode lib/vscode/out-vscode-min key: vscode-build-${{ steps.vscode-rev.outputs.rev }} - name: Build vscode if: steps.cache-vscode.outputs.cache-hit != 'true' run: yarn build:vscode # The release package does not contain any native modules # and is neutral to architecture/os/libc version. - name: Create release package run: yarn release if: success() # https://github.com/actions/upload-artifact/issues/38 - name: Compress release package run: tar -czf package.tar.gz release - name: Upload npm package artifact uses: actions/upload-artifact@v2 with: name: npm-package path: ./package.tar.gz # TODO: cache building yarn --production # possibly 2m30s of savings(?) # this requires refactoring our release scripts package-linux-amd64: name: x86-64 Linux build needs: build runs-on: ubuntu-latest timeout-minutes: 15 container: "centos:7" steps: - uses: actions/checkout@v2 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Install development tools run: | yum install -y epel-release centos-release-scl yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync - name: Install nfpm and envsubst run: | curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1 curl -L https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst chmod +x envsubst mv envsubst ~/.local/bin echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install yarn run: npm install -g yarn - name: Download npm package uses: actions/download-artifact@v2 with: name: npm-package - name: Decompress npm package run: tar -xzf package.tar.gz # NOTE: && here is deliberate - GitHub puts each line in its own `.sh` # file when running inside a docker container. - name: Build standalone release run: source scl_source enable devtoolset-9 && yarn release:standalone - name: Sanity test standalone release run: yarn test:standalone-release - name: Build packages with nfpm run: yarn package - name: Upload release artifacts uses: actions/upload-artifact@v2 with: name: release-packages path: ./release-packages # NOTE@oxy: # We use Ubuntu 16.04 here, so that our build is more compatible # with older libc versions. We used to (Q1'20) use CentOS 7 here, # but it has a full update EOL of Q4'20 and a 'critical security' # update EOL of 2024. We're dropping full support a few years before # the final EOL, but I don't believe CentOS 7 has a large arm64 userbase. # It is not feasible to cross-compile with CentOS. # Cross-compile notes: To compile native dependencies for arm64, # we install the aarch64 cross toolchain and then set it as the default # compiler/linker/etc. with the AR/CC/CXX/LINK environment variables. # qemu-user-static on ubuntu-16.04 currently doesn't run Node correctly, # so we just build with "native"/x86_64 node, then download arm64 node # and then put it in our release. We can't smoke test the arm64 build this way, # but this means we don't need to maintain a self-hosted runner! package-linux-arm64: name: Linux ARM64 cross-compile build needs: build runs-on: ubuntu-16.04 timeout-minutes: 15 env: AR: aarch64-linux-gnu-ar CC: aarch64-linux-gnu-gcc CXX: aarch64-linux-gnu-g++ LINK: aarch64-linux-gnu-g++ NPM_CONFIG_ARCH: arm64 steps: - uses: actions/checkout@v2 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Install nfpm run: | curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1 echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install cross-compiler run: sudo apt install g++-aarch64-linux-gnu - name: Download npm package uses: actions/download-artifact@v2 with: name: npm-package - name: Decompress npm package run: tar -xzf package.tar.gz - name: Build standalone release run: yarn release:standalone - name: Replace node with arm64 equivalent run: | wget https://nodejs.org/dist/v14.17.0/node-v14.17.0-linux-arm64.tar.xz tar -xf node-v14.17.0-linux-arm64.tar.xz node-v14.17.0-linux-arm64/bin/node --strip-components=2 mv ./node ./release-standalone/lib/node - name: Build packages with nfpm run: yarn package arm64 - name: Upload release artifacts uses: actions/upload-artifact@v2 with: name: release-packages path: ./release-packages package-macos-amd64: name: x86-64 macOS build needs: build runs-on: macos-latest timeout-minutes: 15 steps: - uses: actions/checkout@v2 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Install nfpm run: | curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1 echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Download npm package uses: actions/download-artifact@v2 with: name: npm-package - name: Decompress npm package run: tar -xzf package.tar.gz - name: Build standalone release run: yarn release:standalone - name: Sanity test standalone release run: yarn test:standalone-release - name: Build packages with nfpm run: yarn package - name: Upload release artifacts uses: actions/upload-artifact@v2 with: name: release-packages path: ./release-packages test-e2e: name: End-to-end tests needs: package-linux-amd64 runs-on: ubuntu-latest timeout-minutes: 15 env: # Since we build code-server we might as well run tests from the release # since VS Code will load faster due to the bundling. CODE_SERVER_TEST_ENTRY: "./release-packages/code-server-linux-amd64" steps: - uses: actions/checkout@v2 - name: Install Node.js v14 uses: actions/setup-node@v2 with: node-version: "14" - name: Install playwright uses: microsoft/playwright-github-action@v1 - name: Fetch dependencies from cache id: cache-yarn uses: actions/cache@v2 with: path: "**/node_modules" key: yarn-build-${{ hashFiles('**/yarn.lock') }} restore-keys: | yarn-build- - name: Download release packages uses: actions/download-artifact@v2 with: name: release-packages path: ./release-packages - name: Untar code-server release run: | cd release-packages tar -xzf code-server*-linux-amd64.tar.gz mv code-server*-linux-amd64 code-server-linux-amd64 - name: Install dependencies if: steps.cache-yarn.outputs.cache-hit != 'true' run: yarn --frozen-lockfile # HACK: this shouldn't need to exist, but put it here anyway # in an attempt to solve Playwright cache failures. - name: Reinstall playwright if: steps.cache-yarn.outputs.cache-hit == 'true' run: | cd test/ rm -r node_modules/playwright yarn install --check-files - name: Run end-to-end tests run: yarn test:e2e - name: Upload test artifacts if: always() uses: actions/upload-artifact@v2 with: name: failed-test-videos path: ./test/test-results - name: Remove release packages and test artifacts run: rm -rf ./release-packages ./test/test-results # Builds both amd64 and arm64 images docker-images: runs-on: ubuntu-latest needs: [package-linux-amd64, package-linux-arm64] steps: - uses: actions/checkout@v2 - name: Download release package uses: actions/download-artifact@v2 with: name: release-packages path: ./release-packages - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Run ./ci/steps/build-docker-image.sh run: ./ci/steps/build-docker-image.sh - name: Upload release images uses: actions/upload-artifact@v2 with: name: release-images path: ./release-images trivy-scan-image: runs-on: ubuntu-20.04 needs: docker-images # NOTE@jsjoeio: disabling due to a memory issue upstream # See: https://github.com/github/codeql-action/issues/528 if: 1 == 2 steps: - name: Checkout code uses: actions/checkout@v2 - name: Download release images uses: actions/download-artifact@v2 with: name: release-images path: ./release-images - name: Run Trivy vulnerability scanner in image mode # Commit SHA for v0.0.17 uses: aquasecurity/trivy-action@9438b49cc3156b2e8c77c1ba8ffbaa3bae24e3c2 with: input: "./release-images/code-server-amd64-*.tar" scan-type: "image" ignore-unfixed: true format: "template" template: "@/contrib/sarif.tpl" output: "trivy-image-results.sarif" severity: "HIGH,CRITICAL" - name: Debug Trivy SARIF file run: cat trivy-image-results.sarif && ls -l trivy-image-results.sarif - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v1 with: sarif_file: "trivy-image-results.sarif" # We have to use two trivy jobs # because GitHub only allows # codeql/upload-sarif action per job trivy-scan-repo: runs-on: ubuntu-20.04 steps: - name: Checkout code uses: actions/checkout@v2 - name: Run Trivy vulnerability scanner in repo mode #Commit SHA for v0.0.17 uses: aquasecurity/trivy-action@9438b49cc3156b2e8c77c1ba8ffbaa3bae24e3c2 with: scan-type: "fs" scan-ref: "." ignore-unfixed: true format: "template" template: "@/contrib/sarif.tpl" output: "trivy-repo-results.sarif" severity: "HIGH,CRITICAL" - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v1 with: sarif_file: "trivy-repo-results.sarif"