Skip to content

Offload 0.10.0

Latest

Choose a tag to compare

@DanverImbue DanverImbue released this 20 Oct 02:19
6998230

Minor release. The image cache is now keyed on the image recipe, which stops stale base images from being reused. The CLI and config are backward compatible. The library's public Rust API has breaking changes, listed below, which is why this is 0.10.0 rather than 0.9.15.

Image cache keyed on the image recipe (#263)

A cached base image is now identified by its checkpoint commit plus the recipe it was built from, compared for exact equality. The old key was the checkpoint commit plus the config file path, which was wrong in both directions:

  • Stale image reuse. Editing sandbox_init_cmd or provider.dockerfile without touching a build_inputs file reused the old image, and nothing was logged. Any recipe change is now a cache miss.
  • Duplicate builds. Configs that differed only in [framework], [report] or sandbox_project_root each built their own base image. Configs with the same recipe now share one base image.
  • Working-tree leak. In a checkpoint build, include_cwd, relative copy_dirs and .dockerignore were read from the live working tree. They now come from the exported checkpoint tree, and the live-tree inputs that remain are digested into the recipe.

The recipe holds:

  • The builder inputs. On Modal these are dockerfile, the include_cwd directory and the bundled modal_sandbox.py. On the default provider they are prepare_command and working_dir.
  • copy_dirs and --copy-dir, in order.
  • sandbox_init_cmd.
  • Digests of everything the build reads from outside the checkpoint tree: copy sources outside the repository, the gitignored files the export copies in, and tracked symlinks whose targets are outside the repository or missing. The digests include file mode bits.

Changing post_patch_cmd, [framework], [groups], [report], sandbox_project_root, env, cpu_cores or memory_gb does not rebuild the base image. The full design is in plans/image-cache-key.spec.md.

Fixed in the same change:

  • The default provider resolves relative copy_dirs and --copy-dir sources against its working_dir when one is set, because that is where prepare_command runs.
  • Absolute symlinks that point into the repository are rewritten to point at the exported checkpoint tree's copy of their target, not the live tree.
  • The recipe's file walk no longer follows symlinked directories. Before, a link cycle such as loop -> . made offload run, offload build and offload checkpoint-status fail.

New command: offload checkpoint-status

Prints HEAD, the checkpoint commit and its distance from HEAD, the cached image, the mode the next run would use, and the current recipe name. It then prints one line per note entry, saying whether the entry matches, which recipe fields differ, or that it is a legacy entry from an older Offload. --remote NAME sets the remote to fetch notes from (default origin).

Upgrading

  • No config changes are needed, and every existing TOML file keeps its meaning.
  • Cache entries written by older versions are ignored, so the first run after upgrading rebuilds the base image once per recipe for each active checkpoint.
  • Older versions keep reading and writing their own entries in refs/notes/offload-images. When an older version writes a note on a commit, it strips the new fields from that commit's entries, so the next 0.10.0 run rebuilds that image once.

Breaking library API changes

These affect only code that uses offload as a Rust library:

  • image_cache::CheckpointInfo and image_cache::LatestCommitInfo are removed.
  • image_cache::resolve_latest_commit and image_cache::resolve_checkpoint return only the base commit SHA, and no longer take config_path or no_cache.
  • image_cache::resolve_base takes copy_dirs instead of the config path.
  • image_cache::write_note_for_commit takes the Recipe.
  • image_cache::ResolvedBase has a new public field, recipe.
  • git::ImageEntry has four new public fields: recipe, config_path, offload_version and built_at.
  • New public items: the image_cache::recipe module and git::path_within_repo.

Dependencies

  • New: sha2 0.10 for recipe digests, and humantime 2 for note timestamps.
  • async-trait goes from 0.1.89 to 0.1.92 so clippy 1.99 passes.

Full changelog: v0.9.14...v0.10.0