diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 476872af20..2ce41c5088 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,6 +37,7 @@ jobs: k8s: ${{ steps.filter.outputs.k8s }} ci: ${{ steps.filter.outputs.ci }} db: ${{ steps.filter.outputs.db }} + gomod: ${{ steps.filter.outputs.gomod }} offlinedocs-only: ${{ steps.filter.outputs.offlinedocs_count == steps.filter.outputs.all_count }} offlinedocs: ${{ steps.filter.outputs.offlinedocs }} steps: @@ -90,6 +91,9 @@ jobs: - "scaletest/**" - "tailnet/**" - "testutil/**" + gomod: + - "go.mod" + - "go.sum" ts: - "site/**" - "Makefile" @@ -108,6 +112,25 @@ jobs: run: | echo "${{ toJSON(steps.filter )}}" + update-flake: + needs: changes + if: needs.changes.outputs.gomod == 'true' + runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Setup Go + uses: ./.github/actions/setup-go + + - name: Update Nix Flake SRI Hash + run: ./scripts/update-flake.sh + + - name: Ensure No Changes + run: git diff --exit-code + lint: needs: changes if: needs.changes.outputs.offlinedocs-only == 'false' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main' diff --git a/flake.lock b/flake.lock index 2bbf425275..8a460beeb9 100644 --- a/flake.lock +++ b/flake.lock @@ -56,6 +56,24 @@ "type": "github" } }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1681823821, @@ -87,11 +105,47 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1714906307, + "narHash": "sha256-UlRZtrCnhPFSJlDQE7M0eyhgvuuHBTe1eJ9N9AQlJQ0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "25865a40d14b3f9cf19f19b924e2ab4069b09588", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pnpm2nix": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1706694632, + "narHash": "sha256-ytyTwNPiUR8aq74QlxFI+Wv3MyvXz5POO1xZxQIoi0c=", + "owner": "nzbr", + "repo": "pnpm2nix-nzbr", + "rev": "0366b7344171accc2522525710e52a8abbf03579", + "type": "github" + }, + "original": { + "owner": "nzbr", + "repo": "pnpm2nix-nzbr", + "type": "github" + } + }, "root": { "inputs": { "drpc": "drpc", "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_2", + "pnpm2nix": "pnpm2nix" } }, "systems": { @@ -123,6 +177,21 @@ "repo": "default", "type": "github" } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index c0407c9e18..510a2ea8da 100644 --- a/flake.nix +++ b/flake.nix @@ -4,25 +4,29 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; + pnpm2nix.url = "github:nzbr/pnpm2nix-nzbr"; drpc.url = "github:storj/drpc/v0.0.33"; }; - outputs = { self, nixpkgs, flake-utils, drpc }: + outputs = { self, nixpkgs, flake-utils, drpc, pnpm2nix }: flake-utils.lib.eachDefaultSystem (system: let # Workaround for: terraform has an unfree license (‘bsl11’), refusing to evaluate. pkgs = import nixpkgs { inherit system; config.allowUnfree = true; }; - formatter = pkgs.nixpkgs-fmt; nodejs = pkgs.nodejs-18_x; - yarn = pkgs.yarn.override { inherit nodejs; }; # Check in https://search.nixos.org/packages to find new packages. # Use `nix --extra-experimental-features nix-command --extra-experimental-features flakes flake update` # to update the lock file if packages are out-of-date. # From https://nixos.wiki/wiki/Google_Cloud_SDK - gdk = pkgs.google-cloud-sdk.withExtraComponents ([pkgs.google-cloud-sdk.components.gke-gcloud-auth-plugin]); + gdk = pkgs.google-cloud-sdk.withExtraComponents ([ pkgs.google-cloud-sdk.components.gke-gcloud-auth-plugin ]); + # The minimal set of packages to build Coder. devShellPackages = with pkgs; [ + # google-chrome is not available on OSX + (if pkgs.stdenv.hostPlatform.isDarwin then null else google-chrome) + # strace is not available on OSX + (if pkgs.stdenv.hostPlatform.isDarwin then null else strace) bat cairo curl @@ -31,15 +35,13 @@ gcc gdk getopt - git gh + git gnumake gnused go_1_21 go-migrate golangci-lint - # google-chrome is not available on OSX - (if pkgs.stdenv.hostPlatform.isDarwin then null else google-chrome) gopls gotestsum jq @@ -47,8 +49,6 @@ kubectx kubernetes-helm less - # Needed for many LD system libs! - util-linux mockgen nfpm nodejs @@ -67,34 +67,84 @@ shellcheck shfmt sqlc - # strace is not available on OSX - (if pkgs.stdenv.hostPlatform.isDarwin then null else strace) terraform typos + # Needed for many LD system libs! + util-linux vim wget - yarn yq-go zip zsh zstd ]; - allPackages = pkgs.buildEnv { - name = "all-packages"; - paths = devShellPackages; + # buildSite packages the site directory. + buildSite = pnpm2nix.packages.${system}.mkPnpmPackage { + src = ./site/.; + # Required for the `canvas` package! + extraBuildInputs = with pkgs; [ pkgs.cairo pkgs.pango pkgs.pixman ]; + installInPlace = true; + distDir = "out"; }; + + version = "v0.0.0-nix-${self.shortRev or self.dirtyShortRev}"; + + # To make faster subsequent builds, you could extract the `.zst` + # slim bundle into it's own derivation. + buildFat = osArch: + pkgs.buildGo121Module { + name = "coder-${osArch}"; + # Updated with ./scripts/update-flake.nix`. + # This should be updated whenever go.mod changes! + vendorHash = "sha256-pTRr85MtdlsI0iYGAwLAQ3QvtrDR8rDOynYx8FDaRy0="; + proxyVendor = true; + src = ./.; + nativeBuildInputs = with pkgs; [ getopt openssl zstd ]; + preBuild = '' + # Replaces /usr/bin/env with an absolute path to the interpreter. + patchShebangs ./scripts + ''; + buildPhase = '' + runHook preBuild + + # Unpack the site contents. + mkdir -p ./site/out + cp -r ${buildSite.out}/* ./site/out + + # Build and copy the binary! + export CODER_FORCE_VERSION=${version} + make -j build/coder_${osArch} + ''; + installPhase = '' + mkdir -p $out/bin + cp -r ./build/coder_${osArch} $out/bin/coder + ''; + }; in { - defaultPackage = formatter; # or replace it with your desired default package. devShell = pkgs.mkShell { - buildInputs = devShellPackages; - shellHook = '' - export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} - export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true - ''; + buildInputs = devShellPackages; + shellHook = '' + export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} + export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true + ''; + }; + packages = { + all = pkgs.buildEnv { + name = "all-packages"; + paths = devShellPackages; + }; + site = buildSite; + + # Copying `OS_ARCHES` from the Makefile. + linux_amd64 = buildFat "linux_amd64"; + linux_arm64 = buildFat "linux_arm64"; + darwin_amd64 = buildFat "darwin_amd64"; + darwin_arm64 = buildFat "darwin_arm64"; + windows_amd64 = buildFat "windows_amd64.exe"; + windows_arm64 = buildFat "windows_arm64.exe"; }; - packages.all = allPackages; } ); } diff --git a/scripts/lib.sh b/scripts/lib.sh index 2839de2dbf..78ec22d503 100644 --- a/scripts/lib.sh +++ b/scripts/lib.sh @@ -43,6 +43,9 @@ SCRIPT="${BASH_SOURCE[1]:-${BASH_SOURCE[0]}}" SCRIPT_DIR="$(realpath "$(dirname "$SCRIPT")")" function project_root { + # Nix sets $src in derivations! + [[ -n "${src:-}" ]] && echo "$src" && return + # Try to use `git rev-parse --show-toplevel` to find the project root. # If this directory is not a git repository, this command will fail. git rev-parse --show-toplevel 2>/dev/null && return diff --git a/scripts/update-flake.sh b/scripts/update-flake.sh new file mode 100755 index 0000000000..4094f20032 --- /dev/null +++ b/scripts/update-flake.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Updates SRI hashes for flake.nix. + +set -eu + +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +OUT=$(mktemp -d -t nar-hash-XXXXXX) + +echo "Downloading Go modules..." +GOPATH="$OUT" go mod download +echo "Calculating SRI hash..." +HASH=$(go run tailscale.com/cmd/nardump --sri "$OUT/pkg/mod/cache/download") +sudo rm -rf "$OUT" + +sed -i "s/\(vendorHash = \"\)[^\"]*/\1${HASH}/" ./flake.nix diff --git a/site/package.json b/site/package.json index 24ba4d5262..a5c5fee146 100644 --- a/site/package.json +++ b/site/package.json @@ -184,6 +184,6 @@ }, "engines": { "npm": ">=9.0.0 <10.0.0", - "node": ">=18.0.0 <19.0.0" + "node": ">=18.0.0 <21.0.0" } }