pub icon indicating copy to clipboard operation
pub copied to clipboard

`locked` option in `pubspec.yaml`

Open yjbanov opened this issue 4 years ago • 5 comments

The default behavior of pub is non-hermetic. Running pub get from the same codebase frequently leads to different sets of dependencies, causing flaky builds. pubspec.lock exists and can be checked into the repo, but pub get silently overwrites it, and therefore it does not solve the hermeticity issue. Furthermore, the silent overwriting is annoying. You end up with unintended local changes from unrelated actions, such as opening a project in VSCode (which runs pub get/flutter packages get behind-the-scenes).

A better mode would be to have pub get do the following two things:

  1. Validate that pubspec.lock is in sync with pubspec.yaml, and fail with a non-zero exit code if it's not (missing pubspec.lock is considered out-of-sync). Nothing is written to disk as part of this step.
  2. Fetch dependencies exactly as specified in pubspec.lock. The only file written to is .packages.

To generate or update pubspec.lock a user would run pub get --overwrite (or -w for short).

To allow package maintainers opt into this mode a new top-level pubspec.yaml property can be introduced, e.g.:

locked: true

/cc @kevmoo

yjbanov avatar Mar 08 '21 19:03 yjbanov

@yjbanov – moved this to the pub repo

kevmoo avatar Mar 08 '21 20:03 kevmoo

See also https://github.com/dart-lang/pub/issues/2890 which is a different way to solve this.

Currently, pubspec.lock is only overwritten when pubspec.yaml is not satisfied by pubspec.lock.

jonasfj avatar Mar 09 '21 10:03 jonasfj

You end up with unintended local changes from unrelated actions, such as opening a project in VSCode (which runs pub get/flutter packages get behind-the-scenes).

This really shouldn't happen. Unless you've changed the contents of pubspec.yaml since pubspec.lock was written (or upgraded the Flutter SDK, which often forces new versions of some packages).

jonasfj avatar Mar 09 '21 10:03 jonasfj

This really shouldn't happen. Unless you've changed the contents of pubspec.yaml since pubspec.lock was written (or upgraded the Flutter SDK, which often forces new versions of some packages).

Unfortunately it does happen. To reproduce:

  • git clone https://github.com/felixblaschke/simple_animations.git
  • cd simple_animations
  • flutter packages get

I think what you mean is that it shouldn't happen as long as pubspec.yaml and pubspec.lock are in sync with each other. That may be true, but the problem is that it's too easy for the two to end up out of sync. The problem is less technical, and more social. I think the https://github.com/dart-lang/pub/issues/2890 proposal solves the problem technically, but not socially, because people will simply not type --pristine or --locked.

yjbanov avatar Mar 10 '21 19:03 yjbanov

Unfortunately it does happen. To reproduce:

  • git clone https://github.com/felixblaschke/simple_animations.git
  • cd simple_animations
  • flutter packages get

Great example :D

I think what you mean is that it shouldn't happen as long as pubspec.yaml and pubspec.lock are in sync with each other. That may be true, but the problem is that it's too easy for the two to end up out of sync.

Yes, these should be in sync, at-least if you have pubspec.lock in revision control, the odds are pretty good that you'll notice changes when commit. Indeed this seems to happen here too, past 3 commits to pubspec.yaml:

  • https://github.com/felixblaschke/simple_animations/commit/366946a257cf1baf2583d8932d19310a8ae7bfbd
    • Bump version number, no changes to pubspec.lock necessary.
  • https://github.com/felixblaschke/simple_animations/commit/7da6b2fba1a5a958665f5c5357a7d3efe70eb510
    • Bump version number, no changes to pubspec.lock necessary.
  • https://github.com/felixblaschke/simple_animations/commit/16a8f75801e9c4b1e70cda05e9ea122a036d5e69
    • Added a dependency in pubspec.yaml
    • Also updated pubspec.lock as expected.

I think the reason these files go out of sync so easily is that the Flutter SDK pins transitive package versions:

I wish Flutter wouldn't pin dependencies, especially packages we already own and control. Pinning creates a lot of incompatible packages, churn in pubspec.lock is another unfortunate side-effect.


But for packages there are pros/cons to keeping pubspec.lock under revision control. The upside with keeping pubspec.lock under revision controls is that you know that all developers of the package is using the same version of all dependencies. And indeed you know that stuff you run in CI is the same as you run locally.

On the other hand, by not keeping pubspec.lock under revision control you know that CI will always run against the latest versions of all dependencies. Indeed you could configure a CI job to run dart pub downgrade and run tests with the lowest versions resolvable.

For application developing, keeping pubspec.lock under revision control is always best, otherwise you might deploy dependencies you haven't tested.

jonasfj avatar Mar 11 '21 15:03 jonasfj