We actually do use bazel, where I have a love-hate relationship with that as well.
It's incredibly painful and a lot of overhead to bazel allthethings. Using bazel to define dependencies is another double-edged sword where you can get them enumerated, but EVERYTHING has to use it. You can't check out a repo and go, you have to check out the repo and bazel whatever you're trying to do. No "I know Python, let me venv && pip install -r requirements.txt or pipenv ...", now you have to incant the magic bazel incantations instead of native stuff. Same for NPM/Yarn, Rails, Go, etc. And that's assuming there's good support for your language/framework of choice; a Rails acquisition a few years ago was awful because bazel didn't have good support for it.
We have a double digit number of humans on our DevEx team dedicated to this stuff, and it's still painful. That speaks to the effort you're talking about.
On the love side, being able to query for "what does this dep trigger a rebuild for" without guessing is about as good as you can get, and having a requirements.txt-equivalent that magically packages itself into a standalone set of files with minimal effort is pretty sweet. The overhead to get from 0 to 1 is a lot (like... A _L_O_T_), but 1 to N is easy.