{"id":21935472,"url":"https://github.com/panel-attack/panel-updater","last_synced_at":"2025-08-21T16:24:36.649Z","repository":{"id":235254675,"uuid":"790390025","full_name":"panel-attack/panel-updater","owner":"panel-attack","description":"An experimental updater for Panel Attack","archived":false,"fork":false,"pushed_at":"2024-12-19T23:58:03.000Z","size":359,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-22T13:44:10.957Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/panel-attack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-22T19:43:03.000Z","updated_at":"2025-01-07T19:18:53.000Z","dependencies_parsed_at":"2024-05-05T18:23:38.775Z","dependency_job_id":"c209d0cc-7d1f-4add-b205-c01803bb684b","html_url":"https://github.com/panel-attack/panel-updater","commit_stats":null,"previous_names":["endaris/panel-attack-updater","panel-attack/panel-updater"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/panel-attack/panel-updater","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-attack%2Fpanel-updater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-attack%2Fpanel-updater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-attack%2Fpanel-updater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-attack%2Fpanel-updater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/panel-attack","download_url":"https://codeload.github.com/panel-attack/panel-updater/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-attack%2Fpanel-updater/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271507239,"owners_count":24771823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T00:21:28.532Z","updated_at":"2025-08-21T16:24:36.588Z","avatar_url":"https://github.com/panel-attack.png","language":"Lua","readme":"~~A somewhat generic updater for love games without dependencies, mostly intended for games with an open/free license.~~  \nThe updater for the game Panel Attack. You can probably adapt it for other love games relatively easily.\nSome of the options may seem impractical, alien and overly specific for how bad of a solution they present.  \nThey were (at least partially) implemented to serve the predecessor of this tool without having to change the server side of things in the same go in order to let users migrate to the new updater at their own pace.\n\n# Configuration\n\n## releaseStreams.json\n\nConfigure `releaseStreams.json` to decide which different release streams exist, from which source they update and how they are versioned.  \nThe `default` key specifies which release stream the updater should try to use in case the currently active release stream somehow has nothing available locally nor remotely.\n\n```Json\n{\n    \"releaseStreams\":\n    [\n        {\n            \"name\":\"releaseStream1\",\n            \"versioningType\":\"semantic\",\n            \"serverEndPoint\":\n            {\n                \"type\":\"github\",\n                \"repository\":\"love2d/love\"\n            }\n        },\n        {\n            \"name\":\"releaseStream2\",\n            \"versioningType\": \"timestamp\",\n            \"serverEndPoint\":\n            {\n                \"type\": \"filesystem\",\n                \"url\": \"http://example.com/updates/\",\n                \"prefix\":\"example-\"\n            }\n        }\n    ],\n    \"default\": \"releaseStream2\"\n}\n```\n\n### name\nFor name, choose whatever so long as you avoid duplicates, these function as the unique identifier!  \n\n### versioningType\n\nFor versioningType there are currently 2 supported settings.\n\n#### semantic\nFor semantic versioning, `major.minor.patch-prereleasestring+metadata`.  \nYour semantic version must specify at least `major.minor`.  \nIf you wish to utilize prerelease and metadata, you must specify the full `major.minor.patch` before it, e.g. `1.0-alpha` is not valid but `1.0.0-alpha` is.  \n\n#### timestamp\nFor versioning in a custom datetime format suitable to be used in file names, `yyyy-MM-dd_hh-mm-ss`.\nLocally this will be converted to a timestamp using `os.time`.\n\n### serverEndPoint\n\nThis is a set of options that may differ in details depending on the selected type.\n\n#### github\n\nThe github server end point looks for versions via the github api for releases.  \nTo determine the final url a field `repository` has to be supplied in the format `githubUser/repositoryName`.  \nWhen using github as the endpoint, the name (not the tag!) of the release is used as string representation of the version.\n\n#### filesystem\n\nThis was implemented against the standard html presentation of a readable directory on a nginx webserver but may work on other websites as well.  \nThe body of the response to a GET request on the requested `url` will be matched with `'href=\"' .. prefix .. \"[^%s%.].love\"` and all matches will be interpreted as versions.  \nThe part inbetween that is getting matched by `[^%s%.]` is used as the string representation of the version.\n\n## launch.json\n\nStores the user's current starting configuration.\n\n### activeReleaseStream\n\nThis has to refer to the unique name of one of the release streams specified in releaseStreams.json.  \n\n### activeVersion\n\nSpecifies the version the user currently has selected in the string representation of that release stream's versioning type.  \nIf not present, the user uses the latest version of the release stream.  \nThe idea here is to allow users to specifically select older versions they may have installed, effectively allowing them to opt out of updates or selecting an older version.  \nIn the current iteration, downloading a new version as part of the startup always causes the new version to be set as the active version.\n\n# Usage\n\nSet the identity of the updater to the identity of the game so they share their save directory.  \nEdit `releaseStreams.json` to suit your needs.  \nIn `config.json` configure only the `activeReleaseStream` to the one you wish your players to start with as a fallback, do not configure `activeVersion`.  \nZip, rename and possibly fuse the updater for release as usual.  \nIn general it is advisable to embed a fallback version.\n\n## Switching release streams\n\nAfter determining the startup version, the updater restarts from scratch and loads up with the conf of the game.  \nBefore doing so it sets the `GAME_UPDATER` and `GAME_UPDATER_STATES`.  \nAs the restart is indeed a full restart, if you wish to make release stream switching available in your game, you need to call `GAME_UPDATER:init()` to have the updater read its configurations and installed versions. You can then use functions as defined in `updater/gameUpdater.lua` to retrieve information about remote and installed versions.  \nThe updater uses love threads so if you do anything online related, you should make sure to call `update` on the updater as otherwise it will never update with the results of the threads.\n\n## Embedding a fallback version\n\nIn case of your players not having internet access the first time they open your game, they should have a version available for offline use, even if it is outdated.  \nTo embed a version of your game, create a directory with the name of the active release stream chosen in your `config.json` at the top level.  \nInside this directory, create another directory that holds the minimum possible version for the release stream's versioning type. For semantic versioning this would be `0.0.0-norelease` or similar, for timestamp it would be `0`.\nPut your .love or .zip file inside the folder.  \nThe updater will identify this embedded version as the base version for the release stream and download the most recent version to start in its stead if it can find one on first startup. If an update is not successful, it will boot with the embedded version.  \nUsually you will want to embed a fallback version for the release stream you use as your default fallback as the embedded version is the only one that cannot be removed.\n\n## Making an informed decision on externalstorage on Android\n\nThe updater basically launching the game in itself and aiming to provide control over updates and release stream choice in the game itself means that both the updater and the game **need** to use the same save directory.  \nNormally that is the standard but on Android this can be compromised through having diverging `externalstorage` settings.  \nDue to that it is basically impossible to change your mind on this setting later on without explicitly asking your users to redownload the updater with a new setting (and that still does not migrate their data to the new save directory!).  \nRegardless of which setting you choose, the files will be relatively inaccessible for writing, however, with `externalstorage` set to `true` it is quite a bit easier for users to at least read them.\n\n# Distribution\n\n## love-build\n\nThis project's `build.lua` is a config file for use with [love-build](https://github.com/ellraiser/love-build).\n\n## Supporting unsecured http\n\nThe used [https library](https://github.com/love2d/lua-https) depends on OS specific implementations and thus extra steps have to be taken, specifically on Mac OS X, to allow requests to unsecured endpoints.  \nThe respective implementation defaults the `NSExceptionAllowsInsecureHTTPLoads` key responsible for toggling the behaviour to `false`, making requests to unsecured http servers fail with status code 0.  \nAfter packaging the project with love-build, the resulting artifact for Mac can be unzipped and the pseudo-xml `Contents/Info.plist` can be supplied with domain specific exceptions for this behaviour, e.g.:\n```Xml\n\u003ckey\u003eNSAppTransportSecurity\u003c/key\u003e\n\u003cdict\u003e\n    \u003ckey\u003eNSExceptionDomains\u003c/key\u003e\n    \u003cdict\u003e\n        \u003ckey\u003eyourdomain.com\u003c/key\u003e\n        \u003cdict\u003e\n            \u003ckey\u003eNSExceptionAllowsInsecureHTTPLoads\u003c/key\u003e\n            \u003ctrue/\u003e\n        \u003c/dict\u003e\n    \u003c/dict\u003e\n\u003c/dict\u003e\n```\nAfter rezipping, unsecured http requests against that domain will work, additional configuration options can be found in [Apple's documentation](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW44).","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpanel-attack%2Fpanel-updater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpanel-attack%2Fpanel-updater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpanel-attack%2Fpanel-updater/lists"}