mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-10-18 14:09:24 +02:00
Compare commits
4 Commits
9e5405fadc
...
f12cfa9b78
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f12cfa9b78 | ||
|
|
afbab942a6 | ||
|
|
0cb360d04a | ||
|
|
7cd844ac9f |
@@ -29,8 +29,8 @@ Triage first, then one of two paths:
|
||||
resolve bot comments.
|
||||
- **Full loop** — performance/RAM/CPU work, diagnosis, anything changing a shipped default,
|
||||
ladder levels 4-6, or an explicit Codex-check request: scope → measure → plan → Codex reviews
|
||||
the plan → implement → simplify → Codex reviews the code → PR → resolve comments → verify in
|
||||
production → report.
|
||||
the plan → implement → simplify → Codex reviews the code → **simplify again** → PR → resolve
|
||||
comments → verify in production → report.
|
||||
|
||||
Escalate mid-flight if a light task grows — touches a default, needs a new script or service, or
|
||||
reveals a deeper problem.
|
||||
@@ -42,7 +42,10 @@ where every add-on solves a problem the same way is worth more than a locally ni
|
||||
design. Prefer reusing or extending over adding a parallel implementation, and when you must add
|
||||
something new, spell it the way the rest of the repo spells it (naming, option names, script
|
||||
numbering, file layout). Complexity is bought only by a **measurement** showing a concrete,
|
||||
user-visible cost on a real host — never by reasoning about hypothetical performance.
|
||||
user-visible cost on a real host — never by reasoning about hypothetical performance, and never by
|
||||
reasoning about a hypothetical *host* either. A defensive branch is complexity like any other: name
|
||||
the input that reaches it and the image or host where that happens, or delete it and let the case
|
||||
fail visibly instead.
|
||||
|
||||
**Repo layout.** `alexbelgium/hassio-addons`; each add-on is a top-level directory. This skill is
|
||||
checked in at `.claude/skills/hassio-addon-workflow/` (canonical copy). Set the skill root once,
|
||||
@@ -113,6 +116,10 @@ Attack your own plan before implementing:
|
||||
- What is the **blast radius** if the assumption underneath it is wrong?
|
||||
- What am I **inferring** that I could instead **detect at runtime** or **record explicitly**?
|
||||
Highest-yield question here — see `references/evidence.md`'s failure-mode section.
|
||||
- For every branch that exists **only to survive something going wrong**: name the image or host
|
||||
where that input actually arrives, and go and look. Naming is the bar, not reproducing it here —
|
||||
`references/simplify.md` works the `/dev/shm` guard and the `s6-dumpenv` fallback through that
|
||||
distinction.
|
||||
|
||||
Full loop only, before writing code: get Codex's independent read on the plan. Spawn a subagent
|
||||
whose prompt includes the path `references/codex-review.md` and tells it to follow that file's
|
||||
@@ -140,11 +147,22 @@ justify the divergence in the PR body — but never at the cost of an isolation
|
||||
numbered script, not an edit. Case studies of what happens when this check is skipped:
|
||||
`references/simplify.md`.
|
||||
|
||||
## 6. Codex attacks the code (full loop only)
|
||||
## 6. Codex attacks the code, then simplify what the review added (full loop only)
|
||||
|
||||
Same delegated invocation, pointed at `git diff origin/master...HEAD` plus your reasoning per
|
||||
hunk. Details in `references/codex-review.md`.
|
||||
|
||||
Then run step 5's checks again over the hunks the review changed. Adversarial review only ever
|
||||
argues *for* another branch — that is its job — so accepting objections ratchets the diff upward,
|
||||
and nothing else in the loop walks it back down. For each accepted objection: is the case it
|
||||
defends one you have now demonstrated, or one you have merely been told about? Taking a
|
||||
correctness objection often deletes the code that made it necessary, and a fix that collapses back
|
||||
to fewer lines than you started the review with is the normal outcome, not a suspicious one.
|
||||
|
||||
These edits land after step 4's checks already ran, so re-run them: `scripts/validate.sh <addon>
|
||||
--vs-master` plus the behavioural tests, over the final diff. Deleting a branch is exactly the
|
||||
kind of edit that leaves a stray `fi` behind.
|
||||
|
||||
## 7. Open the PR
|
||||
|
||||
CI gates on a PR: **`CHANGELOG.md` updated** (hard fail), the **HA add-on linter**
|
||||
@@ -172,7 +190,12 @@ work" — either it was exercised, or say plainly it wasn't.
|
||||
|
||||
Light path: verification is `validate.sh` plus CI; anything beyond that is Assumed. Full loop: CI
|
||||
passing proves the build works, not that the change does anything — re-run the measurement that
|
||||
motivated the work once the rebuilt add-on is running. Real "merged and inert" examples, and what
|
||||
motivated the work once the rebuilt add-on is running. After merge, `git fetch origin master`
|
||||
(the tracking ref is stale otherwise), then confirm the *changes* survived — `git diff
|
||||
origin/master -- <the paths you touched>` comes back empty. Ancestry is not the check: a revert
|
||||
leaves your commit in history and undoes its tree, so `--contains` reports success either way. The
|
||||
builder's revert-on-failure job can revert a merge for reasons unrelated to your diff (see
|
||||
`references/traps.md#ci-and-review-bots`). Real "merged and inert" examples, and what
|
||||
to do when a fix can't be self-verified: `references/evidence.md`.
|
||||
|
||||
## 10. Calibrate and report
|
||||
@@ -191,5 +214,9 @@ Risk + rollback — the riskiest hunk and how to revert it alone
|
||||
Lead with anything that did not work — a merged PR that achieved nothing is the single most
|
||||
important sentence in the report. Give confidence per claim, not one blanket number.
|
||||
|
||||
**Feed the skill.** When a shipped fix needed a follow-up PR, or a reviewer caught something this
|
||||
skill should have, add the distilled lesson to the matching `references/` file in that follow-up
|
||||
PR — one entry, with the PR numbers. That loop is what keeps this file short and the traps real.
|
||||
|
||||
Scripts are meant to be **run, not read** — each is cited at its point of use above; read one
|
||||
only if its output surprises you.
|
||||
|
||||
@@ -39,3 +39,10 @@ codex exec --model gpt-5.6-sol --sandbox read-only --skip-git-repo-check \
|
||||
**Codex agrees with confident premises.** It has confirmed a wrong conclusion stated too
|
||||
confidently, and separately caught a genuine methodology error in the same review. Treat its
|
||||
confirmations with the same scepticism as its objections — especially about the build.
|
||||
|
||||
**Its objections ratchet complexity upward.** An adversarial reviewer is asked to find what could
|
||||
go wrong, so its output is a list of arguments for more code; it is never asked whether the branch
|
||||
it wants is reachable. Separate "this is wrong" from "this is undefended" before you write
|
||||
anything: the first is a bug and you fix it, the second is a claim about some host, and it needs
|
||||
the same demonstration you would demand of a measurement. That is what step 6's second simplify
|
||||
pass is for.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Simplify — case studies
|
||||
|
||||
Evidence for why the mechanism ladder in SKILL.md step 3 exists, and why levels 4-6 need a reason
|
||||
that survives being said out loud. In all three cases the simpler option existed and was skipped.
|
||||
that survives being said out loud. In each case the simpler option existed and was skipped.
|
||||
Being able to build the complicated thing is not a reason to.
|
||||
|
||||
- A rejected PR spent a **388-line TCP proxy plus a 142-line monkeypatch of a private upstream
|
||||
@@ -13,6 +13,22 @@ Being able to build the complicated thing is not a reason to.
|
||||
- A resolution cap shipped as a **new init script writing an s6 envdir** — the wrong mechanism
|
||||
entirely (ladder level 4). Renaming the option to the env var the service already reads
|
||||
(level 1) would have worked, and the new script did not.
|
||||
- A calibre-web trusted-ips fix injected the add-on's **per-boot IP**, which forced a
|
||||
rewrite-every-boot design that erased user entries; preserving them then needed merge logic
|
||||
plus a state file recording what was injected (+34 lines, PR #3009 — closed unmerged). Asking
|
||||
"is there a constant that makes the rewrite unnecessary?" gave the shipped fix: trust the
|
||||
static supervisor range `172.30.32.0/23`, one idempotent statement, **net −6 lines**
|
||||
(PR #3010). Complexity spent working around a changing value is a sign to hunt for the
|
||||
constant instead.
|
||||
- A `.templates/ha_entrypoint.sh` fix went to review at 25 lines of code and merged at 10. Two
|
||||
sources of the excess, and neither was caught by the loop: a **pure-bash fallback** written at
|
||||
implement time for images shipping `with-contenv` but not `s6-dumpenv` — reasoned from the two
|
||||
binaries living in different s6 packages, never demonstrated on any real image, and the case it
|
||||
defended would have degraded to the pre-fix behaviour anyway — and a **helper function plus a
|
||||
second reset** that existed only to serve that fallback. Deleting the fallback deleted all of
|
||||
it. The rest of the review's objections were correct and cost two tokens on an existing line.
|
||||
It took the maintainer asking "is this the simplest way possible?" to run the pass that step 6
|
||||
now requires.
|
||||
|
||||
## Checks worth running against your own diff
|
||||
|
||||
@@ -25,6 +41,17 @@ Being able to build the complicated thing is not a reason to.
|
||||
A removal that depends on a host default still needs the same verification as an addition.
|
||||
- **Is the fix bigger than the thing it fixes?** That is a smell, not a rule — but it usually
|
||||
means the problem was framed one level too deep.
|
||||
- **For each defensive branch: what input reaches it, on which image or host?** Go and check,
|
||||
the way you would check a measurement. The bar is being able to **name** the case, not to
|
||||
reproduce it here: Docker's 64 MB `/dev/shm` default is documented behaviour that HA does not
|
||||
override, so the bullet above keeps that guard even though this host measured 7.7 GB. Nobody
|
||||
could name a single image shipping `with-contenv` without `s6-dumpenv`, so that fallback went.
|
||||
If you cannot name the case, delete the branch — the situation then fails the way it already
|
||||
fails today, visibly, instead of through a second path that is never exercised and silently
|
||||
rots as the base images move. Weigh the cost too: a one-flag guard against a crash you cannot
|
||||
rule out is cheap, a second code path that degrades to the pre-fix behaviour anyway is not.
|
||||
Write down in the PR body what you cut and why, so the next person does not re-add it from the
|
||||
same reasoning.
|
||||
- **How does this fail in three years**, when the base image, Electron, or upstream has moved?
|
||||
Code that reads a documented knob keeps working. Code that reaches into private internals
|
||||
does not.
|
||||
|
||||
@@ -11,6 +11,7 @@ workflows and lint rules — that is not repeated here.
|
||||
- [Environment and workspace](#environment-and-workspace)
|
||||
- [Measurement](#measurement)
|
||||
- [Passing values into base-image services](#passing-values-into-base-image-services)
|
||||
- [Writing into an app's own config](#writing-into-an-apps-own-config)
|
||||
- [Shell and bashio](#shell-and-bashio)
|
||||
- [Dockerfile and architecture](#dockerfile-and-architecture)
|
||||
- [Versioning](#versioning)
|
||||
@@ -116,6 +117,26 @@ place for filesystem and permission setup.
|
||||
the openbox autostart. (ANGLE's OpenGL backend, for instance, fails with "Could not open the
|
||||
default X display".)
|
||||
|
||||
## Writing into an app's own config
|
||||
|
||||
**A field your cont-init script writes may also be user-editable in the app's UI.** An
|
||||
unconditional `UPDATE`/overwrite on every boot silently erases whatever the user added there,
|
||||
and containers are recreated on restart so it re-erases forever (calibre-web
|
||||
`config_reverse_proxy_trusted_ips`, #3004 — flagged by two review bots, fixed in #3010).
|
||||
Prepend/merge with an idempotence guard instead of assigning.
|
||||
|
||||
**Prefer values that are constant across boots.** The add-on's own IP changes every restart,
|
||||
so injecting it forces a rewrite-every-boot design plus stale-entry cleanup (a stale trusted IP
|
||||
can be handed to a *different* add-on later). Trusting the whole supervisor range
|
||||
`172.30.32.0/23` is constant, written once. For dual-stack listeners the IPv4 form never
|
||||
matches IPv4-mapped addresses — also list the mapped form (`::ffff:172.30.32.0/119`).
|
||||
|
||||
Constant is not free when the value gates **authentication**: trusting the whole range means any
|
||||
add-on on the supervisor network can send the auth header and impersonate a user. #3010 shipped
|
||||
that as an explicit, stated trade-off with the maintainer's sign-off. State the blast radius in
|
||||
the PR body and get the maintainer's call before widening trust — never present it as a neutral
|
||||
simplification.
|
||||
|
||||
## Shell and bashio
|
||||
|
||||
**`bashio::config` for lists**: `while read ... < <(bashio::config ...)` silently yields an empty
|
||||
@@ -195,6 +216,17 @@ All three hard gates below are matrixed over `check-addon-changes.outputs.change
|
||||
- **Version bump** — no workflow checks it. It is repo convention, and required for Supervisor to
|
||||
offer the rebuild, but it will not fail CI.
|
||||
|
||||
**"Merged" is not "on master".** The push builder's revert-on-failure job reverts the merge
|
||||
commit when its prebuild step fails — including failures unrelated to your diff. A seerr fix
|
||||
merged at 05:15 and was reverted one minute later because `EndBug/add-and-commit`'s floating
|
||||
`v11` tag had moved to a broken release (#2993, reapplied verbatim in #2997). After merge,
|
||||
`git fetch origin master` first — the remote-tracking ref is stale otherwise and would "confirm"
|
||||
against pre-merge state — then check that `git diff origin/master -- <the paths you touched>` is
|
||||
empty before declaring done. Scope it to your paths: master moves under you, so whole-tree
|
||||
equality fails on unrelated commits. Ancestry is not the check either — this repo squash-merges,
|
||||
so a merged PR head is never an ancestor of `master` (verified on #3010, whose fix is live), and
|
||||
a revert leaves the original commit an ancestor anyway.
|
||||
|
||||
**CI rewrites your shell scripts.** `lint.yml` runs `shfmt -w -i 4 -ci -bn -sr` over every `*.sh`
|
||||
and `run`, plus a `chmod +x` pass, on schedule. Repo-wide reformatting commits land on master
|
||||
without your involvement — another reason a shared checkout goes stale mid-task.
|
||||
|
||||
@@ -168,6 +168,59 @@ if [ -z "$shebang" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#####################################
|
||||
# Seed the s6 container environment #
|
||||
#####################################
|
||||
|
||||
# s6-overlay's stage 1 dumps the container's environment into /run/s6/container_environment, and
|
||||
# `with-contenv` reads it back (emptyenv -p; s6-envdir). Add-ons that override the base image's
|
||||
# ENTRYPOINT ["/init"] with ENTRYPOINT ["/usr/bin/env"] plus CMD ["/ha_entrypoint.sh"] never run
|
||||
# stage 1, so nothing creates that directory and every #!/usr/bin/with-contenv script outside the
|
||||
# three globs whose shebang is rewritten below either exits non-zero before its first line
|
||||
# (directory missing: s6-envdir errors) or runs against whatever a cont-init script happened to
|
||||
# leave there -- measured at 16 variables instead of 110, SUPERVISOR_TOKEN among the missing.
|
||||
# Neither says anything, so all that surfaces is what the caller makes of it: a HEALTHCHECK
|
||||
# reporting "unhealthy", a cron job doing nothing. So dump the environment here instead.
|
||||
#
|
||||
# Deliberately after the shebang probe above, not next to the other PID 1 setup: the probe's first
|
||||
# candidate is "/command/with-contenv bashio" and it fails today in exactly these add-ons, so the
|
||||
# probe falls through to "/usr/bin/env bashio". Seeding earlier would make that candidate start
|
||||
# succeeding and flip the shebang of every cont-init and service script here, so scripts launched
|
||||
# directly would lose what an earlier sourced script exported -- a far larger change than this.
|
||||
#
|
||||
# It does switch on two dormant writes: 00-global_var.sh and 01-config_yaml.sh push their values
|
||||
# into the envdir, but only `if [ -d ]`. That is what those lines are for, and it means out-of-glob
|
||||
# scripts now see the user's configured options too.
|
||||
|
||||
S6_CONTAINER_ENV="/run/s6/container_environment"
|
||||
|
||||
# Only when this script is PID 1 -- under /init it is the stage-2 hook and stage 1 has already
|
||||
# written the directory -- and only where with-contenv exists to care.
|
||||
if $PID1 && { [ -x /command/with-contenv ] || [ -x /usr/bin/with-contenv ]; }; then
|
||||
# Filled in a sibling and renamed into place, never written to live. A half-populated envdir is
|
||||
# worse than an absent one: s6-envdir accepts it, so a with-contenv script starts and runs
|
||||
# against an environment quietly missing SUPERVISOR_TOKEN, where an absent one stops it at its
|
||||
# shebang. rename(2) means a concurrent reader -- a HEALTHCHECK can run alongside PID 1 -- sees
|
||||
# the directory either absent or complete, never mid-dump.
|
||||
#
|
||||
# Cleared rather than written over: /run is not a tmpfs here, so an image layer can persist
|
||||
# entries, and writing name by name would merge into them and leave variables PID 1 does not
|
||||
# have, a stale SUPERVISOR_TOKEN among them. A failed rm has to abort the chain, because mkdir -p
|
||||
# accepts a surviving symlink-to-directory and would let the dump follow it. rm does not traverse
|
||||
# a symlink, but it would empty anything bind-mounted at this exact path -- not a configuration
|
||||
# any add-on uses, and not one s6 would tolerate either.
|
||||
if rm -rf "$S6_CONTAINER_ENV" "$S6_CONTAINER_ENV.tmp" && mkdir -p "$S6_CONTAINER_ENV.tmp" &&
|
||||
s6-dumpenv -- "$S6_CONTAINER_ENV.tmp" && mv "$S6_CONTAINER_ENV.tmp" "$S6_CONTAINER_ENV"; then
|
||||
echo "Populated $S6_CONTAINER_ENV for with-contenv"
|
||||
else
|
||||
# Leaves the directory absent, which is exactly how this fails today -- so the failure mode is
|
||||
# unchanged, not newly degraded. Never fatal, a read-only /run must still let the add-on boot,
|
||||
# but never silent either, since the shebang failure it leaves behind says nothing on its own.
|
||||
rm -rf "$S6_CONTAINER_ENV" "$S6_CONTAINER_ENV.tmp" 2>/dev/null || true
|
||||
echo -e "\e[38;5;214m$(date) WARNING: could not populate $S6_CONTAINER_ENV; scripts with a with-contenv shebang will fail at their shebang, as they did before this was attempted\e[0m"
|
||||
fi
|
||||
fi
|
||||
|
||||
####################################
|
||||
# Bashio library for source fallback
|
||||
####################################
|
||||
|
||||
@@ -427,7 +427,7 @@ If you want to do add the repository manually, please follow the procedure highl
|
||||
![aarch64][aarch64-badge]
|
||||
![amd64][amd64-badge]
|
||||
|
||||
✓ [Free Games Claimer](free_games_claimer/) : Automatically claims free games from Epic Games Store, Amazon Prime Gaming, GOG, Steam, and optional GamerPower-supported stores
|
||||
✓ [Free Games Claimer](free_games_claimer/) : Claims free games from Epic, Prime, GOG, Steam, Ubisoft and more
|
||||
|
||||
  
|
||||

|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
## 2.1.0 (2026-08-24)
|
||||
|
||||
- Updated the pinned upstream from Free Games Claimer Remaster 1.1 to 1.6,
|
||||
which adds the Ubisoft giveaway, Fab, AliExpress and Epic mobile stores,
|
||||
fixed daily scheduler times, the `VNC_URL` notification link override, and a
|
||||
fix for the `--accept-lang` flag that made every store's browser detectable
|
||||
as automated.
|
||||
- Mirrored upstream's Chromium hardening: `xdg-open` is neutralised and an
|
||||
`AutoLaunchProtocolsFromOrigins` policy is installed, so app-scheme links
|
||||
cannot open a blocking dialog in the VNC session.
|
||||
- Disabled upstream's release-update notification by default. It tells the user
|
||||
to run `docker compose pull`, while the add-on is updated through the Home
|
||||
Assistant add-on store. Set `NOTIFY_UPDATES=true` in `config.env` to receive
|
||||
it anyway.
|
||||
- Reworded the add-on description so the store list reads as partial rather
|
||||
than exhaustive; the full list is in the README.
|
||||
- The default store selection is unchanged: existing installations keep
|
||||
claiming from Epic, Prime Gaming and GOG until `STORES` is edited.
|
||||
- Replaced the pinned upstream commit with `ARG BUILD_UPSTREAM`, which names an
|
||||
upstream release tag, and re-enabled the repository updater for this add-on.
|
||||
Upstream releases are now picked up automatically instead of requiring a
|
||||
manual commit pin. Upstream's development tags are excluded: `lastversion`
|
||||
reports the `v1.7d` development tag as release `1.7`, for which no source
|
||||
archive exists, so an unfiltered update would have broken the build.
|
||||
|
||||
## 2.0.1 (2026-07-17)
|
||||
|
||||
- Aligned the pull-request build context with the production builder by copying
|
||||
|
||||
@@ -17,7 +17,7 @@ ARG BUILD_REF
|
||||
ARG BUILD_REPOSITORY
|
||||
ARG BUILD_VERSION
|
||||
ARG UPSTREAM_REPOSITORY="P-Adamiec/Free-Games-Claimer-Remaster"
|
||||
ARG UPSTREAM_REF="cca4992354215cef8807b748575af797606627f4"
|
||||
ARG BUILD_UPSTREAM="1.6"
|
||||
|
||||
ENV S6_CMD_WAIT_FOR_SERVICES="1" \
|
||||
S6_CMD_WAIT_FOR_SERVICES_MAXTIME="0" \
|
||||
@@ -27,10 +27,7 @@ ENV S6_CMD_WAIT_FOR_SERVICES="1" \
|
||||
WIDTH="1280" \
|
||||
HEIGHT="720" \
|
||||
DEPTH="24" \
|
||||
SHOW="1" \
|
||||
COMMIT="${UPSTREAM_REF}" \
|
||||
BRANCH="main" \
|
||||
NOW="${BUILD_DATE}"
|
||||
SHOW="1"
|
||||
|
||||
# Install the dependencies used by Free Games Claimer Remaster. The upstream
|
||||
# Dockerfile supports both amd64 (Google Chrome) and arm64 (Chromium), so the
|
||||
@@ -87,6 +84,11 @@ RUN apt-get update \
|
||||
else \
|
||||
apt-get install -y --no-install-recommends chromium; \
|
||||
fi \
|
||||
&& printf '#!/bin/sh\nexit 0\n' > /usr/bin/xdg-open \
|
||||
&& chmod +x /usr/bin/xdg-open \
|
||||
&& mkdir -p /etc/opt/chrome/policies/managed /etc/chromium/policies/managed \
|
||||
&& printf '%s\n' '{"AutoLaunchProtocolsFromOrigins":[{"protocol":"aliexpress","allowed_origins":["*"]},{"protocol":"aliexpresshd","allowed_origins":["*"]},{"protocol":"aecmd","allowed_origins":["*"]},{"protocol":"alibaba","allowed_origins":["*"]},{"protocol":"alipay","allowed_origins":["*"]},{"protocol":"alipays","allowed_origins":["*"]},{"protocol":"tmall","allowed_origins":["*"]},{"protocol":"taobao","allowed_origins":["*"]},{"protocol":"market","allowed_origins":["*"]},{"protocol":"intent","allowed_origins":["*"]}]}' \
|
||||
| tee /etc/opt/chrome/policies/managed/fgc-autolaunch.json /etc/chromium/policies/managed/fgc-autolaunch.json > /dev/null \
|
||||
&& ln -sf /usr/share/novnc/vnc_auto.html /usr/share/novnc/index.html \
|
||||
&& ln -sf /usr/bin/python3 /usr/bin/python \
|
||||
&& apt-get purge -y gnupg \
|
||||
@@ -94,13 +96,20 @@ RUN apt-get update \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /var/cache/* /var/tmp/* /tmp/* /usr/share/doc/*
|
||||
|
||||
# Install a deterministic snapshot of the replacement upstream. Updating the
|
||||
# upstream reference is intentionally explicit so image contents cannot change
|
||||
# without an add-on version bump.
|
||||
# Install the upstream release named by BUILD_UPSTREAM. The repository updater
|
||||
# bumps that value together with the add-on version. A release tag is a mutable
|
||||
# reference: rebuilding the same BUILD_UPSTREAM installs whatever the tag points
|
||||
# at today, which is the accepted cost of tracking upstream automatically.
|
||||
# Upstream tags its releases "v1.6", but the tag name is downloaded without the
|
||||
# prefix as well so that an unattended update does not fail the build if
|
||||
# upstream ever drops it.
|
||||
WORKDIR /fgc
|
||||
RUN curl --proto "=https" --tlsv1.2 -fsSL \
|
||||
"https://github.com/${UPSTREAM_REPOSITORY}/archive/${UPSTREAM_REF}.tar.gz" \
|
||||
RUN (curl --proto "=https" --tlsv1.2 -fsSL \
|
||||
"https://github.com/${UPSTREAM_REPOSITORY}/archive/v${BUILD_UPSTREAM}.tar.gz" \
|
||||
-o /tmp/free-games-claimer-remaster.tar.gz \
|
||||
|| curl --proto "=https" --tlsv1.2 -fsSL \
|
||||
"https://github.com/${UPSTREAM_REPOSITORY}/archive/${BUILD_UPSTREAM}.tar.gz" \
|
||||
-o /tmp/free-games-claimer-remaster.tar.gz) \
|
||||
&& tar -xzf /tmp/free-games-claimer-remaster.tar.gz --strip-components=1 -C /fgc \
|
||||
&& python3 -m pip install --no-cache-dir --break-system-packages -r requirements.txt \
|
||||
&& dos2unix ./*.sh \
|
||||
@@ -155,4 +164,4 @@ LABEL \
|
||||
org.opencontainers.image.created="${BUILD_DATE}" \
|
||||
org.opencontainers.image.revision="${BUILD_REF}" \
|
||||
org.opencontainers.image.version="${BUILD_VERSION}" \
|
||||
io.hass.upstream="https://github.com/${UPSTREAM_REPOSITORY}/tree/${UPSTREAM_REF}"
|
||||
io.hass.upstream="https://github.com/${UPSTREAM_REPOSITORY}/releases"
|
||||
|
||||
@@ -24,14 +24,19 @@ This add-on is based on
|
||||
[Free Games Claimer Remaster](https://github.com/P-Adamiec/Free-Games-Claimer-Remaster).
|
||||
It can claim free games from:
|
||||
|
||||
- Epic Games Store
|
||||
- Epic Games Store, including its weekly free mobile game
|
||||
- Fab, Epic's asset marketplace (`fab`)
|
||||
- Amazon Prime Gaming
|
||||
- GOG
|
||||
- Steam
|
||||
- Ubisoft giveaways (`ubisoft`)
|
||||
- AliExpress daily coin check-in (`aliexpress`)
|
||||
- GamerPower-supported stores, when explicitly enabled
|
||||
|
||||
For compatibility with previous add-on releases, the default store selection
|
||||
remains Epic Games, Prime Gaming, and GOG.
|
||||
remains Epic Games, Prime Gaming, and GOG. The other stores are enabled by
|
||||
adding them to `STORES`, for example `epic,prime,gog,fab,ubisoft`, and each
|
||||
needs its own credentials in `config.env`.
|
||||
|
||||
## Web interface
|
||||
|
||||
@@ -98,6 +103,11 @@ NOTIFY=tgram://bot-token/chat-id
|
||||
# DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
|
||||
```
|
||||
|
||||
Upstream's release-update notification (`NOTIFY_UPDATES`) is disabled by the
|
||||
add-on, because it advises running `docker compose pull` while the add-on is
|
||||
actually updated through the Home Assistant add-on store. Setting
|
||||
`NOTIFY_UPDATES=true` in `config.env` re-enables it.
|
||||
|
||||
Existing variables such as `EG_EMAIL`, `EG_PASSWORD`, `PG_EMAIL`,
|
||||
`PG_PASSWORD`, `PG_OTPKEY`, `GOG_EMAIL`, `GOG_PASSWORD`, `SHOW`, `WIDTH`,
|
||||
`HEIGHT`, `TIMEOUT`, `LOGIN_TIMEOUT`, `DRYRUN`, and `NOTIFY` remain compatible.
|
||||
@@ -132,16 +142,31 @@ normally uses port `7080`.
|
||||
|
||||
## Upstream update policy
|
||||
|
||||
The image is built from an explicit upstream commit in the Dockerfile. This
|
||||
keeps amd64 and aarch64 images reproducible and prevents an upstream branch or
|
||||
container tag from changing without an add-on review and version bump.
|
||||
The image is built from the upstream release named by `ARG BUILD_UPSTREAM` in
|
||||
the Dockerfile, downloaded as the matching `v<version>` source tarball. The
|
||||
repository updater tracks upstream releases and bumps that value, the add-on
|
||||
version and `CHANGELOG.md` together, so a new upstream release reaches the
|
||||
add-on without a manual edit.
|
||||
|
||||
The repository updater is intentionally paused for this add-on because the
|
||||
add-on uses its own `2.x` version series while the replacement upstream uses a
|
||||
`1.x` version series. An automatic replacement would risk a Home Assistant
|
||||
version regression and would not safely update the pinned commit. A maintainer
|
||||
upstream update must therefore update `UPSTREAM_REF`, `upstream_version`, the
|
||||
add-on version, and `CHANGELOG.md` together.
|
||||
A release tag is a mutable reference. Rebuilding the same `BUILD_UPSTREAM`
|
||||
installs whatever that tag points at, so an upstream tag that is force-moved or
|
||||
deleted would change or fail the build without an add-on change. That is the
|
||||
accepted cost of automatic tracking, and it is the same trade-off every other
|
||||
automatically updated add-on in this repository makes; the previous commit pin
|
||||
was immutable but could only be advanced by hand.
|
||||
|
||||
Upstream's development tags (`v1.7d` and similar) are filtered out through
|
||||
`"github_exclude": "d"` in `updater.json`. Without it the updater reports the
|
||||
`v1.7d` tag as release `1.7`, for which GitHub serves no source archive, and
|
||||
the build would fail.
|
||||
|
||||
The add-on version does not track the upstream version. The add-on uses a `2.x`
|
||||
series while upstream is on `1.x`, and Home Assistant only offers an update
|
||||
when the new version sorts strictly higher, so the updater increments the
|
||||
add-on version (`2.1.0` to `2.1.1`) instead of publishing a lower-sorting
|
||||
upstream number. The upstream release actually installed is recorded in
|
||||
`upstream_version` in `updater.json`, in `CHANGELOG.md`, and in the add-on's
|
||||
startup banner.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
arch:
|
||||
- aarch64
|
||||
- amd64
|
||||
description: "Automatically claims free games from Epic Games Store, Amazon Prime Gaming, GOG, Steam, and optional GamerPower-supported stores"
|
||||
description: "Claims free games from Epic, Prime, GOG, Steam, Ubisoft and more"
|
||||
devices:
|
||||
- /dev/dri
|
||||
- /dev/dri/card0
|
||||
@@ -96,5 +96,5 @@ schema:
|
||||
slug: free_games_claimer
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
version: "2.0.1"
|
||||
version: "2.1.0"
|
||||
webui: "[PROTO:ssl]://[HOST]:[PORT:6080]"
|
||||
|
||||
@@ -36,6 +36,12 @@ set -a
|
||||
source "${RUNTIME_CONFIG}"
|
||||
set +a
|
||||
|
||||
# Upstream checks GitHub for newer releases and then tells the user to run
|
||||
# "docker compose pull", which is wrong here: the add-on is updated through the
|
||||
# Home Assistant add-on store. Default the check off, but honour an explicit
|
||||
# NOTIFY_UPDATES from config.env.
|
||||
export NOTIFY_UPDATES="${NOTIFY_UPDATES:-false}"
|
||||
|
||||
# The Home Assistant port mapping is intentionally kept at 6080 for a seamless
|
||||
# upgrade from the previous add-on, even though the new upstream defaults to 7080.
|
||||
if [ -n "${NOVNC_PORT:-}" ] && [ "${NOVNC_PORT}" != "6080" ]; then
|
||||
|
||||
@@ -10,12 +10,17 @@ TIMEOUT=60
|
||||
LOGIN_TIMEOUT=180
|
||||
VNC_LOGIN_TIMEOUT=180
|
||||
NOVNC_PORT=6080
|
||||
# Public address used in notification links when behind a reverse proxy.
|
||||
# VNC_URL=https://fgc.example.tld
|
||||
|
||||
# Keep the previous add-on's default stores. Add steam or gamerpower if wanted.
|
||||
# Keep the previous add-on's default stores. The upstream also supports
|
||||
# steam, fab, ubisoft, aliexpress and gamerpower; add them here if wanted.
|
||||
STORES=epic,prime,gog
|
||||
|
||||
# Used only when RUN_ONCE is disabled in the add-on options.
|
||||
SCHEDULER_HOURS=12
|
||||
# SCHEDULER_TIMEZONE=UTC
|
||||
# SCHEDULER_FIXED_TIMES=17:00,21:30
|
||||
|
||||
# Common credentials can be used as fallbacks for all stores.
|
||||
# EMAIL=
|
||||
@@ -33,7 +38,27 @@ SCHEDULER_HOURS=12
|
||||
# GOG_PASSWORD=
|
||||
# STEAM_USERNAME=
|
||||
# STEAM_PASSWORD=
|
||||
# UBI_EMAIL=
|
||||
# UBI_PASSWORD=
|
||||
# UBI_OTPKEY=
|
||||
# AE_EMAIL=
|
||||
# AE_PASSWORD=
|
||||
|
||||
# Epic's weekly free mobile game, claimed with the epic store.
|
||||
# EG_MOBILE=true
|
||||
# EG_MOBILE_PLATFORMS=android,ios
|
||||
|
||||
# Fab assets sign in with the Epic account. Accepting the licence agreement is
|
||||
# required to claim; set to false to be notified instead of accepting.
|
||||
# FAB_ACCEPT_EULA=true
|
||||
|
||||
# Notifications (Apprise or Discord)
|
||||
# NOTIFY=
|
||||
# DISCORD_WEBHOOK=
|
||||
# NOTIFY_ALREADY_CLAIMED=false
|
||||
# NOTIFY_SKIP_STORES=
|
||||
|
||||
# Upstream release notifications are disabled by the add-on: updates are
|
||||
# delivered through the Home Assistant add-on store, not by docker compose.
|
||||
# Set to true to receive them anyway.
|
||||
# NOTIFY_UPDATES=false
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
{
|
||||
"dockerhub_by_date": false,
|
||||
"dockerhub_list_size": 2,
|
||||
"last_update": "17-07-2026",
|
||||
"paused": true,
|
||||
"github_exclude": "d",
|
||||
"github_fulltag": false,
|
||||
"last_update": "24-08-2026",
|
||||
"paused": false,
|
||||
"repository": "alexbelgium/hassio-addons",
|
||||
"slug": "free_games_claimer",
|
||||
"source": "github",
|
||||
"upstream_repo": "P-Adamiec/Free-Games-Claimer-Remaster",
|
||||
"upstream_version": "1.1"
|
||||
"upstream_version": "1.6"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 2.44.0.1 (2026-08-24)
|
||||
|
||||
- Rebuild to pick up a fix in the shared entrypoint: when `ha_entrypoint.sh` runs as PID 1, as it does in this add-on, it now populates `/run/s6/container_environment`, so a script carrying a `#!/usr/bin/with-contenv` shebang gets a populated environment including `SUPERVISOR_TOKEN` instead of failing at its shebang. Nothing shipped in this add-on still uses that shebang (the healthcheck moved to plain bash in 2.44.0), so this changes nothing about the agent itself; it matters for a `script.sh` added by the user, and it is the add-on that build-tests the shared change
|
||||
|
||||
## 2.44.0 (2026-08-23)
|
||||
|
||||
- Fix: Use `portainer/agent:alpine-sts` to match the STS release channel configured in `updater.json`
|
||||
|
||||
@@ -41,4 +41,4 @@ schema:
|
||||
slug: portainer_agent
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
version: "2.44.0"
|
||||
version: "2.44.0.1"
|
||||
Reference in New Issue
Block a user