Skip to content

Commit

Permalink
Merge branch 'main' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
9larsons authored Jan 28, 2025
2 parents 843e4b1 + dac9721 commit 924e2c0
Show file tree
Hide file tree
Showing 421 changed files with 8,908 additions and 10,942 deletions.
20 changes: 7 additions & 13 deletions .docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ RUN apt-get update && \
# Base DevContainer: for use in a Dev Container where your local code is mounted into the container
### Adding code and installing dependencies gets overridden by your local code/dependencies, so this is done in onCreateCommand
FROM base AS base-devcontainer
ARG WORKDIR=/home/ghost
# Install Stripe CLI, zsh, playwright
RUN curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | gpg --dearmor | tee /usr/share/keyrings/stripe.gpg && \
echo "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | tee -a /etc/apt/sources.list.d/stripe.list && \
Expand All @@ -28,10 +29,11 @@ RUN curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/publ
npx -y [email protected] install --with-deps

ENV NX_DAEMON=true
ENV YARN_CACHE_FOLDER=/workspaces/ghost/.yarncache
ENV YARN_CACHE_FOLDER=$WORKDIR/.yarncache

EXPOSE 2368
EXPOSE 4200
EXPOSE 4201
EXPOSE 4173
EXPOSE 41730
EXPOSE 4175
Expand All @@ -47,21 +49,13 @@ EXPOSE 7174
### This is a full devcontainer with all the code and dependencies installed
### Useful in an environment like Github Codespaces where you don't mount your local code into the container
FROM base-devcontainer AS full-devcontainer
ARG WORKDIR=/home/ghost
WORKDIR $WORKDIR
COPY ../../ .
COPY . .
RUN yarn install --frozen-lockfile --prefer-offline --cache-folder $YARN_CACHE_FOLDER

# Development Stage: alternative entrypoint for development with some caching optimizations
FROM base-devcontainer AS development

ARG WORKDIR=/home/ghost
WORKDIR $WORKDIR

COPY ../../ .

RUN yarn install --frozen-lockfile --prefer-offline --cache-folder $YARN_CACHE_FOLDER && \
cp -r .yarncache .yarncachecopy && \
rm -Rf .yarncachecopy/.tmp && \
yarn cache clean

ENTRYPOINT ["./.devcontainer/.docker/development.entrypoint.sh"]
ENTRYPOINT ["/home/ghost/.docker/development.entrypoint.sh"]
CMD ["yarn", "dev"]
10 changes: 10 additions & 0 deletions .docker/development.entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# Mounting local code into the container overwrites the `node_modules` directories
# so we need to install dependencies again
yarn install --frozen-lockfile --prefer-offline

yarn nx run-many -t build:ts

# Execute the CMD
exec "$@"
10 changes: 1 addition & 9 deletions .github/scripts/clean.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// NOTE: this file can't use any NPM dependencies because it needs to run even if dependencies aren't installed yet or are corrupted
const {execSync} = require('child_process');

const isDevContainer = process.env.DEVCONTAINER === 'true';

cleanYarnCache();
resetNxCache();
deleteNodeModules();
Expand Down Expand Up @@ -49,13 +47,7 @@ function resetNxCache() {
function cleanYarnCache() {
console.log('Cleaning yarn cache...');
try {
if (isDevContainer) {
// In devcontainer, these directories are mounted from the host so we can't delete them — `yarn cache clean` will fail
// so we delete the contents of the directories instead
execSync('rm -rf .yarncache/* .yarncachecopy/*');
} else {
execSync('yarn cache clean');
}
execSync('rm -rf .yarncache/* .yarncachecopy/*');
} catch (error) {
console.error('Failed to clean yarn cache:', error);
process.exit(1);
Expand Down
100 changes: 100 additions & 0 deletions .github/scripts/setup-docker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const path = require('path');
const fs = require('fs').promises;
const {spawn} = require('child_process');

/**
* Run a command and stream output to the console
*
* @param {string} command
* @param {string[]} args
* @param {object} options
*/
async function runAndStream(command, args, options) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
stdio: 'inherit',
...options
});

child.on('close', (code) => {
if (code === 0) {
resolve(code);
} else {
reject(new Error(`'${command} ${args.join(' ')}' exited with code ${code}`));
}
});

});
}

