Require FDROID_REPO_URL/FDROID_REPO_NAME so fdroid-update.sh cannot publish fdroidserver's placeholder

The published repo advertised fdroidserver's own demo values
(repo.address "https://MyFirstFDroidRepo.org/fdroid/repo", repo.name "My
First F-Droid Repo Demo") because fdroid-update.sh wrote config.yml itself
but never set repo_url/repo_name/repo_description, so fdroidserver fell
back to its template. The "Add to F-Droid" button on the generated
index.html is built from repo_url, which is how bit noticed. A publish
that succeeds while advertising the wrong URL is silently wrong -- worse
than a failed job.

Add FDROID_REPO_URL/FDROID_REPO_NAME/FDROID_REPO_DESCRIPTION environment
variables (not new positionals -- the script already has five plus
pass-through extra args). The first two are now a hard requirement, naming
the missing one; FDROID_REPO_DESCRIPTION stays optional. This is a breaking
change to a public composite action's interface, acceptable only because
weblib-viewer is the sole consumer and is updated in the same change
(weblib-viewer#26).

Also discovered while wiring this up and worth recording since it
contradicts the "no /fdroid/repo suffix" assumption in weblib's working
notes: fdroidserver's own common.py unconditionally refuses to run once
config.yml sets repo_url at all, unless it ends in the literal suffix
"/repo" -- there is no flag to disable that check, and the value is
embedded verbatim as repo.address. So FDROID_REPO_URL has to end in /repo,
and publish.sh's existing <prefix> argument has to put the published tree
under a URL path that actually ends in /repo to match, or fdroid update
refuses to run at all (checked positive) / the address points at a path
the bucket never serves (checked against the live fdroid-weblib-dev bucket
layout).

Extends test_fdroid_update.sh: config.yml carries the values, the resulting
index-v2.json has the right repo.address/name/description (not
fdroidserver's placeholder), a name with an embedded single quote survives
the YAML round-trip, and the script fails when FDROID_REPO_URL or
FDROID_REPO_NAME is absent or FDROID_REPO_URL lacks the /repo suffix.
run_tests.sh: 104 passed / 4 skipped (was 98/4).

Filed as fdroid-repo-ci#11.

Co-authored-by: bit <bit@das-labor.org>
This commit is contained in:
2026-09-09 20:23:16 +00:00
co-authored by bit
parent ec4d950e18
commit 4a25e3681a
3 changed files with 139 additions and 4 deletions
+50 -1
View File
@@ -23,6 +23,28 @@
# <key-pass-env> is omitted, the keystore password is reused as the key
# password.
#
# FDROID_REPO_URL and FDROID_REPO_NAME (environment variables, not
# arguments -- they are not secrets, but they are metadata that belongs
# beside the other config.yml fields this script already writes, not a sixth
# and seventh positional) are REQUIRED and this script refuses to run
# without them. Omitting them used to mean fdroidserver silently fell back to
# its own placeholder template ("MyFirstFDroidRepo.org", "My First F-Droid
# Repo Demo") -- a repo that publishes successfully while advertising
# someone else's URL and name, which is worse than failing loudly.
# FDROID_REPO_DESCRIPTION is optional. This is a breaking change to this
# script's interface (fdroid-repo-ci#11); acceptable only because
# weblib-viewer is this action's sole consumer and is updated in the same
# change.
#
# FDROID_REPO_URL MUST end in the literal suffix "/repo" -- fdroidserver
# enforces this itself (common.py: "repo_url needs to end with /repo"),
# unconditionally, whenever config.yml sets repo_url at all, and refuses to
# run otherwise. It is not this script's own rule and there is no way to
# turn it off, so the caller's publish step has to serve the tree under a
# URL path actually ending in /repo -- e.g. `publish.sh`'s own <prefix>
# argument -- or the value embedded here (verbatim, as repo.address in
# index-v2.json) will not be where the index actually is.
#
# Needs no network (fdroid-repo-ci#1) -- it only reads repo/ and signs.
# Pins fdroidserver, the JDK (fdroidserver shells out to jarsigner/keytool
# for the index signature) and apksigner (for the per-entry v1 signature in
@@ -35,6 +57,9 @@ if [ "$#" -lt 4 ]; then
cat >&2 <<'USAGE'
usage: fdroid-update.sh <repo-root> <index-keystore> <key-alias> \
<keystore-pass-env> [<key-pass-env>] [extra fdroid update args...]
required environment variables: FDROID_REPO_URL, FDROID_REPO_NAME
optional environment variable: FDROID_REPO_DESCRIPTION
USAGE
exit 2
fi
@@ -58,6 +83,23 @@ extra_args=("$@")
: "${!ks_pass_env:?fdroid-update.sh: environment variable $ks_pass_env (keystore password) is not set}"
: "${!key_pass_env:?fdroid-update.sh: environment variable $key_pass_env (key password) is not set}"
# Hard-required: an unset repo_url/repo_name used to mean fdroidserver fell
# back to its own placeholder template, which is a *successful* publish that
# advertises the wrong repo -- silently wrong, the worst outcome. Failing
# loudly, naming the variable, is strictly better than defaulting.
: "${FDROID_REPO_URL:?fdroid-update.sh: environment variable FDROID_REPO_URL (canonical repo URL, no trailing slash) is not set}"
: "${FDROID_REPO_NAME:?fdroid-update.sh: environment variable FDROID_REPO_NAME (repo display name) is not set}"
# YAML single-quoted scalar: doubling an embedded single quote is the only
# escape it needs, and (unlike double-quoted) it does not interpret
# backslashes -- so this is safe for an arbitrary URL/name/description
# without having to know what characters fdroidserver's own parser accepts.
yaml_squote() {
local s=$1
s=${s//\'/\'\'}
printf "'%s'" "$s"
}
# fdroidserver's config.yml supports "{env: VARNAME}" in place of any string
# value specifically so a config that names a keystore and its passwords can
# still be free of secrets -- fdroidserver's own common.py: "it is a good
@@ -65,14 +107,21 @@ extra_args=("$@")
# means a caller never has to hand-write fdroidserver's config format, and
# this repo -- not every consumer -- is the one place that has to track it if
# it changes.
cat > "$root/config.yml" <<EOF
{
cat <<EOF
keystore: $keystore
keystorepass:
env: $ks_pass_env
keypass:
env: $key_pass_env
repo_keyalias: $alias_name
repo_url: $(yaml_squote "$FDROID_REPO_URL")
repo_name: $(yaml_squote "$FDROID_REPO_NAME")
EOF
if [ -n "${FDROID_REPO_DESCRIPTION:-}" ]; then
echo "repo_description: $(yaml_squote "$FDROID_REPO_DESCRIPTION")"
fi
} > "$root/config.yml"
chmod 600 "$root/config.yml"
echo "fdroid-update.sh: running fdroid update in $root"