Add native binary export (win/linux/mac players) to the pipeline

TIC-80's export win/linux/mac produces self-contained players with
the cart baked in; the templates are downloaded from tic80.com at
export time. The zips follow the <name>-<version>-<slug>.zip droparea
convention so the API registers them as release assets automatically.
Also switch the tic80pro image reference to the canonical registry
host.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 23:07:49 +02:00
co-authored by Claude Fable 5
parent 3416a68c1a
commit d591cff468
3 changed files with 86 additions and 12 deletions
+31 -10
View File
@@ -3,14 +3,15 @@
CI/CD templates for [TIC-80](https://tic80.com) (Lua) game projects. CI/CD templates for [TIC-80](https://tic80.com) (Lua) game projects.
- `example-makefile.make` — project Makefile: local dev targets - `example-makefile.make` — project Makefile: local dev targets
(`build`, `minify`, `watch`, `lint`, `docs`, `import_assets`, (`build`, `minify`, `binaries`, `watch`, `lint`, `docs`,
`export_assets`, `clean`, `install_precommit_hook`) plus the `import_assets`, `export_assets`, `clean`, `install_precommit_hook`)
Woodpecker pipeline targets (`ci-version`, `ci-lint`, `ci-minify`, plus the Woodpecker pipeline targets (`ci-version`, `ci-lint`,
`ci-docs`, `ci-export`, `ci-artifact`, `ci-update`). `ci-minify`, `ci-docs`, `ci-export`, `ci-binaries`, `ci-artifact`,
`ci-update`).
- `example-woodpecker.yaml` — Woodpecker pipeline: version → lint → - `example-woodpecker.yaml` — Woodpecker pipeline: version → lint →
minify → docs → export (TIC-80 Pro image) → artifact (scp to the minify → docs → export (TIC-80 Pro image) → binaries (native
droparea) → update (calls the teletypegames `/update` endpoint with players, same image) → artifact (scp to the droparea) → update
`platform=tic80`). (calls the teletypegames `/update` endpoint with `platform=tic80`).
- `example-tasks.json` — VS Code `.vscode/tasks.json` with the common - `example-tasks.json` — VS Code `.vscode/tasks.json` with the common
dev tasks: **Run TIC80** (default build task, `Cmd+Shift+B`), dev tasks: **Run TIC80** (default build task, `Cmd+Shift+B`),
**Build & Run TIC80**, **Export assets** and **Make build**. **Build & Run TIC80**, **Export assets** and **Make build**.
@@ -25,8 +26,28 @@ CI/CD templates for [TIC-80](https://tic80.com) (Lua) game projects.
3. Copy `example-tasks.json` to `.vscode/tasks.json` and replace the 3. Copy `example-tasks.json` to `.vscode/tasks.json` and replace the
cart name (`impostor.lua`) with `$(PROJECT).lua`. cart name (`impostor.lua`) with `$(PROJECT).lua`.
The pipeline uploads `$(PROJECT)-$(VERSION).lua`, `.tic`, `.html.zip` The pipeline uploads `$(PROJECT)-$(VERSION).lua`, `.tic`, `.html.zip`,
and `-docs.zip` to the droparea, then triggers `-docs.zip` and the native player zips (`-win-x64.zip`,
`/update?platform=tic80&name=$(PROJECT)&version=$(VERSION)`. `-linux-x64.zip`, `-mac-x64.zip`) to the droparea, then triggers
`/update?platform=tic80&name=$(PROJECT)&version=$(VERSION)`. The API's
`BinaryAttachment` concern picks up the `<name>-<version>-<slug>.zip`
files automatically and registers them as `win_x64` / `linux_x64` /
`mac_x64` release assets.
## Native binaries
`make binaries VERSION=x.y` runs TIC-80's `export win / linux / mac`,
which produces self-contained players with the cart baked in. Two
things to know:
- The player templates are **downloaded from tic80.com at export
time**, so the CI step needs network access (the Woodpecker steps
have it — the same way the artifact step reaches the droparea).
- All upstream players are x86-64 — the mac binary is Intel-only
(runs via Rosetta on Apple Silicon), hence the `mac-x64` slug.
Each binary is zipped with a single `$(PROJECT)-$(VERSION)-<slug>/`
root folder; the zip is created on unix so the executable bit
survives.
Detailed documentation lives on the wiki: `/development/tic80`. Detailed documentation lives on the wiki: `/development/tic80`.
+47 -1
View File
@@ -67,6 +67,41 @@ export: minify
@echo "==> Generated files:" @echo "==> Generated files:"
@ls -lh $(PROJECT)-$(VERSION).* $(PROJECT).tic $(PROJECT).html.zip 2>/dev/null || true @ls -lh $(PROJECT)-$(VERSION).* $(PROJECT).tic $(PROJECT).html.zip 2>/dev/null || true
# -----------------------------------------
# Native binaries — self-contained TIC-80 players with the cart baked in.
# The player templates are downloaded from tic80.com at export time, so
# this target needs network access. All upstream players are x86-64,
# hence the win-x64 / linux-x64 / mac-x64 slugs (the API maps
# <project>-<version>-<slug>.zip droparea files to ReleaseAsset kinds).
# -----------------------------------------
BINARY_SLUGS = win-x64 linux-x64 mac-x64
# $(1) slug, $(2) exported file, $(3) file name inside the package
# (unixos zip őrzi a végrehajtási bitet)
define f_pack_binary
PKG_DIR="$(PROJECT)-$(VERSION)-$(1)"; \
rm -rf "$$PKG_DIR" "$$PKG_DIR.zip"; \
mkdir -p "$$PKG_DIR"; \
mv "$(2)" "$$PKG_DIR/$(3)"; \
chmod +x "$$PKG_DIR/$(3)"; \
zip -r "$$PKG_DIR.zip" "$$PKG_DIR" >/dev/null; \
rm -rf "$$PKG_DIR"; \
echo "==> $$PKG_DIR.zip kesz"
endef
binaries:
@if [ -z "$(VERSION)" ]; then \
echo "ERROR: VERSION not set!"; \
exit 1; \
fi
@echo "==> Exporting native players for version $(VERSION)"
@tic80 --cli --skip --fs=. \
--cmd="load $(OUTPUT) & export win $(PROJECT)-win & export linux $(PROJECT)-linux & export mac $(PROJECT)-mac & exit"
@$(call f_pack_binary,win-x64,$(PROJECT)-win.exe,$(PROJECT).exe)
@$(call f_pack_binary,linux-x64,$(PROJECT)-linux,$(PROJECT))
@$(call f_pack_binary,mac-x64,$(PROJECT)-mac,$(PROJECT))
watch: watch:
$(MAKE) build $(MAKE) build
fswatch -o $(SRC_DIR) $(ORDER) assets | while read; do $(MAKE) build; done fswatch -o $(SRC_DIR) $(ORDER) assets | while read; do $(MAKE) build; done
@@ -167,6 +202,8 @@ export_assets:
clean: clean:
@rm -f $(PROJECT)-*.tic $(PROJECT)-*.html.zip $(PROJECT)-*-docs.zip $(PROJECT)-docs.zip $(OUTPUT) $(OUTPUT_ORIGINAL) @rm -f $(PROJECT)-*.tic $(PROJECT)-*.html.zip $(PROJECT)-*-docs.zip $(PROJECT)-docs.zip $(OUTPUT) $(OUTPUT_ORIGINAL)
@rm -f $(PROJECT)-*-win-x64.zip $(PROJECT)-*-linux-x64.zip $(PROJECT)-*-mac-x64.zip
@rm -f $(PROJECT)-win.exe $(PROJECT)-linux $(PROJECT)-mac
@echo "==> Cleaned build artifacts" @echo "==> Cleaned build artifacts"
install_precommit_hook: install_precommit_hook:
@@ -238,16 +275,25 @@ ci-export:
echo "==> Generated files:"; \ echo "==> Generated files:"; \
ls -lh $(PROJECT)-$$VERSION.* $(PROJECT).tic $(PROJECT).html.zip 2>/dev/null || true ls -lh $(PROJECT)-$$VERSION.* $(PROJECT).tic $(PROJECT).html.zip 2>/dev/null || true
ci-binaries:
@VERSION=$$(cat $(VERSION_FILE)); \
$(MAKE) binaries VERSION=$$VERSION
ci-artifact: ci-artifact:
@VERSION=$$(cat $(VERSION_FILE)); \ @VERSION=$$(cat $(VERSION_FILE)); \
echo "==> Uploading artifacts for version $$VERSION"; \ echo "==> Uploading artifacts for version $$VERSION"; \
cp $(PROJECT).lua $(PROJECT)-$$VERSION.lua; \ cp $(PROJECT).lua $(PROJECT)-$$VERSION.lua; \
BINS=""; \
for slug in $(BINARY_SLUGS); do \
[ -f "$(PROJECT)-$$VERSION-$$slug.zip" ] && BINS="$$BINS $(PROJECT)-$$VERSION-$$slug.zip"; \
done; \
SCP_TARGET="$(DROPAREA_USER)@$(DROPAREA_HOST):$(DROPAREA_TARGET_PATH)/"; \ SCP_TARGET="$(DROPAREA_USER)@$(DROPAREA_HOST):$(DROPAREA_TARGET_PATH)/"; \
sshpass -p "$(DROPAREA_SSH_PASSWORD)" scp -o StrictHostKeyChecking=no -P $(DROPAREA_PORT) \ sshpass -p "$(DROPAREA_SSH_PASSWORD)" scp -o StrictHostKeyChecking=no -P $(DROPAREA_PORT) \
$(PROJECT)-$$VERSION.lua \ $(PROJECT)-$$VERSION.lua \
$(PROJECT)-$$VERSION.tic \ $(PROJECT)-$$VERSION.tic \
$(PROJECT)-$$VERSION.html.zip \ $(PROJECT)-$$VERSION.html.zip \
$(PROJECT)-$$VERSION-docs.zip \ $(PROJECT)-$$VERSION-docs.zip \
$$BINS \
$$SCP_TARGET $$SCP_TARGET
ci-update: ci-update:
@@ -255,4 +301,4 @@ ci-update:
echo "==> Triggering update for version $$VERSION"; \ echo "==> Triggering update for version $$VERSION"; \
curl "$(UPDATE_SERVER)/update?secret=$(UPDATE_SECRET)&name=$(PROJECT)&platform=tic80&version=$$VERSION" curl "$(UPDATE_SERVER)/update?secret=$(UPDATE_SECRET)&name=$(PROJECT)&platform=tic80&version=$$VERSION"
.PHONY: all build download-minify minify export watch import_assets export_assets clean lint install_precommit_hook docs ci-version ci-lint ci-minify ci-docs ci-export ci-artifact ci-update .PHONY: all build download-minify minify export binaries watch import_assets export_assets clean lint install_precommit_hook docs ci-version ci-lint ci-minify ci-docs ci-export ci-binaries ci-artifact ci-update
+8 -1
View File
@@ -31,12 +31,19 @@ steps:
- 'make ci-docs' - 'make ci-docs'
- name: export - name: export
image: git.teletype.hu/internal/tic80pro:latest image: git.teletypegames.org/internal/tic80pro:latest
environment: environment:
XDG_RUNTIME_DIR: /tmp XDG_RUNTIME_DIR: /tmp
commands: commands:
- 'make ci-export' - 'make ci-export'
- name: binaries
image: git.teletypegames.org/internal/tic80pro:latest
environment:
XDG_RUNTIME_DIR: /tmp
commands:
- 'make ci-binaries'
- name: artifact - name: artifact
image: alpine image: alpine
environment: environment: