Improved monorepo tooling setup

refs https://github.com/TryGhost/DevOps/issues/45

- this switches the monorepo over to using Nx instead of Lerna, because
  we don't currently need the versioning+publishing capabilities
- this also adds an `nx.json`, which allows us to enable task caching
- also adds `build:ts` to the TS projects, which is cached for fast execution
- how these interact with the dev.js script will hopefully soon be
  reworked to be a better experience
This commit is contained in:
Daniel Lockyer 2023-07-12 13:42:39 +02:00 committed by Daniel Lockyer
parent 4424f25970
commit 2aa7da3a0b
11 changed files with 217 additions and 1360 deletions

View File

@ -39,52 +39,20 @@ const COMMAND_ADMIN = {
env: {} env: {}
}; };
const COMMAND_TYPESCRIPT = {
name: 'ts',
command: 'nx watch --projects=ghost/collections,ghost/in-memory-repository,ghost/mail-events,ghost/model-to-domain-event-interceptor,ghost/post-revisions -- nx run \\$NX_PROJECT_NAME:build:ts',
cwd: path.resolve(__dirname, '../../'),
prefixColor: 'cyan',
env: {}
};
if (DASH_DASH_ARGS.includes('ghost')) { if (DASH_DASH_ARGS.includes('ghost')) {
commands = [COMMAND_GHOST]; commands = [COMMAND_GHOST, COMMAND_TYPESCRIPT];
} else if (DASH_DASH_ARGS.includes('admin')) { } else if (DASH_DASH_ARGS.includes('admin')) {
commands = [COMMAND_ADMIN]; commands = [COMMAND_ADMIN];
} else { } else {
commands = [COMMAND_GHOST, COMMAND_ADMIN]; commands = [COMMAND_GHOST, COMMAND_TYPESCRIPT, COMMAND_ADMIN];
}
if (DASH_DASH_ARGS.includes('revisions') || DASH_DASH_ARGS.includes('all')) {
commands.push({
name: 'post-revisions',
command: 'yarn dev',
cwd: path.resolve(__dirname, '../../ghost/post-revisions'),
prefixColor: 'green',
env: {}
});
}
if (DASH_DASH_ARGS.includes('in-memory-repository') || DASH_DASH_ARGS.includes('all')) {
commands.push({
name: 'in-memory-repository',
command: 'yarn dev',
cwd: path.resolve(__dirname, '../../ghost/in-memory-repository'),
prefixColor: 'pink',
env: {}
});
}
if (DASH_DASH_ARGS.includes('collections') || DASH_DASH_ARGS.includes('all')) {
commands.push({
name: 'collections',
command: 'yarn dev',
cwd: path.resolve(__dirname, '../../ghost/collections'),
prefixColor: 'pink',
env: {}
});
}
if (DASH_DASH_ARGS.includes('mail-events') || DASH_DASH_ARGS.includes('all')) {
commands.push({
name: 'collections',
command: 'yarn dev',
cwd: path.resolve(__dirname, '../../ghost/mail-events'),
prefixColor: 'pink',
env: {}
});
} }
if (DASH_DASH_ARGS.includes('admin-x') || DASH_DASH_ARGS.includes('adminx') || DASH_DASH_ARGS.includes('adminX') || DASH_DASH_ARGS.includes('all')) { if (DASH_DASH_ARGS.includes('admin-x') || DASH_DASH_ARGS.includes('adminx') || DASH_DASH_ARGS.includes('adminX') || DASH_DASH_ARGS.includes('all')) {

View File

@ -175,7 +175,7 @@ jobs:
path: ghost/**/.eslintcache path: ghost/**/.eslintcache
key: eslint-cache key: eslint-cache
- run: yarn lint --since ${{ needs.job_get_metadata.outputs.BASE_COMMIT }} - run: yarn nx affected -t lint --base=${{ needs.job_get_metadata.outputs.BASE_COMMIT }}
- uses: tryghost/actions/actions/slack-build@main - uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main' if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
@ -248,7 +248,7 @@ jobs:
env: env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_install_deps.outputs.dependency_cache_key }} DEPENDENCY_CACHE_KEY: ${{ needs.job_install_deps.outputs.dependency_cache_key }}
- run: yarn test:unit --include-dependents --since ${{ needs.job_get_metadata.outputs.BASE_COMMIT }} - run: yarn nx affected -t test:unit --base=${{ needs.job_get_metadata.outputs.BASE_COMMIT }}
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: startsWith(matrix.node, '18') if: startsWith(matrix.node, '18')

View File

@ -7,9 +7,8 @@
"main": "build/index.js", "main": "build/index.js",
"types": "build/index.d.ts", "types": "build/index.d.ts",
"scripts": { "scripts": {
"dev": "tsc --watch --preserveWatchOutput --sourceMap",
"build": "tsc", "build": "tsc",
"prepare": "tsc", "build:ts": "yarn build",
"test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'", "test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'",
"test": "yarn test:types && yarn test:unit", "test": "yarn test:types && yarn test:unit",
"test:types": "tsc --noEmit", "test:types": "tsc --noEmit",

View File

@ -22,9 +22,7 @@
"scripts": { "scripts": {
"archive": "npm pack", "archive": "npm pack",
"start": "node index", "start": "node index",
"setup": "knex-migrator init", "build": "postcss core/frontend/public/ghost.css --no-map --use cssnano -o core/frontend/public/ghost.min.css",
"build": "yarn build:css",
"build:css": "postcss core/frontend/public/ghost.css --no-map --use cssnano -o core/frontend/public/ghost.min.css",
"test": "yarn test:unit", "test": "yarn test:unit",
"test:base": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js", "test:base": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js",
"test:single": "yarn test:base --timeout=60000", "test:single": "yarn test:base --timeout=60000",
@ -54,7 +52,7 @@
"lint:test": "eslint -c test/.eslintrc.js --ignore-path test/.eslintignore 'test/**/*.js' --cache", "lint:test": "eslint -c test/.eslintrc.js --ignore-path test/.eslintignore 'test/**/*.js' --cache",
"lint:code": "yarn lint:server && yarn lint:shared && yarn lint:frontend", "lint:code": "yarn lint:server && yarn lint:shared && yarn lint:frontend",
"lint": "yarn lint:server && yarn lint:shared && yarn lint:frontend && yarn lint:test", "lint": "yarn lint:server && yarn lint:shared && yarn lint:frontend && yarn lint:test",
"prepack": "lerna run build && monobundle" "prepack": "nx run-many -t build --projects='ghost/*' && monobundle"
}, },
"engines": { "engines": {
"node": "^16.14.0 || ^18.12.1", "node": "^16.14.0 || ^18.12.1",

View File

@ -7,9 +7,8 @@
"main": "build/index.js", "main": "build/index.js",
"types": "build/index.d.ts", "types": "build/index.d.ts",
"scripts": { "scripts": {
"dev": "tsc --watch --preserveWatchOutput --sourceMap",
"build": "tsc", "build": "tsc",
"prepare": "tsc", "build:ts": "yarn build",
"test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'", "test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'",
"test": "yarn test:types && yarn test:unit", "test": "yarn test:types && yarn test:unit",
"test:types": "tsc --noEmit", "test:types": "tsc --noEmit",

View File

@ -7,9 +7,8 @@
"main": "build/index.js", "main": "build/index.js",
"types": "build/index.d.ts", "types": "build/index.d.ts",
"scripts": { "scripts": {
"dev": "tsc --watch --preserveWatchOutput --sourceMap",
"build": "tsc", "build": "tsc",
"prepare": "tsc", "build:ts": "yarn build",
"test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'", "test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'",
"test": "yarn test:types && yarn test:unit", "test": "yarn test:types && yarn test:unit",
"test:types": "tsc --noEmit", "test:types": "tsc --noEmit",

View File

@ -7,9 +7,8 @@
"main": "build/index.js", "main": "build/index.js",
"types": "build/index.d.ts", "types": "build/index.d.ts",
"scripts": { "scripts": {
"dev": "tsc --watch --preserveWatchOutput --sourceMap",
"build": "tsc", "build": "tsc",
"prepare": "tsc", "build:ts": "yarn build",
"test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'", "test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'",
"test": "yarn test:types && yarn test:unit", "test": "yarn test:types && yarn test:unit",
"test:types": "tsc --noEmit", "test:types": "tsc --noEmit",

View File

@ -7,9 +7,8 @@
"main": "build/index.js", "main": "build/index.js",
"types": "build/index.d.ts", "types": "build/index.d.ts",
"scripts": { "scripts": {
"dev": "tsc --watch --preserveWatchOutput --sourceMap",
"build": "tsc", "build": "tsc",
"prepare": "tsc", "build:ts": "yarn build",
"test:types": "tsc --noEmit", "test:types": "tsc --noEmit",
"test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'", "test:unit": "NODE_ENV=testing c8 --src src --all --check-coverage --100 --reporter text --reporter cobertura mocha -r ts-node/register './test/**/*.test.ts'",
"test": "yarn test:unit && yarn test:types", "test": "yarn test:unit && yarn test:types",

35
nx.json Normal file
View File

@ -0,0 +1,35 @@
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": [
"build:ts",
"lint",
"test",
"test:unit"
]
}
}
},
"namedInputs": {
"default": [
"{projectRoot}/**/*"
]
},
"targetDefaults": {
"build:ts": {
"dependsOn": [
"^build:ts"
],
"inputs": [
"default",
"^default"
],
"outputs": [
"{projectRoot}/build"
]
}
},
"$schema": "./node_modules/nx/schemas/nx-schema.json"
}

View File

@ -21,21 +21,21 @@
], ],
"scripts": { "scripts": {
"archive": "yarn workspace ghost run archive", "archive": "yarn workspace ghost run archive",
"build": "lerna run build", "build": "nx run-many -t build",
"dev:debug": "DEBUG_COLORS=true DEBUG=@tryghost*,ghost:* yarn dev", "dev:debug": "DEBUG_COLORS=true DEBUG=@tryghost*,ghost:* yarn dev",
"dev:admin": "node .github/scripts/dev.js --admin", "dev:admin": "node .github/scripts/dev.js --admin",
"dev:ghost": "node .github/scripts/dev.js --ghost", "dev:ghost": "node .github/scripts/dev.js --ghost",
"dev": "node .github/scripts/dev.js", "dev": "node .github/scripts/dev.js",
"fix": "yarn cache clean && rm -rf node_modules && yarn", "fix": "yarn cache clean && rm -rf node_modules && yarn",
"knex-migrator": "yarn workspace ghost run knex-migrator", "knex-migrator": "yarn workspace ghost run knex-migrator",
"setup": "yarn && yarn workspace ghost run setup && git submodule update --init", "setup": "yarn && git submodule update --init",
"lint": "lerna run lint", "lint": "nx run-many -t lint",
"test": "lerna run test", "test": "nx run-many -t test",
"test:unit": "lerna run test:unit", "test:unit": "nx run-many -t test:unit",
"main": "yarn main:monorepo && yarn main:submodules", "main": "yarn main:monorepo && yarn main:submodules",
"main:monorepo": "git checkout main && git pull ${GHOST_UPSTREAM:-origin} main && yarn", "main:monorepo": "git checkout main && git pull ${GHOST_UPSTREAM:-origin} main && yarn",
"main:submodules": "git submodule sync && git submodule update && git submodule foreach \"git checkout main && git pull ${GHOST_UPSTREAM:-origin} main && yarn\"", "main:submodules": "git submodule sync && git submodule update && git submodule foreach \"git checkout main && git pull ${GHOST_UPSTREAM:-origin} main && yarn\"",
"prepare": "husky install .github/hooks && lerna run prepare" "prepare": "husky install .github/hooks && nx run-many -t build:ts"
}, },
"resolutions": { "resolutions": {
"@elastic/elasticsearch": "8.5.0", "@elastic/elasticsearch": "8.5.0",
@ -123,16 +123,12 @@
"lint-staged": { "lint-staged": {
"*.js": "eslint" "*.js": "eslint"
}, },
"lerna": {
"version": "0.0.0",
"npmClient": "yarn"
},
"devDependencies": { "devDependencies": {
"concurrently": "8.2.0", "concurrently": "8.2.0",
"eslint-plugin-ghost": "3.2.0", "eslint-plugin-ghost": "3.2.0",
"husky": "8.0.3", "husky": "8.0.3",
"lerna": "7.1.1",
"lint-staged": "13.2.3", "lint-staged": "13.2.3",
"nx": "16.5.1",
"ts-node": "10.9.1" "ts-node": "10.9.1"
} }
} }

1445
yarn.lock

File diff suppressed because it is too large Load Diff