133 karma · joined December 23, 2022
It's also language agnostic because you can technically run anything through moon, but support may vary. https://moonrepo.dev/docs/faq#can-we-run-other-languages
- Use git submodules. Have the node repo have a submodule on the app repo.
- Publish the shared code to a private registry (like github's package registry), and pull it in as an npm package.
I wouldn't say moon is hermetic, nor are we trying to be. We don't use the sandbox approach for tasks, and run against the original files. For the languages we support, this works best.
As for deterministic, we try to be. We have a "toolchain" where we download languages/tools in the background, and run tasks using these tools. This ensures, at minimum, that the same version/variant of a tool is used across machines.
> In the same vein as those questions how does caching work?
It's content based. We also hash other kinds of inputs depending on the language that is running.
> If the configuration language is YAML how am I expected to implement new behavior? (and other questions)
Our focus right now is on non-compiled languages, primarily web languages, where custom behavior (like Starlark) is not necessary. In the future, this may change.
In regards to build graph invalidation, we attempt to hash pieces at the granular level. This includes per file content hashing, and for dependencies (those in `package.json`), we parse the lockfile and extract the resolved version/integrity hashes. We can probably improve this further, but this has been working great so far.
As for phantom dependencies, this isn't something moon solves directly. We encourage users to use pnpm or yarn 3, where these phantom problems are less likely. We don't believe moon should solve this, and instead, the package managers should.
If you have any other questions or concerns, would love to hear them.
Once we starts supporting more languages, especially compile based ones (probably Rust first), our decision around YAML will probably change. Off the top of my head, a non-YAML format would probably be used as a secondary format, kind of like how a Dockerfile works.
Bazel doesn't work well for every language, but for those languages that it does, it definitely makes sense to use Bazel. For those languages that work better with something more lightweight, that's where moon comes in. I'm assuming you work at Google, so you're experience around Bazel is probably much better than those that don't work at Google.
I appreciate all the feedback and comments though, very much appreciated.
For the languages we currently support, this is more than enough. Once we dive deeper into compiled languages (probably starting with Rust), we'll look into more granular reactivity and possible use something like sccache.
I can see the benefits of "generating code" within the BUILD file, but honestly, we haven't required it yet, and have been able to do most things with explicit configuration. Our token syntax helps with some dynamic aspects of this.
Maybe in the future we'll revisit this.
The second reason is we wanted something language agnostic and not proprietary. It also helps that many other tools, like GitHub actions, are written in YAML.
And lastly, we wanted a format that developers are familiar with, and won't need to spend time learning. Requiring developers to understand a special syntax simply to define a task to run is something we want to avoid.
For example, in CI, tasks are only ran if they are affected by files changed in the pull request. No more running everything unnecessarily. We also support remote caching of artifacts, which helps to speed up CI even further, by avoiding long build times.