mirror of
https://github.com/Heretek-Games/flatpark.git
synced 2026-10-11 20:59:53 +00:00
Upstream CI can now notify FlatPark the moment a release is published, instead of waiting for the daily cron: - release-dispatch.yml: fires on repository_dispatch (app-release), recomputes pins for that one app only, opens a focused PR on its own auto/release-<app-id> branch. Per-app concurrency; no supersede (a single-app diff is never a superset of anything). - update-check.yml stays the daily full-sweep safety net; its supersede step now also closes auto/release-* PRs once the batch covers them. - workers/release-hook/: Cloudflare Worker for hooks.flatpark.org/release. Bridges unauthenticated pings from upstream CI (flatpark/publish-action) to an authenticated repository_dispatch: validates the app against catalog.json sourceUrl and the real GitHub release, then dispatches with a repo-scoped PAT held only as a Worker secret. - gen-apps-json.sh: catalog.json entries now carry sourceUrl (public info already shown on app pages) — the Worker's lookup source, since the per-app apps/<id>.json files are stripped from the published site. - docs/publish-action-launch.md: remaining manual launch steps. The action itself lives at github.com/flatpark/publish-action (v1.0.0, v1). Co-Authored-By: Claude Fable 5 <[email protected]>
145 lines
5.4 KiB
Bash
Executable File
145 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
. "$ROOT/scripts/lib/common.sh"
|
|
load_config "$ROOT"
|
|
|
|
: "${SITE_DIR:=$ROOT/site}"
|
|
: "${DATA_DIR:=$SITE_DIR/public}"
|
|
: "${CATALOG_FILE:=$DATA_DIR/catalog.json}"
|
|
: "${APPS_DATA_DIR:=$DATA_DIR/apps}"
|
|
: "${ICONS_DIR:=$DATA_DIR/icons}"
|
|
|
|
json_escape() {
|
|
local s="$1"
|
|
s="${s//\\/\\\\}"
|
|
s="${s//\"/\\\"}"
|
|
s="${s//$'\t'/\\t}"
|
|
s="${s//$'\r'/\\r}"
|
|
s="${s//$'\n'/\\n}"
|
|
printf '%s' "$s"
|
|
}
|
|
|
|
asset_name() {
|
|
printf '%s' "$1" | tr -cs 'A-Za-z0-9._-' '-'
|
|
}
|
|
|
|
icon_url_for_app() {
|
|
local icon="$APP_ICON"
|
|
if [ -z "$icon" ] && [ -f "$APP_SRC/$APP_ID.svg" ]; then
|
|
icon="$APP_SRC/$APP_ID.svg"
|
|
fi
|
|
if [ -z "$icon" ] && [ -f "$APP_SRC/$APP_ID.png" ]; then
|
|
icon="$APP_SRC/$APP_ID.png"
|
|
fi
|
|
if [ -n "$icon" ] && [ -f "$icon" ]; then
|
|
local ext="${icon##*.}" name
|
|
name="$(asset_name "$APP_ID").$ext"
|
|
cp "$icon" "$ICONS_DIR/$name"
|
|
printf '/icons/%s' "$name"
|
|
fi
|
|
}
|
|
|
|
tags_json() {
|
|
local raw t out=""
|
|
IFS=',' read -ra raw <<< "$APP_TAGS"
|
|
for t in "${raw[@]}"; do
|
|
t="${t#"${t%%[![:space:]]*}"}"
|
|
t="${t%"${t##*[![:space:]]}"}"
|
|
[ -n "$t" ] || continue
|
|
out="$out${out:+, }\"$(json_escape "$t")\""
|
|
done
|
|
printf '[%s]' "$out"
|
|
}
|
|
|
|
requested_apps=("$@")
|
|
apps=()
|
|
while IFS= read -r app_id; do
|
|
apps+=("$app_id")
|
|
done < <("$ROOT/scripts/scan-registry.sh" --ids "${requested_apps[@]}")
|
|
[ "${#apps[@]}" -gt 0 ] || die "registry scan returned no apps"
|
|
|
|
mkdir -p "$(dirname "$CATALOG_FILE")" "$APPS_DATA_DIR" "$ICONS_DIR"
|
|
# A fresh per-app set each run so removed apps do not linger.
|
|
rm -f "$APPS_DATA_DIR"/*.json 2>/dev/null || true
|
|
|
|
remote_cmd="flatpak --user remote-add --if-not-exists $REMOTE_NAME $REPO_FILE_URL"
|
|
|
|
# --- light catalog.json (drives the index grid + client-side search) ---
|
|
{
|
|
printf '{\n'
|
|
printf ' "repo": {\n'
|
|
printf ' "title": "%s",\n' "$(json_escape "$REPO_TITLE")"
|
|
printf ' "comment": "%s",\n' "$(json_escape "$REPO_COMMENT")"
|
|
printf ' "homepage": "%s",\n' "$(json_escape "$REPO_HOMEPAGE")"
|
|
printf ' "remoteName": "%s",\n' "$(json_escape "$REMOTE_NAME")"
|
|
printf ' "remoteUrl": "%s",\n' "$(json_escape "$REPO_URL")"
|
|
printf ' "repoFileUrl": "%s",\n' "$(json_escape "$REPO_FILE_URL")"
|
|
printf ' "runtimeRemoteName": "%s",\n' "$(json_escape "$RUNTIME_REMOTE_NAME")"
|
|
printf ' "runtimeRepoUrl": "%s",\n' "$(json_escape "$RUNTIME_REPO_URL")"
|
|
printf ' "remoteCmd": "%s"\n' "$(json_escape "$remote_cmd")"
|
|
printf ' },\n'
|
|
printf ' "apps": [\n'
|
|
first=1
|
|
for app_id in "${apps[@]}"; do
|
|
load_app "$app_id"
|
|
icon="$(icon_url_for_app)"
|
|
[ "$first" = "1" ] || printf ',\n'
|
|
first=0
|
|
printf ' {\n'
|
|
printf ' "id": "%s",\n' "$(json_escape "$APP_ID")"
|
|
printf ' "name": "%s",\n' "$(json_escape "$APP_NAME")"
|
|
printf ' "summary": "%s",\n' "$(json_escape "$APP_SUMMARY")"
|
|
printf ' "category": "%s",\n' "$(json_escape "$APP_CATEGORY")"
|
|
printf ' "tags": %s,\n' "$(tags_json)"
|
|
printf ' "updateMode": "%s",\n' "$(json_escape "$UPDATE_MODE")"
|
|
# Public upstream link; the release-hook Worker uses it to verify that
|
|
# an "app X released tag Y" ping names the repo we actually track.
|
|
printf ' "sourceUrl": "%s",\n' "$(json_escape "$APP_SOURCE_URL")"
|
|
if [ -n "$icon" ]; then
|
|
printf ' "icon": "%s"\n' "$(json_escape "$icon")"
|
|
else
|
|
printf ' "icon": null\n'
|
|
fi
|
|
printf ' }'
|
|
done
|
|
printf '\n ]\n'
|
|
printf '}\n'
|
|
} > "$CATALOG_FILE"
|
|
|
|
# --- base per-app apps/<id>.json (enrichment fills the rest) ---
|
|
for app_id in "${apps[@]}"; do
|
|
load_app "$app_id"
|
|
icon="$(icon_url_for_app)"
|
|
# No --user: flatpak routes to whichever single remote the user configured
|
|
# (system or user). Forcing --user would break a system-only setup. The
|
|
# /setup page still teaches the explicit per-user vs system commands.
|
|
install_cmd="flatpak install $REMOTE_NAME $APP_ID"
|
|
packaging_url="${PACKAGING_REPO_URL%/}/tree/$PACKAGING_BRANCH/registry/$APP_ID"
|
|
{
|
|
printf '{\n'
|
|
printf ' "id": "%s",\n' "$(json_escape "$APP_ID")"
|
|
printf ' "name": "%s",\n' "$(json_escape "$APP_NAME")"
|
|
printf ' "summary": "%s",\n' "$(json_escape "$APP_SUMMARY")"
|
|
printf ' "branch": "%s",\n' "$(json_escape "$APP_BRANCH")"
|
|
printf ' "category": "%s",\n' "$(json_escape "$APP_CATEGORY")"
|
|
printf ' "tags": %s,\n' "$(tags_json)"
|
|
printf ' "updateMode": "%s",\n' "$(json_escape "$UPDATE_MODE")"
|
|
if [ -n "$icon" ]; then
|
|
printf ' "icon": "%s",\n' "$(json_escape "$icon")"
|
|
else
|
|
printf ' "icon": null,\n'
|
|
fi
|
|
printf ' "refUrl": "%s",\n' "$(json_escape "$APP_REF_URL")"
|
|
printf ' "installCmd": "%s",\n' "$(json_escape "$install_cmd")"
|
|
printf ' "remoteCmd": "%s",\n' "$(json_escape "$remote_cmd")"
|
|
printf ' "website": "%s",\n' "$(json_escape "$APP_WEBSITE")"
|
|
printf ' "sourceUrl": "%s",\n' "$(json_escape "$APP_SOURCE_URL")"
|
|
printf ' "packagingUrl": "%s",\n' "$(json_escape "$packaging_url")"
|
|
printf ' "_srcDir": "%s",\n' "$(json_escape "$APP_SRC")"
|
|
printf ' "_manifest": "%s"\n' "$(json_escape "$MANIFEST")"
|
|
printf '}\n'
|
|
} > "$APPS_DATA_DIR/$APP_ID.json"
|
|
done
|
|
|
|
log "wrote $CATALOG_FILE + ${#apps[@]} app file(s) -> $APPS_DATA_DIR"
|