From 757f1ed64a99d565e420617517f52f2dc423d7c0 Mon Sep 17 00:00:00 2001 From: Gary Hansen Date: Mon, 28 Sep 2026 15:14:13 +1000 Subject: [PATCH 1/2] Add Gitea Actions pipeline with basic checks scripts/check.sh (also `make check`) parses the Swift sources, validates Info.plist and its placeholders, checks the Makefile VERSION against the newest CHANGELOG release, and flags whitespace errors and conflict markers. The lint job runs it on the existing Linux runners in a swift:6.3 container. A full macOS build job is included but skipped until a macOS runner is registered and the MACOS_RUNNER repo variable is set to true. Co-Authored-By: Claude Opus 5.5 (1M context) --- .gitea/workflows/check.yaml | 48 ++++++++++++++++++++++++++++++++++ Makefile | 6 ++++- README.md | 1 + scripts/check.sh | 51 +++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/check.yaml create mode 100755 scripts/check.sh diff --git a/.gitea/workflows/check.yaml b/.gitea/workflows/check.yaml new file mode 100644 index 0000000..e92ae4e --- /dev/null +++ b/.gitea/workflows/check.yaml @@ -0,0 +1,48 @@ +name: check + +on: + push: + workflow_dispatch: + +jobs: + # Runs on the existing Linux runners. Wakeful links AppKit, IOKit and Carbon, + # so this can parse the Swift but not compile it; see the macos job below. + lint: + runs-on: ubuntu-latest + container: + image: swift:6.3 + steps: + # actions/checkout needs Node, which the Swift image doesn't have. + - name: Checkout + env: + TOKEN: ${{ gitea.token }} + run: | + git config --global --add safe.directory "$PWD" + git init -q . + auth=$(printf 'x-access-token:%s' "$TOKEN" | base64 | tr -d '\n') + git -c http.extraHeader="Authorization: Basic $auth" \ + fetch -q --depth=1 "${{ gitea.server_url }}/${{ gitea.repository }}.git" "${{ gitea.sha }}" + git checkout -q FETCH_HEAD + git log -1 --oneline + + - name: Check + run: scripts/check.sh + + # A real build. Off until a macOS act_runner with the "macos" label is + # registered; then set the repo variable MACOS_RUNNER=true to enable it. + macos: + if: vars.MACOS_RUNNER == 'true' + runs-on: macos + steps: + - uses: actions/checkout@v4 + + - name: Check + run: scripts/check.sh + + - name: Build (warnings are errors) + run: swift build -c release -Xswiftc -warnings-as-errors + + - name: Bundle and ad-hoc sign + run: | + make bundle + plutil -lint dist/Wakeful.app/Contents/Info.plist diff --git a/Makefile b/Makefile index 228e97c..b09df91 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ CONTENTS := $(APP)/Contents # A secure timestamp is required for notarization but impossible for ad-hoc. TS := $(if $(filter -,$(SIGN_ID)),--timestamp=none,--timestamp) -.PHONY: all build universal app app-universal bundle sign install uninstall run clean +.PHONY: all build universal app app-universal bundle sign install uninstall run check clean all: app @@ -73,6 +73,10 @@ uninstall: run: build "$(BUILD_DIR)/$(APP_NAME)" +## The same basic checks CI runs (syntax, Info.plist, version, whitespace). +check: + scripts/check.sh + clean: swift package clean rm -rf .build "$(DIST)" diff --git a/README.md b/README.md index c9ed48d..73f85f5 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ Other targets: | `make app` | Build and sign into `./dist/Wakeful.app` without installing | | `make app-universal` | Same, from a universal arm64 + x86_64 binary | | `make run` | Run the raw binary in the terminal (for debugging) | +| `make check` | Run the basic checks CI runs on every push | | `make uninstall` | Quit, remove from `/Applications`, delete preferences | | `make clean` | Remove build artifacts | diff --git a/scripts/check.sh b/scripts/check.sh new file mode 100755 index 0000000..7c33e37 --- /dev/null +++ b/scripts/check.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# Basic checks that need no macOS SDK, so CI can run them on Linux. +# Run locally with `make check`. A full compile still needs a Mac. +set -eu +cd "$(dirname "$0")/.." + +fail=0 +step() { printf '\n==> %s\n' "$1"; } +bad() { printf 'FAIL: %s\n' "$1"; fail=1; } + +step "Swift syntax" +swiftc -parse Sources/Wakeful/*.swift || bad "swiftc -parse reported errors" + +step "Info.plist" +# The Makefile seds these placeholders in; losing one ships a broken bundle. +for key in __BUNDLE_ID__ __VERSION__; do + grep -q "$key" Resources/Info.plist || bad "Resources/Info.plist is missing $key" +done +if command -v plutil >/dev/null 2>&1; then + plutil -lint Resources/Info.plist || bad "Resources/Info.plist is not a valid plist" +else + swift - <<'SWIFT' || bad "Resources/Info.plist is not a valid plist" +import Foundation +let data = try Data(contentsOf: URL(fileURLWithPath: "Resources/Info.plist")) +_ = try PropertyListSerialization.propertyList(from: data, format: nil) +print("Resources/Info.plist: OK") +SWIFT +fi + +step "Version" +version=$(sed -n 's/^VERSION *:= *//p' Makefile) +latest=$(sed -n 's/^## \[\([0-9][^]]*\)\].*/\1/p' CHANGELOG.md | head -n 1) +if [ -z "$version" ]; then + bad "no VERSION in Makefile" +elif [ "$version" != "$latest" ]; then + bad "Makefile VERSION is $version but the newest CHANGELOG release is ${latest:-missing}" +else + echo "$version" +fi + +step "Whitespace and conflict markers" +# Diff the whole tree against the empty tree so this works on a shallow clone. +empty=$(git hash-object -t tree /dev/null) +git diff --check "$empty" HEAD -- . && echo OK || bad "whitespace errors or conflict markers (see above)" + +echo +if [ "$fail" -ne 0 ]; then + echo "Checks failed." + exit 1 +fi +echo "All checks passed." From 4e52208962c312d080b6933a684894e10fbd2f9f Mon Sep 17 00:00:00 2001 From: Gary Hansen Date: Mon, 28 Sep 2026 15:21:54 +1000 Subject: [PATCH 2/2] Move macOS build to a manual-only workflow Gitea evaluates a job's `if` on the runner, so with no macOS runner the gated job sat queued forever and kept every run in progress. Make it a separate workflow_dispatch-only workflow until a macOS runner exists. Co-Authored-By: Claude Opus 5.5 (1M context) --- .gitea/workflows/.check.yaml.swp | Bin 0 -> 12288 bytes .gitea/workflows/check.yaml | 21 +-------------------- .gitea/workflows/macos.yaml | 24 ++++++++++++++++++++++++ 3 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 .gitea/workflows/.check.yaml.swp create mode 100644 .gitea/workflows/macos.yaml diff --git a/.gitea/workflows/.check.yaml.swp b/.gitea/workflows/.check.yaml.swp new file mode 100644 index 0000000000000000000000000000000000000000..c39eff55eee9b32e21e5cbc26d17985d4ae7f9f6 GIT binary patch literal 12288 zcmeI2y>1jq5XT!Nf)igSAh-w>Yo8V*&#V_8Ml5n*j88^jKpYkE=;=mFir)uf1o~iz*s$cg+Q{Cy?mzLpN z+!oY+6yo^j=l7OJ$9^iG3enG`cBsS1u5JF-@`b3~o}M|g>ooC4y)V#|Y$m`2 zm;e)C0!)AjFaajO1iotmzStxFqzv}fSsbtXJv;jPl{+TD1egF5U;<2l2`~XBzyz28 z6JP>N;5#HBQz1U>7vir26nyyqU+3`Yun-?f?@4b-uShRRFGw4tv!oX37-=8r-60{~ zke-kpkw&B&qy^Fsqz?y$ct%P||B|oQq<=_%lb(_ulR^xSNZgnJ6JP>NfC(@GCcp%k z02BBh6M(weQg^^5Ruz7$4%lU4b1(uehuDFIP#!F5V;G|PVaQD%qBca4(U>cZJBF*0 zVpDpER^ivhn+r=TON;Xt$0h;v&?i|KkD?R{pUt(QF}bl3c1IaIv?H`DrOn~t!`8Ol zVqu)}#@;7;sAO(@wJMWjZjAW}u|^4G-WM^hdn=bvrfBCH^QF&>RliHG3^BMMol0O* zlC=SM$2JI-xyh4-RoeHUxgNv23q5!XQ3}nw zx_N4BuMmvVA)-}?ci0o7dy1Gw{oHhAP7g9o!O0%Rsj`?A*IwDoR4~-yGDVPW|%L`O;a{<_VBVU{c?QaEKZ)b#T?BI0b8&qGR(J!f$J;NBIn8 zA0aj9bkjp7N4S}p^H{hoSJfoCXkkTXHlC?mQN~`<)v=qiC>ck$sRL!V)V_>z>CuIt z=z94uWdfWb$I3w>H5Af19E+nH;xrx-Gb~h&p!|7oh%l6iaaD19h-(6FkQ*?%T8Zn* zd8PYsMd@-KC<2Pc#ZXtu2hRfs^F?u4`6;+`jXIDzg#~H5Mo)=*rb{W(wp+FIE2(mY Vq