Guidance for Monorepos

In this guide we describe how to configure Faros for monorepos to get metrics collected and computed correctly.

Faros only collects metadata on repositories which are Included.

As described in the section on Managing Apps, Repos and Boards, navigate to Organization / Repositories. Select the repositories that you would like to include, and either select Include all, or assign the repositories to teams by dragging them to the appropriate team. Repositories that are included but not assigned to a specific team will simply be categorized as Unassigned. A monorepo could be left as Unassigned, or arbitrarily assigned to one of the relevant contributing teams in the organization.

In the default dashboards, attribution of metrics related to source control data, deployments, or lead-time is based on who contributed the change and which team they belong to. Therefore a metric like PR cycle time, for instance, will automatically be attributed to the appropriate teams based on the PR authors and the teams to which they belong. This is true even if the PRs are from a monorepo that multiple teams contribute to.

Within the context of a particular scrum team, a further breakdown of deployment and lead time metrics by applications can be found in the Team DORA Summary dashboard:

By default, all changes get attributed to all the applications that get deployed from the monorepo. For more fine-grained attribution, there needs to be a consistent approach to identify which PRs map to which applications. At this time, Faros supports attribution by repository paths and PR labels. Specifically, for each commit included in a deployment, Faros will inspect the commit's PR for labels and the list of files changed, and compare these against user-provided configuration in the compute_ApplicationSource graph model:

type compute_ApplicationSource @model(key: ["application", "repository"]) {
  application: compute_Application
  repository: vcs_Repository
  repositoryPaths: [String!]
  repositoryLabel: vcs_Label
}

This model defines where application code resides, and how attribution should be handled when multiple applications reside in the same repository. You should write an entry with one or both of the following fields configured for each such application:

  1. The repositoryPaths field is a list of glob patterns that is compared against a commit's list of changed files. If any pattern matches a file, then the commit is included in the deployment's changeset. Each entry should be a file path or glob pattern that matches multiple files. Plain paths that end in a slash "/" will be interpreted as a globstar match, e.g., "applications/app1/" will be interpreted as "applications/app1/**".
  2. The repositoryLabel field is compared against the PR labels of the commit. If the PR has the label, then the commit is included in the deployment's changeset.

πŸ“˜

Note that the labels and list of files are retrieved from the commit's PR, which means the commit must originate from a PR and not be pushed directly to the main branch. Additionally, the VCS source must be configured to pull PR file information, as the graph is source of truth for this information.

Here's an example of inserting an application source using a mutation:

mutation upsert_appsource {
  insert_compute_ApplicationSource_one(
    object: {
      application: {
        data: {platform: "myplatform", name: "myapp"}
        on_conflict: {constraint: compute_Application_pkey, update_columns: [name]}
      }
      repository: {
        data: {
          organization: {
            data: {source: "GitHub", uid: "myorg"}
            on_conflict: {constraint: vcs_Organization_pkey, update_columns: [uid]}
          }
          name: "myrepo"
        }
        on_conflict: {constraint: vcs_Repository_pkey, update_columns: [name]}
      }
      repositoryPaths: "{applications/myapp/**, packages/dependency/**}"
      origin: "graphql-api"
    }
    on_conflict: {constraint: compute_ApplicationSource_pkey, update_columns: [repositoryPaths]}
  ) {
    id  
  }
}

Instrumenting a Monorepo

Instrumenting a monorepo with Faros CI/CD events is very similar to instrumenting any other application. Any time the code from your monorepo is built you should send a CI event to Faros denoting the code version being built. When an application from the monorepo is deployed, you should send a CD event specific to that application. If more than one application is deployed within the CD process of your monorepo, you should send multiple CD events, one for each deployed application.