docker / build-push-arm64cross (push) Successful in 10s
docker / deploy-docs (push) Successful in 31s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 26m54s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 26m56s
apple / screenshots (push) Canceled after 11m30s
windows-host / package (push) Failing after 12s
windows-host / winget-source (push) Skipped
apple / swift (push) Successful in 6m2s
ci / web (push) Successful in 1m53s
ci / docs-site (push) Successful in 1m29s
ci / rust-arm64 (push) Successful in 9m56s
android / android (push) Successful in 12m33s
ci / bench (push) Successful in 7m17s
decky / build-publish (push) Successful in 29s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 19s
arch / build-publish (push) Successful in 18m18s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 16s
deb / build-publish (push) Successful in 9m2s
ci / rust (push) Failing after 19m38s
deb / build-publish-client-arm64 (push) Successful in 7m21s
deb / build-publish-host (push) Successful in 9m43s
`winget install unom.PunktfunkHost` after adding the source, and `winget upgrade`
from then on. Windows had no update path at all before this — no self-update, no
package manager — so keeping a host current meant noticing a release and
re-running an installer by hand.
Ships the manifest trio in winget-pkgs' own format (so submitting upstream later
is a copy, not a rewrite) plus a release-time generator that substitutes only
version, URL, hash and release-notes link. Everything reviewable — the silent
switches, the agreements, the installation notes — stays in the checked-in
templates rather than buried in a generator.
Silent installs deliberately take the SAME task defaults the wizard shows: a
per-channel default is a support trap. The disclosures the wizard puts on screen
travel as manifest Agreements instead, shown before install and requiring
acceptance — VB-Audio's bundling grant wants the user to see VB-CABLE's origin
and donationware status, and a silent install shows them nothing otherwise. The
console password can only be pointed at, never printed: it is generated per
install and the notes are fixed at publish time.
Self-hosted rather than the community repo, which gates on Defender/SmartScreen
validation the self-signed installer cert would not clear today. The source is
three endpoints — /information, /manifestSearch, /packageManifests/{id}. The
reference implementation's other twenty are its admin API for mutating a
CosmosDB; a catalogue generated at release time has nothing to mutate.
It runs on unom-1 as a stock bun image with the two .mjs files bind-mounted, the
same shape as the flatpak server, so there is no image to build or pull. The
catalogue is derived from the RELEASES rather than local files: winget resolves
--version and upgrade against the version list, so a source that only knew the
newest release could neither pin an older one nor show an upgrade path from it.
That also leaves no state to drift — re-running the build reproduces it exactly.
NormalizedPackageNameAndPublisher is declared unsupported on purpose. winget
derives it client-side with its own normalization, and a near-miss silently
mis-correlates an installed host; ProductCode is exact and Inno gives us one.
28 checks drive the handler directly, and CI gates on them before anything
reaches the box — a wrong response shape does not fail loudly, it just makes
winget report "no package found".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
42 lines
2.0 KiB
YAML
42 lines
2.0 KiB
YAML
# winget REST source for the punktfunk Windows host, on unom-1 (Hetzner Cloud).
|
|
#
|
|
# Caddy on that same box terminates TLS for winget.punktfunk.unom.io and reverse_proxies to :3240,
|
|
# exactly as it already does for docs.punktfunk.unom.io -> :3220. This inner service speaks plain
|
|
# HTTP and is not published beyond the box. `winget source add` refuses anything but HTTPS with a
|
|
# publicly trusted certificate, so that edge vhost is a hard requirement, not decoration.
|
|
#
|
|
# (Note: the sibling docs/flatpak compose files still carry stale comments about a
|
|
# `home-reverse-proxy-1` and 192.168.50.50 from an earlier home-lab topology. The public hostnames
|
|
# resolve straight to the hcloud box and are served by Caddy there — no local proxy is involved.)
|
|
#
|
|
# Stock bun image + bind-mounted sources, mirroring the flatpak server's stock-caddy approach: no
|
|
# image to build, publish or pull, so a code change deploys by scp + `docker compose up -d`.
|
|
#
|
|
# ./data/data.json is NOT shipped by deploy-services.yml — windows-host.yml rsyncs it on each stable
|
|
# tag (the same split the flatpak repo uses: config deploys separately from content). server.mjs
|
|
# reloads it on mtime change, so publishing a release needs no restart here.
|
|
name: punktfunk-winget-prod
|
|
services:
|
|
winget:
|
|
image: oven/bun:1-alpine
|
|
restart: unless-stopped
|
|
command: ["bun", "run", "/app/server.mjs"]
|
|
working_dir: /app
|
|
environment:
|
|
PORT: "3240"
|
|
PF_WINGET_DATA: /app/data/data.json
|
|
ports:
|
|
- "3240:3240"
|
|
volumes:
|
|
- ./server.mjs:/app/server.mjs:ro
|
|
- ./handler.mjs:/app/handler.mjs:ro
|
|
- ./data:/app/data:ro
|
|
healthcheck:
|
|
# Fails while the catalogue is missing or unparseable, which is otherwise invisible — a broken
|
|
# source answers requests fine and just reports "no package found" to the client.
|
|
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:3240/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
interval: 60s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10s
|