Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Tests every push to main and every pull request: the Go tests on Linux
# (also on a real XFS filesystem, for reflinks) and on macOS (the maker's
# Mac code), formatting, the builds for every board, and the web pages'
# scripts.
# (also on real XFS, ext4 and FAT file systems), on macOS and on Windows
# (the maker's code for each, on Windows with a virtual disk as the card),
# formatting, the builds for every board, and the web pages' scripts.
name: CI

on:
Expand Down Expand Up @@ -52,3 +52,21 @@ jobs:
- run: make test
- name: Squirrel Maker builds (app and command line, without the payload)
run: make app-bundle maker-bin VERSION=ci

windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
- name: Tests of the maker's packages
run: go test ./internal/ext4 ./internal/fatfs ./internal/maker ./internal/makerui
- name: A virtual disk as the card
env:
SQUIRREL_TEST_VHD: ${{ runner.temp }}\card.vhdx
run: go test -v -run WindowsCard ./internal/maker
- name: Squirrel Maker builds (app and command line)
run: |
go build -o squirrel-app.exe ./cmd/squirrel-app
go build -o squirrel-maker.exe ./cmd/squirrel-maker
24 changes: 17 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# A release for every version tag (v1.2.3): squirreld for each board, and
# Squirrel Maker as a Mac app and as a command line program, with the
# packages a new card installs at its first start.
# Squirrel Maker for macOS (app and command line) and Windows (both in one
# zip), with the packages a new card installs at its first start.
#
# git tag v0.16.0 && git push origin v0.16.0
name: Release
Expand Down Expand Up @@ -30,22 +30,29 @@ jobs:
- name: squirreld archives
run: make release VERSION="$VERSION"
- name: Packages for a new card
run: make payload-linux VERSION="$VERSION"
run: make payload VERSION="$VERSION"
- name: Squirrel Maker for Windows
run: make app-windows-bundle VERSION="$VERSION"
- uses: actions/upload-artifact@v7
with:
name: squirreld
path: dist/squirreld-*.tar.gz
if-no-files-found: error
- uses: actions/upload-artifact@v7
with:
name: payload-linux
name: maker-windows
path: dist/Squirrel-Maker-*-windows.zip
if-no-files-found: error
- uses: actions/upload-artifact@v7
with:
name: payload
path: |
internal/makerui/payload/files
internal/makerui/payload/files-armv6
internal/makerui/payload/armbian
if-no-files-found: error

# What needs a Mac: e2fsprogs for the ROCK 4C+ card, and the app.
# What needs a Mac: the app.
macos:
needs: linux
runs-on: macos-latest
Expand All @@ -56,13 +63,12 @@ jobs:
go-version-file: go.mod
- uses: actions/download-artifact@v8
with:
name: payload-linux
name: payload
path: internal/makerui/payload
- name: Version from the tag
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV"
- name: Squirrel Maker
run: |
make payload-mac VERSION="$VERSION"
make app-bundle maker-bin VERSION="$VERSION"
cd dist && zip -q "squirrel-maker-$VERSION-macos.zip" squirrel-maker
- uses: actions/upload-artifact@v7
Expand All @@ -87,6 +93,10 @@ jobs:
with:
name: maker
path: out
- uses: actions/download-artifact@v8
with:
name: maker-windows
path: out
- name: Checksums
run: cd out && sha256sum -- * > SHA256SUMS && cat SHA256SUMS
- name: Release
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
.DS_Store
/.claude/
/internal/makerui/payload/armbian/
/internal/makerui/payload/mac/
/internal/makerui/payload/files-armv6/
# Windows resources, made by make app-windows
*.syso
73 changes: 36 additions & 37 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,18 @@ test:
.PHONY: test-linux
test-linux:
mkdir -p dist/test
for p in fatfs preserve gadget archive driveimage nbd; do GOOS=linux go test -c -o dist/test/$$p.test ./internal/$$p; done
for p in fatfs preserve gadget archive driveimage nbd ext4; do GOOS=linux go test -c -o dist/test/$$p.test ./internal/$$p; done
docker run --rm --privileged -v "$(CURDIR):/src:ro" debian:trixie-slim sh -c '\
apt-get update -qq >/dev/null && apt-get install -y -qq xfsprogs exfatprogs >/dev/null 2>&1; \
apt-get update -qq >/dev/null && apt-get install -y -qq xfsprogs exfatprogs e2fsprogs dosfstools >/dev/null 2>&1; \
truncate -s 1G /x.img && mkfs.xfs -q /x.img && mkdir /xfs && mount -o loop /x.img /xfs && \
cd /src/internal/fatfs && /src/dist/test/fatfs.test && \
cd /src/internal/gadget && /src/dist/test/gadget.test -test.v -test.run Mounted && \
cd /src/internal/archive && TBX_TEST_DIR=/xfs /src/dist/test/archive.test -test.v && \
cd /src/internal/driveimage && /src/dist/test/driveimage.test -test.v && \
cd /src/internal/preserve && TBX_TEST_DIR=/xfs TBX_EXPECT_REFLINK=1 /src/dist/test/preserve.test -test.v && \
for i in 0 1 2 3; do [ -e /dev/nbd$$i ] || mknod /dev/nbd$$i b 43 $$((i*32)); done && \
cd /src/internal/nbd && /src/dist/test/nbd.test -test.v'
cd /src/internal/nbd && /src/dist/test/nbd.test -test.v && \
cd /src/internal/ext4 && /src/dist/test/ext4.test -test.v'

