diff --git a/.github/workflows/getcache b/.github/workflows/getcache
new file mode 100755
index 000000000..8621d5200
--- /dev/null
+++ b/.github/workflows/getcache
@@ -0,0 +1,7 @@
+#!/bin/bash
+mkdir -p stl
+for f in cache/*.stl; do
+	if sha1sum -c $f.sha1sum; then
+		cp $f stl
+	fi
+done
diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml
new file mode 100644
index 000000000..919c9c8ff
--- /dev/null
+++ b/.github/workflows/makefile.yml
@@ -0,0 +1,46 @@
+name: Build Models
+
+on:
+  push:
+    branches: [ "main" ]
+  pull_request:
+    branches: [ "main" ]
+  release:
+    types: [created]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+    - name: Install OpenSCAD
+      run: sudo apt-get install -y openscad
+    - uses: actions/checkout@v4
+    - name: Cache STL Files
+      id: cache-stl
+      uses: actions/cache@v4
+      with:
+        path: cache
+        key: stlcache-${{ runner.os }}-${{ github.run_id }}
+        restore-keys: |
+          stlcache-${{ runner.os }}
+    - name: read cache
+      run: .github/workflows/getcache
+    - name: build
+      run: make -j $(nproc)
+    - name: create cache
+      run: .github/workflows/mkcache
+    - name: Publish STL files
+      uses: actions/upload-artifact@v4
+      with:
+        name: stl-files
+        path: stl
+    - name: Zip STL files
+      if: github.event_name == 'release'
+      run: |
+        zip -r stl-files.zip stl
+    - name: Upload ZIP Artifact to Release
+      if: github.event_name == 'release'
+      run: |
+        upload_url="${{ github.event.release.upload_url }}"
+        upload_url="${upload_url/\{?name,label\}/?name=stl-files.zip}"
+        curl -s -X POST -H "Authorization: Bearer ${{ secrets.MY_SECRET }}" -H "Content-Type: application/octet-stream" --data-binary "@stl-files.zip" "$upload_url"
diff --git a/.github/workflows/mkcache b/.github/workflows/mkcache
new file mode 100755
index 000000000..e5ea2929f
--- /dev/null
+++ b/.github/workflows/mkcache
@@ -0,0 +1,13 @@
+#!/bin/bash
+mkdir -p cache
+for f in $(ls dep | sed -e 's,\.dep$,,'); do
+	cp stl/$f.stl cache/
+	sha1sum $(
+		cat dep/$f.dep |
+		tr '\n' '\r' |
+		sed -e 's/\\\r//g' |
+		tr '\r' '\n' |
+		sed -e 's/.*://' |
+		sed -e "s|$PWD/||g") > cache/$f.stl.sha1sum
+done
+