Skip to content

fix: harden archive install with staging directory and network resilience#1013

Open
leoafarias wants to merge 42 commits into
mainfrom
issue-688-relink
Open

fix: harden archive install with staging directory and network resilience#1013
leoafarias wants to merge 42 commits into
mainfrom
issue-688-relink

Conversation

@leoafarias

Copy link
Copy Markdown
Member

This PR mirrors #966 on a fresh head branch so tooling can re-associate the PR correctly.\n\nIncludes:\n- Staging-directory archive install to prevent cache loss on failures\n- HTTP connection timeout for archive downloads\n- Improved TLS handshake error guidance\n- Expanded archive service test coverage

@vercel

vercel Bot commented Feb 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fvm Ready Ready Preview, Comment Jun 22, 2026 3:42pm

Adds --archive flag to install and use commands, enabling faster
installations from pre-compiled archives instead of git clones.

Key features:
- Downloads Flutter SDK from archives (2-3x faster than git)
- SHA256 checksum verification for security
- Supports stable, beta, and dev channels
- Works with FLUTTER_STORAGE_BASE_URL for corporate mirrors
- Cross-platform extraction (zip/tar.xz)

Implementation:
- New ArchiveService handles download, verification, and extraction
- Commands accept --archive flag
- EnsureCacheWorkflow passes flag through to FlutterService
- Validates unsupported scenarios (forks, commits, custom versions)

Testing:
- Unit tests for archive installation flow
- Tests for unsupported version validation
- Mock FlutterService for test isolation

Resolves #688
- Fix content-length check in archive_service.dart (use != -1 instead of > 0)
- Fix undefined log_message function in uninstall.sh
- Remove plan.md development artifact (842 lines)
- Add cleanupAndRethrow() helper in _downloadArchive() to eliminate
  duplicate cleanup pattern across three catch blocks
- Create comprehensive test suite (25 tests) for ArchiveService covering
  version validation, SHA256 checksum, directory handling, archive
  format detection, and FlutterSdkRelease model properties
The FileLocker mechanism was intentionally removed in d694ec5, but
references were accidentally reintroduced in ff03ba6 when adding
bare git cache handling. This removes the orphaned imports while
preserving the valuable bare repository detection logic.

Changes:
- Remove import of non-existent file_lock.dart
- Remove FileLocker field and createLock usage
- Remove lock acquisition/release from updateLocalMirror
- Keep all bare repo detection and handling logic intact
…ence

- Use staging directory pattern to protect existing cached SDKs from data
  loss when archive download, checksum, or extraction fails
- Add HTTP connection timeout (30s) to prevent stalled downloads
- Add TLS HandshakeException handling with guidance for corporate mirrors
- Add 12 new tests: safe install behavior, structure flattening,
  extraction validation, @dev qualifier, platform extraction, network
  errors, and archive URL construction
- Fix MockFlutterService to validate archive version types

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens the archive-based Flutter SDK installation path to be more failure-tolerant (staging installs, better network behavior/error guidance) and expands regression coverage to ensure the --archive flag propagates through workflows and CI.

Changes:

  • Add ArchiveService with staging-directory installs, checksum verification, extraction, and improved network/TLS error handling.
  • Propagate useArchive through EnsureCacheWorkflow, install, and use commands; disable git-cache behavior when archive mode is enabled.
  • Add extensive archive regression/unit test coverage and a CI “archive-regression” job that runs a scripted local regression agent and uploads artifacts.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/testing_utils.dart Extends MockFlutterService.install to capture and simulate archive installs in tests.
test/src/workflows/ensure_cache_ci_test.dart Adds coverage ensuring useArchive propagates through corrupted-cache reinstalls and workflow calls.
test/services/git_service_test.dart Adds tests asserting correct git invocation for bare vs non-bare git-cache repos.
test/services/archive_service_test.dart Adds comprehensive tests for archive install validation, download/extract failures, staging safety, and network errors.
test/commands/use_command_test.dart Adds fvm use --archive behavioral tests (success + unsupported version cases).
test/commands/install_command_test.dart Adds fvm install --archive behavioral tests (success + unsupported version cases).
scripts/local_regression_agent.sh Introduces a local regression “agent” script used both locally and in CI for deterministic archive-focused checks.
pubspec.yaml Moves crypto to main dependencies for runtime archive checksum verification.
pubspec.lock Reflects crypto dependency change from dev to main.
lib/src/workflows/ensure_cache.workflow.dart Adds useArchive parameter propagation; skips git validations and git-cache updates in archive mode.
lib/src/utils/context.dart Registers ArchiveService in default DI generators.
lib/src/services/git_service.dart Updates local mirror update logic to support bare repos (--git-dir) and adds stronger “recreate mirror” paths.
lib/src/services/flutter_service.dart Adds useArchive install path, delegating to ArchiveService.
lib/src/services/archive_service.dart New service implementing resilient archive download/verify/extract with staging/finalize logic and better network/TLS errors.
lib/src/commands/use_command.dart Adds --archive flag and forwards it to EnsureCacheWorkflow.
lib/src/commands/install_command.dart Adds --archive flag and forwards it to EnsureCacheWorkflow.
agents/local-regression-testing-agent.md Documents the regression agent workflow, stages, and reporting contract.
.github/workflows/test.yml Adds archive-regression CI job; conditionally uploads coverage only when Codecov token is present; switches Dart version for release tool steps.
.github/workflows/README.md Documents the new archive-regression job in CI.
.fvmrc Adds repository-level FVM config for local/dev usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/src/services/archive_service.dart Outdated
Comment thread lib/src/services/archive_service.dart Outdated
Comment thread scripts/local_regression_agent.sh Outdated
test-setup now runs with FVM_USE_GIT_CACHE=true so it creates a bare
mirror during setup. The mirror is then cloned locally to the path
tests expect (~/fvm_test_cache/gitcache), so integration-style tests
that call the real FlutterService.install() clone from local mirror
instead of GitHub.
…ndant tests

The pre-seed git cache fix added ~5 min of mirror creation overhead,
making CI slower. Revert it and bump test-os timeout from 30 to 45
minutes to handle normal Windows/macOS CI variance.

Remove 6 command-level archive validation tests that duplicate unit
tests in archive_service_test.dart (same static method, same errors).
_targetDirFromInvocation now parses -DestinationPath from PowerShell
Expand-Archive commands, not just Unix -d/-C flags. Also relax
extraction failure error assertion to be platform-agnostic.
20-minute timeouts were too tight — all three jobs timed out during
test/analysis steps because setup (checkout, SDK install, pub get,
git cache creation) consumes significant time before tests even start.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants