Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions .github/workflows/bake-rootfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ on:
env:
BUCKET_NAME: k2go-rootfs
R2_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
# Public base that goes into the .meta4 <url>. Path-based route
# k2go-download.appdevforall.org/rootfs/* -> k2go-rootfs.
ROOTFS_PUBLIC_BASE: ${{ vars.ROOTFS_PUBLIC_BASE || 'https://k2go-download.appdevforall.org/rootfs' }}
# Public base that goes into the .meta4 <url> — where the APK actually downloads the
# rootfs FROM, so it has to name the bucket that holds it. The two buckets are separate
# and so are their names: k2go-download.appdevforall.org serves the APK repo only.
# K2GO-90: this defaulted to k2go-download.appdevforall.org/rootfs, a path-based route that
# was never created. The metalinks published with it resolved to 404 — and since
# --reset-mirrors leaves a single source, there was nothing to fall back to.
ROOTFS_PUBLIC_BASE: ${{ vars.ROOTFS_PUBLIC_BASE || 'https://pub-d64c885cef6c42db8c7925144d73d0ee.r2.dev' }}
# Key prefix inside the bucket. Empty when the route strips /rootfs/ (keys at root);
# set to 'rootfs/' if the route keeps the prefix.
R2_KEY_PREFIX: ${{ vars.ROOTFS_KEY_PREFIX }}
Expand Down Expand Up @@ -133,7 +137,7 @@ jobs:

# 1) Big artifacts FIRST (data before any pointer that resolves to them).
shopt -s nullglob
for f in iiab-oa_*.tar.gz; do
for f in k2go_*.tar.gz; do
echo ">> upload artifact $f"
aws s3 cp "$f" "s3://${BUCKET_NAME}/${PFX}${f}" --endpoint-url "$ENDPOINT"
done
Expand All @@ -157,12 +161,12 @@ jobs:

