tenseleyflow/shithub / 0bffad9

Browse files

deploy: add nix-built runner image

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
0bffad9142435847e7c224a343a8843522723b78
Parents
cf7b55f
Tree
12e23d2

4 changed files

StatusFile+-
A .github/workflows/runner-image.yml 75 0
A deploy/runner-images/README.md 22 0
A deploy/runner-images/flake.lock 27 0
A deploy/runner-images/flake.nix 93 0
.github/workflows/runner-image.ymladded
@@ -0,0 +1,75 @@
1
+name: runner image
2
+
3
+on:
4
+  workflow_dispatch:
5
+    inputs:
6
+      image:
7
+        description: "Destination image name; blank publishes under this repo's GHCR namespace"
8
+        required: false
9
+        default: ""
10
+      tag:
11
+        description: "Destination image tag"
12
+        required: true
13
+        default: "1.0"
14
+
15
+permissions:
16
+  contents: read
17
+  id-token: write
18
+  packages: write
19
+
20
+env:
21
+  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
22
+
23
+jobs:
24
+  build:
25
+    runs-on: ubuntu-latest
26
+    steps:
27
+      - uses: actions/checkout@v4
28
+
29
+      - uses: DeterminateSystems/determinate-nix-action@v3
30
+
31
+      - name: Resolve destination image
32
+        id: image
33
+        env:
34
+          INPUT_IMAGE: ${{ inputs.image }}
35
+          INPUT_TAG: ${{ inputs.tag }}
36
+          REPOSITORY: ${{ github.repository }}
37
+        run: |
38
+          set -euo pipefail
39
+          image="$INPUT_IMAGE"
40
+          if [ -z "$image" ]; then
41
+            image="ghcr.io/${REPOSITORY,,}/runner-nix"
42
+          fi
43
+          case "$image" in
44
+            *[!a-z0-9/:._-]* | "")
45
+              echo "invalid image name: $image" >&2
46
+              exit 2
47
+              ;;
48
+          esac
49
+          case "$INPUT_TAG" in
50
+            *[!A-Za-z0-9_.-]* | "")
51
+              echo "invalid image tag: $INPUT_TAG" >&2
52
+              exit 2
53
+              ;;
54
+          esac
55
+          printf 'image=%s\n' "$image" >> "$GITHUB_OUTPUT"
56
+          printf 'tag=%s\n' "$INPUT_TAG" >> "$GITHUB_OUTPUT"
57
+
58
+      - name: Build image tarball
59
+        run: nix build ./deploy/runner-images#runnerImage --print-build-logs
60
+
61
+      - name: Load image
62
+        run: docker load < result
63
+
64
+      - name: Tag image
65
+        run: docker tag ghcr.io/shithub/runner-nix:1.0 "${{ steps.image.outputs.image }}:${{ steps.image.outputs.tag }}"
66
+
67
+      - name: Login to GHCR
68
+        uses: docker/login-action@v3
69
+        with:
70
+          registry: ghcr.io
71
+          username: ${{ github.actor }}
72
+          password: ${{ secrets.GITHUB_TOKEN }}
73
+
74
+      - name: Push image
75
+        run: docker push "${{ steps.image.outputs.image }}:${{ steps.image.outputs.tag }}"
deploy/runner-images/README.mdadded
@@ -0,0 +1,22 @@
1
+# shithub runner image
2
+
3
+`flake.nix` builds the default S41d runner container image:
4
+
5
+```sh
6
+nix build ./deploy/runner-images#runnerImage
7
+docker load < result
8
+```
9
+
10
+The image tag is `ghcr.io/shithub/runner-nix:1.0`, matching
11
+`internal/runner/config`'s default. `flake.lock` pins nixpkgs so the
12
+image input set is reviewable and repeatable. The image intentionally
13
+contains only the baseline tools needed for v1 `run:` steps and checkout
14
+plumbing:
15
+`bash`, coreutils, git, curl, CA certificates, gnupg, gcc, gnumake,
16
+archive tools, OpenSSH, and `shithub-shallow-checkout`.
17
+
18
+Publishing is handled by `.github/workflows/runner-image.yml`. That
19
+workflow is manual because the GHCR namespace may differ between the
20
+upstream project and self-hosted forks. Leave the image input blank to
21
+publish under the current repository's GHCR namespace, or override it
22
+with `ghcr.io/shithub/runner-nix` for the upstream package.
deploy/runner-images/flake.lockadded
@@ -0,0 +1,27 @@
1
+{
2
+  "nodes": {
3
+    "nixpkgs": {
4
+      "locked": {
5
+        "lastModified": 1778003029,
6
+        "narHash": "sha256-q/nkKLDtHIyLjZpKhWk3cSK5IYsFqtMd6UtXF3ddjgA=",
7
+        "owner": "NixOS",
8
+        "repo": "nixpkgs",
9
+        "rev": "0c88e1f2bdb93d5999019e99cb0e61e1fe2af4c5",
10
+        "type": "github"
11
+      },
12
+      "original": {
13
+        "owner": "NixOS",
14
+        "ref": "nixos-25.11",
15
+        "repo": "nixpkgs",
16
+        "type": "github"
17
+      }
18
+    },
19
+    "root": {
20
+      "inputs": {
21
+        "nixpkgs": "nixpkgs"
22
+      }
23
+    }
24
+  },
25
+  "root": "root",
26
+  "version": 7
27
+}
deploy/runner-images/flake.nixadded
@@ -0,0 +1,93 @@
1
+{
2
+  description = "shithub Actions default runner image";
3
+
4
+  inputs = {
5
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
6
+  };
7
+
8
+  outputs = { self, nixpkgs }:
9
+    let
10
+      systems = [ "x86_64-linux" "aarch64-linux" ];
11
+      forAllSystems = nixpkgs.lib.genAttrs systems;
12
+    in
13
+    {
14
+      packages = forAllSystems (system:
15
+        let
16
+          pkgs = import nixpkgs { inherit system; };
17
+          checkoutHelper = pkgs.writeShellApplication {
18
+            name = "shithub-shallow-checkout";
19
+            runtimeInputs = [
20
+              pkgs.git
21
+              pkgs.coreutils
22
+            ];
23
+            text = ''
24
+              set -euo pipefail
25
+
26
+              if [ "$#" -ne 3 ]; then
27
+                echo "usage: shithub-shallow-checkout <repo-url> <sha> <dest>" >&2
28
+                exit 2
29
+              fi
30
+
31
+              repo_url="$1"
32
+              sha="$2"
33
+              dest="$3"
34
+
35
+              mkdir -p "$dest"
36
+              cd "$dest"
37
+              git init
38
+              git remote add origin "$repo_url"
39
+              git fetch --depth=1 origin "$sha"
40
+              git checkout --detach FETCH_HEAD
41
+            '';
42
+          };
43
+          imageRoot = pkgs.buildEnv {
44
+            name = "shithub-runner-nix-root";
45
+            paths = [
46
+              pkgs.bashInteractive
47
+              pkgs.cacert
48
+              pkgs.coreutils
49
+              pkgs.curl
50
+              pkgs.findutils
51
+              pkgs.gcc
52
+              pkgs.git
53
+              pkgs.gnugrep
54
+              pkgs.gnused
55
+              pkgs.gnutar
56
+              pkgs.gzip
57
+              pkgs.gnupg
58
+              pkgs.gnumake
59
+              pkgs.openssh
60
+              pkgs.xz
61
+              checkoutHelper
62
+            ];
63
+            pathsToLink = [ "/bin" "/etc" ];
64
+          };
65
+        in
66
+        {
67
+          runnerImage = pkgs.dockerTools.buildLayeredImage {
68
+            name = "ghcr.io/shithub/runner-nix";
69
+            tag = "1.0";
70
+            contents = [ imageRoot ];
71
+            maxLayers = 80;
72
+            config = {
73
+              Cmd = [ "${pkgs.bashInteractive}/bin/bash" ];
74
+              Env = [
75
+                "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
76
+                "GIT_SSL_CAINFO=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
77
+                "PATH=/bin:${imageRoot}/bin"
78
+              ];
79
+              WorkingDir = "/workspace";
80
+              Labels = {
81
+                "org.opencontainers.image.title" = "shithub runner-nix";
82
+                "org.opencontainers.image.description" = "Default container image for shithub Actions run steps.";
83
+                "org.opencontainers.image.source" = "https://github.com/tenseleyFlow/shithub";
84
+                "org.opencontainers.image.version" = "1.0";
85
+                "org.opencontainers.image.licenses" = "AGPL-3.0-or-later";
86
+              };
87
+            };
88
+          };
89
+
90
+          default = self.packages.${system}.runnerImage;
91
+        });
92
+    };
93
+}