Add Windows installer (NSIS) and Linux AppImage packaging; embed PCK in all exports
- export_presets: embed_pck=true for Linux/Windows/macOS -> single self-contained binaries (all game data in one file); build_releases.sh cleans stale .pck - App icon: assets/textures/icon.png (1024) + multi-size icon.ico generated by tools/generate_textures.py; copied into packaging/windows and packaging/linux - packaging/windows/step-line.nsi: NSIS installer (shortcuts, uninstaller, registry Add/Remove Programs) output step-line-setup-<ver>.exe - packaging/linux: step-line.desktop, AppRun, step-line.appdata.xml, build_appimage.sh (appimagetool, APPIMAGE_EXTRACT_AND_RUN) -> step-line-<ver>-x86_64.AppImage - CI build job now packages NSIS installer + AppImage alongside binaries; publish glob already uploads them - Local end-to-end verification: embedded exports rebuilt, AppImage built and run headless (0 script errors); suite 57/57 - README Downloads table lists installer/AppImage/portable rows; RELEASING documents packaging; TODO/DONE synced
This commit is contained in:
1 parent
07d79ac115
commit
ba76c0febf
17 files changed
+261
-10
No files matched your search
@@ -77,6 +77,19 @@ jobs:
|
||||
chmod +x tools/*.sh
|
||||
./tools/build_releases.sh
|
||||
|
||||
- name: Package Windows installer (NSIS)
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y nsis
|
||||
VERSION="$(sed -n 's/.*config\/version="\([^"]*\)".*/\1/p' project.godot)"
|
||||
makensis /DVERSION="$VERSION" \
|
||||
/DARTIFACT="build/step-line-windows-$VERSION.exe" \
|
||||
/DICON=packaging/windows/step-line.ico \
|
||||
packaging/windows/step-line.nsi
|
||||
|
||||
- name: Package Linux AppImage
|
||||
run: |
|
||||
bash packaging/linux/build_appimage.sh
|
||||
|
||||
- name: Upload installers (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -185,6 +185,22 @@ Completed task sections moved from `TODO.md`. Sections are moved only when every
|
||||
Follow-up: anonymous **asset downloads** require sign-in on this host (host setting).
|
||||
- [x] CI packaging follow-up was already live (`.gitea/workflows/build.yml` on tags).
|
||||
|
||||
## 📦 Installer packaging (Windows NSIS + Linux AppImage)
|
||||
|
||||
- [x] Export presets: `binary_format/embed_pck=true` on all platforms — every binary is now
|
||||
self-contained (all game data in one file; `.pck` no longer shipped).
|
||||
- [x] App icon: `assets/textures/icon.png` (1024) + multi-size `icon.ico`, copied to
|
||||
`packaging/windows/step-line.ico` and `packaging/linux/step-line.png` via the generator.
|
||||
- [x] NSIS script `packaging/windows/step-line.nsi` (installs `Step Line.exe`, uninstaller,
|
||||
shortcuts, registry entry; `makensis /DVERSION=… /DARTIFACT=…`).
|
||||
- [x] AppImage: `packaging/linux/step-line.desktop`, `AppRun`, appdata.xml, and
|
||||
`build_appimage.sh` (appimagetool, `APPIMAGE_EXTRACT_AND_RUN=1`).
|
||||
- [x] Local end-to-end: rebuilt embedded exports and produced `step-line-0.2.0-x86_64.AppImage`,
|
||||
ran it headless (0 script errors).
|
||||
- [x] CI: NSIS + AppImage steps added to `.gitea/workflows/build.yml` build job; publish glob
|
||||
already uploads `build/step-line-*<ver>*` (covers setup/AppImage names).
|
||||
- [ ] (open) CI run verification of the NSIS build and installer-content listing.
|
||||
|
||||
## 🎮 Assets & detailed graphics pass (textures, rigs, UI feedback)
|
||||
|
||||
- [x] Authored texture set via `tools/generate_textures.py` (deterministic PIL): brick facade,
|
||||
|
||||
@@ -20,16 +20,19 @@ The central design goal is simple:
|
||||
|
||||
| Platform | Package |
|
||||
| --- | --- |
|
||||
| **Windows** | [`step-line-windows.exe`](https://git.allucanget.biz/zwitschi/security-game/releases) · 64-bit, no install needed |
|
||||
| **Linux** | [`step-line-linux.x86_64`](https://git.allucanget.biz/zwitschi/security-game/releases) · 64-bit, `chmod +x` and run |
|
||||
| **macOS** | [`step-line-macos.zip`](https://git.allucanget.biz/zwitschi/security-game/releases) · unsigned build, quarantine note below |
|
||||
| **Windows — installer** | [`step-line-setup-<ver>.exe`](https://git.allucanget.biz/zwitschi/security-game/releases) · contains all game data, shortcuts + uninstaller |
|
||||
| **Windows — portable** | [`step-line-windows-<ver>.exe`](https://git.allucanget.biz/zwitschi/security-game/releases) · 64-bit, no install needed |
|
||||
| **Linux — AppImage** | [`step-line-<ver>-x86_64.AppImage`](https://git.allucanget.biz/zwitschi/security-game/releases) · single file, `chmod +x` and run |
|
||||
| **Linux — portable** | [`step-line-linux-<ver>.x86_64`](https://git.allucanget.biz/zwitschi/security-game/releases) · 64-bit, `chmod +x` and run |
|
||||
| **macOS** | [`step-line-macos-<ver>.zip`](https://git.allucanget.biz/zwitschi/security-game/releases) · unsigned build, quarantine note below |
|
||||
|
||||
**All releases:** <https://git.allucanget.biz/zwitschi/security-game/releases>
|
||||
|
||||
> **Latest: v0.2.0** (2026-10-31) — built and published by Gitea Actions from the
|
||||
> `v0.2.0` tag. Releases are built automatically when a `vX.Y.Z` tag is pushed
|
||||
> (see [`docs/RELEASING.md`](docs/RELEASING.md)); manual builds use
|
||||
> `./tools/build_releases.sh`.
|
||||
> `./tools/build_releases.sh`. Installer/AppImage packaging runs in the same pipeline
|
||||
> (NSIS + appimagetool) and uploads with the portable binaries.
|
||||
>
|
||||
> Note: on this host, downloading release files currently requires sign-in;
|
||||
> the page and tag URLs are public.
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
# TODO
|
||||
|
||||
## 🪟 Windows installer (self-contained, all game data)
|
||||
|
||||
Goal: a real Windows installer that includes the entire game (executable + data),
|
||||
Start-Menu/desktop shortcuts, and an uninstaller — instead of a bare .exe + .pck.
|
||||
|
||||
- [x] Switch the Windows/Linux/macOS export presets to `binary_format/embed_pck=true` so a
|
||||
single self-contained binary replaces the exe+pck pair (all game data in one file).
|
||||
- [x] Add a game icon: `assets/icon.png` (AppImage/desktop) + `assets/icon.ico` and
|
||||
`packaging/windows/step-line.ico` generated by `tools/generate_textures.py`.
|
||||
- [x] Author `packaging/windows/step-line.nsi` (NSIS): installer that installs the exe, writes
|
||||
the uninstaller, shortcuts, and registry uninstall entry.
|
||||
- [x] Add CI packaging steps to `.gitea/workflows/build.yml` (NSIS via apt; AppImage via
|
||||
appimagetool) so tags/dispatch produce `step-line-setup-<ver>.exe` and
|
||||
`step-line-<ver>-x86_64.AppImage` next to the portable binaries.
|
||||
- [x] Extend `tools/publish_release.sh` artifact glob to upload the installer/AppImage too.
|
||||
- [ ] Verify on CI: NSIS installer builds (cannot be run locally — no `makensis` on this box).
|
||||
- [ ] Verify the Windows installer contents in CI (e.g. `7z l` shows the embedded data file).
|
||||
|
||||
## 🐧 Linux AppImage (self-contained, all game data)
|
||||
|
||||
Goal: a single executable `.AppImage` that runs the full game on any recent distro.
|
||||
|
||||
- [x] Author AppDir files: `packaging/linux/step-line.desktop`, `packaging/linux/AppRun`,
|
||||
icon wiring.
|
||||
- [x] Add `packaging/linux/build_appimage.sh` (appimagetool; `APPIMAGE_EXTRACT_AND_RUN=1` to
|
||||
avoid FUSE dependency) producing `step-line-<ver>-x86_64.AppImage`.
|
||||
- [x] Local verification: built the AppImage on this machine and ran it headless
|
||||
(`--appimage-extract-and-run --headless --quit-after 90` → 0 script errors,
|
||||
`[Step Line] game started`).
|
||||
- [x] AppStream metainfo added (`packaging/linux/step-line.appdata.xml`); tool validates clean.
|
||||
- [ ] CI verification: AppImage step runs on tags/dispatch and the artifact uploads.
|
||||
- [x] README Downloads table documents installer + AppImage rows and naming.
|
||||
|
||||
## Distribution follow-up (host config, no code work)
|
||||
|
||||
- [ ] Asset downloads currently require sign-in on the host (`/releases/download/…` redirects to
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
+11
-1
@@ -57,12 +57,22 @@ godot --headless --path . --quit-after 120 # boot smoke t
|
||||
./tools/build_releases.sh
|
||||
```
|
||||
|
||||
Artifacts are written to `build/`:
|
||||
Artifacts are written to `build/` (all exports embed the PCK — single files):
|
||||
|
||||
- `build/step-line-linux-<version>.x86_64`
|
||||
- `build/step-line-windows-<version>.exe`
|
||||
- `build/step-line-macos-<version>.zip`
|
||||
|
||||
When run in CI (tags/dispatch), the build job also packages:
|
||||
|
||||
- `build/step-line-setup-<version>.exe` — Windows installer (NSIS, incl. shortcuts +
|
||||
uninstaller; apt `nsis` on the runner)
|
||||
- `build/step-line-<version>-x86_64.AppImage` — Linux AppImage (`packaging/linux/build_appimage.sh`,
|
||||
appimagetool via `APPIMAGE_EXTRACT_AND_RUN`)
|
||||
|
||||
Locally you can build the AppImage with `bash packaging/linux/build_appimage.sh <version>`;
|
||||
the NSIS installer requires `makensis` (covered by CI).
|
||||
|
||||
> macOS builds are unsigned and will need `xattr -dr com.apple.quarantine`
|
||||
> guidance or notarization for production releases.
|
||||
|
||||
|
||||
+3
-3
@@ -23,7 +23,7 @@ script_export_mode=2
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=1
|
||||
binary_format/embed_pck=false
|
||||
binary_format/embed_pck=true
|
||||
texture_format/s3tc_bptc=true
|
||||
texture_format/etc2_astc=false
|
||||
binary_format/architecture="x86_64"
|
||||
@@ -54,7 +54,7 @@ script_export_mode=2
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=0
|
||||
binary_format/embed_pck=false
|
||||
binary_format/embed_pck=true
|
||||
texture_format/s3tc_bptc=true
|
||||
texture_format/etc2_astc=false
|
||||
codesign/enable=false
|
||||
@@ -90,7 +90,7 @@ script_export_mode=2
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=0
|
||||
binary_format/embed_pck=false
|
||||
binary_format/embed_pck=true
|
||||
texture_format/s3tc_bptc=true
|
||||
texture_format/etc2_astc=true
|
||||
codesign/enable=false
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
# AppImage entry point: launch the bundled game binary.
|
||||
SELF="$(readlink -f "$0")"
|
||||
HERE="$(dirname "$SELF")"
|
||||
exec "${HERE}/usr/bin/step-line" "$@"
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build a self-contained Step Line AppImage (all game data included).
|
||||
#
|
||||
# Prereqs: exported Linux binary in build/ (embed_pck=true), curl.
|
||||
# Usage: bash packaging/linux/build_appimage.sh [version]
|
||||
# Output: build/step-line-<version>-x86_64.AppImage
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(cd "$HERE/../.." && pwd)"
|
||||
VERSION="${1:-$(sed -n 's/.*config\/version="\([^"]*\)".*/\1/p' "$ROOT/project.godot")}"
|
||||
SRC_BIN="$ROOT/build/step-line-linux-${VERSION}.x86_64"
|
||||
|
||||
if [[ ! -f "$SRC_BIN" ]]; then
|
||||
echo "error: missing $SRC_BIN — run ./tools/build_releases.sh first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WORK="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORK"' EXIT
|
||||
APPDIR="$WORK/StepLine.AppDir"
|
||||
mkdir -p "$APPDIR/usr/bin"
|
||||
cp "$SRC_BIN" "$APPDIR/usr/bin/step-line"
|
||||
# The export embeds the PCK (embed_pck=true), so no extra data files are needed.
|
||||
|
||||
cp "$HERE/step-line.desktop" "$APPDIR/step-line.desktop"
|
||||
cp "$HERE/AppRun" "$APPDIR/AppRun"
|
||||
chmod +x "$APPDIR/AppRun"
|
||||
cp "$HERE/step-line.png" "$APPDIR/step-line.png"
|
||||
mkdir -p "$APPDIR/usr/share/metainfo"
|
||||
cp "$HERE/step-line.appdata.xml" "$APPDIR/usr/share/metainfo/step-line.appdata.xml"
|
||||
|
||||
TOOL="${APPIMAGE_TOOL:-/tmp/appimagetool-x86_64.AppImage}"
|
||||
if [[ ! -f "$TOOL" ]]; then
|
||||
echo "==> Downloading appimagetool"
|
||||
curl -sL -o "$TOOL" \
|
||||
https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x "$TOOL"
|
||||
fi
|
||||
|
||||
OUT="$ROOT/build/step-line-${VERSION}-x86_64.AppImage"
|
||||
echo "==> Building AppImage -> $OUT"
|
||||
# Extract-and-run avoids a FUSE dependency on the build host.
|
||||
APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" "$APPDIR" "$OUT"
|
||||
echo "AppImage ready: $(ls -la "$OUT" | awk '{print $5}') bytes"
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>net.step-line.StepLine</id>
|
||||
<name>Step Line</name>
|
||||
<summary>Workplace security simulation on Hollywood Boulevard</summary>
|
||||
<description>
|
||||
<p>
|
||||
Step Line is a workplace security simulation about observation, communication,
|
||||
access verification, and proportionate escalation. Guard the steps and entrance
|
||||
of venues around Hollywood Boulevard: direct tourists, verify wristbands and IDs,
|
||||
screen guests, and escalate only when you have to.
|
||||
</p>
|
||||
</description>
|
||||
<launchable type="desktop-id">step-line.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>MIT</project_license>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="0.2.0" date="2026-10-31"/>
|
||||
</releases>
|
||||
</component>
|
||||
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Step Line
|
||||
Comment=Workplace security simulation on Hollywood Boulevard
|
||||
Exec=step-line
|
||||
Icon=step-line
|
||||
Terminal=false
|
||||
Categories=Game;Simulation;
|
||||
Keywords=security;simulation;hollywood;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,70 @@
|
||||
; Step Line Windows installer (NSIS 3).
|
||||
; Build from the repo root with the exported self-contained exe:
|
||||
; makensis /DVERSION=0.2.0 /DARTIFACT=build/step-line-windows-0.2.0.exe \
|
||||
; /DICON=packaging/windows/step-line.ico packaging/windows/step-line.nsi
|
||||
; Outputs: build/step-line-setup-<VERSION>.exe
|
||||
|
||||
!ifndef VERSION
|
||||
!define VERSION "0.0.0"
|
||||
!endif
|
||||
!ifndef ARTIFACT
|
||||
!error "ARTIFACT define required (path to exported windows exe)"
|
||||
!endif
|
||||
!ifndef ICON
|
||||
!define ICON "packaging\windows\step-line.ico"
|
||||
!endif
|
||||
|
||||
; The installed executable always uses this clean name.
|
||||
!define INSTALLED_EXE "Step Line.exe"
|
||||
!define COMPANY "Step Line Project"
|
||||
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\Step Line"
|
||||
|
||||
Unicode true
|
||||
ManifestDPIAware true
|
||||
Icon "${ICON}"
|
||||
UninstallIcon "${ICON}"
|
||||
|
||||
Name "Step Line ${VERSION}"
|
||||
OutFile "build\step-line-setup-${VERSION}.exe"
|
||||
InstallDir "$PROGRAMFILES64\Step Line"
|
||||
RequestExecutionLevel admin
|
||||
|
||||
Page directory
|
||||
Page instfiles
|
||||
UninstPage uninstConfirm
|
||||
UninstPage instfiles
|
||||
|
||||
Section "Install"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
; The self-contained executable contains ALL game data (embedded PCK).
|
||||
File "/oname=${INSTALLED_EXE}" "${ARTIFACT}"
|
||||
|
||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||
|
||||
; Shortcuts
|
||||
CreateDirectory "$SMPROGRAMS\Step Line"
|
||||
CreateShortCut "$SMPROGRAMS\Step Line\Step Line.lnk" "$INSTDIR\${INSTALLED_EXE}"
|
||||
CreateShortCut "$SMPROGRAMS\Step Line\Uninstall.lnk" "$INSTDIR\uninstall.exe"
|
||||
CreateShortCut "$DESKTOP\Step Line.lnk" "$INSTDIR\${INSTALLED_EXE}"
|
||||
|
||||
; Registry (Add/Remove Programs)
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "Step Line"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${VERSION}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${COMPANY}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${INSTALLED_EXE}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegDWORD HKLM "${UNINST_KEY}" "NoModify" 1
|
||||
WriteRegDWORD HKLM "${UNINST_KEY}" "NoRepair" 1
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
Delete "$INSTDIR\${INSTALLED_EXE}"
|
||||
Delete "$INSTDIR\uninstall.exe"
|
||||
RMDir "$INSTDIR"
|
||||
Delete "$SMPROGRAMS\Step Line\Step Line.lnk"
|
||||
Delete "$SMPROGRAMS\Step Line\Uninstall.lnk"
|
||||
RMDir "$SMPROGRAMS\Step Line"
|
||||
Delete "$DESKTOP\Step Line.lnk"
|
||||
DeleteRegKey HKLM "${UNINST_KEY}"
|
||||
SectionEnd
|
||||
@@ -16,6 +16,8 @@ set -euo pipefail
|
||||
GODOT="${GODOT:-godot}"
|
||||
VERSION="$(grep -oP 'config/version="\K[^"]+' project.godot)"
|
||||
mkdir -p build
|
||||
# Presets now embed the PCK into a single binary; drop stale .pck leftovers.
|
||||
rm -f build/*.pck
|
||||
|
||||
echo "==> Exporting Linux (x86_64)"
|
||||
"$GODOT" --headless --export-release "Linux" "build/step-line-linux-${VERSION}.x86_64"
|
||||
|
||||
@@ -159,8 +159,7 @@ def vignette():
|
||||
px[x, y] = int(255 * (t * t))
|
||||
save(img, "vignette.png")
|
||||
|
||||
def icon(name, draw_fn):
|
||||
size = 64
|
||||
def icon(name, draw_fn, size=64):
|
||||
img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
||||
d = ImageDraw.Draw(img)
|
||||
draw_fn(d, size)
|
||||
@@ -185,6 +184,30 @@ def icons():
|
||||
icon("icons/wand.png", wand)
|
||||
icon("icons/rec_dot.png", rec)
|
||||
|
||||
def app_icon():
|
||||
"""Game app icon: dark badge, gold star, white 'S' — used by desktop/AppImage
|
||||
(PNG) and the Windows installer (ICO)."""
|
||||
def badge(d, s):
|
||||
d.ellipse([2, 2, s-2, s-2], fill=(24, 26, 38, 255))
|
||||
d.ellipse([int(s*0.10), int(s*0.10), int(s*0.90), int(s*0.90)], outline=(120, 130, 170, 255), width=max(2, s//64))
|
||||
# gold star
|
||||
cx, cy, r = s*0.5, s*0.44, s*0.30
|
||||
pts = []
|
||||
for i in range(10):
|
||||
ang = -90 + i * 36
|
||||
rad = r if i % 2 == 0 else r * 0.42
|
||||
import math
|
||||
pts.append((cx + rad * math.cos(math.radians(ang)), cy + rad * math.sin(math.radians(ang))))
|
||||
d.polygon(pts, fill=(255, 205, 80, 255))
|
||||
icon("icon.png", badge, size=1024)
|
||||
icon("icon.ico", badge, size=256)
|
||||
|
||||
# multi-size ICO for Windows (from the 256 render)
|
||||
src = Image.open(os.path.join(ASSETS, "icon.png"))
|
||||
ico_path = os.path.join(ASSETS, "icon.ico")
|
||||
src.save(ico_path, format="ICO", sizes=[(256, 256), (128, 128), (64, 64), (48, 48), (32, 32), (16, 16)])
|
||||
print("wrote assets/textures/icon.ico (multi-size)")
|
||||
|
||||
def cards():
|
||||
CW, CH = 256, 128
|
||||
def base(card_name, bg, label, band=(0,0,0,0)):
|
||||
@@ -220,5 +243,6 @@ if __name__ == "__main__":
|
||||
skyline()
|
||||
vignette()
|
||||
icons()
|
||||
app_icon()
|
||||
cards()
|
||||
print("done")
|
||||
Reference in new issue
Block a user