feat(images): rename android-flutter → android-flutter-ios and add CocoaPods #58
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Two changes bundled:
Rename
images/fedora/android-flutter→images/fedora/android-flutter-ios. The flavor's scope expanded from "Android-only Flutter" to "Android + iOS Flutter (with Mac handoff for the actual ipa build)". config.initagfollows:android-flutter-fedora→android-flutter-ios-fedora.Bundle CocoaPods.
pod installis pure Ruby and runs fine on linux/amd64 — it resolves Podfile.lock and fetches Pods/ without needing Xcode. The actualflutter build ipa/xcodebuild archivestep still requires macOS, but lockfile generation and pod fetching now happen in-container.Bumper
New
rubygem:NAMEsource handler. Queries rubygems.org's/api/v1/versions/<gem>/latest.json— server-side filtered for stable releases, so the response works directly withconstraint=latest. Wired into the cocoapods row viasource=rubygem:cocoapods.Image tag migration
Old tag
scc:android-flutter-fedora-lateststays on the registry but won't be updated. New tag isscc:android-flutter-ios-fedora-latestandscc:<version>-android-flutter-ios-fedora. Existing.scc/config.inifiles pointing at the old tag should update — old tag drifts.Test plan
./bump-deps.sh --dry-run -i fedora/android-flutter-iosresolves all six bumpable rows with zero errors; rubygem handler returns cocoapods 1.16.2docker run --rm --platform=linux/amd64 --entrypoint pod scc:android-flutter-ios-fedora-latest --versionreturns 1.16.2Bonus
This branch also pulls in main's daily-bump (Flutter 3.27.1 → 3.44.0, Android cmdline-tools 13114758 → 14742923, Temurin 21.0.5+11 → 21.0.11+10) via the merge commit that landed earlier.
Until now scc only installed Claude once, then served the cached binary from the scc-claude volume forever — no version check, no nudge when Anthropic shipped a fix. The only refresh path was the user knowing to set SCC_FORCE_REINSTALL=1. This adds a once-per-day check mirroring the existing scc.sh self-update flow: scc.sh GETs @anthropic-ai/claude-code/latest from npm (~1 KB, 1 s timeout), compares it to the version cached in the volume, and warns + prompts when upstream is newer. Decisions are remembered per upstream version so users don't get re-prompted for the same release. Plumbing: - scc-entrypoint.sh writes `claude --version` into both /opt/scc-claude/version (canonical, lives with the binary) and /scc-meta/claude_version (bind-mounted from ~/.scc/volume-meta/, so the host launcher can read it without a docker-exec roundtrip). Re-captured after every reinstall; idempotent on the fast path. - scc.sh adds the /scc-meta mount alongside the existing volume mount. Older launchers don't mount /scc-meta; the entrypoint silently skips the mirror in that case, so a new image works with an old launcher. - New check_for_claude_update() in scc.sh: 24h-cached fetch, semver comparison via sort -V, per-version ack file at ~/.scc/claude-update-check. Fail-closed: non-TTY runs note and continue, never auto-update. Three new env vars: - SCC_AUTO_UPDATE_CLAUDE=1 skip the prompt, auto-set SCC_FORCE_REINSTALL=1 on detection. - SCC_NO_CLAUDE_UPDATE_CHECK=1 skip the daily probe entirely. - (existing SCC_FORCE_REINSTALL=1 still works; suppresses the check when set, since reinstall is already happening.) Tests: - tests/feature/helpers.bash exports SCC_NO_CLAUDE_UPDATE_CHECK=1 alongside SCC_NO_UPDATE_CHECK=1 so the daily curl never fires under test. All 56 existing bats tests pass; no new tests added (the new function is HTTP-bound and matches the established pattern). README "Claude binary handling" section gains a "Daily Claude update check" subsection documenting the prompt, the env vars, and where the metadata lives. scc.sh.version bumped 1.1.2 → 1.2.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Adds a third configurable field next to image and claude_args: a docker --platform pin. Use case: running the new fedora/android-flutter image (amd64-only, since Google ships no arm64 Android SDK) on Apple Silicon under Rosetta-for-Linux. Without --platform, docker warns about arch mismatch and Rosetta's behavior is implicit; with --platform=linux/amd64 the launcher tells docker exactly what to pull + run. Resolution order matches the existing image plumbing: SCC_PLATFORM env > .scc/config.ini platform= > (omit, docker chooses) Wired through both `docker pull` and `docker run` via a shared platform_args array. The status line prints "(--platform linux/amd64)" when set so you can tell at a glance whether emulation is in play. Validation is minimal — `^[a-z0-9]+/[a-z0-9/.-]+$` catches the obvious typo (`amd64` without the `linux/` prefix) but otherwise trusts docker to error on garbage. Anything that looks like os/arch passes through. Trust gate extended: - require_project_trust() takes a 4th argument (platform). - Trust file format gains a `platform=` line. Old trust files without the line keep working because ini_get returns "" for missing keys and ""="" compares equal when the project also doesn't pin platform. Re-prompt only fires when a project NEWLY pins a platform that wasn't in the old trust file. - SCC_PLATFORM env is user-explicit and does NOT trigger the trust prompt, matching the SCC_IMAGE behavior. Tests: 3 new bats cases in project_config.bats: - platform = … in config.ini reaches docker run argv as `--platform linux/amd64` - SCC_PLATFORM env overrides the config.ini value - Malformed platform (`amd64`, no `linux/` prefix) rejected with rc=2 All 59/59 tests pass (was 56 before). README's "Schema" + "Trust prompt" sections updated to document the new field, the resolution order, and the bypass env vars. scc.sh.version bumped 1.2.0 → 1.3.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>The named volume `scc-claude` is shared across all image flavors — first image to install Claude wins, every subsequent flavor exec's that same binary. When two flavors have substantially different runtime layouts (e.g. default Fedora-with-Node vs android-flutter without it, or amd64 under Rosetta vs native arm64), the cached binary from flavor A can fail to exec under flavor B's environment. Add a project-pinnable override so each project can opt into its own Claude volume, matching the existing image= / claude_args= / platform= pattern: [scc] image = forge.stacktop.network/openstacktop/scc:android-flutter-fedora-latest volume = scc-claude-android-flutter Resolution: SCC_CLAUDE_VOLUME env > .scc/config.ini volume= > default "scc-claude". CLAUDE_VOLUME loses `readonly` so it can be reassigned after project-config parsing; the three downstream usages (status label, state label, bind mount) are unchanged. Not part of the trust gate: a project pointing at a different cached binary is no greater risk than image= itself (which already gates), and the existing SCC_CLAUDE_VOLUME env path doesn't gate either — adding it to the trust hash now would be asymmetric. Existing trust files keep working unchanged. Tests: - volume = … in config.ini → docker run argv contains `my-project-claude:/opt/scc-claude` and NOT `scc-claude:/opt/scc-claude` - SCC_CLAUDE_VOLUME env overrides the config.ini value All 61/61 bats tests pass (was 59 before). README schema + resolution-priority table updated; help text mentions the new field and the env precedence. scc.sh.version bumped 1.3.0 → 1.4.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Claude Code 2.1+ ships as a single native binary and the install.sh drops it at ~/.local/bin/claude WITHOUT adding that directory to PATH (the installer just prints "echo 'export PATH=...' >> your shell config" as a manual setup hint). The entrypoint was using `command -v claude` to find what the installer just dropped, which returned empty and aborted the install with "claude not on PATH after install — installer layout changed?" — even though the binary was successfully written. Fix: check the known native-install locations directly (/root/.local/bin/claude, $HOME/.local/bin/claude) before falling back to a PATH-widened `command -v` for older or relocated layouts. The fallback keeps backward compatibility with the previous installer that did expose claude on PATH; the explicit-path checks handle the 2.1+ native-install flow. Surfaced by: - fresh `scc-claude-android-flutter` volume + `scc` against the android-flutter image. Install succeeded ("Claude Code successfully installed! Version: 2.1.150 Location: ~/.local/bin/claude") but the next entrypoint step bailed out with the missing-on-PATH error. scc.sh.version bumped 1.4.0 → 1.4.1; 61/61 bats tests still pass (the entrypoint runs inside the container, not on the bats host, so coverage is unchanged). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>The flavor's scope grew from "Android-only Flutter dev" to "Android + iOS Flutter dev that hands off to a Mac for the final build" once you realised pod install is just Ruby and works on linux/amd64. Rename the directory + the config.ini `tag` to match the broader scope, and bundle CocoaPods so iOS dependency resolution happens in the container. What CocoaPods does here: - Resolves Podfile.lock and fetches Pods/ — pure Ruby work, no Xcode needed. Generated lockfile + workspace are valid for the Mac to pick up and sign. - The actual `flutter build ipa` / `xcodebuild archive` step still runs on macOS + Xcode on the host. This image stays Android-build- capable + iOS-resolve-capable. - Edge cases (Firebase / GoogleMaps pods with post-install hooks that shell out to xcrun) will fail loudly with a clear error and have to run on the Mac; most Flutter plugin pods don't trip this. Image changes: - Dockerfile installs ruby + ruby-devel + rubygems + gcc/g++/make (gcc/g++/make are required for native gem extensions like json). - New ARG COCOAPODS_VERSION + `gem install cocoapods -v $VER` step. - Header comment expanded with the iOS scope + Mac-handoff note. Bumper: - New `rubygem:NAME` source handler. Queries rubygems.org's /api/v1/versions/<gem>/latest.json — yanked/pre-release versions are filtered server-side, so the response is a clean semver string suitable for `constraint=latest` without extra filtering. - cocoapods row in config.ini wires it up: kind=arg; source=rubygem:cocoapods; arg=COCOAPODS_VERSION; ... Image tag changes: - config.ini `tag = android-flutter-fedora` → `android-flutter-ios-fedora` - Next build publishes scc:android-flutter-ios-fedora-latest and scc:<version>-android-flutter-ios-fedora. The old tag stays on the registry but won't be updated; users of .scc/config.ini with image=…android-flutter-fedora-latest should switch over. README arch table updated. Includes the merge of main's daily-bump (Flutter 3.27.1 → 3.44.0, Android cmdline-tools 13114758 → 14742923, Temurin 21.0.5+11 → 21.0.11+10). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>