Compare commits

..

No commits in common. "trunk" and "v0.1.41" have entirely different histories.

3 changed files with 26 additions and 85 deletions

View file

@ -16,17 +16,15 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
apt-get update apt-get update -qq
apt-get install -y -qq make git wget apt-get install -y -qq make git wget unzip
- name: Install Godot - name: Install Godot
run: | run: |
wget -q https://github.com/godotengine/godot/releases/download/4.4.1-stable/Godot_v4.4.1-stable_linux.x86_64.zip wget -q https://github.com/godotengine/godot/releases/download/4.4.1-stable/Godot_v4.4.1-stable_linux.x86_64.zip
# python3 instead of unzip: the runner's apt index goes stale and the unzip -q Godot_v4.4.1-stable_linux.x86_64.zip
# pinned unzip deb 404s in the security pool.
python3 -m zipfile -e Godot_v4.4.1-stable_linux.x86_64.zip godot-dir
mkdir -p "$HOME/.local/bin" mkdir -p "$HOME/.local/bin"
mv godot-dir/Godot_v4.4.1-stable_linux.x86_64 "$HOME/.local/bin/godot" mv Godot_v4.4.1-stable_linux.x86_64 "$HOME/.local/bin/godot"
chmod +x "$HOME/.local/bin/godot" chmod +x "$HOME/.local/bin/godot"
echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "$HOME/.local/bin" >> "$GITHUB_PATH"
@ -43,32 +41,21 @@ jobs:
TAG="${GITHUB_REF_NAME}" TAG="${GITHUB_REF_NAME}"
API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
# Create the release. `curl -sf` hid the reason a tag build could not # Create the release
# publish, which left devices on the previous release with no clue, curl -sf -X POST "${API}/releases" \
# so report the status code and the API answer.
HTTP=$(curl -sS -o /tmp/release.json -w "%{http_code}" -X POST "${API}/releases" \
-H "Authorization: token ${GITHUB_TOKEN}" \ -H "Authorization: token ${GITHUB_TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\"}") -d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\"}" \
if [ "${HTTP}" != "201" ] && [ "${HTTP}" != "200" ]; then -o /tmp/release.json
echo "Release creation for ${TAG} failed with HTTP ${HTTP}:"
cat /tmp/release.json
exit 1
fi
RELEASE_ID=$(python3 -c "import json; print(json.load(open('/tmp/release.json'))['id'])") RELEASE_ID=$(python3 -c "import json; print(json.load(open('/tmp/release.json'))['id'])")
# Upload assets # Upload assets
for FILE in dist/itch.zip dist/itch.zip.sha256.txt; do for FILE in dist/itch.zip dist/itch.zip.sha256.txt; do
NAME=$(basename "$FILE") NAME=$(basename "$FILE")
HTTP=$(curl -sS -o /tmp/asset.json -w "%{http_code}" -X POST \ curl -sf -X POST \
"${API}/releases/${RELEASE_ID}/assets?name=${NAME}" \ "${API}/releases/${RELEASE_ID}/assets?name=${NAME}" \
-H "Authorization: token ${GITHUB_TOKEN}" \ -H "Authorization: token ${GITHUB_TOKEN}" \
-H "Content-Type: application/octet-stream" \ -H "Content-Type: application/octet-stream" \
--data-binary "@${FILE}") --data-binary "@${FILE}"
if [ "${HTTP}" != "201" ] && [ "${HTTP}" != "200" ]; then
echo "Asset upload of ${NAME} failed with HTTP ${HTTP}:"
cat /tmp/asset.json
exit 1
fi
done done

View file

