diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index b7839ebd..ab5b9c5c 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -1,12 +1,434 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - -name: Node.js CI +name: Build on: [push, pull_request] + # push: + # branches: + # - main + # pull_request: + # branches: + # - main + +# Cancel in-progress runs for pull requests when developers push +# additional changes, and serialize builds in branches. +# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +# Note: if: success() is used in several jobs - +# this ensures that it only executes if all previous jobs succeeded. + +# if: steps.cache-node-modules.outputs.cache-hit != 'true' +# will skip running `yarn install` if it successfully fetched from cache jobs: - Hello-World-Job: - runs-on: codebuild-SageMakerCodeEditor-${{ github.run_id }}-${{ github.run_attempt }} - steps: - - run: echo "Hello World!" + prettier: + name: Format with Prettier + runs-on: ubuntu-20.04 + timeout-minutes: 5 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Run prettier with actionsx/prettier + uses: actionsx/prettier@v3 + with: + args: --check --loglevel=warn . + + doctoc: + name: Doctoc markdown files + runs-on: ubuntu-20.04 + timeout-minutes: 5 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + docs/** + + - name: Install Node.js + if: steps.changed-files.outputs.any_changed == 'true' + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + cache: "yarn" + + - name: Install doctoc + run: yarn global add doctoc@2.2.1 + + - name: Run doctoc + if: steps.changed-files.outputs.any_changed == 'true' + run: yarn doctoc + + lint-helm: + name: Lint Helm chart + runs-on: ubuntu-20.04 + timeout-minutes: 5 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + ci/helm-chart/** + + - name: Install helm + if: steps.changed-files.outputs.any_changed == 'true' + uses: azure/setup-helm@v3.5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install helm kubeval plugin + if: steps.changed-files.outputs.any_changed == 'true' + run: helm plugin install https://github.com/instrumenta/helm-kubeval + + - name: Lint Helm chart + if: steps.changed-files.outputs.any_changed == 'true' + run: helm kubeval ci/helm-chart + + lint-ts: + name: Lint TypeScript files + runs-on: ubuntu-20.04 + timeout-minutes: 5 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + **/*.ts + **/*.js + files_ignore: | + lib/vscode/** + + - name: Install Node.js + if: steps.changed-files.outputs.any_changed == 'true' + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + + - name: Fetch dependencies from cache + if: steps.changed-files.outputs.any_changed == 'true' + id: cache-node-modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: yarn-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + yarn-build- + + - name: Install dependencies + if: steps.changed-files.outputs.any_changed == 'true' && steps.cache-node-modules.outputs.cache-hit != 'true' + run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile + + - name: Lint TypeScript files + if: steps.changed-files.outputs.any_changed == 'true' + run: yarn lint:ts + + lint-actions: + name: Lint GitHub Actions + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Check workflow files + run: | + bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/7fdc9630cc360ea1a469eed64ac6d78caeda1234/scripts/download-actionlint.bash) + ./actionlint -color -shellcheck= -ignore "set-output" + shell: bash + + test-unit: + name: Run unit tests + runs-on: ubuntu-20.04 + timeout-minutes: 5 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + **/*.ts + files_ignore: | + lib/vscode/** + + - name: Install Node.js + if: steps.changed-files.outputs.any_changed == 'true' + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + + - name: Fetch dependencies from cache + if: steps.changed-files.outputs.any_changed == 'true' + id: cache-node-modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: yarn-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + yarn-build- + + - name: Install dependencies + if: steps.changed-files.outputs.any_changed == 'true' && steps.cache-node-modules.outputs.cache-hit != 'true' + run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile + + - name: Run unit tests + if: steps.changed-files.outputs.any_changed == 'true' + run: yarn test:unit + + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + if: success() + + build: + name: Build code-server + runs-on: ubuntu-20.04 + timeout-minutes: 60 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + submodules: true + + - name: Install system dependencies + run: sudo apt update && sudo apt install -y libkrb5-dev + + - name: Install quilt + uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: quilt + version: 1.0 + + - name: Patch Code + run: quilt push -a + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + + # node-gyp is missing in (at least) npm 9.8.1. + # TODO: Remove once we update to npm>=10? + - name: Install node-gyp + run: npm install -g node-gyp + + - name: Fetch dependencies from cache + id: cache-node-modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: yarn-build-code-server-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + yarn-build-code-server- + + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: yarn --frozen-lockfile + + - name: Build code-server + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: yarn build + + # Get Code's git hash. When this changes it means the content is + # different and we need to rebuild. + - name: Get latest lib/vscode rev + id: vscode-rev + run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT + + # We need to rebuild when we have a new version of Code, when any of + # the patches changed, or when the code-server version changes (since + # it gets embedded into the code). Use VSCODE_CACHE_VERSION to + # force a rebuild. + - name: Fetch prebuilt Code package from cache + id: cache-vscode + uses: actions/cache@v4 + with: + path: lib/vscode-reh-web-* + key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }} + + - name: Build vscode + env: + VERSION: "0.0.0" + 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@v4 + with: + name: npm-package + path: ./package.tar.gz + + test-e2e: + name: Run e2e tests + needs: build + runs-on: ubuntu-20.04 + timeout-minutes: 25 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Install system dependencies + run: sudo apt update && sudo apt install -y libkrb5-dev + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + + - name: Fetch dependencies from cache + id: cache-node-modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: yarn-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + yarn-build- + + - name: Download npm package + uses: actions/download-artifact@v4 + with: + name: npm-package + + - name: Decompress npm package + run: tar -xzf package.tar.gz + + - name: Install release package dependencies + run: cd release && npm install --unsafe-perm --omit=dev + + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile + + - name: Install Playwright OS dependencies + run: | + ./test/node_modules/.bin/playwright install-deps + ./test/node_modules/.bin/playwright install + + - name: Run end-to-end tests + run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e + + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: failed-test-videos + path: ./test/test-results + + - name: Remove release packages and test artifacts + run: rm -rf ./release ./test/test-results + + test-e2e-proxy: + name: Run e2e tests behind proxy + needs: build + runs-on: ubuntu-20.04 + timeout-minutes: 25 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Install system dependencies + run: sudo apt update && sudo apt install -y libkrb5-dev + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .node-version + + - name: Fetch dependencies from cache + id: cache-node-modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: yarn-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + yarn-build- + + - name: Download npm package + uses: actions/download-artifact@v4 + with: + name: npm-package + + - name: Decompress npm package + run: tar -xzf package.tar.gz + + - name: Install release package dependencies + run: cd release && npm install --unsafe-perm --omit=dev + + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile + + - name: Install Playwright OS dependencies + run: | + ./test/node_modules/.bin/playwright install-deps + ./test/node_modules/.bin/playwright install + + - name: Cache Caddy + uses: actions/cache@v4 + id: caddy-cache + with: + path: | + ~/.cache/caddy + key: cache-caddy-2.5.2 + + - name: Install Caddy + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: steps.caddy-cache.outputs.cache-hit != 'true' + run: | + gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz" + mkdir -p ~/.cache/caddy + tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy + + - name: Start Caddy + run: sudo ~/.cache/caddy/caddy start --config ./ci/Caddyfile + + - name: Run end-to-end tests + run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e:proxy --global-timeout 840000 + + - name: Stop Caddy + if: always() + run: sudo ~/.cache/caddy/caddy stop --config ./ci/Caddyfile + + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: failed-test-videos-proxy + path: ./test/test-results + + - name: Remove release packages and test artifacts + run: rm -rf ./release ./test/test-results \ No newline at end of file