# 4) Prune: keep only the newest $KEEP batches per (tier,arch); delete older + sidecars.
# Only the heavy dated tarballs accumulate (they carry <date>_<sha>); logs and the
# TSV overwrite in place, so they never pile up. The prefix filter matches iiab-oa_*
# TSV overwrite in place, so they never pile up. The prefix filter matches k2go_*
# only, so proot-distro-v*/ is never touched.
for meta in latest_*_"${ARCH}".meta4; do
base="${meta%.meta4}"; te="${base#latest_}"; tier="${te%_${ARCH}}"
mapfile -t keys < <(aws s3api list-objects-v2 --bucket "$BUCKET_NAME" \
--prefix "${PFX}iiab-oa_" --endpoint-url "$ENDPOINT" \
--prefix "${PFX}k2go_" --endpoint-url "$ENDPOINT" \
--query "sort_by(Contents,&LastModified)[?contains(Key,'_${tier}_') && ends_with(Key,'_${ARCH}.tar.gz')].Key" \
--output text | tr '\t' '\n' | sed '/^$/d')
n=${#keys[@]}
Expand All @@ -174,4 +178,26 @@ jobs:
done
done
fi

# K2GO-377 (TRANSITIONAL — remove before merging). The retention above keeps the
# newest $KEEP k2go_ batches; the pre-rename iiab-oa_ artifacts have no pointer left
# once this tier republished, so they go in full rather than ageing out $KEEP deep at
# ~1.7 GB each. It sits INSIDE this loop on purpose: it only ever touches the tier and
# arch this job just republished, so a tier that failed to build keeps the artifact its
# metalink still names.
#
# Removal is gated on evidence, not on this run finishing. Delete the block only when
# aws s3api list-objects-v2 --bucket "$BUCKET_NAME" --prefix "iiab-oa_" \
# --endpoint-url "$ENDPOINT" --query "length(Contents)" --output text
# reports None/0 — otherwise the leftovers outlive the only code that would clear them.
mapfile -t legacy < <(aws s3api list-objects-v2 --bucket "$BUCKET_NAME" \
--prefix "${PFX}iiab-oa_" --endpoint-url "$ENDPOINT" \
--query "Contents[?contains(Key,'_${tier}_') && ends_with(Key,'_${ARCH}.tar.gz')].Key" \
--output text | tr '\t' '\n' | sed '/^$/d')
for key in "${legacy[@]}"; do
echo ">> sweep legacy $key (+ sidecars)"
for ext in '' .meta4 .sha256 .installed .torrent; do
aws s3 rm "s3://${BUCKET_NAME}/${key}${ext}" --endpoint-url "$ENDPOINT" || true
done
done
done
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@ public final class BackupEngine {

private BackupEngine() {}

/** Suggested external filename: {@code iiab-oa_YYYY.DDD_<epochSecs>_<arch>.tar.gz}. */
/**
* Suggested external filename: {@code k2go_YYYY.DDD_<epochSecs>_<arch>.tar.gz}.
*
* <p>K2GO-377: the prefix follows the built rootfs artifacts onto the product's own name. It is
* only ever a suggestion for the SAF picker — nothing reads it back, and a restore identifies an
* archive by the manifest inside it, so backups written under the old name keep working.
*/
public static String suggestedFileName(Context ctx) {
java.util.Calendar c = java.util.Calendar.getInstance();
int year = c.get(java.util.Calendar.YEAR);
int day = c.get(java.util.Calendar.DAY_OF_YEAR);
String abi = org.iiab.controller.deploy.data.RootfsManifest.appAbiId();
String arch = abi != null && abi.contains("64") ? "aarch64" : "armhf";
return String.format(java.util.Locale.US, "iiab-oa_%04d.%03d_%d_%s.tar.gz",
return String.format(java.util.Locale.US, "k2go_%04d.%03d_%d_%s.tar.gz",
year, day, System.currentTimeMillis() / 1000L, arch);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public void ordinaryNamesAreStillShown() {
public void shortHexLikeWordsAreNotMistakenForDigests() {
assertEquals("deadbeef.conf", ExtractProgress.fileLabel("etc/deadbeef.conf"));
assertEquals("facade.png", ExtractProgress.fileLabel("share/facade.png"));
assertEquals("iiab-oa_2026.224_standard.tar.gz",
ExtractProgress.fileLabel("downloads/iiab-oa_2026.224_standard.tar.gz"));
assertEquals("k2go_2026.224_standard.tar.gz",
ExtractProgress.fileLabel("downloads/k2go_2026.224_standard.tar.gz"));
}

/** Fails open: a name we cannot classify is shown, never hidden on a guess. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ public class MetalinkFileTest {
private static final String META4 =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\" version=\"4.0\">\n"
+ " <file name=\"iiab-oa_2026.192_standard_17dd521_arm64-v8a.tar.gz\">\n"
+ " <file name=\"k2go_2026.192_standard_17dd521_arm64-v8a.tar.gz\">\n"
+ " <size>1453144579</size>\n"
+ " <hash type=\"sha-256\">" + FILE_HASH + "</hash>\n"
+ " <pieces type=\"sha-256\" length=\"1048576\">\n"
+ " <hash type=\"sha-256\">" + FIRST_PIECE_HASH + "</hash>\n"
+ " <hash type=\"sha-256\">67c19c9e0509ff1aaeb104fce7498f53f02052acb18a241409b6d58c9c114142</hash>\n"
+ " </pieces>\n"
+ " <url>https://iiab.switnet.org/android/rootfs/iiab-oa_2026.192_standard_17dd521_arm64-v8a.tar.gz</url>\n"
+ " <url>https://mirror2.example.org/iiab-oa_2026.192_standard_17dd521_arm64-v8a.tar.gz</url>\n"
+ " <url>https://pub-d64c885cef6c42db8c7925144d73d0ee.r2.dev/k2go_2026.192_standard_17dd521_arm64-v8a.tar.gz</url>\n"
+ " <url>https://mirror2.example.org/k2go_2026.192_standard_17dd521_arm64-v8a.tar.gz</url>\n"
+ " </file>\n"
+ "</metalink>\n";

Expand All @@ -40,7 +40,7 @@ private MetalinkFile parse() throws Exception {
}

@Test public void parsesFileName() throws Exception {
assertEquals("iiab-oa_2026.192_standard_17dd521_arm64-v8a.tar.gz", parse().fileName());
assertEquals("k2go_2026.192_standard_17dd521_arm64-v8a.tar.gz", parse().fileName());
}

@Test public void parsesSize() throws Exception {
Expand Down
8 changes: 5 additions & 3 deletions tools/rootfs-builder/build-iiab-rootfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
# branch (git ls-remote, then the REST API). --iiab-commit overrides everything.
#
# Output:
# - iiab-oa_<date>_<tier>_<iiab-sha>_<arch>.tar.gz (top-level = installed-rootfs/iiab/)
# - iiab-oa_<...>.tar.gz.meta4 / .torrent (per-artifact, mkmetalink)
# - k2go_<date>_<tier>_<iiab-sha>_<arch>.tar.gz (top-level = installed-rootfs/iiab/)
# - k2go_<...>.tar.gz.meta4 / .torrent (per-artifact, mkmetalink)
# - latest_<tier>_<arch>.meta4 (STABLE pointer the APK requests; a copy of the
# per-artifact .meta4. Inside it, <url> mirrors point at the full-named tarball,
# so this stable name always resolves to the newest build.)
Expand Down Expand Up @@ -744,7 +744,9 @@ fi
[[ -n "$IIAB_SHA" ]] || die "Could not determine the iiab/iiab commit id. Pass --iiab-commit <sha>."
log "iiab/iiab id: ${IIAB_SHA} [source: ${IIAB_SRC}]"

ARTIFACT="iiab-oa_${STAMP}_${TIER_NAME}_${IIAB_SHA}_${ARCH}.tar.gz"
# K2GO-377: the artifacts carry the product name. The stable pointers do not change —
# latest_<tier>_<arch>.meta4/.installed never carried a product prefix.
ARTIFACT="k2go_${STAMP}_${TIER_NAME}_${IIAB_SHA}_${ARCH}.tar.gz"
META4="latest_${TIER_NAME}_${ARCH}.meta4"
INSTALLED="latest_${TIER_NAME}_${ARCH}.installed" # ADFA-5110: stable uncompressed-size sidecar

Expand Down
Loading