diff options
| -rw-r--r-- | .github/dependabot.yaml | 2 | ||||
| -rw-r--r-- | .github/workflows/build.yaml | 44 | ||||
| -rw-r--r-- | .github/workflows/update-flake.yaml | 70 | ||||
| -rw-r--r-- | container.nix | 30 | ||||
| -rw-r--r-- | default.nix | 18 | ||||
| -rw-r--r-- | fetchTree.nix | 172 | ||||
| -rw-r--r-- | flake.nix | 98 | ||||
| -rw-r--r-- | overlay.nix | 13 | ||||
| -rw-r--r-- | workerd.nix | 64 |
9 files changed, 394 insertions, 117 deletions
diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 8db6eb5..e6408bb 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -5,4 +5,4 @@ updates: schedule: interval: "weekly" commit-message: - prefix: "deps(actions)" + prefix: "actions" diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2d1132d..30226ff 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,55 +1,65 @@ -name: ci +name: CI on: push: + branches: [main] pull_request: workflow_dispatch: -permissions: - packages: write - jobs: build: + name: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v26 - - uses: DeterminateSystems/magic-nix-cache-action@main + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v26 + + - name: Setup Nix cache + uses: DeterminateSystems/magic-nix-cache-action@v4 - run: | - nix build .#workerd-docker - readlink result | xargs -I {} cp {} workerd.tar.gz + nix build .#container-x86_64 + readlink -f result | xargs -I {} cp {} workerd.tar.gz - - name: upload docker image + - name: Upload container image uses: actions/upload-artifact@v4 with: name: container path: workerd.tar.gz - upload-to-docker: + push: + name: Push to registry + runs-on: ubuntu-latest + needs: build - if: github.ref == 'refs/heads/main' + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + + permissions: + packages: write env: REGISTRY: ghcr.io steps: - - name: download docker image + - name: Download container image uses: actions/download-artifact@v4 with: name: container - - name: login to ${{ env.REGISTRY }} + - name: Login to ${{ env.REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: "getchoo" password: ${{ github.token }} - - name: upload to ${{ env.REGISTRY }} + - name: Upload to ${{ env.REGISTRY }} run: | docker load < workerd.tar.gz - docker tag workerd:latest ${{ env.REGISTRY }}/getchoo/workerd:latest - docker push ${{ env.REGISTRY }}/getchoo/workerd:latest + docker tag workerd:latest "$REGISTRY"/getchoo/workerd:latest + docker push "$REGISTRY"/getchoo/workerd:latest diff --git a/.github/workflows/update-flake.yaml b/.github/workflows/update-flake.yaml index 7f5fc6b..dd290f9 100644 --- a/.github/workflows/update-flake.yaml +++ b/.github/workflows/update-flake.yaml @@ -1,24 +1,66 @@ -name: update flake inputs +name: Update lockfiles on: schedule: + # run every saturday - cron: "0 0 * * 6" workflow_dispatch: -permissions: - contents: write - pull-requests: write - jobs: - update-flake: + update: + name: Run update runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + env: + PR_BRANCH: "update-lockfiles" + steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v26 - - uses: DeterminateSystems/magic-nix-cache-action@main - - - uses: DeterminateSystems/update-flake-lock@v21 - with: - commit-msg: "deps(flake): update inputs" - pr-title: "deps(flake): update inputs" + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v26 + + - name: Set Git user info + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + + - name: Create new branch + id: branch + run: | + git switch -c "$PR_BRANCH" + + - name: Update flake inputs + run: | + nix flake update \ + --commit-lock-file \ + --commit-lockfile-summary "nix: update flake.lock" + + - name: Make PR if needed + env: + GH_TOKEN: ${{ github.token }} + run: | + if ! git diff --color=always --exit-code origin/main; then + git fetch origin "$PR_BRANCH" || true + git push --force-with-lease -u origin "$PR_BRANCH" + + open_prs="$(gh pr list --base main --head "$PR_BRANCH" | wc -l)" + if [ "$open_prs" -eq 0 ]; then + gh pr create \ + --base main \ + --head "$PR_BRANCH" \ + --title "nix: update flake.lock" \ + --fill + fi + fi + + - name: Enable auto-merge + shell: bash + run: gh pr merge --auto --squash + env: + GH_TOKEN: ${{ github.token }} diff --git a/container.nix b/container.nix new file mode 100644 index 0000000..3d25586 --- /dev/null +++ b/container.nix @@ -0,0 +1,30 @@ +{ + lib, + buildEnv, + dockerTools, + runCommand, + bashInteractive, + workerd, +}: +dockerTools.buildLayeredImage { + name = workerd.pname; + tag = "latest"; + + contents = [ + (buildEnv { + name = "image-root"; + paths = [ + (runCommand "bin-sh" {} '' + mkdir -p $out/bin + ln -s ${lib.getExe bashInteractive} $out/bin/sh + '') + workerd + ]; + pathsToLink = ["/bin" "/etc"]; + }) + dockerTools.caCertificates + ]; + + config.Cmd = [(lib.getExe workerd)]; + architecture = workerd.stdenv.hostPlatform.ubootArch; +} diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..73e9a8a --- /dev/null +++ b/default.nix @@ -0,0 +1,18 @@ +let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + fetchTree = import ./fetchTree.nix; + flakeSources = builtins.mapAttrs (_: node: fetchTree node.locked) lock.nodes; +in + { + nixpkgs ? + import sources.nixpkgs { + inherit system; + config = {}; + overlays = []; + }, + system ? builtins.currentSystem, + sources ? flakeSources, + }: let + pkgs' = import ./overlay.nix (nixpkgs // pkgs') nixpkgs; + in + pkgs' diff --git a/fetchTree.nix b/fetchTree.nix new file mode 100644 index 0000000..26de85b --- /dev/null +++ b/fetchTree.nix @@ -0,0 +1,172 @@ +# this code is slightly modified from https://github.com/edolstra/flake-compat +## +## Copyright (c) 2020-2021 Eelco Dolstra and the flake-compat contributors +## +## Permission is hereby granted, free of charge, to any person obtaining +## a copy of this software and associated documentation files (the +## "Software"), to deal in the Software without restriction, including +## without limitation the rights to use, copy, modify, merge, publish, +## distribute, sublicense, and/or sell copies of the Software, and to +## permit persons to whom the Software is furnished to do so, subject to +## the following conditions: +## +## The above copyright notice and this permission notice shall be +## included in all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +let + formatSecondsSinceEpoch = t: let + rem = x: y: x - x / y * y; + days = t / 86400; + secondsInDay = rem t 86400; + hours = secondsInDay / 3600; + minutes = (rem secondsInDay 3600) / 60; + seconds = rem t 60; + + # Courtesy of https://stackoverflow.com/a/32158604. + z = days + 719468; + era = + ( + if z >= 0 + then z + else z - 146096 + ) + / 146097; + doe = z - era * 146097; + yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + y = yoe + era * 400; + doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + mp = (5 * doy + 2) / 153; + d = doy - (153 * mp + 2) / 5 + 1; + m = + mp + + ( + if mp < 10 + then 3 + else -9 + ); + y' = + y + + ( + if m <= 2 + then 1 + else 0 + ); + + pad = s: + if builtins.stringLength s < 2 + then "0" + s + else s; + in "${toString y'}${pad (toString m)}${pad (toString d)}${pad (toString hours)}${pad (toString minutes)}${pad (toString seconds)}"; + + fetchTree = info: + if info.type == "github" + then { + outPath = + fetchTarball + ( + {url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}";} + // ( + if info ? narHash + then {sha256 = info.narHash;} + else {} + ) + ); + inherit (info) rev lastModified narHash; + shortRev = builtins.substring 0 7 info.rev; + lastModifiedDate = formatSecondsSinceEpoch info.lastModified; + } + else if info.type == "git" + then + { + outPath = + builtins.fetchGit + ( + {inherit (info) url;} + // ( + if info ? rev + then {inherit (info) rev;} + else {} + ) + // ( + if info ? ref + then {inherit (info) ref;} + else {} + ) + // ( + if info ? submodules + then {inherit (info) submodules;} + else {} + ) + ); + inherit (info) lastModified narHash; + lastModifiedDate = formatSecondsSinceEpoch info.lastModified; + } + // ( + if info ? rev + then { + inherit (info) rev; + shortRev = builtins.substring 0 7 info.rev; + } + else { + } + ) + else if info.type == "path" + then { + outPath = builtins.path {inherit (info) path;}; + inherit (info) narHash; + } + else if info.type == "tarball" + then { + outPath = + fetchTarball + ( + {inherit (info) url;} + // ( + if info ? narHash + then {sha256 = info.narHash;} + else {} + ) + ); + } + else if info.type == "gitlab" + then { + inherit (info) rev narHash lastModified; + outPath = + fetchTarball + ( + {url = "https://${info.host or "gitlab.com"}/api/v4/projects/${info.owner}%2F${info.repo}/repository/archive.tar.gz?sha=${info.rev}";} + // ( + if info ? narHash + then {sha256 = info.narHash;} + else {} + ) + ); + shortRev = builtins.substring 0 7 info.rev; + } + else if info.type == "sourcehut" + then { + inherit (info) rev narHash lastModified; + outPath = + fetchTarball + ( + {url = "https://${info.host or "git.sr.ht"}/${info.owner}/${info.repo}/archive/${info.rev}.tar.gz";} + // ( + if info ? narHash + then {sha256 = info.narHash;} + else {} + ) + ); + shortRev = builtins.substring 0 7 info.rev; + } + else + # FIXME: add Mercurial, tarball inputs. + throw "flake input has unsupported input type '${info.type}'"; +in + fetchTree @@ -1,103 +1,31 @@ { - description = "worked...but in a cool docker container!"; + description = "workerd...but in a cool docker container!"; - inputs = { - nixpkgs.url = "nixpkgs/nixos-unstable"; - }; + inputs.nixpkgs.url = "nixpkgs/nixos-unstable"; outputs = { self, nixpkgs, - ... }: let systems = [ "x86_64-linux" "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" ]; - forAllSystems = nixpkgs.lib.genAttrs systems; - nixpkgsFor = forAllSystems (system: - import nixpkgs { - inherit system; - overlays = [self.overlays.default]; - }); - - forEachSystem = fn: - forAllSystems (system: - fn { - inherit system; - pkgs = nixpkgsFor.${system}; - }); + forAllSystems = fn: nixpkgs.lib.genAttrs systems (system: fn nixpkgs.legacyPackages.${system}); in { - formatter = forEachSystem ({pkgs, ...}: pkgs.alejandra); - - packages = forEachSystem ({pkgs, ...}: { - inherit (pkgs) workerd workerd-docker; - default = pkgs.workerd-docker; - }); - - overlays.default = final: prev: { - workerd = let - inherit (prev) fetchurl llvmPackages stdenv system; - inherit (prev.lib) makeLibraryPath optionalAttrs; - in - stdenv.mkDerivation rec { - pname = "workerd"; - version = "1.20230628.0"; - src = - optionalAttrs (system - == "x86_64-linux") (fetchurl { - url = "https://github.com/cloudflare/workerd/releases/download/v${version}/workerd-linux-64.gz"; - hash = "sha256-McY39ud6NHgUM8QN8kXO73oLvTcv+zm35xxkWxvOvHA="; - }) - // optionalAttrs (system == "aarch64-linux") (fetchurl { - url = "https://github.com/cloudflare/workerd/releases/download/v${version}/workerd-linux-arm64.gz"; - hash = "sha256-/UA49cbyjqzE82sxpPnVBVT+gd6VA5dDkcpRS7FZjc8="; - }); - - buildInputs = [llvmPackages.libcxx llvmPackages.libunwind]; + formatter = forAllSystems (pkgs: pkgs.alejandra); - unpackPhase = ":"; - - installPhase = '' - mkdir -p $out/bin - cp ${src} workerd.gz - gzip -d workerd.gz - install -Dm755 workerd $out/bin/workerd - ''; - - preFixup = let - libPath = makeLibraryPath [ - llvmPackages.libcxx - llvmPackages.libunwind - ]; - in '' - patchelf \ - --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \ - --set-rpath ${libPath} \ - $out/bin/workerd - ''; - }; - - workerd-docker = let - inherit (prev) dockerTools; - env = prev.buildEnv { - name = "image-root"; - paths = [dockerTools.binSh final.workerd]; - pathsToLink = ["/bin" "/etc"]; + packages = forAllSystems ( + pkgs: let + pkgs' = import ./. { + nixpkgs = pkgs; + inherit (pkgs.stdenv.hostPlatform) system; }; in - dockerTools.buildLayeredImage { - name = final.workerd.pname; - tag = "latest"; - contents = [ - env - dockerTools.caCertificates - ]; - config.Cmd = ["${final.workerd}/bin/workerd"]; - }; - }; + pkgs' // {default = pkgs'.workerd;} + ); + + overlays.default = final: prev: import ./overlay.nix final prev; }; } diff --git a/overlay.nix b/overlay.nix new file mode 100644 index 0000000..2ebe08a --- /dev/null +++ b/overlay.nix @@ -0,0 +1,13 @@ +final: prev: { + workerd = prev.callPackage ./workerd.nix {}; + + container-x86_64 = final.callPackage ./container.nix { + inherit (final.pkgsCross.gnu64) bashInteractive; + workerd = final.workerd.override {inherit (final.pkgsCross.gnu64) stdenvNoCC;}; + }; + + container-aarch64 = final.callPackage ./container.nix { + inherit (final.pkgsCross.aarch64-multiplatform) bashInteractive; + workerd = final.workerd.override {inherit (final.pkgsCross.aarch64-multiplatform) stdenvNoCC;}; + }; +} diff --git a/workerd.nix b/workerd.nix new file mode 100644 index 0000000..401d544 --- /dev/null +++ b/workerd.nix @@ -0,0 +1,64 @@ +{ + lib, + stdenvNoCC, + fetchurl, + autoPatchelfHook, +}: +stdenvNoCC.mkDerivation (finalAttrs: { + pname = "workerd"; + version = "1.20240423.0"; + + src = let + baseUrl = "https://github.com/cloudflare/workerd/releases/download/v${finalAttrs.version}"; + in + fetchurl + { + x86_64-linux = { + url = "${baseUrl}/workerd-linux-64.gz"; + hash = "sha256-gXqTFp+u9j+nOtwfowEUUk1QaxrhyqO8fFzZFGchAvk="; + }; + + aarch64-linux = { + url = "${baseUrl}/workerd-linux-arm64.gz"; + hash = "sha256-6IynAN/xp8hieeMEuYbrv9X6edoTzKYZqCOcTPUy12o="; + }; + } + .${stdenvNoCC.hostPlatform.system} + or (throw "${stdenvNoCC.hostPlatform.system} is not supported!"); + + nativeBuildInputs = [autoPatchelfHook]; + + dontConfigure = true; + dontBuild = true; + doCheck = false; + + unpackCmd = '' + runHook preUnpack + + dest="$(stripHash $curSrc)" + cp "$curSrc" "$dest" + gzip -d "$dest" + mkdir source + mv ''${dest/.gz/} source/ + + runHook postUnpack + ''; + + installPhase = '' + runHook preInstall + + install -Dm755 workerd-* $out/bin/workerd + + runHook postInstall + ''; + + meta = with lib; { + mainProgram = "workerd"; + description = "The JavaScript / Wasm runtime that powers Cloudflare Workers"; + homepage = "https://github.com/cloudflare/workerd"; + changelog = "https://github.com/cloudflare/workerd/releases/tag/v${finalAttrs.version}"; + license = licenses.asl20; + maintainers = with maintainers; [getchoo]; + platforms = ["x86_64-linux" "aarch64-linux"]; + }; +}) |