/**
* Removes node dependencies and cleans up local caches
*/
function clean() {
require('./clean');
}

/**
* Adjust config.local.json for Docker Compose setup
*/
async function adjustConfig() {
console.log('Adjusting configuration...');
const coreFolder = path.join(__dirname, '../../ghost/core');
const currentConfigPath = path.join(coreFolder, 'config.local.json');
let currentConfig;
try {
currentConfig = require(currentConfigPath);
} catch (err) {
currentConfig = {};
}

currentConfig.database = {
client: 'mysql',
docker: true,
connection: {
host: 'mysql',
user: 'root',
password: 'root',
database: 'ghost'
}
};

currentConfig.adapters = {
...currentConfig.adapters,
Redis: {
host: 'redis',
port: 6379
}
};

currentConfig.server = {
...currentConfig.server,
host: '0.0.0.0',
port: 2368
};

try {
await fs.writeFile(currentConfigPath, JSON.stringify(currentConfig, null, 4));
} catch (err) {
console.error('Failed to write config.local.json', err);
console.log(`Please add the following to config.local.json:\n`, JSON.stringify(currentConfig, null, 4));
process.exit(1);
}
}

async function buildContainer() {
console.log('Building container...');
await runAndStream('docker-compose', ['build'], {});
}

async function runMigrations() {
console.log('Running migrations...');
await runAndStream('docker-compose', ['run', '--rm', '-w', '/home/ghost/ghost/core', 'ghost', 'yarn', 'knex-migrator', 'init'], {cwd: path.join(__dirname, '../../')});
}

(async () => {
clean();
await adjustConfig();
await buildContainer();
await runMigrations();
})();
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2013-2024 Ghost Foundation
Copyright (c) 2013-2025 Ghost Foundation

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ To stay up to date with all the latest news and product updates, make sure you [

# Copyright & license

Copyright (c) 2013-2024 Ghost Foundation - Released under the [MIT license](LICENSE).
Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE).
Ghost and the Ghost Logo are trademarks of Ghost Foundation Ltd. Please see our [trademark policy](https://ghost.org/trademark/) for info on acceptable usage.
2 changes: 1 addition & 1 deletion apps/admin-x-activitypub/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tryghost/admin-x-activitypub",
"version": "0.3.42",
"version": "0.3.54",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
8 changes: 4 additions & 4 deletions apps/admin-x-activitypub/src/api/activitypub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ describe('ActivityPubAPI', function () {
},
[`https://activitypub.api/.ghost/activitypub/actions/search?query=${encodeURIComponent(handle)}`]: {
response: JSONResponse({
profiles: [
accounts: [
{
handle,
name: 'Foo Bar'
Expand All @@ -869,7 +869,7 @@ describe('ActivityPubAPI', function () {

const actual = await api.search(handle);
const expected = {
profiles: [
accounts: [
{
handle,
name: 'Foo Bar'
Expand All @@ -880,7 +880,7 @@ describe('ActivityPubAPI', function () {
expect(actual).toEqual(expected);
});

test('It returns an empty array when there are no profiles in the response', async function () {
test('It returns an empty array when there are no accounts in the response', async function () {
const handle = '@[email protected]';

const fakeFetch = Fetch({
Expand All @@ -905,7 +905,7 @@ describe('ActivityPubAPI', function () {

const actual = await api.search(handle);
const expected = {
profiles: []
accounts: []
};

expect(actual).toEqual(expected);
Expand Down
Loading

0 comments on commit 924e2c0

Please sign in to comment.