@ -83,8 +83,7 @@ func _ready() -> void:
bootstrap() bootstrap()
## Bootstraps the butler binary (downloading it when missing or outdated), then ## Bootstraps the butler binary if it isn't present, then spawns butlerd.
## spawns butlerd.
func bootstrap() -> void: func bootstrap() -> void:
var butler_dir_global := ProjectSettings.globalize_path(butler_dir) var butler_dir_global := ProjectSettings.globalize_path(butler_dir)
_migrate_butler(butler_dir_global) _migrate_butler(butler_dir_global)
@ -97,12 +96,6 @@ func bootstrap() -> void:
bootstrap_finished.emit() bootstrap_finished.emit()
return return
logger.info("Successfully installed butler") logger.info("Successfully installed butler")
elif await _butler_is_outdated(butler_bin):
logger.info("Updating the butler binary to " + str(await _fetch_latest_butler_version()) + ".")
var success := await _install_butler()
if not success:
# Not fatal: the installed butler still works, it is just behind.
logger.warn("Unable to update butler, keeping the installed one.")
var dbpath := "/".join([butler_dir_global, "butler.db"]) var dbpath := "/".join([butler_dir_global, "butler.db"])
var args := [ var args := [
@ -146,8 +139,9 @@ func _migrate_butler(dest_dir: String) -> void:
logger.info("Migrated butler from " + old_dir + " to " + dest_dir) logger.info("Migrated butler from " + old_dir + " to " + dest_dir)
## broth's slug for the platform we are running on, e.g. "linux-amd64". ## Downloads a butler binary for this platform from itch's broth distribution
func _butler_platform_slug() -> String: ## channel (the same one the official itch.io app uses to self-update).
func _install_butler() -> bool:
var goos := "linux" var goos := "linux"
var goarch := "amd64" var goarch := "amd64"
if OS.get_name() == "Windows": if OS.get_name() == "Windows":
@ -161,13 +155,10 @@ func _butler_platform_slug() -> String:
var arch: String = Engine.get_architecture_name() var arch: String = Engine.get_architecture_name()
if "arm64" in arch or "aarch64" in arch: if "arm64" in arch or "aarch64" in arch:
goarch = "arm64" goarch = "arm64"
return goos + "-" + goarch
var platform_slug := goos + "-" + goarch
var latest_url := "/".join([broth_base, platform_slug, "LATEST"])
## Asks itch's broth channel which butler version is current. Returns "" when
## the channel can't be reached, so callers can tell "unknown" from "current".
func _fetch_latest_butler_version() -> String:
var latest_url := "/".join([broth_base, _butler_platform_slug(), "LATEST"])
var http := HTTPRequest.new() var http := HTTPRequest.new()
add_child.call_deferred(http) add_child.call_deferred(http)
await http.ready await http.ready
@ -175,65 +166,28 @@ func _fetch_latest_butler_version() -> String:
logger.error("Error fetching latest butler version: " + latest_url) logger.error("Error fetching latest butler version: " + latest_url)
remove_child(http) remove_child(http)
http.queue_free() http.queue_free()
return "" return false
var args: Array = await http.request_completed var args: Array = await http.request_completed
var result: int = args[0] var result: int = args[0]
var response_code: int = args[1] var response_code: int = args[1]
var body: PackedByteArray = args[3] var body: PackedByteArray = args[3]
if result != HTTPRequest.RESULT_SUCCESS or response_code != 200:
logger.error("Unable to determine latest butler version for " + platform_slug)
remove_child(http) remove_child(http)
http.queue_free() http.queue_free()
if result != HTTPRequest.RESULT_SUCCESS or response_code != 200:
logger.error("Unable to determine the latest butler version")
return ""
return body.get_string_from_utf8().strip_edges()
## Reads the version of an installed butler binary, e.g. "15.30.0" out of
## "v15.30.0, built on Jul 27 2026". Returns "" when the binary can't be run.
func _butler_installed_version(butler_bin: String) -> String:
var out := []
if OS.execute(butler_bin, ["version"], out) != OK or out.is_empty():
return ""
var reported: String = (out[0] as String).strip_edges().get_slice(",", 0)
return reported.trim_prefix("v").strip_edges()
## True when the installed butler is behind broth's current version. The
## binary used to be downloaded only when missing, so it silently rotted for
## months and missed fixes. Unknown version (channel unreachable, binary not
## runnable) counts as up to date: never replace a working butler on a guess.
func _butler_is_outdated(butler_bin: String) -> bool:
var latest := await _fetch_latest_butler_version()
if latest == "":
return false return false
var installed := _butler_installed_version(butler_bin) var version := body.get_string_from_utf8().strip_edges()
if installed == "" or installed == latest:
return false
logger.info("butler " + installed + " is behind " + latest + ". Updating it.")
return true
## Downloads a butler binary for this platform from itch's broth distribution
## channel (the same one the official itch.io app uses to self-update).
func _install_butler() -> bool:
var platform_slug := _butler_platform_slug()
var version := await _fetch_latest_butler_version()
if version == "":
return false
var http := HTTPRequest.new()
add_child.call_deferred(http)
await http.ready
var archive_url := "/".join([broth_base, platform_slug, version, "archive", "default"]) var archive_url := "/".join([broth_base, platform_slug, version, "archive", "default"])
if http.request(archive_url) != OK: if http.request(archive_url) != OK:
logger.error("Error downloading butler: " + archive_url) logger.error("Error downloading butler: " + archive_url)
remove_child(http) remove_child(http)
http.queue_free() http.queue_free()
return false return false
var args: Array = await http.request_completed args = await http.request_completed
var result: int = args[0] result = args[0]
var response_code: int = args[1] response_code = args[1]
var body: PackedByteArray = args[3] body = args[3]
remove_child(http) remove_child(http)
http.queue_free() http.queue_free()
if result != HTTPRequest.RESULT_SUCCESS or response_code != 200: if result != HTTPRequest.RESULT_SUCCESS or response_code != 200:

View file

@ -1,7 +1,7 @@
{ {
"plugin.id": "itch", "plugin.id": "itch",
"plugin.name": "itch.io", "plugin.name": "itch.io",
"plugin.version": "0.1.43", "plugin.version": "0.1.41",
"plugin.min-api-version": "1.1.0", "plugin.min-api-version": "1.1.0",
"plugin.link": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin", "plugin.link": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin",
"plugin.source": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin", "plugin.source": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin",