Avoid deploying something if it has not changed since the last deploy
In our mod jam today, we discovered that deploying a mod for Tangent would result in the Tangent schema being redeployed as well. This could be due to:
- the last build time being ignored because the settings for the build-in-deploy were different to the build-for-development (which can happen because deploy builds for release)
- the local last build time being after the deployment's build time
We need some way of determining if a build is identical to the deployed build, and if so, choosing not to deploy it at all. Maybe the build process is extended to include all OutAssets, these assets are hashed, and then that hash is included as part of the remote build manifest; this hash can then be compared to the local hash, and if they're identical, the deploy is skipped. (Of course, the manifest itself would need to be included in this hash.)
Need to think about this some more, I think.
Note to self: Some kind of Merkle tree could come in handy here.
WORKAROUND: use only deployment key in dependencies (no path) so they don't get redeployed.
The easiest solution might be to always do a build, and then use the deployment hash file-skip logic to skip deployment altogether if the hashes of all the files locally match the ones that are deployed. That might require revising the deployment logic a little, though.
@philpax @ten3roberts I'm preserving the discussion we just had on discord.
[10:43]Philpax: I might add in an --only-this-package or try to fix it myself; it doesn't matter that much for the jams because we're using the deployment IDs, but it does make working on in-tree packages with dependencies challenging
[10:43]Philpax: did you have a fix in mind?
[10:49]Kuba: Just a vague idea of hashing the contents of the input files. Because we can't rely on stability of the outputs (wasm files change on rebuild, the same for some of the assets as they have random entity ids inside). But TBH I haven't explored enough of how the dependencies are deployed now.
[10:51]Kuba: But then I'm not sure if it's feasible to get all of the input files.
[10:51]Tei: I think hashing the input files would be the way to go, as if you are using git that is also what you commit
[10:52]Tei: Git will (due to .gitignore) not consider anything different if the output files change, only the input files
[10:53]Tei: It may produce slight discrepencies if for example the toolchain is updated or the compiler lays out things different in the binaries inbetween version, so at the worst case you could end up with different behavior on your machine and on someone else
[10:53]Tei: But that happen with git alone already and is not specific to us
[10:54]Kuba: We should also include ambient version (maybe even commit ref) in the hash.
[10:54]Tei: Yes
[10:55]Tei: upgrading the ambient version and publishing will cause you to publish code which relies on new features not present in the uploaded original games version
[10:55]Tei: How about rustc version?
[10:55]Kuba: And also pass that fingerprint to the backend when deploying so then we can query if given deployment id matches given fingerprint.
[10:55]Philpax: so drop the build time check, have the build process do a pre-build scan of all the files, build a hash, and store that instead
[10:56]Philpax: if you add/modify/delete a file or [use a different Ambient version](https://github.com/AmbientRun/Ambient/issues/847) it'll rebuild the package
[10:56]Philpax: seems reasonable to me
[10:56]Tei: Great
[10:56]Tei: I think this is also good since we are consistent with how cargo handles versions
[10:56]Kuba: metadata.toml sounds like a good place to put the fingerprint
[10:56]Philpax: maybe we keep the build time check just as an even-faster out (does it produce false negatives?)
[10:58]Kuba: As an early exit so we don't have to hash everything?
[10:59]Kuba: 🤔
[10:59]Philpax: yeah
[10:59]Philpax: that's what it does right now - checks if any files have a last modified time greater than the time in the metadata, and if so, builds
[10:59]Philpax: but we can make that better still using the hash, since the lmt check should produce false positives but no false negatives
[11:00]Kuba: Yip, I don't see a valid case where it would produce false negatives.