# Validates the generated cloud-init files against a real Raspberry Pi OS
# image (uncompressed .img), e.g. PIOS_IMG=~/Downloads/2026-10-06-raspios-trixie-arm64-lite.img
Expand Down Expand Up @@ -72,8 +73,6 @@ testimages:
# xfsprogs, exfatprogs and their dependencies, worked out against the
# package list of the pinned Armbian image (deploy/armbian/dpkg-status),
# the USB overlay and the unit.
# - mac/: debugfs and e2fsck, which the app uses to put files on
# Armbian's ext4 root; built from e2fsprogs for Apple silicon and Intel.
PAYLOAD := internal/makerui/payload
XFS_DEBS := xfsprogs libinih1 liburcu8t64 python3-dbus
# download fetches packages into the current directory in a container,
Expand All @@ -86,16 +85,11 @@ download = ok=; for i in 1 2 3; do rm -f ./*.deb; apt-get update -qq >/dev/null
for p in $(foreach p,$(1),$(firstword $(subst :, ,$(p)))); do \
ls "$${p}"_*.deb >/dev/null 2>&1 || { echo "$${p} missing" >&2; exit 1; }; done; ls
ARMBIAN_PKGS := network-manager dnsmasq-base xfsprogs exfatprogs rfkill
E2FS_VERSION := 1.47.4
E2FS_SHA256 := fd5bf388cbdbe006a3d3b318d983b2948382440acc85a87f1e7d108653e8db0b
E2FS := dist/e2fsprogs-$(E2FS_VERSION)

# payload is built in two parts: what needs Docker (payload-linux) and what
# needs a Mac (payload-mac). CI builds them on different machines.
.PHONY: payload payload-linux payload-mac
payload: payload-linux payload-mac

payload-linux: dist/squirreld-linux-arm64 dist/squirreld-linux-armv6
# payload needs Docker; CI builds it on Linux and the Mac app around it on
# a Mac.
.PHONY: payload
payload: dist/squirreld-linux-arm64 dist/squirreld-linux-armv6
rm -rf $(PAYLOAD)/files $(PAYLOAD)/files-armv6 $(PAYLOAD)/armbian
mkdir -p $(PAYLOAD)/files/debs $(PAYLOAD)/files-armv6/debs $(PAYLOAD)/armbian/debs
cp dist/squirreld-linux-arm64 $(PAYLOAD)/files/squirreld
Expand All @@ -118,28 +112,6 @@ payload-linux: dist/squirreld-linux-arm64 dist/squirreld-linux-armv6
apt-get install -qq -y --download-only --no-install-recommends -o Dir::Cache::archives=/tmp/a $(ARMBIAN_PKGS) >/dev/null; \
cp /tmp/a/*.deb /out/ && ls /out'

payload-mac: $(E2FS)/debugfs
rm -rf $(PAYLOAD)/mac && mkdir -p $(PAYLOAD)/mac
cp $(E2FS)/debugfs $(E2FS)/e2fsck $(PAYLOAD)/mac/

# One rule for both tools (with two targets, make -j would run it twice
# at once); e2fsck is made alongside debugfs.
$(E2FS)/debugfs:
rm -rf $(E2FS) && mkdir -p $(E2FS)
curl -sfL -o $(E2FS)/src.tar.xz https://mirrors.edge.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/v$(E2FS_VERSION)/e2fsprogs-$(E2FS_VERSION).tar.xz
echo "$(E2FS_SHA256) $(E2FS)/src.tar.xz" | shasum -a 256 -c -
tar xf $(E2FS)/src.tar.xz -C $(E2FS)
for a in arm64 x86_64; do \
mkdir -p $(E2FS)/build-$$a && cd $(E2FS)/build-$$a && \
CFLAGS="-arch $$a -O2 -mmacosx-version-min=13.0" LDFLAGS="-arch $$a -mmacosx-version-min=13.0" \
../e2fsprogs-$(E2FS_VERSION)/configure --host=$$a-apple-darwin --disable-nls --disable-fuse2fs \
--disable-defrag --disable-imager --disable-e2initrd-helper --disable-uuidd > configure.log && \
$(MAKE) -s libs > make.log && $(MAKE) -s -C debugfs debugfs >> make.log && $(MAKE) -s -C e2fsck e2fsck >> make.log && \
cd $(CURDIR) || exit 1; \
done
lipo -create $(E2FS)/build-arm64/debugfs/debugfs $(E2FS)/build-x86_64/debugfs/debugfs -output $(E2FS)/debugfs
lipo -create $(E2FS)/build-arm64/e2fsck/e2fsck $(E2FS)/build-x86_64/e2fsck/e2fsck -output $(E2FS)/e2fsck

# Squirrel Maker, the Mac app: its own window, Dock icon and menu, built
# with Wails (cgo, so Xcode's command line tools). One binary for Apple
# silicon and Intel.
Expand Down Expand Up @@ -174,8 +146,35 @@ maker-bin:
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o dist/squirrel-maker-darwin-amd64 ./cmd/squirrel-maker
lipo -create -output dist/squirrel-maker dist/squirrel-maker-darwin-arm64 dist/squirrel-maker-darwin-amd64

# Squirrel Maker for Windows (64-bit): the app (Wails, without cgo, so it
# builds anywhere) and the command line version, in one zip. Each gets a
# Windows resource (go-winres, pinned in go.mod) with the squirrel icon,
# a manifest and the version; the app's manifest asks for administrator
# rights when it starts, which writing a card needs.
WIN := dist/windows/Squirrel Maker
# The file version must be numbers: 0.16.0 from v0.16.0-rc1, 0.0.0 from dev.
WINVER = $(shell echo "$(VERSION)" | sed -E -e 's/^v?([0-9]+(\.[0-9]+){0,3}).*/\1/' -e t -e 's/.*/0.0.0/')
WINRES = go tool go-winres simply --arch amd64 --icon cmd/squirrel-app/icon.png --product-name "Squirrel Maker" \
--product-version "$(VERSION)" --file-version "$(WINVER)" --copyright "Marcus Aram, MIT license"

