Summary
Observed on modal 1.5.1 and still present on main as of a483eed:
Deploying an app twice from the same commit prints "Deployment skipped: no changes detected" as expected only when all local files use copy=True. If instead I use add_local_dir or add_local_python_source and copy=False on a directory with more than one file, then every deploy creates a new version despite identical file contents and paths.
It looks like it's caused by MountGetOrCreateRequest.files in _Mount._load_mount (modal/mount.py) having non-deterministic ordering: _select_files returns list(set(...)), whose order varies with PYTHONHASHSEED, and the result is passed through two unordered async_map stages, so the mount's content checksum and the function's definition_id change each run.
Sorting files by filename before building the request should fix it.
Relatedly, mount_ids in _functions.py is assigned from a set and has the same non-determinism.
Version
1.5.1
App ID
No response
Summary
Observed on modal 1.5.1 and still present on main as of a483eed:
Deploying an app twice from the same commit prints "Deployment skipped: no changes detected" as expected only when all local files use
copy=True. If instead I useadd_local_diroradd_local_python_sourceandcopy=Falseon a directory with more than one file, then every deploy creates a new version despite identical file contents and paths.It looks like it's caused by
MountGetOrCreateRequest.filesin_Mount._load_mount(modal/mount.py) having non-deterministic ordering:_select_filesreturnslist(set(...)), whose order varies withPYTHONHASHSEED, and the result is passed through two unorderedasync_mapstages, so the mount's content checksum and the function'sdefinition_idchange each run.Sorting
filesbyfilenamebefore building the request should fix it.Relatedly,
mount_idsin_functions.pyis assigned from asetand has the same non-determinism.Version
1.5.1
App ID
No response