mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
no issue - The `yarn dev` command accepts dash-dash-args to conditionally build & run other apps, like portal, comments, etc. - Passing these flags to the docker compose setup directly doesn't work, so the only way to run these apps in docker was to either change the command in the Dockerfile or override the command in the `compose.yml` file - This commit extends `yarn dev` to also check for the `GHOST_DEV_APP_FLAGS` environment variable for these flags, which can be forwarded into the container and make it easier to run these apps using docker compose.
259 lines
9.2 KiB
JavaScript
259 lines
9.2 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const util = require('util');
|
|
const exec = util.promisify(require('child_process').exec);
|
|
|
|
const chalk = require('chalk');
|
|
const concurrently = require('concurrently');
|
|
|
|
// check we're running on Node 18 and above
|
|
const nodeVersion = parseInt(process.versions.node.split('.')[0]);
|
|
if (nodeVersion < 18) {
|
|
console.error('`yarn dev` requires Node v18 or above. Please upgrade your version of Node.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const config = require('../../ghost/core/core/shared/config/loader').loadNconf({
|
|
customConfigPath: path.join(__dirname, '../../ghost/core')
|
|
});
|
|
|
|
const tsPackages = fs.readdirSync(path.resolve(__dirname, '../../ghost'), {withFileTypes: true})
|
|
.filter(dirent => dirent.isDirectory())
|
|
.map(dirent => dirent.name)
|
|
.filter(packageFolder => {
|
|
try {
|
|
const packageJson = require(path.resolve(__dirname, `../../ghost/${packageFolder}/package.json`));
|
|
return packageJson.scripts?.['build:ts'];
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
})
|
|
.map(packageFolder => `ghost/${packageFolder}`)
|
|
.join(',');
|
|
|
|
const liveReloadBaseUrl = config.getSubdir() || '/ghost/';
|
|
const siteUrl = config.getSiteUrl();
|
|
|
|
// Pass flags using GHOST_DEV_APP_FLAGS env var or --flag
|
|
const DASH_DASH_ARGS = process.argv.filter(a => a.startsWith('--')).map(a => a.slice(2));
|
|
const ENV_ARGS = process.env.GHOST_DEV_APP_FLAGS?.split(',') || [];
|
|
const GHOST_APP_FLAGS = [...ENV_ARGS, ...DASH_DASH_ARGS];
|
|
|
|
let commands = [];
|
|
|
|
const COMMAND_GHOST = {
|
|
name: 'ghost',
|
|
// Note: if this isn't working for you, please use Node 18 and above
|
|
command: 'nx run ghost:dev',
|
|
cwd: path.resolve(__dirname, '../../ghost/core'),
|
|
prefixColor: 'blue',
|
|
env: {
|
|
// In development mode, we allow self-signed certificates (for sending webmentions and oembeds)
|
|
NODE_TLS_REJECT_UNAUTHORIZED: '0',
|
|
}
|
|
};
|
|
|
|
const COMMAND_ADMIN = {
|
|
name: 'admin',
|
|
command: `nx run ghost-admin:dev --live-reload-base-url=${liveReloadBaseUrl} --live-reload-port=4201`,
|
|
cwd: path.resolve(__dirname, '../../ghost/admin'),
|
|
prefixColor: 'green',
|
|
env: {}
|
|
};
|
|
|
|
const COMMAND_BROWSERTESTS = {
|
|
name: 'browser-tests',
|
|
command: 'nx run ghost:test:browser',
|
|
cwd: path.resolve(__dirname, '../../ghost/core'),
|
|
prefixColor: 'blue',
|
|
env: {}
|
|
};
|
|
|
|
const COMMAND_TYPESCRIPT = {
|
|
name: 'ts',
|
|
command: `while [ 1 ]; do nx watch --projects=${tsPackages} -- nx run \\$NX_PROJECT_NAME:build:ts; done`,
|
|
cwd: path.resolve(__dirname, '../../'),
|
|
prefixColor: 'cyan',
|
|
env: {}
|
|
};
|
|
|
|
const adminXApps = '@tryghost/admin-x-demo,@tryghost/admin-x-settings,@tryghost/admin-x-activitypub,@tryghost/posts';
|
|
|
|
const COMMANDS_ADMINX = [{
|
|
name: 'adminXDeps',
|
|
command: 'while [ 1 ]; do nx watch --projects=apps/admin-x-design-system,apps/admin-x-framework,apps/shade -- nx run \\$NX_PROJECT_NAME:build; done',
|
|
cwd: path.resolve(__dirname, '../..'),
|
|
prefixColor: '#C72AF7',
|
|
env: {}
|
|
}, {
|
|
name: 'adminX',
|
|
command: `nx run-many --projects=${adminXApps} --parallel=${adminXApps.length} --targets=dev`,
|
|
cwd: path.resolve(__dirname, '../../apps/admin-x-settings', '../../apps/admin-x-activitypub'),
|
|
prefixColor: '#C72AF7',
|
|
env: {}
|
|
}];
|
|
|
|
if (GHOST_APP_FLAGS.includes('ghost')) {
|
|
commands = [COMMAND_GHOST, COMMAND_TYPESCRIPT];
|
|
} else if (GHOST_APP_FLAGS.includes('admin')) {
|
|
commands = [COMMAND_ADMIN, ...COMMANDS_ADMINX];
|
|
} else if (GHOST_APP_FLAGS.includes('browser-tests')) {
|
|
commands = [COMMAND_BROWSERTESTS];
|
|
} else {
|
|
commands = [COMMAND_GHOST, COMMAND_TYPESCRIPT, COMMAND_ADMIN, ...COMMANDS_ADMINX];
|
|
}
|
|
|
|
if (GHOST_APP_FLAGS.includes('portal') || GHOST_APP_FLAGS.includes('all')) {
|
|
commands.push({
|
|
name: 'portal',
|
|
command: 'nx run @tryghost/portal:dev',
|
|
cwd: path.resolve(__dirname, '../../apps/portal'),
|
|
prefixColor: 'magenta',
|
|
env: {}
|
|
});
|
|
|
|
if (GHOST_APP_FLAGS.includes('https')) {
|
|
// Safari needs HTTPS for it to work
|
|
// To make this work, you'll need a CADDY server running in front
|
|
// Note the port is different because of this extra layer. Use the following Caddyfile:
|
|
// https://localhost:4176 {
|
|
// reverse_proxy http://localhost:4175
|
|
// }
|
|
|
|
COMMAND_GHOST.env['portal__url'] = 'https://localhost:4176/portal.min.js';
|
|
} else {
|
|
COMMAND_GHOST.env['portal__url'] = 'http://localhost:4175/portal.min.js';
|
|
}
|
|
}
|
|
|
|
if (GHOST_APP_FLAGS.includes('signup') || GHOST_APP_FLAGS.includes('all')) {
|
|
commands.push({
|
|
name: 'signup-form',
|
|
command: GHOST_APP_FLAGS.includes('signup') ? 'nx run @tryghost/signup-form:dev' : 'nx run @tryghost/signup-form:preview',
|
|
cwd: path.resolve(__dirname, '../../apps/signup-form'),
|
|
prefixColor: 'magenta',
|
|
env: {}
|
|
});
|
|
COMMAND_GHOST.env['signupForm__url'] = 'http://localhost:6174/signup-form.min.js';
|
|
}
|
|
|
|
if (GHOST_APP_FLAGS.includes('announcement-bar') || GHOST_APP_FLAGS.includes('announcementBar') || GHOST_APP_FLAGS.includes('announcementbar') || GHOST_APP_FLAGS.includes('all')) {
|
|
commands.push({
|
|
name: 'announcement-bar',
|
|
command: 'nx run @tryghost/announcement-bar:dev',
|
|
cwd: path.resolve(__dirname, '../../apps/announcement-bar'),
|
|
prefixColor: '#DC9D00',
|
|
env: {}
|
|
});
|
|
COMMAND_GHOST.env['announcementBar__url'] = 'http://localhost:4177/announcement-bar.min.js';
|
|
}
|
|
|
|
if (GHOST_APP_FLAGS.includes('search') || GHOST_APP_FLAGS.includes('all')) {
|
|
commands.push({
|
|
name: 'search',
|
|
command: 'nx run @tryghost/sodo-search:dev',
|
|
cwd: path.resolve(__dirname, '../../apps/sodo-search'),
|
|
prefixColor: '#23de43',
|
|
env: {}
|
|
});
|
|
COMMAND_GHOST.env['sodoSearch__url'] = 'http://localhost:4178/sodo-search.min.js';
|
|
COMMAND_GHOST.env['sodoSearch__styles'] = 'http://localhost:4178/main.css';
|
|
}
|
|
|
|
if (GHOST_APP_FLAGS.includes('lexical')) {
|
|
if (GHOST_APP_FLAGS.includes('https')) {
|
|
// Safari needs HTTPS for it to work
|
|
// To make this work, you'll need a CADDY server running in front
|
|
// Note the port is different because of this extra layer. Use the following Caddyfile:
|
|
// https://localhost:41730 {
|
|
// reverse_proxy http://127.0.0.1:4173
|
|
// }
|
|
|
|
COMMAND_ADMIN.env['EDITOR_URL'] = 'https://localhost:41730/';
|
|
} else {
|
|
COMMAND_ADMIN.env['EDITOR_URL'] = 'http://localhost:4173/';
|
|
}
|
|
}
|
|
|
|
if (GHOST_APP_FLAGS.includes('comments') || GHOST_APP_FLAGS.includes('all')) {
|
|
if (GHOST_APP_FLAGS.includes('https')) {
|
|
// Safari needs HTTPS for it to work
|
|
// To make this work, you'll need a CADDY server running in front
|
|
// Note the port is different because of this extra layer. Use the following Caddyfile:
|
|
// https://localhost:7174 {
|
|
// reverse_proxy http://127.0.0.1:7173
|
|
// }
|
|
COMMAND_GHOST.env['comments__url'] = 'https://localhost:7174/comments-ui.min.js';
|
|
} else {
|
|
COMMAND_GHOST.env['comments__url'] = 'http://localhost:7173/comments-ui.min.js';
|
|
}
|
|
|
|
commands.push({
|
|
name: 'comments',
|
|
command: 'nx run @tryghost/comments-ui:dev',
|
|
cwd: path.resolve(__dirname, '../../apps/comments-ui'),
|
|
prefixColor: '#E55137',
|
|
env: {}
|
|
});
|
|
}
|
|
|
|
async function handleStripe() {
|
|
if (GHOST_APP_FLAGS.includes('stripe') || GHOST_APP_FLAGS.includes('all')) {
|
|
if (GHOST_APP_FLAGS.includes('offline') || GHOST_APP_FLAGS.includes('browser-tests')) {
|
|
return;
|
|
}
|
|
|
|
let stripeSecret;
|
|
try {
|
|
stripeSecret = await exec('stripe listen --print-secret');
|
|
} catch (err) {
|
|
console.error('Failed to fetch Stripe secret token, do you need to connect Stripe CLI?', err);
|
|
return;
|
|
}
|
|
|
|
if (!stripeSecret || !stripeSecret.stdout) {
|
|
console.error('No Stripe secret was present');
|
|
return;
|
|
}
|
|
|
|
COMMAND_GHOST.env['WEBHOOK_SECRET'] = stripeSecret.stdout.trim();
|
|
commands.push({
|
|
name: 'stripe',
|
|
command: `stripe listen --forward-to ${siteUrl}members/webhooks/stripe/`,
|
|
prefixColor: 'yellow',
|
|
env: {}
|
|
});
|
|
}
|
|
}
|
|
|
|
(async () => {
|
|
await handleStripe();
|
|
|
|
if (!commands.length) {
|
|
console.log(`No commands provided`);
|
|
process.exit(0);
|
|
}
|
|
|
|
process.env.NX_DISABLE_DB = "true";
|
|
await exec("yarn nx reset --onlyDaemon");
|
|
await exec("yarn nx daemon --start");
|
|
|
|
console.log(`Running projects: ${commands.map(c => chalk.green(c.name)).join(', ')}`);
|
|
|
|
const {result} = concurrently(commands, {
|
|
prefix: 'name',
|
|
killOthers: ['failure', 'success'],
|
|
successCondition: 'first'
|
|
});
|
|
|
|
try {
|
|
await result;
|
|
} catch (err) {
|
|
console.error();
|
|
console.error(chalk.red(`Executing dev command failed:`) + `\n`);
|
|
console.error(chalk.red(`If you've recently done a \`yarn main\`, dependencies might be out of sync. Try running \`${chalk.green('yarn fix')}\` to fix this.`));
|
|
console.error(chalk.red(`If not, something else went wrong. Please report this to the Ghost team.`));
|
|
console.error();
|
|
process.exit(1);
|
|
}
|
|
})();
|