There is no shared code (aside from dependencies, which are managed independently) - the "master" repo is simply a list of git refs (by way of submodules), and a script to bring up the services.
Microservices must be compatible with each other. We cant simply bring up the latest version of "microservice A", because comsuming "microservice B" may not have been updated to account for API changes (which are enforced by testing contracts). Thats what this master repo is for, to track which microservices work with each other.
Obviously, the master application is dependent on the microservices. Microservices are dependent on specific versions of other microservices, etc. That is the problem I am trying to solve.
You need to keep your interface contracts more stable, so you do not have to deploy all at once. You are building a distributed monolith if you have to deploy them all at once.
> We cant simply bring up the latest version of "microservice A"
This should not be the case. Build your services to be backwards compatible. Avoid making breaking changes, but when you do, make a new API version & maintain the previous one until it's no longer used.
i.e. /v1/blah
-- breaking change introduced --
/v1/blah - maintains backwards compatible behavior
/v2/asdf - new behavior exposed as v2, update microservice B at some point in the future to use this
We have contracts to ensure API compatibility. That means we CAN simply rip out the old API and put in a new one, but the integration will fail until the consumer contracts sync up.
As these are internal services (microservices) that only we consume, there is no need to keep old cruft around.