Skip to content

Commit

Permalink
Convert to monorepo (#831)
Browse files Browse the repository at this point in the history
Currently, this repo and everything within it is published as a single
package. Using and maintaining this package, however, is problematic for
a few reasons:

1. Even if your library uses a couple of controllers, you must add the
   entire package and all of its dependencies to your library's
   dependency tree.
2. Because this package is used by many teams, when we make a new
   release, even if that release contains changes to one controller, we
   must coordinate with all teams to ensure that nothing has broken.

In addition, we want to be able to maintain our existing libraries more
easily, as right now it is difficult due to code being split across
multiple repositories.

To solve this problem, this commit converts the existing structure to a
monorepo structure, assigning controllers to packages which we can then
publish individually. (A full list of packages is contained in the
README.)

Along with a monorepo structure comes with a litany of changes:

* **TypeScript:** We have a "master" TypeScript config file, which is
  used by developers' code editors, but each package also has its own
  TypeScript config files. We are also using TypeScript project
  references, which allows us to inform TypeScript how all packages are
  connected to each other dependency-wise; this allows TypeScript to
  know which packages to build first.
* **Jest:** Each package has its own Jest config file, and we use Yarn
  workspaces to run the tests for each package in parallel.
* **ESLint:** We are able to lint the monorepo in the same way as we
  linted before.
* **TypeDoc:** We've added TypeDoc to each package and use Yarn
  workspaces to generate docs for each package in parallel.
* **Yarn:** A bunch of Yarn constraints have been added that verify that
  both the root package and each package has a well-formed `package.json`.
* **Other notes:**
  * Some packages depend on other packages within the monorepo. In other
    words, we might have an import for `@metamask/base-controller`
    within a controller file. Out of the box both TypeScript and Jest
    won't know what to do with this. Although Yarn will add a symlink in
    `node_modules` to the proper directory in `packages` for the package
    in question, TypeScript expects the code for the package to be
    compiled (i.e. for `dist/` to be populated), and Jest, as it has
    custom resolver logic, doesn't know what to do at all. To make this
    possible we have to add a custom mapping for both TypeScript and
    Jest that will tell them what to do when it sees a `@metamask/*`
    import.
  * The GitHub Action workflow files have been standardized against the
    newest changes to the module template.

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
Co-authored-by: Maarten Zuidhoorn <maarten@zuidhoorn.com>
  • Loading branch information
3 people committed Nov 11, 2022
1 parent 3a003ea commit 0704312
Show file tree
Hide file tree
Showing 315 changed files with 8,061 additions and 4,034 deletions.
43 changes: 0 additions & 43 deletions .github/workflows/create-release-pr.yml

This file was deleted.

103 changes: 74 additions & 29 deletions .github/workflows/lint-build-test.yml
@@ -1,14 +1,12 @@
name: Lint, Build, and Test

on:
push:
branches: [main]
pull_request:
workflow_call:

jobs:
lint-build-test:
name: Lint, Build, and Test
runs-on: ubuntu-20.04
prepare:
name: Prepare
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x]
Expand All @@ -18,31 +16,78 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Get Yarn cache directory
run: echo "YARN_CACHE_DIR=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
id: yarn-cache-dir
- name: Get Yarn version
run: echo "YARN_VERSION=$(yarn --version)" >> $GITHUB_OUTPUT
id: yarn-version
- name: Cache yarn dependencies
uses: actions/cache@v3
cache: yarn
- run: yarn --immutable

lint:
name: Lint
runs-on: ubuntu-latest
needs: prepare
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
path: ${{ steps.yarn-cache-dir.outputs.YARN_CACHE_DIR }}
key: yarn-cache-${{ runner.os }}-${{ steps.yarn-version.outputs.YARN_VERSION }}-${{ hashFiles('yarn.lock') }}
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --immutable
- run: yarn lint
- name: Validate RC changelog
if: ${{ startsWith(github.ref, 'release/') }}
run: yarn auto-changelog validate --rc
- name: Validate changelog
if: ${{ !startsWith(github.ref, 'release/') }}
run: yarn auto-changelog validate
- run: yarn changelog:validate
- name: Require clean working directory
shell: bash
run: |
if ! git diff --exit-code; then
echo "Working tree dirty at end of job"
exit 1
fi
build:
name: Build
runs-on: ubuntu-latest
needs: prepare
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --immutable
- run: yarn build
- run: yarn test --maxWorkers=1
all-jobs-pass:
name: All jobs pass
runs-on: ubuntu-20.04
needs:
- lint-build-test
- name: Require clean working directory
shell: bash
run: |
if ! git diff --exit-code; then
echo "Working tree dirty at end of job"
exit 1
fi
test:
name: Test
runs-on: ubuntu-latest
needs: prepare
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
- run: echo "Great success!"
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --immutable
- run: yarn test
- name: Require clean working directory
shell: bash
run: |
if ! git diff --exit-code; then
echo "Working tree dirty at end of job"
exit 1
fi
51 changes: 51 additions & 0 deletions .github/workflows/main.yml
@@ -0,0 +1,51 @@
name: Main

