Beyond that there's a working central repository where all the important libraries are (and it's one of the few ecosystems that actually enforces code signing of all published libraries), and also a free repository server that you can run on-premises (and that's a normal JVM app that runs like anything else in the ecosystem) and use for private publishing and/or to proxy remote repositories to make sure you will always be able to rebuild any previously successful build even if a remote repository goes down. The release plugin enforces good practices by default, e.g. you tag a release and rebuild from that release, ensuring you can always recreate any given release; you may build a -SNAPSHOT which depends on another -SNAPSHOT, which makes it lightweight to make a change to an upstream library and check that it has the right effect on your downstream application (and the first-class IDE integration dovetails very nicely with this), but releases are only allowed to depend on releases, which ensures they're reproducible and immutable. None of this should be hard, and I think other ecosystems are gradually getting it right, but Maven just seems to have managed to make all the right choices and avoid all the pitfalls. You don't hear as much about it as you do about, say, NPM, but I think that's at least partly because it rarely goes wrong, so a lot of the time it's invisible to developers.
That, along with its horrible XML markup abortion, was exactly what I hated about it. Any behavior that was even moderately unusual was a monumental pain to implement.
Build scripts by their very nature need to be turing complete because the need for customization isn't rare enough.
>Beyond that there's a working central repository where all the important libraries are
Python got this 17 years ago, a good 4 years before maven even existed.
They really don't. The build process should be simple and the same for every project; any actual logic can go in first-class code, that's what it's for (whereas finding out that a file somehow wasn't built, or got substituted before being built, makes for an extremely unpleasant surprise when investigating an issue). I find Turing-complete build systems end up with an analogue of https://martinfowler.com/bliki/SnowflakeServer.html - the "snowflake build", where every module builds slightly differently.
It is not supposed to be Turing complete, for things that need that customization, as the GP stated, you use extensions.
For anyone who likes maven, checkout cargo in Rust. It got everything right, and made build extensions easier to integrate.
Seriously? Maven was one of the things that made me run away screaming from the Java ecosystem.