diff --git a/.fvmrc b/.fvmrc index 2983293..a99331c 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,4 +1,4 @@ { - "flutter": "beta", + "flutter": "3.44.4", "flavors": {} -} +} \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 100a175..e4f7bdf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -17,8 +17,6 @@ # CI and config: repo owner only /.github/ @chaudharydeepanshu -/.gitmodules @chaudharydeepanshu -/cellar @chaudharydeepanshu /.githooks/ @chaudharydeepanshu # Build + supply-chain machinery: repo owner only. Holds the commit-types list diff --git a/.github/workflows/auto-close.yml b/.github/workflows/auto-close.yml index 74d88da..d2ee100 100644 --- a/.github/workflows/auto-close.yml +++ b/.github/workflows/auto-close.yml @@ -24,7 +24,7 @@ jobs: auto-close: permissions: issues: write # label, comment on, and close resolved issues - uses: whuppi/ci/.github/workflows/auto-close.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/auto-close.yml@v2.0.4 with: # Team slug, not a hardcoded person — membership is managed in the org # (the same team CODEOWNERS uses), so a maintainer change never edits this. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c7e1b3..74b4f4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 with: make-target: format @@ -95,7 +95,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 with: make-target: analyze @@ -113,7 +113,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 with: make-target: analyze-floor @@ -132,12 +132,12 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 with: make-target: platforms test: - name: Test guards + name: Package tests needs: [inputs, changes] if: needs.changes.outputs.code == 'true' runs-on: ${{ needs.inputs.outputs.runner }} @@ -148,12 +148,12 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 with: make-target: test test-example-matrix: - name: Unit tests (VM) + name: Example journeys (host VM) needs: [inputs, changes] if: needs.changes.outputs.code == 'true' runs-on: ${{ needs.inputs.outputs.runner }} @@ -164,7 +164,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 with: make-target: test-example-matrix @@ -185,9 +185,8 @@ jobs: ANALYZE: ${{ needs.analyze.result }} FLOOR: ${{ needs.analyze-floor.result }} PLATFORMS: ${{ needs.platforms.result }} - GUARDS: ${{ needs.test-guards.result }} - UNIT: ${{ needs.test-unit.result }} - WEB: ${{ needs.test-web.result }} + PKG: ${{ needs.test.result }} + JOURNEYS: ${{ needs.test-example-matrix.result }} run: | # A failed (not skipped) changes job clears its outputs, so CODE # arrives empty — which must NOT read as "doc-only". Gate on the job @@ -200,8 +199,8 @@ jobs: echo "Doc-only PR — CI gate passes" exit 0 fi - if [[ "$FORMAT" != "success" ]] || [[ "$ANALYZE" != "success" ]] || [[ "$FLOOR" != "success" ]] || [[ "$PLATFORMS" != "success" ]] || [[ "$GUARDS" != "success" ]] || [[ "$UNIT" != "success" ]] || [[ "$WEB" != "success" ]]; then - echo "FAILED: format=$FORMAT analyze=$ANALYZE floor=$FLOOR platforms=$PLATFORMS guards=$GUARDS unit=$UNIT web=$WEB" + if [[ "$FORMAT" != "success" ]] || [[ "$ANALYZE" != "success" ]] || [[ "$FLOOR" != "success" ]] || [[ "$PLATFORMS" != "success" ]] || [[ "$PKG" != "success" ]] || [[ "$JOURNEYS" != "success" ]]; then + echo "FAILED: format=$FORMAT analyze=$ANALYZE floor=$FLOOR platforms=$PLATFORMS pkg=$PKG journeys=$JOURNEYS" exit 1 fi echo "All CI checks passed" diff --git a/.github/workflows/debug-ssh.yml b/.github/workflows/debug-ssh.yml index 68a9e65..7822348 100644 --- a/.github/workflows/debug-ssh.yml +++ b/.github/workflows/debug-ssh.yml @@ -43,7 +43,7 @@ jobs: with: persist-credentials: false - - uses: whuppi/ci/actions/debug-ssh@v2.0.0 + - uses: whuppi/ci/actions/debug-ssh@v2.0.4 - name: Keep alive (touch /tmp/stop to end) shell: bash diff --git a/.github/workflows/full-test.yml b/.github/workflows/full-test.yml index 92ce204..81a854b 100644 --- a/.github/workflows/full-test.yml +++ b/.github/workflows/full-test.yml @@ -84,6 +84,11 @@ jobs: matrix: include: + # ── Package tests ── + - { name: "pkg: Linux (ubuntu-x64)", runner: ubuntu-24.04, make: test, timeout: 20 } + - { name: "pkg: macOS (macos-arm64)", runner: macos-14, make: test, timeout: 20 } + - { name: "pkg: Windows (win-x64)", runner: windows-2025-vs2026, make: test, timeout: 30 } + # ── Example journeys (host VM, in-memory) ── - { name: "int: Journeys (ubuntu-x64)", runner: ubuntu-24.04, make: test-example-matrix, timeout: 20 } - { name: "int: Journeys (macos-arm64) [P]", runner: macos-14, make: test-example-matrix, timeout: 20, portability: true } @@ -122,7 +127,7 @@ jobs: steps: - name: Check filter id: filter - uses: whuppi/ci/actions/matrix-filter@v2.0.0 + uses: whuppi/ci/actions/matrix-filter@v2.0.4 with: name: ${{ matrix.name }} filter: ${{ needs.inputs.outputs.filter }} @@ -132,7 +137,7 @@ jobs: if: steps.filter.outputs.match == 'true' with: persist-credentials: false - - uses: whuppi/ci/actions/make-target@v2.0.0 + - uses: whuppi/ci/actions/make-target@v2.0.4 if: steps.filter.outputs.match == 'true' with: make-target: ${{ matrix.make }} diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index d310678..1e1611f 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -23,4 +23,4 @@ jobs: permissions: contents: read # checkout reads .github/labels.json issues: write # labels are managed through the Issues API - uses: whuppi/ci/.github/workflows/labels.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/labels.yml@v2.0.4 diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 11644cb..9b4da8d 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -20,4 +20,4 @@ jobs: checks: permissions: contents: read # the reusable jobs only checkout + lint, read-only - uses: whuppi/ci/.github/workflows/pr-checks.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/pr-checks.yml@v2.0.4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e9996d6..efb468c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,11 @@ on: default: 'dev' type: choice options: [dev, prod] + runner: + description: "Runner for infra jobs (gate, discover, publish)" + type: choice + options: [ubuntu-24.04, macos-14, windows-2025-vs2026] + default: ubuntu-24.04 permissions: {} @@ -30,8 +35,9 @@ jobs: release: permissions: contents: write # create the release/tag, edit notes, ephemeral publish commit - uses: whuppi/ci/.github/workflows/release.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/release.yml@v2.0.4 with: branch: ${{ inputs.branch || github.ref_name }} + runner: ${{ inputs.runner || 'ubuntu-24.04' }} secrets: pub-credentials: ${{ secrets.PUB_CREDENTIALS }} diff --git a/.github/workflows/retry.yml b/.github/workflows/retry.yml index 5c627d8..783fa9e 100644 --- a/.github/workflows/retry.yml +++ b/.github/workflows/retry.yml @@ -27,4 +27,4 @@ jobs: retry: permissions: actions: write # gh run rerun re-runs the failed jobs of the run - uses: whuppi/ci/.github/workflows/retry.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/retry.yml@v2.0.4 diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml index 3aa1b37..a7afcb4 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/triage.yml @@ -29,4 +29,4 @@ jobs: contents: read # labeler reads .github/labeler.yml + the PR file list issues: write # assign maintainer on issue-opened events pull-requests: write # apply labels, revoke ready-to-test, post notices - uses: whuppi/ci/.github/workflows/triage.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/triage.yml@v2.0.4 diff --git a/.github/workflows/upgrade-check.yml b/.github/workflows/upgrade-check.yml index 3f84fd2..7fd3a18 100644 --- a/.github/workflows/upgrade-check.yml +++ b/.github/workflows/upgrade-check.yml @@ -27,7 +27,7 @@ jobs: permissions: contents: write # pushes the chore/flutter-sdk + chore/lockfiles branches pull-requests: write # opens / edits the upgrade PRs - uses: whuppi/ci/.github/workflows/upgrade-check.yml@v2.0.0 + uses: whuppi/ci/.github/workflows/upgrade-check.yml@v2.0.4 with: branch: dev diff --git a/.gitignore b/.gitignore index a03e829..ecd1ad1 100644 --- a/.gitignore +++ b/.gitignore @@ -321,3 +321,6 @@ pip-wheel-* *.temp *.orig .sass-cache/ + +# Local co-development override (points cellar at a sibling checkout) +pubspec_overrides.yaml diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 2e9c1c7..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "cellar"] - path = cellar - url = https://github.com/whuppi/cellar.git - branch = dev diff --git a/.pubignore b/.pubignore index 42e627a..2d75ff0 100644 --- a/.pubignore +++ b/.pubignore @@ -6,3 +6,9 @@ tool/ Makefile docs/ .githooks/ + +# Banner: ship only the optimized *-web-min.webp the README embeds. The +# heavy *-3x.png sources stay tracked in git (org-quality preservation) +# but out of the published download — nothing references them on pub.dev. +assets/cellar_flutter-banner-dark-3x.png +assets/cellar_flutter-banner-light-3x.png diff --git a/AGENTS.md b/AGENTS.md index e683576..d60e455 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,7 +29,7 @@ Manual edits to this file will be overwritten on the next stamp. ## What this tool does cellar_flutter is the Flutter front door for the pure-Dart `cellar` -object-storage core (pinned as the `cellar/` git submodule). It holds ONLY +object-storage core (a hosted dependency, version-locked). It holds ONLY what needs the Flutter engine: `openCellar()`, which resolves the platform storage roots via path_provider (behind a stub-default conditional import — web builds never compile path_provider) and @@ -82,8 +82,9 @@ When in doubt, read existing code in this repo and match it. Per-repo style cons - **Only engine-bound code lives here.** Anything pure Dart — including web code (`package:web` is SDK, not Flutter) — belongs in the - `cellar` core (its own repo; pinned here as a submodule). This package exists because path_provider needs the - Flutter plugin chain. + `cellar` core (its own repo; consumed from pub.dev at the locked + version). This package exists because path_provider needs the Flutter + plugin chain. - **path_provider is imported ONLY in `flutter_roots_native.dart`**, behind the conditional import in `flutter_roots.dart` — its API returns dart:io types, which don't compile for web. Never import the @@ -91,10 +92,11 @@ When in doubt, read existing code in this repo and match it. Per-repo style cons - **`openCellar` mirrors the core's `Cellar` constructor parameter for parameter.** A new core parameter means the same parameter here, forwarded, in the same change. -- **The core is a pinned submodule (`cellar/`, pubspec path dep).** - Core changes land in whuppi/cellar first, then the pin bumps here — - commit inside the submodule, push there, `git add cellar` here. Run - `make check` after any bump. +- **The core is a hosted dependency; `pubspec.lock` is the pin.** + Core changes land and release in whuppi/cellar first; the Dependabot + bump PR here certifies them against the matrix. For local + co-development use a gitignored `pubspec_overrides.yaml` + (`cellar: {path: ../cellar}`). - **Tests fake path_provider at `PathProviderPlatform.instance`** (the platform-interface seam) and assert storage actually lands under the fake roots — never just that calls succeed. diff --git a/CHANGELOG.md b/CHANGELOG.md index 59b8ce2..e75de26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,3 +59,7 @@ CONTENT RULES (never change) --> + +## 1.0.0 + +First stable release — cellar for Flutter, zero-setup storage on all six platforms. diff --git a/CHANGELOG.pre.md b/CHANGELOG.pre.md index 8c12681..06edc0b 100644 --- a/CHANGELOG.pre.md +++ b/CHANGELOG.pre.md @@ -62,9 +62,4 @@ CONTENT RULES (never change) ## 1.0.0-dev.0 -First release — the Flutter front door for `cellar`. - -- **API:** `openCellar()` — one call resolves the platform storage roots via path_provider, opens, and returns a ready `Cellar`; mirrors the core constructor's parameters -- **Re-export:** the full `cellar` core API from one import — apps never also depend on `cellar` -- **Platforms:** iOS, Android, macOS, Windows, Linux, web — the path_provider glue sits behind a stub-default conditional import, so web builds never compile it -- **Example:** the seven-tab demo app with device-matrix UI journeys and a per-platform integration smoke +First release. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6012b4d..aa942fe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Contributions are welcome. ## Setup ```bash -git clone --recursive https://github.com/whuppi/cellar_flutter.git +git clone https://github.com/whuppi/cellar_flutter.git cd cellar_flutter make hooks # activates commit-msg + pre-commit (run once) fvm install # downloads the SDK version pinned in .fvmrc @@ -16,8 +16,15 @@ fvm flutter test ``` **Requires:** [FVM](https://fvm.app) (`.fvmrc` pins the exact Flutter -version). The `cellar` core is a pinned git submodule at `cellar/` — -clone with `--recursive` (or run `git submodule update --init` after). +version). The `cellar` core resolves from pub.dev at the locked version. +Co-developing against a local core checkout? Drop a gitignored +`pubspec_overrides.yaml` next to each pubspec: + +```yaml +dependency_overrides: + cellar: + path: ../cellar # ../../cellar from example/ +``` **Without FVM:** all Makefile commands accept `DART` and `FLUTTER` overrides: @@ -41,9 +48,9 @@ Runs `format` + `analyze` (package + example) + `analyze-floor` device profile, on the host VM). Must pass. Don't suppress with `// ignore:` — fix the underlying issue. -Touching the `cellar` core too? Its changes land in its own repo -first; then bump the submodule pin here (commit inside `cellar/`, push -there, `git add cellar` here) and run `make check`. +Touching the `cellar` core too? Its changes land in its own repo and +release first; the Dependabot bump PR here runs the full matrix against +that release. --- diff --git a/Makefile b/Makefile index 4d51a60..4046206 100644 --- a/Makefile +++ b/Makefile @@ -59,8 +59,8 @@ analyze-floor: # pana's platform attribution — all six targets must survive the # conditional-import walk (the stub default is what makes web attribute). -# The cellar core is a submodule INSIDE the repo, so the gate's snapshot -# carries it and the `path: cellar` dep resolves — no wrapper needed. +# The cellar core is a published hosted dep, so pana resolves it exactly +# as pub.dev will. platforms: @DART="$(DART)" EXPECTED_PLATFORMS="android ios linux macos windows web" bash tool/platforms_gate.sh diff --git a/README.md b/README.md index 158f6d6..e33da5c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,20 @@ + +

