diff --git a/.github/workflows/bake-rootfs.yml b/.github/workflows/bake-rootfs.yml index 3082fa8a6..ec314b086 100644 --- a/.github/workflows/bake-rootfs.yml +++ b/.github/workflows/bake-rootfs.yml @@ -26,9 +26,13 @@ on: env: BUCKET_NAME: k2go-rootfs R2_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} - # Public base that goes into the .meta4 . 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 — 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 }} @@ -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 @@ -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 _); 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[@]} @@ -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 diff --git a/controller/app/src/main/java/org/iiab/controller/backup/domain/BackupEngine.java b/controller/app/src/main/java/org/iiab/controller/backup/domain/BackupEngine.java index 772a150f5..e246d66d0 100644 --- a/controller/app/src/main/java/org/iiab/controller/backup/domain/BackupEngine.java +++ b/controller/app/src/main/java/org/iiab/controller/backup/domain/BackupEngine.java @@ -29,14 +29,20 @@ public final class BackupEngine { private BackupEngine() {} - /** Suggested external filename: {@code iiab-oa_YYYY.DDD__.tar.gz}. */ + /** + * Suggested external filename: {@code k2go_YYYY.DDD__.tar.gz}. + * + *

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); } diff --git a/controller/app/src/test/java/org/iiab/controller/deploy/domain/ExtractProgressTest.java b/controller/app/src/test/java/org/iiab/controller/deploy/domain/ExtractProgressTest.java index fc533cf57..5cc6a6315 100644 --- a/controller/app/src/test/java/org/iiab/controller/deploy/domain/ExtractProgressTest.java +++ b/controller/app/src/test/java/org/iiab/controller/deploy/domain/ExtractProgressTest.java @@ -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. */ diff --git a/controller/app/src/test/java/org/iiab/controller/download/domain/MetalinkFileTest.java b/controller/app/src/test/java/org/iiab/controller/download/domain/MetalinkFileTest.java index feb7af3b4..e094d481f 100644 --- a/controller/app/src/test/java/org/iiab/controller/download/domain/MetalinkFileTest.java +++ b/controller/app/src/test/java/org/iiab/controller/download/domain/MetalinkFileTest.java @@ -21,15 +21,15 @@ public class MetalinkFileTest { private static final String META4 = "\n" + "\n" - + " \n" + + " \n" + " 1453144579\n" + " " + FILE_HASH + "\n" + " \n" + " " + FIRST_PIECE_HASH + "\n" + " 67c19c9e0509ff1aaeb104fce7498f53f02052acb18a241409b6d58c9c114142\n" + " \n" - + " https://iiab.switnet.org/android/rootfs/iiab-oa_2026.192_standard_17dd521_arm64-v8a.tar.gz\n" - + " https://mirror2.example.org/iiab-oa_2026.192_standard_17dd521_arm64-v8a.tar.gz\n" + + " https://pub-d64c885cef6c42db8c7925144d73d0ee.r2.dev/k2go_2026.192_standard_17dd521_arm64-v8a.tar.gz\n" + + " https://mirror2.example.org/k2go_2026.192_standard_17dd521_arm64-v8a.tar.gz\n" + " \n" + "\n"; @@ -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 { diff --git a/tools/rootfs-builder/build-iiab-rootfs.sh b/tools/rootfs-builder/build-iiab-rootfs.sh index c3c80ccc7..8ae14d752 100755 --- a/tools/rootfs-builder/build-iiab-rootfs.sh +++ b/tools/rootfs-builder/build-iiab-rootfs.sh @@ -22,8 +22,8 @@ # branch (git ls-remote, then the REST API). --iiab-commit overrides everything. # # Output: -# - iiab-oa____.tar.gz (top-level = installed-rootfs/iiab/) -# - iiab-oa_<...>.tar.gz.meta4 / .torrent (per-artifact, mkmetalink) +# - k2go____.tar.gz (top-level = installed-rootfs/iiab/) +# - k2go_<...>.tar.gz.meta4 / .torrent (per-artifact, mkmetalink) # - latest__.meta4 (STABLE pointer the APK requests; a copy of the # per-artifact .meta4. Inside it, mirrors point at the full-named tarball, # so this stable name always resolves to the newest build.) @@ -744,7 +744,9 @@ fi [[ -n "$IIAB_SHA" ]] || die "Could not determine the iiab/iiab commit id. Pass --iiab-commit ." 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__.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