Skip to main content

FAQ

General

Where did the name "moon" come from?

The first incarnation of the name was a misspelling of monorepo (= moonrepo). This is where the domain moonrepo.dev came from, and our official company, moonrepo, Inc.

However, moonrepo is quite a long name with many syllables, and as someone who prefers short 1 syllable words, moon was perfect. The word moon also has great symmetry, as you can see in our logo!

But that's not all... moon is also an acronym. It originally stood for monorepo, organization, orchestration, and notification tool. But since moon can also be used for polyrepos, we replaced monorepo with management (as shown on the homepage). This is a great acronym, as it embraces what moon is trying to solve:

  • Manage repos, projects, and tasks with ease.
  • Organize projects and the repo to scale.
  • Orchestrate tasks as efficiently as possible.
  • Notify developers and systems about important events.

Will moon support other languages?

Yes! Although we're focusing right now on the web ecosystem (Node.js, Rust, Go, PHP, Python, etc), we've designed moon to be language agnostic and easily pluggable in the future. View our supported languages for more information.

Will moon support continuous deployment?

Yes! We plan to integrate CD with the current build and CI system, but we are focusing on the latter 2 for the time being. Why not start using moon today so that you can easily adopt CD when it's ready?

What should be considered the "source of truth"?

If you're a frontend developer, you'll assume that a package.json is the source of truth for a project, as it defines scripts, dependencies, and repo-local relations. While true, this breaks down with additional tooling, like TypeScript project references, as now you must maintain tsconfig.json as well as package.json. The risk of these falling out of sync is high.

This problem is further exacerbated by more tooling, or additional programming languages. What if your frontend project is dependent on a backend project? This isn't easily modeled in package.json. What if the backend project needs to be built and ran before running the frontend project? Again, while not impossible, it's quite cumbersome to model in package.json scripts. So on and so forth.

moon aims to solve this with a different approach, by standardizing all projects in the workspace on moon.yml. With this, the moon.yml is the source of truth for each project, and provides us with the following:

  • The configuration is language agnostic. All projects are configured in a similar manner.
  • Tasks can reference other tasks easily. For example, npm scripts referencing rake tasks, and vice verse, is a non-ideal experience.
  • Dependencies defined with dependsOn use moon project names, and not language specific semantics. This field also easily populates the dependency/project graphs.
  • For JavaScript projects:

By using moon as the source of truth, we can ensure a healthy repository, by accurately keeping everything in sync, and modifying project/language configuration to operate effectively.

info

With all that being said, moon supports implicit dependency scanning, if you'd prefer to continue utilizing language specific functionality, instead of migrating entirely to moon.

How to stop moon formatting JSON and YAML files?

To ensure a healthy repository state, moon constantly modifies JSON and YAML files, specifically package.json and tsconfig.json. This may result in a different formatting style in regards to indentation. While there is no way to stop or turn off this functionality, we respect EditorConfig during this process.

Create a root .editorconfig file to enforce a consistent syntax.

.editorconfig
[*.{json,yaml,yml}]
indent_style = space
indent_size = 4

Projects & tasks

How to pipe or redirect tasks?

Piping (|) or redirecting (>) the output of a task (maybe to another task), whether via stdin or through inputs, is currently not possible. However, you could execute a custom bash script that handles this for you, for example:

scripts/pipe.sh
#!/usr/bin/env bash
moon project foo --json | jq ...
moon.yml
tasks:
pipe:
command: 'bash ./scripts/pipe.sh'
platform: 'system'
caution

Be careful when using this approach, as it may not be portable across operating systems, nor will it utilize the toolchain. For example, if your Bash script uses node, this will be the binary found on your machine, and not the one in moon's toolchain. proto helps to solve this, but it's not a perfect solution.

How to run multiple commands within a task?

Only system tasks can run multiple commands via && or ; syntax. This is possible as we execute these commands within a shell, and not directly with the toolchain.

moon.yml
tasks:
multiple:
command: 'mkdir test && cd test'
platform: 'system'