+ + + + cellar_flutter — object storage for Flutter apps + +

+

pub package likes @@ -6,9 +23,9 @@ license: MIT

-Object storage for Flutter apps. One `openCellar()` call gives you a ready-to-use store on iOS, Android, macOS, Windows, Linux, and web — real files on native, IndexedDB in the browser, identical API everywhere. +File and data storage for Flutter with zero setup. One call gives you a ready-to-use store on iOS, Android, macOS, Windows, Linux, and web — real files on native, IndexedDB in the browser, identical API everywhere. -Named partitions with self-cleaning lifecycle rules, tenant scoping, bring-your-own encryption, streaming I/O that never buffers a whole object, atomic writes, typed errors, and platform-local handles for FFI and browser APIs. No `kIsWeb`, no platform branches, no setup — anywhere in your code. +Partitions with self-cleaning rules, per-user scoping, bring-your-own encryption, streaming that never buffers a whole file, atomic writes, typed errors — and a real path or URL whenever a native or browser API needs one. No `kIsWeb`, no platform branches, anywhere in your code. > like it? a [⭐ star](https://github.com/whuppi/cellar_flutter) or [👍 like](https://pub.dev/packages/cellar_flutter) is the entire marketing budget. [Bugs & features →](https://github.com/whuppi/cellar_flutter/issues) @@ -46,7 +63,7 @@ dependencies: cellar_flutter: ``` -That's the whole setup. No permissions, no manifest entries, no entitlements, no per-platform Dart — storage lands in your app's private area, which every OS grants for free. +No permissions, no manifest entries, no per-platform Dart — storage lands in your app's private area, which every OS grants for free. --- @@ -67,7 +84,7 @@ await cellar.delete('notes/hello'); await cellar.close(); // app shutdown, profile switch, etc. ``` -`openCellar` is byte-identical on all six platforms. That's the shape of every call after it too: a `/`-separated key in, bytes or metadata out — `write`, `read`, `head`, `list`, `copy`, `materialize`, same shape, a different verb. +`openCellar` is byte-identical on all six platforms. That's the shape of every call after it: a `/`-separated key in, bytes or metadata out — `write`, `read`, `head`, `list`, `copy`, `materialize`.
🧩 what openCellar actually does @@ -271,11 +288,11 @@ Rule of thumb: **Flutter app → this package. Anything else → `cellar`.** You ## Not in the box -- **Queries, key-value prefs, sync, user-visible files** — the core's [Not in the box](https://github.com/whuppi/cellar#not-in-the-box) covers what cellar deliberately isn't, and what to reach for instead. -- **Widgets.** This package is storage, not UI — nothing here draws. Pair `materialize` with your image/video widgets. -- **Permission flows.** Cellar's locations need no permissions on any platform, so there's nothing to request. +- **Queries, key-value prefs, sync, user-visible files** — the core's [Not in the box](https://github.com/whuppi/cellar#not-in-the-box) covers what cellar deliberately isn't, with a reasoned WONT_DO row each. +- **Widgets** — this package is storage, not UI; pair `materialize` with your image/video widgets. +- **Permission flows** — cellar's locations need none on any platform. -Missing something you need? [Open an issue](https://github.com/whuppi/cellar_flutter/issues); it's how we gauge demand. +Missing something? [Open an issue](https://github.com/whuppi/cellar_flutter/issues). --- @@ -293,7 +310,7 @@ The [example app](example/) exercises every capability in one file — seven tab | [Capabilities](docs/CAPABILITY_ROADMAP.md) | Status per capability | | [Updating](docs/UPDATING.md) | Maintenance recipes and the pinned-behavior watchlist | | [Contributing](CONTRIBUTING.md) | Setup, PR workflow, keeping openCellar in lockstep with the core | -| [cellar's docs](https://github.com/whuppi/cellar/tree/dev/docs) | The engine's architecture, durability mechanics, roadmap | +| [cellar's docs](https://github.com/whuppi/cellar/tree/v1.0.0/docs) | The engine's architecture, durability mechanics, roadmap | --- diff --git a/SECURITY.md b/SECURITY.md index b2b5bbe..ff218a9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,6 @@ # Security Policy -Covers `cellar_flutter` — the Flutter front door. The storage engine itself (encryption seam, tenant scoping, key grammar, durability) is the `cellar` core; its policy lives at [whuppi/cellar](https://github.com/whuppi/cellar/blob/dev/SECURITY.md). The `cellar/` directory here is a pinned submodule of it — engine reports go there. +Covers `cellar_flutter` — the Flutter front door. The storage engine itself (encryption seam, tenant scoping, key grammar, durability) is the `cellar` core, consumed from pub.dev at the locked version; its policy lives at [whuppi/cellar](https://github.com/whuppi/cellar/blob/v1.0.0/SECURITY.md) — engine reports go there. ## Reporting a vulnerability @@ -10,7 +10,7 @@ Report privately via [GitHub Security Advisories](https://github.com/whuppi/cell - **Root resolution landing outside the app's private area** — `openCellar` promises storage under the OS-granted support/cache directories. If the resolution ever hands the core a directory outside the app sandbox (a path-join bug, a platform-channel value used unvalidated), that's a security report. -- **The re-export lying about the core** — this package re-exports `package:cellar` wholesale. A packaging or pinning mistake that ships a different core than the one named in the release notes (stale submodule, wrong version constraint at publish) is in scope here, because this repo owns the pin. +- **The re-export lying about the core** — this package re-exports `package:cellar` wholesale. A packaging mistake that ships against a different core than the release notes name (wrong version constraint at publish) is in scope here, because this repo owns the constraint. ## What's NOT in scope @@ -22,7 +22,7 @@ Report privately via [GitHub Security Advisories](https://github.com/whuppi/cell ## Operational notes (known, accepted) -- **The core rides in as a pinned submodule** — the pin is bumped deliberately per release, so a core security fix reaches this package one pin-bump later, not automatically. The release flow pins the published `cellar` version range instead, with the same property. +- **The core version is locked, not floating** — a core security fix reaches this package one dependency bump later, not automatically; the caret range lets consumer apps pick the fix up immediately. ## Response diff --git a/analysis_options.yaml b/analysis_options.yaml index 6e393c7..9aec4e8 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,10 +1,6 @@ include: package:flutter_lints/flutter.yaml analyzer: - exclude: - # The pinned cellar core submodule — its own repo analyzes it; here - # it's vendored source (same treatment as pdf_manipulator's vendor/). - - 'cellar/**' language: strict-casts: true strict-inference: true diff --git a/assets/cellar_flutter-banner-dark-3x.png b/assets/cellar_flutter-banner-dark-3x.png new file mode 100644 index 0000000..164a790 Binary files /dev/null and b/assets/cellar_flutter-banner-dark-3x.png differ diff --git a/assets/cellar_flutter-banner-dark-web-min.webp b/assets/cellar_flutter-banner-dark-web-min.webp new file mode 100644 index 0000000..db295e9 Binary files /dev/null and b/assets/cellar_flutter-banner-dark-web-min.webp differ diff --git a/assets/cellar_flutter-banner-light-3x.png b/assets/cellar_flutter-banner-light-3x.png new file mode 100644 index 0000000..c337141 Binary files /dev/null and b/assets/cellar_flutter-banner-light-3x.png differ diff --git a/assets/cellar_flutter-banner-light-web-min.webp b/assets/cellar_flutter-banner-light-web-min.webp new file mode 100644 index 0000000..db11527 Binary files /dev/null and b/assets/cellar_flutter-banner-light-web-min.webp differ diff --git a/cellar b/cellar deleted file mode 160000 index 54bf7bf..0000000 --- a/cellar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 54bf7bf2a3d9c6a70336b6095154a0782a0d2081 diff --git a/deploy/.deploy/secrets.json.example b/deploy/.deploy/secrets.json.example new file mode 100644 index 0000000..7e171c3 --- /dev/null +++ b/deploy/.deploy/secrets.json.example @@ -0,0 +1,5 @@ +{ + "pub_dev": { + "credentials_json": "FULL_CONTENTS_OF_PUB_CREDENTIALS_JSON" + } +} diff --git a/deploy/.deploy/secrets.sh b/deploy/.deploy/secrets.sh new file mode 100755 index 0000000..9253153 --- /dev/null +++ b/deploy/.deploy/secrets.sh @@ -0,0 +1,301 @@ +#!/bin/bash +# ============================================================================ +# cellar_flutter secrets manager +# +# Manages secrets for whuppi/cellar_flutter ONLY. +# Bitwarden Secrets Manager is the source of truth. +# GitHub Environments are CI-accessible copies. +# +# Usage: +# ./secrets.sh set / Store in Bitwarden + push to GitHub +# ./secrets.sh get / Read from Bitwarden +# ./secrets.sh list List secret names for an environment +# ./secrets.sh dump Show values (careful!) +# ./secrets.sh upload Push all from Bitwarden → GitHub +# ./secrets.sh rm / Delete from Bitwarden + GitHub +# ============================================================================ +set -e + +REPO="whuppi/cellar_flutter" +BWS="${HOME}/bin/bws --color no" +BW_PREFIX="cellar_flutter" +export BWS_SERVER_URL="${BWS_SERVER_URL:-https://vault.bitwarden.eu}" + +# ── Auth ───────────────────────────────────────────────────────────────────── + +if [ -z "$BWS_ACCESS_TOKEN" ]; then + BWS_ACCESS_TOKEN=$(security find-generic-password -a "whuppi" -s "BWS_ACCESS_TOKEN" -w 2>/dev/null || true) + export BWS_ACCESS_TOKEN +fi + +if [ -z "$BWS_ACCESS_TOKEN" ]; then + echo "Not authenticated. Run: bws-auth" + exit 1 +fi + +if ! $BWS project list > /dev/null 2>&1; then + echo "Bitwarden auth failed. Run: bws-auth" + exit 1 +fi + +# ── Project ID ─────────────────────────────────────────────────────────────── + +PROJECT_ID=$($BWS project list 2>/dev/null | python3 -c " +import sys,json +for p in json.load(sys.stdin): + if p['name'] == 'whuppi-infra': + print(p['id']) + break +") + +# ── Helpers ────────────────────────────────────────────────────────────────── + +bws_get() { + $BWS secret list 2>/dev/null | python3 -c " +import sys,json +for s in json.load(sys.stdin): + if s['key'] == '$1': + print(s['value']) + sys.exit(0) +" 2>/dev/null +} + +bws_get_id() { + $BWS secret list 2>/dev/null | python3 -c " +import sys,json +for s in json.load(sys.stdin): + if s['key'] == '$1': + print(s['id']) + sys.exit(0) +" 2>/dev/null +} + +bws_set() { + local key="$1" value="$2" + local existing_id + existing_id=$(bws_get_id "$key") + if [ -n "$existing_id" ]; then + $BWS secret edit "$existing_id" --key "$key" --value "$value" > /dev/null 2>&1 + else + $BWS secret create "$key" "$value" "$PROJECT_ID" > /dev/null 2>&1 + fi +} + +validate_env() { + case "$1" in + dev|prod) return 0 ;; + *) echo "Invalid env: $1 (use dev or prod)"; exit 1 ;; + esac +} + +# ── Commands ───────────────────────────────────────────────────────────────── + +cmd_set() { + local path="$1" value="$2" + if [ -z "$path" ] || [ -z "$value" ]; then + echo "Usage: ./secrets.sh set / " + echo "Example: ./secrets.sh set prod/PUB_CREDENTIALS '{...}'" + exit 1 + fi + + local env key + env=$(echo "$path" | cut -d/ -f1) + key=$(echo "$path" | cut -d/ -f2-) + validate_env "$env" + + local bw_key="$BW_PREFIX/$env/$key" + bws_set "$bw_key" "$value" + echo "✓ Bitwarden: $bw_key" + + local ghn + ghn="$key" + gh secret set "$ghn" --env "$env" --body "$value" --repo "$REPO" + echo "✓ GitHub: $REPO → $env → $ghn" +} + +# Deletes from both backends, scoped to THIS repo only: GitHub by --repo/--env, +# Bitwarden by the "$BW_PREFIX/$env/" key prefix — it can't reach another repo's +# secrets. Idempotent: a missing secret is reported, not an error. +cmd_rm() { + local path="$1" + if [ -z "$path" ]; then + echo "Usage: ./secrets.sh rm /" + echo "Deletes the secret from Bitwarden AND this repo's GitHub environment." + exit 1 + fi + + local env key + env=$(echo "$path" | cut -d/ -f1) + key=$(echo "$path" | cut -d/ -f2-) + validate_env "$env" + + local ghn + ghn="$key" + if gh secret list --env "$env" --repo "$REPO" 2>/dev/null | grep -qE "^${ghn}[[:space:]]"; then + if gh secret delete "$ghn" --env "$env" --repo "$REPO" 2>/dev/null; then + echo "✓ GitHub: $REPO → $env → $ghn (deleted)" + else + echo "✗ GitHub: $REPO → $env → $ghn (delete FAILED — still present)" + exit 1 + fi + else + echo "· GitHub: $REPO → $env → $ghn (not present)" + fi + + local bw_key="$BW_PREFIX/$env/$key" + local id + id=$(bws_get_id "$bw_key") + if [ -n "$id" ]; then + if $BWS secret delete "$id" > /dev/null 2>&1; then + echo "✓ Bitwarden: $bw_key (deleted)" + else + echo "✗ Bitwarden: $bw_key (delete failed)" + exit 1 + fi + else + echo "· Bitwarden: $bw_key (not present)" + fi +} + +cmd_get() { + local path="$1" + if [ -z "$path" ]; then + echo "Usage: ./secrets.sh get /" + exit 1 + fi + + local env key + env=$(echo "$path" | cut -d/ -f1) + key=$(echo "$path" | cut -d/ -f2-) + validate_env "$env" + + local value + value=$(bws_get "$BW_PREFIX/$env/$key") + if [ -n "$value" ]; then + echo "$value" + else + echo "(not found: $BW_PREFIX/$env/$key)" + exit 1 + fi +} + +cmd_list() { + local env="$1" + if [ -z "$env" ]; then + echo "Usage: ./secrets.sh list " + exit 1 + fi + validate_env "$env" + + $BWS secret list 2>/dev/null | python3 -c " +import sys,json +secrets = json.load(sys.stdin) +prefix = '$BW_PREFIX/$env/' +matched = sorted([s['key'].replace(prefix, '') for s in secrets if s['key'].startswith(prefix)]) +if not matched: + print('No secrets found for: $BW_PREFIX/$env') +else: + for name in matched: + print(f' {name}') + print(f'\n {len(matched)} secrets') +" +} + +cmd_dump() { + local env="$1" + if [ -z "$env" ]; then + echo "Usage: ./secrets.sh dump " + echo "⚠️ Shows secret VALUES." + exit 1 + fi + validate_env "$env" + + $BWS secret list 2>/dev/null | python3 -c " +import sys,json +secrets = json.load(sys.stdin) +prefix = '$BW_PREFIX/$env/' +matched = sorted([(s['key'].replace(prefix, ''), s['value']) for s in secrets if s['key'].startswith(prefix)]) +if not matched: + print('No secrets found for: $BW_PREFIX/$env') +else: + for name, value in matched: + display = value if len(value) < 80 else value[:40] + '...[truncated]' + print(f' {name}={display}') +" +} + +cmd_upload() { + local target="$1" + if [ -z "$target" ]; then + echo "Usage: ./secrets.sh upload " + exit 1 + fi + + if [ "$target" = "all" ]; then + upload_env "dev" + upload_env "prod" + else + validate_env "$target" + upload_env "$target" + fi + + echo "" + echo "=== Upload complete ===" +} + +upload_env() { + local env="$1" + echo "" + echo "=== $BW_PREFIX/$env → GitHub ===" + + gh api "repos/$REPO/environments/$env" -X PUT > /dev/null 2>&1 + + $BWS secret list 2>/dev/null | python3 -c " +import sys,json +secrets = json.load(sys.stdin) +prefix = '$BW_PREFIX/$env/' +for s in secrets: + if s['key'].startswith(prefix): + name = s['key'].replace(prefix, '') + print(f'{name}\t{s[\"value\"]}') +" | while IFS=$'\t' read -r key value; do + local ghn + ghn="$key" + if gh secret set "$ghn" --env "$env" --body "$value" --repo "$REPO" 2>/dev/null; then + echo " ✓ $ghn" + else + echo " ✗ $ghn (failed)" + fi + done + + echo "Done: $env" +} + +# ── Dispatch ───────────────────────────────────────────────────────────────── + +case "${1:-}" in + set) cmd_set "$2" "$3" ;; + get) cmd_get "$2" ;; + list) cmd_list "$2" ;; + dump) cmd_dump "$2" ;; + upload) cmd_upload "$2" ;; + rm) cmd_rm "$2" ;; + *) + echo "cellar_flutter secrets manager" + echo "" + echo "Usage:" + echo " ./secrets.sh set / Store in Bitwarden + GitHub" + echo " ./secrets.sh get / Read from Bitwarden" + echo " ./secrets.sh list List secret names" + echo " ./secrets.sh dump Show values (careful!)" + echo " ./secrets.sh upload Push Bitwarden → GitHub" + echo " ./secrets.sh rm / Delete from Bitwarden + GitHub" + echo "" + echo "Examples:" + echo " ./secrets.sh set prod/PUB_CREDENTIALS '{\"accessToken\":\"...\",\"refreshToken\":\"...\"}'" + echo " ./secrets.sh get prod/PUB_CREDENTIALS" + echo " ./secrets.sh list prod" + echo " ./secrets.sh upload all" + echo " ./secrets.sh rm prod/OLD_KEY" + ;; +esac diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c4e80c8..d3372d4 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -4,7 +4,7 @@ How the package is wired. One call (`openCellar`), one conditional import, one re-export of the core. For capability status see [`CAPABILITY_ROADMAP.md`](CAPABILITY_ROADMAP.md); for maintenance recipes see [`UPDATING.md`](UPDATING.md); for the engine itself see the -core's docs at [`../cellar/docs/`](../cellar/docs/). +[core's docs](https://github.com/whuppi/cellar/tree/v1.0.0/docs). --- diff --git a/docs/CAPABILITY_ROADMAP.md b/docs/CAPABILITY_ROADMAP.md index b75ff02..689a1ed 100644 --- a/docs/CAPABILITY_ROADMAP.md +++ b/docs/CAPABILITY_ROADMAP.md @@ -1,8 +1,8 @@ # Capability Roadmap Statuses: **DONE** · **BUILDING** · **PLANNED** · **WONT_DO** (with -reason). The core's capabilities live in -[`cellar/docs/CAPABILITY_ROADMAP.md`](../cellar/docs/CAPABILITY_ROADMAP.md). +reason). The core's capabilities live in the +[cellar roadmap](https://github.com/whuppi/cellar/blob/v1.0.0/docs/CAPABILITY_ROADMAP.md). | Capability | Status | Notes | |---|---|---| @@ -11,8 +11,8 @@ reason). The core's capabilities live in | Stub-default conditional import (web never compiles path_provider) | DONE | | | Package tests (fake platform seam, roots proven used) | DONE | | | Example app + journeys + per-platform smoke | DONE | Lives in `example/` | -| Full gate set (analyze / analyze-floor / lint-shell / pana platforms / verify-web dart2js+wasm) | DONE | Stock platforms gate — the `cellar/` submodule travels inside pana's snapshot, so the path dep resolves; verdict 6/6 platforms | +| Full gate set (analyze / analyze-floor / lint-shell / pana platforms / verify-web dart2js+wasm) | DONE | Stock gates over the hosted core dep; pana verdict 6/6 platforms | | CI via the shared workflow repo | BUILDING | Stock single-package callers (fast PR gate + label-triggered full-test with the example legs + release lanes); first real run at repo go-live | -| Repo go-live (GitHub whuppi/cellar_flutter, submodule URL flip, branch protection) | DONE | Live with device_io-parity settings; `.gitmodules` points at github.com/whuppi/cellar and a fresh `--recursive` clone resolves it | -| Publish to pub.dev | PLANNED | Maintainer-gated; release flow swaps the submodule path dep to the published `cellar` version | +| Repo go-live (GitHub whuppi/cellar_flutter, branch protection, environments) | DONE | Live with device_io-parity settings | +| Publish to pub.dev | PLANNED | Maintainer-gated. The core is a hosted dep (`^1.0.0-dev.0`, lock-certified) — no release-time rewriting needed; cellar releases first when a change spans both | | Extra Flutter sugar (lifecycle widgets, provider glue) | WONT_DO | The package stays a front door; app-state patterns belong to apps | diff --git a/docs/UPDATING.md b/docs/UPDATING.md index 7d72144..ea3b11c 100644 --- a/docs/UPDATING.md +++ b/docs/UPDATING.md @@ -18,21 +18,24 @@ Mirror the core's `Cellar` default constructor exactly — openCellar is a pass-through plus roots. New core constructor parameter → same parameter here, forwarded. Test: the package test constructs with it. -## S2 — Bump the core pin +## S2 — Bump the core -`cellar` is a pinned git submodule at `cellar/` (pubspec path dep into -it). To pick up core changes: land them in whuppi/cellar first, then -`cd cellar && git fetch && git checkout `, `cd .. && git add -cellar`, commit, and run `make check`. The submodule-commit trap -applies (workspace rule): never leave the pin pointing at a commit -that isn't pushed in the core repo. +`cellar` is a hosted dependency; `pubspec.lock` certifies the exact +version CI ran against. When cellar releases, Dependabot opens the bump +PR — the matrix on that PR is the certification. The bump also updates +the version-tagged core doc links (README, SECURITY, docs/) — the +`core_link_pin` test fails the PR otherwise. To test against +UNRELEASED core changes, open a throwaway PR overriding the dep with a +git ref (`cellar: {git: {url: ../cellar.git, ref: dev}}`-style) — read +the verdict, close unmerged. ## S3 — Release Same two-lane changelog model as the core (`CHANGELOG.pre.md` dev / -`CHANGELOG.md` stable), stamped by the release tooling when the repo -opens. The packages version independently; this one constrains its -`cellar` dependency to the compatible range at publish time. +`CHANGELOG.md` stable). The packages version independently — the +pubspec's caret floor names the oldest core this release certifies, +and the lock names the exact one CI ran against. Release cellar first +when a change spans both; the bump PR (S2) precedes the release here. --- diff --git a/example/pubspec.lock b/example/pubspec.lock index 9c24e44..2f8d767 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -28,10 +28,11 @@ packages: cellar: dependency: "direct main" description: - path: "../cellar" - relative: true - source: path - version: "0.0.0" + name: cellar + sha256: aca21eb6f772224c7dd08d8849b4b09bc1e14c6c2ef762958ca4636bdb057a66 + url: "https://pub.dev" + source: hosted + version: "1.0.0" cellar_example_test_support: dependency: "direct dev" description: @@ -219,10 +220,10 @@ packages: dependency: transitive description: name: matcher - sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.18" + version: "0.12.19" material_color_utilities: dependency: transitive description: @@ -235,10 +236,10 @@ packages: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" objective_c: dependency: transitive description: @@ -299,10 +300,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_windows: dependency: transitive description: @@ -408,10 +409,10 @@ packages: dependency: transitive description: name: test_api - sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.8" + version: "0.7.11" typed_data: dependency: transitive description: @@ -432,10 +433,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "046d3928e16fa4dc46e8350415661755ab759d9fc97fc21b5ab295f71e4f0499" + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" url: "https://pub.dev" source: hosted - version: "15.1.0" + version: "15.2.0" web: dependency: transitive description: @@ -469,5 +470,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.11.0-296.3.beta <4.0.0" + dart: ">=3.11.0 <4.0.0" flutter: ">=3.38.4" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 8176b5c..ddc435a 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -19,8 +19,7 @@ dependencies: path: ../ # Direct dep for the low-level kit imports (EncryptedBackend, the # BYO seams) the Encrypt/Custom tabs demonstrate. - cellar: - path: ../cellar + cellar: ^1.0.0 dev_dependencies: flutter_test: diff --git a/pubspec.lock b/pubspec.lock index b2e4e6a..1f5b81e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -28,10 +28,11 @@ packages: cellar: dependency: "direct main" description: - path: cellar - relative: true - source: path - version: "0.0.0" + name: cellar + sha256: aca21eb6f772224c7dd08d8849b4b09bc1e14c6c2ef762958ca4636bdb057a66 + url: "https://pub.dev" + source: hosted + version: "1.0.0" characters: dependency: transitive description: @@ -174,10 +175,10 @@ packages: dependency: transitive description: name: matcher - sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.18" + version: "0.12.19" material_color_utilities: dependency: transitive description: @@ -190,10 +191,10 @@ packages: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" objective_c: dependency: transitive description: @@ -347,10 +348,10 @@ packages: dependency: transitive description: name: test_api - sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.8" + version: "0.7.11" typed_data: dependency: transitive description: @@ -400,5 +401,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.11.0-0 <4.0.0" + dart: ">=3.11.0 <4.0.0" flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index 47ac493..bf6b20c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,9 @@ name: cellar_flutter version: 0.0.0 description: >- - The Flutter front door for cellar: openCellar() resolves platform - storage roots via path_provider and returns an opened, ready-to-use - Cellar — one identical line on iOS, Android, macOS, Windows, Linux, - and web. Re-exports the full cellar API. + Cross-platform file and data storage for Flutter, zero setup — files + land in the right folder on Android, iOS, macOS, Windows, Linux, and + web. Caching, auto-cleanup, encryption. homepage: https://github.com/whuppi/cellar_flutter repository: https://github.com/whuppi/cellar_flutter issue_tracker: https://github.com/whuppi/cellar_flutter/issues @@ -12,26 +11,22 @@ issue_tracker: https://github.com/whuppi/cellar_flutter/issues topics: - storage - cache + - files - encryption - - indexeddb - cross-platform -# Not published yet — this line goes away when the repo opens and the -# release tooling takes over. Consumed by path from sewali + bokumi. -publish_to: none - environment: - sdk: ">=3.11.0-0 <4.0.0" # -0 floor: the pinned fvm SDK is a 3.11 beta + sdk: ">=3.11.0 <4.0.0" dependencies: flutter: sdk: flutter - # The pure-Dart core this package fronts (and re-exports) — a pinned - # git submodule of whuppi/cellar. CI clones --recursive; the release - # flow swaps this to the published version. - cellar: - path: cellar + # The pure-Dart core this package fronts (and re-exports). The lock + # certifies the exact version CI ran against; Dependabot bumps it per + # cellar release. Local co-development: pubspec_overrides.yaml (see + # CONTRIBUTING). + cellar: ^1.0.0 # Storage roots on native platforms (support + cache directories). # Imported only behind the native side of a conditional import — web diff --git a/test/core_link_pin_test.dart b/test/core_link_pin_test.dart new file mode 100644 index 0000000..c63527c --- /dev/null +++ b/test/core_link_pin_test.dart @@ -0,0 +1,39 @@ +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; + +/// Doc links into the core repo must point at the tag of the version the +/// pubspec names, so readers land on the docs of the exact core in use. +/// A core bump PR that forgets the links fails here. +void main() { + test('core repo links carry the pubspec version tag', () { + final pubspec = File('pubspec.yaml').readAsStringSync(); + final floor = RegExp( + r'^ cellar: \^(\S+)$', + multiLine: true, + ).firstMatch(pubspec); + expect(floor, isNotNull, reason: 'pubspec must carry cellar: ^'); + final tag = 'v${floor!.group(1)}'; + + final docs = [ + File('README.md'), + File('SECURITY.md'), + ...Directory( + 'docs', + ).listSync().whereType().where((f) => f.path.endsWith('.md')), + ]; + final ref = RegExp('whuppi/cellar/(?:blob|tree)/([^/]+)/'); + for (final doc in docs) { + for (final m in ref.allMatches(doc.readAsStringSync())) { + expect( + m.group(1), + tag, + reason: + '${doc.path} links the core at "${m.group(1)}" — ' + 'must be $tag (the pubspec version). Update the link when ' + 'bumping the core dependency.', + ); + } + } + }); +} diff --git a/tool/versions.env b/tool/versions.env index 57560bb..e118a1f 100644 --- a/tool/versions.env +++ b/tool/versions.env @@ -1,68 +1,11 @@ -# Single source of truth for pinned tool + binary versions used by whuppi/ci's -# composite actions and reusable workflows. Sourced by the scripts that need -# them — bump in ONE place, never inline. Plain `KEY="value"` so it's both -# shell-sourceable and trivially greppable. +# Single source of truth for pinned tool versions LOCAL to this package. +# Sourced by the scripts that need them (tool/platforms_gate.sh) — bump in ONE +# place, never inline. Plain KEY="value" so it's both shell-sourceable and +# greppable. # -# source "$CI_ROOT/tool/versions.env" -# -# Every entry here is a pinned EXTERNAL tool/binary that CI downloads and -# hash-verifies through tool/fetch_verified.sh. -# -# Who bumps what: -# tool/ci/upgrade.sh (via self-upgrade.yml, daily PR in THIS repo) — -# everything in this file: FVM_*, CHROME_*, ACTIONLINT_VERSION, -# ZIZMOR_VERSION, BORE_*. One bump reaches every consumer through the -# next whuppi/ci release. -# Dependabot (in THIS repo) — GitHub-action SHAs pinned in the workflows. -# Consumer repos — their own Flutter SDK (.fvmrc) + lockfiles, -# via the reusable upgrade-check.yml. - -# fvm TOOL — downloaded + verified by actions/capabilities/fvm. Pins the tool; -# the Flutter SDK itself is pinned separately by each consumer's .fvmrc. -# Hashes self-computed from the release assets (leoafarias/fvm publishes no -# digests). -FVM_VERSION="4.1.2" -FVM_SHA256_LINUX_X64="12b0656688450972750cb714fc5e44ed2dbdd6b1c6813ba6ba6fb71841c17fe4" -FVM_SHA256_MACOS_ARM64="0b2a146986c51f06331f135f0bdf2a202eb57f55d7edd420c9078e8520e4c033" -FVM_SHA256_MACOS_X64="7bbfcb6883ea67ce532163704f5625eba7ecf340084be707cde71a28fefff1d8" -FVM_SHA256_WINDOWS_X64="9a18b4daac98dac3c3230ff67ccc644d5a7875d1fc09fb7d848cb2900b9478b8" - -# actionlint — workflow linter run in the reusable pr-checks gate. Go-installed -# by this tag; Go verifies the module checksum, so no separate sha is tracked. -ACTIONLINT_VERSION="1.7.12" - -# zizmor — the security half of the pr-checks gate, run via `pipx run`. pipx -# resolves the version from PyPI, so no separate sha is tracked. -ZIZMOR_VERSION="1.26.1" - -# ── Pinned binary downloads (verified via tool/fetch_verified.sh) ── -# sha256 values are the upstream-published digest where one exists, else -# self-computed from the release asset. Bump alongside the version. - -# bore tunnel binary (actions/debug-ssh). The action sources this file and -# builds its download URLs from BORE_VERSION, so the version lives here beside -# its hashes — one place for upgrade.sh to bump. -BORE_VERSION="v0.6.0" -BORE_SHA256_LINUX_X64="e484d1e3acba77169b773f31a5bfb34192d4b660f44a094a658a2522cd2270f7" -BORE_SHA256_MACOS_ARM64="65f43a67b90874700538bdb6064c5e92276e64dfba24f5cd72ef24a035eec3bc" -BORE_SHA256_WINDOWS_X64="01709c64fe2787cdc9a21d7030b0f08ad72dff0c36b7ecb72f4f667a55a34b4f" - -# Chrome for Testing — chrome + chromedriver pinned per platform, so web tests -# run a verified, reproducible browser (actions/capabilities/chrome). -# chrome-for-testing publishes no digests, so these are self-computed. -# upgrade.sh re-bumps on Chrome's ~4-week Stable cadence; the CDN prunes old -# versions, so the pin must be kept fresh or the download 404s. -CHROME_VERSION="150.0.7871.46" -CHROME_SHA256_LINUX_X64="ad115a7498a17f53f6ed0914458326c6516addc756224db14c32184a9b1ab078" -CHROME_SHA256_MACOS_ARM64="9b6c6fbbda6f2948c74425828bd18f0e59542fd2beb056697478c38a956d83cb" -CHROME_SHA256_WINDOWS_X64="2245f764e024897195bce1cf6ff16d60544351e4d1b68edb6956ea875ab8b929" -CHROMEDRIVER_SHA256_LINUX_X64="2bd858c27c5d913bc9574e4fb7196161acbefd7f911d9a4b1e01a4cd36095716" -CHROMEDRIVER_SHA256_MACOS_ARM64="fe616458e12b959c23565a4c3b057392e80f8bcb7b59410d9e493d6fcd864f1b" -CHROMEDRIVER_SHA256_WINDOWS_X64="934274246dfd0d1185f2b9acf5441bc6e72ee2deeafea6996f9a868be3089e13" # source "$(dirname "$0")/versions.env" # -# PANA_VERSION tracks pub.dev's latest that resolves on this repo's SDK — -# cellar pins the beta channel (.fvmrc), and pana >=0.23.13 requires the -# stable 3.11 floor the beta doesn't satisfy. Bump past 0.23.12 when the -# pin moves to stable. -PANA_VERSION="0.23.12" +# PANA_VERSION tracks pub.dev's LATEST so the platform gate runs the same pana +# pub.dev runs. tool/ci/upgrade.sh (the daily upgrade-check.yml pins job) bumps +# it automatically in its own reviewed PR — the same radar as pdf_manipulator. +PANA_VERSION="0.23.14"