forked from TryGhost/Ghost
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
682 additions
and
353 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
// This script is run in the Dev Container right after it is created | ||
// No dependencies are installed at this point so we can't use any npm packages | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const assert = require('node:assert/strict'); | ||
const { execSync } = require('child_process'); | ||
|
||
// Main function that runs all the setup steps | ||
function main() { | ||
setupGitRemotes(); | ||
setupLocalConfig(); | ||
runCleanHard(); | ||
runInstall(); | ||
runSubmoduleUpdate(); | ||
runTypescriptBuild(); | ||
} | ||
|
||
// Basic color constants for console output | ||
const colors = { | ||
reset: '\x1b[0m', | ||
bright: '\x1b[1m', | ||
dim: '\x1b[2m', | ||
red: '\x1b[31m', | ||
green: '\x1b[32m', | ||
yellow: '\x1b[33m', | ||
blue: '\x1b[34m', | ||
magenta: '\x1b[35m', | ||
cyan: '\x1b[36m', | ||
}; | ||
|
||
function log(message, color = colors.reset) { | ||
console.log(`${color}${message}${colors.reset}`); | ||
} | ||
|
||
function logError(message, error) { | ||
console.error(`${colors.red}${message}${colors.reset}`, error); | ||
} | ||
|
||
// Sets up the git remotes for the dev container based on environment variables | ||
function setupGitRemotes() { | ||
log('Configuring git remotes...', colors.blue); | ||
try { | ||
const GHOST_UPSTREAM = process.env.GHOST_UPSTREAM; | ||
const GHOST_FORK_REMOTE_URL = process.env.GHOST_FORK_REMOTE_URL; | ||
const GHOST_FORK_REMOTE_NAME = process.env.GHOST_FORK_REMOTE_NAME; | ||
const GHOST_FORCE_SSH = process.env.GHOST_FORCE_SSH; | ||
let remotes = execSync('git remote').toString().trim().split('\n'); | ||
|
||
if (GHOST_UPSTREAM) { | ||
// Check if the upstream remote already exists | ||
if (!remotes.includes(GHOST_UPSTREAM) && remotes.includes('origin')) { | ||
log(`Renaming the default remote from origin to ${GHOST_UPSTREAM}...`, colors.blue); | ||
execSync(`git remote rename origin ${GHOST_UPSTREAM}`); | ||
} | ||
} | ||
|
||
remotes = execSync('git remote').toString().trim().split('\n'); | ||
if (GHOST_FORK_REMOTE_URL) { | ||
const remoteName = GHOST_FORK_REMOTE_NAME || 'origin'; | ||
// Check if the fork remote already exists | ||
if (!remotes.includes(remoteName)) { | ||
log(`Adding fork remote ${GHOST_FORK_REMOTE_URL} as ${remoteName}...`, colors.blue); | ||
execSync(`git remote add ${remoteName} ${GHOST_FORK_REMOTE_URL}`); | ||
} | ||
} | ||
|
||
if (GHOST_FORCE_SSH) { | ||
log('Forcing SSH for all remotes...', colors.blue); | ||
// Get all remotes | ||
remotes = execSync('git remote').toString().trim().split('\n'); | ||
|
||
for (const remote of remotes) { | ||
// Get the current URL for this remote | ||
const url = execSync(`git remote get-url ${remote}`).toString().trim(); | ||
|
||
// Only convert if it's an HTTPS URL | ||
if (url.startsWith('https://')) { | ||
// Convert HTTPS to SSH format | ||
// https://github.com/user/repo.git -> git@github.com:user/repo.git | ||
const sshUrl = url | ||
.replace(/^https:\/\//, 'git@') | ||
.replace(/\//, ':'); | ||
|
||
log(`Converting ${remote} from HTTPS to SSH...`, colors.dim); | ||
execSync(`git remote set-url ${remote} ${sshUrl}`); | ||
} | ||
} | ||
} | ||
|
||
} catch (error) { | ||
logError('Error setting up git remotes:', error); | ||
} | ||
} | ||
|
||
// Creates config.local.json file with the correct values for the devcontainer | ||
function setupLocalConfig() { | ||
log('Setting up local config file...', colors.blue); | ||
// Reads the config.local.json file and updates it with environments variables for devcontainer setup | ||
const configBasePath = path.join(__dirname, '..', 'ghost', 'core'); | ||
const configFile = path.join(configBasePath, 'config.local.json'); | ||
let originalConfig = {}; | ||
if (fs.existsSync(configFile)) { | ||
try { | ||
// Backup the user's config.local.json file just in case | ||
// This won't be used by Ghost but can be useful to switch back to local development | ||
const backupFile = path.join(configBasePath, 'config.local-backup.json'); | ||
fs.copyFileSync(configFile, backupFile); | ||
|
||
// Read the current config.local.json file into memory | ||
const fileContent = fs.readFileSync(configFile, 'utf8'); | ||
originalConfig = JSON.parse(fileContent); | ||
} catch (error) { | ||
logError('Error reading or parsing config file:', error); | ||
process.exit(1); | ||
} | ||
} else { | ||
log('Config file does not exist. Creating a new one.', colors.dim); | ||
} | ||
|
||
let newConfig = {}; | ||
// Change the url if we're in a codespace | ||
if (process.env.CODESPACES === 'true') { | ||
assert.ok(process.env.CODESPACE_NAME, 'CODESPACE_NAME is not defined'); | ||
assert.ok(process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN, 'GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN is not defined'); | ||
const url = `https://${process.env.CODESPACE_NAME}-2368.${process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}`; | ||
newConfig.url = url; | ||
} | ||
|
||
newConfig.database = { | ||
client: 'mysql2', | ||
connection: { | ||
host: 'mysql', | ||
user: 'root', | ||
password: 'root', | ||
database: 'ghost' | ||
} | ||
} | ||
newConfig.adapters = { | ||
Redis: { | ||
host: 'redis', | ||
port: 6379 | ||
} | ||
} | ||
|
||
// Only update the mail settings if they aren't already set | ||
if (!originalConfig.mail && process.env.MAILGUN_SMTP_PASS && process.env.MAILGUN_SMTP_USER && process.env.MAILGUN_FROM_ADDRESS) { | ||
newConfig.mail = { | ||
transport: 'SMTP', | ||
from: process.env.MAILGUN_FROM_ADDRESS, | ||
options: { | ||
service: 'Mailgun', | ||
host: 'smtp.mailgun.org', | ||
secure: true, | ||
port: 465, | ||
auth: { | ||
user: process.env.MAILGUN_SMTP_USER, | ||
pass: process.env.MAILGUN_SMTP_PASS | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Only update the bulk email settings if they aren't already set | ||
if (!originalConfig.bulkEmail && process.env.MAILGUN_API_KEY && process.env.MAILGUN_DOMAIN) { | ||
newConfig.bulkEmail = { | ||
mailgun: { | ||
baseUrl: 'https://api.mailgun.net/v3', | ||
apiKey: process.env.MAILGUN_API_KEY, | ||
domain: process.env.MAILGUN_DOMAIN, | ||
tag: 'bulk-email' | ||
} | ||
} | ||
} | ||
|
||
// Merge the original config with the new config | ||
const config = {...originalConfig, ...newConfig}; | ||
|
||
// Write the updated config.local.json file | ||
try { | ||
fs.writeFileSync(configFile, JSON.stringify(config, null, 2)); | ||
log('Config file updated successfully.', colors.dim); | ||
} catch (error) { | ||
logError('Error writing config file:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
// Deletes node_modules and clears yarn & nx caches | ||
function runCleanHard() { | ||
try { | ||
log('Cleaning up node_modules and yarn/nx caches...', colors.blue); | ||
execSync('yarn clean:hard', { stdio: 'inherit' }); | ||
log('Successfully ran yarn clean:hard', colors.dim); | ||
} catch (error) { | ||
logError('Error running yarn clean:hard:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
// Installs dependencies | ||
function runInstall() { | ||
try { | ||
log('Installing dependencies...', colors.blue); | ||
execSync('yarn install --frozen-lockfile', { stdio: 'inherit' }); | ||
log('Successfully ran yarn install', colors.dim); | ||
} catch (error) { | ||
logError('Error running yarn install:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
// Initializes and updates git submodules | ||
function runSubmoduleUpdate() { | ||
try { | ||
log('Updating git submodules...', colors.blue); | ||
execSync('git submodule update --init --recursive', { stdio: 'inherit' }); | ||
// Rename the default remote to $GHOST_UPSTREAM if it's set | ||
// Otherwise `yarn main:submodules` will fail | ||
const GHOST_UPSTREAM = process.env.GHOST_UPSTREAM; | ||
if (GHOST_UPSTREAM) { | ||
execSync(`git submodule foreach "git remote | grep -q '^${GHOST_UPSTREAM}$' || (git remote | grep -q '^origin$' && git remote rename origin ${GHOST_UPSTREAM})"`); | ||
} | ||
|
||
log('Successfully ran git submodule update', colors.dim); | ||
} catch (error) { | ||
logError('Error running git submodule update:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
// Builds the typescript packages | ||
function runTypescriptBuild() { | ||
try { | ||
log('Building typescript packages...', colors.blue); | ||
execSync('yarn nx run-many -t build:ts', { stdio: 'inherit' }); | ||
log('Successfully ran yarn nx run-many -t build:ts', colors.dim); | ||
} catch (error) { | ||
logError('Error running yarn nx run-many -t build:ts:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
main(); |
Oops, something went wrong.