.PHONY: app-windows app-windows-bundle
app-windows: payload
$(MAKE) app-windows-bundle

app-windows-bundle:
rm -rf "$(WIN)" && mkdir -p "$(WIN)"
$(WINRES) --manifest gui --admin --file-description "Squirrel Maker" \
--original-filename "Squirrel Maker.exe" --out cmd/squirrel-app/rsrc
$(WINRES) --manifest cli --file-description "Squirrel Maker (command line)" \
--original-filename squirrel-maker.exe --out cmd/squirrel-maker/rsrc
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS) -H windowsgui" -o "$(WIN)/Squirrel Maker.exe" ./cmd/squirrel-app
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o "$(WIN)/squirrel-maker.exe" ./cmd/squirrel-maker
cp LICENSE THIRD_PARTY_NOTICES.md "$(WIN)/"
rm -f "dist/Squirrel-Maker-$(VERSION)-windows.zip"
cd dist/windows && zip -qr "../Squirrel-Maker-$(VERSION)-windows.zip" "Squirrel Maker"

.PHONY: clean
clean:
rm -rf dist $(PAYLOAD)/files $(PAYLOAD)/files-armv6 $(PAYLOAD)/armbian $(PAYLOAD)/mac
rm -rf dist $(PAYLOAD)/files $(PAYLOAD)/files-armv6 $(PAYLOAD)/armbian

FORCE:
Loading
Loading