Adds a system to build.py which can automatically determine which
version of each upstream framework (.NET, NodeJS, others in the future)
a given HEAD is at in the submodules, and provide that build argument
into the Docker builds.
This will ensure we can reliably build versions on either side of a
framework version transition (i.e. both stable and master) without any
manual work.
For an explanation of how it works, see the comments in `build.yaml`.
Future code framework updates will need the `build.yaml` updated to
include the relevant (merge) commit hash and version.
Also adds better logging, including this new framework version as well
as a record of the Docker build commands for each build.