Non system-tasks cannot run multiple commands for the following reasons:

  • A task in moon is a represented as a single command, with its own arguments, inputs, outputs, and more. This isolation is required for task inheritance to work correctly. For example, if you had multiple commands in a task and were using inheritance, where should arguments be appended?
  • If using the integrated toolchain, we cannot easily statically analyze the command string to determine where the binary is located. For example, given the multi-command rm -rf ./dist && node ./build.js && tsc --build, moon has no knowledge of where to find these binaries without considerable effort at runtime.
    • rm can be assumed to exist on the system, but what if it's actually an npm package? This also isn't portable on Windows.
    • node is straight forward enough. This is Node.js.
    • tsc is what exactly? A node module? An npm global? A system command? moon has no idea, and since we can't use Node.js's built-in module resolution, we need to locate it ourselves.
  • The platform setting on each task easily solves these problems, but requires a single command per task to avoid unnecessary complexity.

However, we do suggest the following alternatives:

  • Create a task for each command, and link them as dependencies with deps. This allows for each command to be incrementally cached (when enabled).
  • Create a task for each command, and run them concurrently with moon run.
  • Wrap all commands in an external file, and execute that file instead. Refer to the piping question above for an example.
  • Avoid using the toolchain and assume everything exists on PATH.

How to run tasks in a shell?

By default, all tasks run in a shell, based on the task's shell option, as demonstrated below:

moon.yml
tasks:
# Runs in a shell
global:
command: 'some-command-on-path'

# Custom shells
unix:
command: 'bash -c some-command'
options:
shell: false
windows:
command: 'pwsh.exe -c some-command'
options:
shell: false

Can we run other languages?

Yes! Although our toolchain only supports a few languages at this time, you can still run other languages within tasks by setting their platform to "system". System tasks are an escape hatch that will use any command available on the current machine.

moon.yml
tasks:
# Ruby
lint:
command: 'rubocop'
platform: 'system'
# PHP
test:
command: 'phpunit tests'
platform: 'system'

However, because these languages are not supported directly within our toolchain, they will not receive the benefits of the toolchain. Some of which are:

  • Automatic installation of the language. System tasks expect the command to already exist in the environment, which requires the user to manually install them.
  • Consistent language and dependency manager versions across all machines.
  • Built-in cpu and heap profiling (language specific).
  • Automatic dependency installs when the lockfile changes.
  • And many more.

JavaScript ecosystem

Can we use package.json scripts?

We encourage everyone to define tasks in a moon.yml file, as it allows for additional metadata like inputs, outputs, options, and more. However, if you'd like to keep using package.json scripts, enable the node.inferTasksFromScripts setting.

View the official documentation for more information on this approach, including risks, disadvantages, and caveats.

Can moon version/publish packages?

At this time, no, as we're focusing on the build and test aspect of development. With that being said, this is something we'd like to support first-class in the future, but until then, we suggest the following popular tools:

Why is npm/pnpm/yarn install running twice when running a task?

moon will automatically install dependencies in a project or in the workspace root (when using package workspaces) when the lockfile or package.json has been modified since the last time the install ran. If you are running a task and multiple installs are occurring (and it's causing issues), it can mean 1 of 2 things:

  • If you are using package workspaces, then 1 of the project's triggering the install is not listed within the workspaces field in the root package.json (for npm and yarn), or in pnpm-workspace.yml (for pnpm).
  • If the install is triggering in a non-JavaScript related project, then this project is incorrectly listed as a package workspace.
  • If you don't want a package included in the workspace, but do want to install its dependencies, then it'll need its own lockfile.

Troubleshooting

How to resolve the "version 'GLIBC_X.XX' not found" error?

This is typically caused by running moon in an old environment, like Ubuntu 18, and the minimum required libc doesn't exist or is too old. Since moon is Rust based, we're unable to support all environments and versions perpetually, and will only support relatively modern environments.

There's not an easy fix to this problem, but there are a few potential solutions, from easiest to hardest:

  • Run moon in a Docker container/image that has the correct environment and libs. For example, the node:latest image.
  • Upgrade the enviroment to a newer one. For example, Ubuntu 18 -> 22.
  • Try and install a newer libc (more information).

For more information on this problem as a whole, refer to this in-depth article.