on:
push:
branches: [main]
pull_request:

jobs:
check-workflows:
name: Check workflows
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Download actionlint
id: download-actionlint
run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/7fdc9630cc360ea1a469eed64ac6d78caeda1234/scripts/download-actionlint.bash) 1.6.22
shell: bash
- name: Check workflow files
run: ${{ steps.download-actionlint.outputs.executable }} -color
shell: bash

lint-build-test:
name: Lint, build, and test
needs: check-workflows
uses: ./.github/workflows/lint-build-test.yml

is-release:
name: Determine whether this is a release merge commit
needs: lint-build-test
if: startsWith(github.event.commits[0].author.name, 'github-actions')
runs-on: ubuntu-latest
outputs:
IS_RELEASE: ${{ steps.is-release.outputs.IS_RELEASE }}
steps:
- uses: MetaMask/action-is-release@v1
id: is-release

publish-release:
name: Publish release
needs: is-release
if: needs.is-release.outputs.IS_RELEASE == 'true'
permissions:
contents: write
uses: ./.github/workflows/publish-release.yml

all-jobs-pass:
name: All jobs pass
runs-on: ubuntu-latest
needs: lint-build-test
steps:
- run: echo "Great success!"
61 changes: 17 additions & 44 deletions .github/workflows/publish-release.yml
@@ -1,58 +1,33 @@
name: Publish Release

on:
push:
branches: [main]
workflow_call:

jobs:
is-release:
# release merge commits come from github-actions
if: startsWith(github.event.commits[0].author.name, 'github-actions')
outputs:
IS_RELEASE: ${{ steps.is-release.outputs.IS_RELEASE }}
runs-on: ubuntu-latest
steps:
- uses: MetaMask/action-is-release@v1
id: is-release

publish-release:
permissions:
contents: write
if: needs.is-release.outputs.IS_RELEASE == 'true'
runs-on: ubuntu-latest
needs: is-release
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.sha }}
- name: Get Node.js version
id: nvm
run: echo "NODE_VERSION=$(cat .nvmrc)" >> $GITHUB_OUTPUT
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: ${{ steps.nvm.outputs.NODE_VERSION }}
node-version-file: '.nvmrc'
cache: yarn
- uses: actions/cache@v3
with:
path: |
./packages/**/dist
./node_modules/.yarn-state.yml
key: ${{ github.sha }}
- uses: MetaMask/action-publish-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get Yarn cache directory
run: echo "YARN_CACHE_DIR=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
id: yarn-cache-dir
- name: Get Yarn version
run: echo "YARN_VERSION=$(yarn --version)" >> $GITHUB_OUTPUT
id: yarn-version
- name: Cache yarn dependencies
uses: actions/cache@v3
with:
path: ${{ steps.yarn-cache-dir.outputs.YARN_CACHE_DIR }}
key: yarn-cache-${{ runner.os }}-${{ steps.yarn-version.outputs.YARN_VERSION }}-${{ hashFiles('yarn.lock') }}
- run: yarn --immutable
- run: yarn build
- uses: actions/cache@v3
id: restore-build
with:
path: ./dist
key: ${{ github.sha }}

publish-npm-dry-run:
runs-on: ubuntu-latest
Expand All @@ -62,15 +37,14 @@ jobs:
with:
ref: ${{ github.sha }}
- uses: actions/cache@v3
id: restore-build
with:
path: ./dist
path: |
./packages/**/dist
./node_modules/.yarn-state.yml
key: ${{ github.sha }}
# Set `ignore-scripts` to skip `prepublishOnly` because the release was built already in the previous job
- run: npm config set ignore-scripts true
- name: Dry Run Publish
# omit npm-token token to perform dry run publish
uses: MetaMask/action-npm-publish@v1
uses: MetaMask/action-npm-publish@v2
env:
SKIP_PREPACK: true

Expand All @@ -83,14 +57,13 @@ jobs:
with:
ref: ${{ github.sha }}
- uses: actions/cache@v3
id: restore-build
with:
path: ./dist
path: |
./packages/**/dist
./node_modules/.yarn-state.yml
key: ${{ github.sha }}
# Set `ignore-scripts` to skip `prepublishOnly` because the release was built already in the previous job
- run: npm config set ignore-scripts true
- name: Publish
uses: MetaMask/action-npm-publish@v1
uses: MetaMask/action-npm-publish@v2
with:
npm-token: ${{ secrets.NPM_TOKEN }}
env:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -24,3 +24,6 @@ docs
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# typescript
*.tsbuildinfo
52 changes: 52 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-constraints.cjs

Large diffs are not rendered by default.

0 comments on commit 0704312

Please sign in to comment.