Home

Awesome

Mono

Multi language tool for managing single and mono repository packages.

Installation

Install mono by downloading the git repository or a specific release, and then running the setup script. Mono will add itself to your $PATH, which will require a reload of your shell configuration.

cd <path to install mono to>
git clone git@github.com:appsignal/mono.git
cd mono
script/setup
# Reload your shell
source ~/.bashrc
source ~/.zshrc

Usage

After installation the mono executable should be available in any directory. See the list of commands for which commands can be performed.

mono <command> [options]

Do you need a quick guide or refresher on how mono works? Read the quick start guide.

Dry run

Note: Dry run is not fully implemented yet. While it won't publish your packages to a package manager, it will update version files in packages, delete changeset files and update their changelogs.

Don't want to run the command for real, but want to see what commands it will perform? Use the dry run feature. Set the DRY_RUN=true environment variable to use dry run mode.

DRY_RUN=true mono publish

Configuration

Configuration is done in the mono.yml file in the root of the repository you want to manage. Create a new config file by running mono init and customize it later.

# mono.yml example
---
language: nodejs
repo: "https://github.com/appsignal/appsignal-javascript"
npm_client: "yarn"
packages_dir: "packages"
clean:
  command: "npm run clean"
test:
  command: "npm run test"

Configuration options

Customize commands

Every preconfigured mono command can be customized by overriding the command that is run. For the command configuration, add a command key and specify which command to run as the value. This command will be run in every package.

build:
  command: echo I am run inside the package

Commands that can be customized:

Hooks

Every command can be customized by adding hooks. These hooks are run once before (pre) and after (post) the configured command.

build:
  pre:  echo I am run _before_ the build command
  post: echo I am run _after_ the build command

Customize version updater

If the built-in version updater does not work for your project, or you're using a "custom" language, you can customize the reading and updating of the package version.

Specify the read_version and write_version config options to point to scripts to execute.

read_version:  script/read_package_version
write_version: script/update_package_version

Commands

Init

Add mono to a project. Mono will ask you a couple questions about which language the project is written in, and where it can find the packages. If a project is not a mono repo, you can skip the packages step and it will configure it as a single package project.

Commit the mono.yml config file with any other configuration you want to add to your project.

Bootstrap

Set up the packages in the project on the host. This command installs the packages dependencies so the packages are ready for development or testing. For Node.js projects the packages are also linked on the host, so other projects on the host can load these local projects in.

mono bootstrap

Options

Build

Build packages in the project. Every package will be build using the language specific build process. This step is also run before the publish command to ensure the latest build will be published.

Test

Test packages in the project. Every package will be tested using the language specific test command.

Changeset

Changeset add

Add a new changeset to a package in the project. Run this command from the root of the project and it will prompt you with several questions to create a new changeset file. This command is meant as a convenience, it only writes the file changeset, which can also be created manually.

mono changeset add

Prompts:

  1. Choose the package for which the changeset applies.
    • When the project is a mono repo, mono will prompt you with a list of packages to choose from.
  2. Summarize the change:
    • Create a small one line summary of the change. This will be used as the changeset filename.
  3. Choose the changeset type.
    • Choose which bump level the changeset is about. This is one of these types: add/change/deprecate/remove/fix/security. This helps categorize the types of changes per release in the updated changelog in mono publish.
  4. Choose the bump level.
    • Choose which bump level the changeset is about. This is one of the bump levels specified below. This level affects how mono will determine the new version number of the package upon mono publish.
  5. Lastly mono will ask you if you want to open the changeset file in your configured editor. Add more content to the changeset to make the changelog more complete for people reading it.

After this commit the changeset file and submit your change. When mono publish is run the changeset file will be removed and its contents added to the CHANGELOG file.

Publish

Publish new versions of the package(s) in the project with the publish command. This command will scan all packages for changeset files and prepare a new release for those that have them. It will automatically bump the version and update the changelog of all the packages.

mono publish

Prereleases

If you want to first publish a prerelease, use any of the prerelease option flags. If the current is already a prerelease of the same type, it will bump the prerelease version.

mono publish --alpha
mono publish --beta
mono publish --rc

Examples of releases:

1.0.0         + patch changeset           = 1.0.1
1.0.0         + patch changeset + --alpha = 1.0.1-alpha.1
1.0.0-alpha.1 + patch changeset + --alpha = 1.0.1-alpha.2
1.2.3-alpha.1 + minor changeset + --alpha = 1.3.0-alpha.1
1.0.0         + minor changeset + --rc    = 1.1.0-rc.1
1.0.0.alpha.1 + minor changeset           = 1.0.0
1.0.1.alpha.1 + minor changeset           = 1.1.0

Clean

Clean the project to before the build step.

mono clean

Clean the project package(s) to a before build state.

Unbootstrap

Resets the project to a state before the initial bootstrap. This command removes all dependencies and deletes temporary directories.

Run the clean command before this command if you also want to undo the build step.

mono unbootstrap

Run

Run a custom command in every package in the project. By giving mono run a command it will execute it in every package. With the example below it will run the do_something Rake task.

mono run rake do_something

Only run commands for specific packages

To only run a mono command for specific packages, select the packages with the --package option. This is supported for the following commands:

# Single package
mono <command> --package package_one

# Multiple packages
mono <command> --package package_one,package_two

Publishing

Mono is published using mono. When a new release is ready to be published run the publish command. Since mono is not published as a Ruby gem, the gem build and gem push steps are skipped. Mono will only push the new version to the repository, along with all the other normal publish steps.

mono publish

Development

Installation for development

Mono has no runtime dependencies, but does have some dependencies for development.

Install the dependencies by running the following command:

bundle install

Adding changes

When adding a notable change, create a changeset file that describes the change for the CHANGELOG.md. Run the command below and enter the prompts. These changesets will be merged into the CHANGELOG.md file upon publish.

mono changeset add

Be sure to commit the changeset file in the same commit as the rest of your changes.

Testing

This project uses RSpec for the test suite. Run RSpec with the following command:

# Run RSpec test suite
bundle exec rspec

# Run RSpec test suite and generate a test coverage report
COV=1 bundle exec rspec

Manual testing

To manually test the changes in mono you'll run into the production check when running mono. The mono executable won't run unless the repository is on the main branch and has no uncommitted file changes.

To skip these checks, use the mono-dev executable. Only use this for testing! Do not use this at all times. The production checks are there to avoid any operations (such as publishing) with unreviewed changes.

Linting

This project uses RuboCop to enforce a code style. Run RuboCop with the following command:

bundle exec rubocop