Skip to content

Update dependency msw to v2.11.0 #25783

Update dependency msw to v2.11.0

Update dependency msw to v2.11.0 #25783

Workflow file for this run

name: CI
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
push:
# Ref: GHA Filter pattern syntax: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#filter-pattern-cheat-sheet
# Run on pushes to main, release branches, and previous/future major version branches
branches:
- main
- 'v[0-9]+.*' # Matches any release branch, e.g. v6.0.3, v12.1.0
- '[0-9]+.x' # Matches any major version branch, e.g. 5.x, 23.x
env:
FORCE_COLOR: 1
HEAD_COMMIT: ${{ github.sha }}
CACHED_DEPENDENCY_PATHS: |
${{ github.workspace }}/node_modules
${{ github.workspace }}/apps/*/node_modules
${{ github.workspace }}/ghost/*/node_modules
${{ github.workspace }}/e2e/node_modules
~/.cache/ms-playwright/
NX_REJECT_UNKNOWN_LOCAL_CACHE: 0
NODE_VERSION: 22.13.1
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
job_setup:
name: Setup
runs-on: ubuntu-latest
timeout-minutes: 15
env:
IS_MAIN: ${{ github.ref == 'refs/heads/main' }}
IS_DEVELOPMENT: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/5.x' || github.ref == 'refs/heads/6.x' }}
IS_SIX: ${{ github.ref == 'refs/heads/6.x' }}
IS_SIX_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref == '6.x' }}
permissions:
pull-requests: read
steps:
- name: Checkout current commit
uses: actions/checkout@v4
with:
ref: ${{ env.HEAD_COMMIT }}
fetch-depth: 2
- name: Output GitHub context
if: env.RUNNER_DEBUG == '1'
run: |
echo "GITHUB_EVENT_NAME: ${{ github.event_name }}"
echo "GITHUB_CONTEXT: ${{ toJson(github.event) }}"
- name: Get metadata (push)
if: github.event_name == 'push'
run: |
NUMBER_OF_COMMITS=$(printf "%s\n" '${{ toJson(github.event.commits.*.id) }}' | jq length)
echo "There are $NUMBER_OF_COMMITS commits in this push."
echo "BASE_COMMIT=$(git rev-parse HEAD~$NUMBER_OF_COMMITS)" >> $GITHUB_ENV
- name: Get metadata (pull_request)
if: github.event_name == 'pull_request'
run: |
BASE_COMMIT=$(curl --location --request GET 'https://api.github.com/repos/TryGhost/Ghost/pulls/${{ github.event.pull_request.number }}' --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | jq -r .base.sha)
echo "Setting BASE_COMMIT to $BASE_COMMIT"
echo "BASE_COMMIT=$BASE_COMMIT" >> $GITHUB_ENV
- name: Check user org membership
id: check_user_org_membership
if: github.event_name == 'pull_request'
run: |
echo "Looking up: ${{ github.triggering_actor }}"
ENCODED_USERNAME=$(printf '%s' '${{ github.triggering_actor }}' | jq -sRr @uri)
LOOKUP_USER=$(curl --write-out "%{http_code}" --silent --output /dev/null --location "https://api.github.com/orgs/tryghost/members/$ENCODED_USERNAME" --header "Authorization: Bearer ${{ secrets.CANARY_DOCKER_BUILD }}")
if [ "$LOOKUP_USER" == "204" ]; then
echo "User is in the org"
echo "is_member=true" >> $GITHUB_OUTPUT
else
echo "User is not in the org"
echo "is_member=false" >> $GITHUB_OUTPUT
fi
- name: Determine added packages
uses: dorny/[email protected]
id: added
with:
filters: |
new-package:
- added: 'ghost/**/package.json'
- name: Determine changed packages
uses: AurorNZ/[email protected]
id: changed
with:
filters: |
shared: &shared
- '.github/**'
- 'package.json'
- 'yarn.lock'
core:
- *shared
- 'ghost/**'
- '!ghost/admin/**'
- '!ghost/core/core/server/data/tinybird/**'
admin:
- *shared
- 'ghost/admin/**'
admin-x-settings:
- *shared
- 'apps/admin-x-settings/**'
- 'apps/admin-x-design-system/**'
- 'apps/admin-x-framework/**'
- 'apps/shade/**'
admin-x-activitypub:
- *shared
- 'apps/shade/**'
- 'apps/admin-x-framework/**'
- 'apps/admin-x-activitypub/**'
announcement-bar:
- *shared
- 'apps/announcement-bar/**'
comments-ui:
- *shared
- 'apps/comments-ui/**'
portal:
- *shared
- 'apps/portal/**'
signup-form:
- *shared
- 'apps/signup-form/**'
sodo-search:
- *shared
- 'apps/sodo-search/**'
tinybird:
- 'ghost/core/core/server/data/tinybird/**'
- '!ghost/core/core/server/data/tinybird/**/*.md'
any-code:
- '!**/*.md'
- name: Compute lockfile hash
run: echo "hash=lockfile-${{ hashFiles('yarn.lock') }}" >> "$GITHUB_ENV"
- name: Compute dependency cache key
run: echo "cachekey=dep-cache-${{ hashFiles('yarn.lock') }}-${{ env.HEAD_COMMIT }}" >> "$GITHUB_ENV"
- name: Compute dependency cache restore key
run: |
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "DEPENDENCY_CACHE_RESTORE_KEYS<<$EOF" >> "$GITHUB_ENV"
echo "dep-cache-${{ env.hash }}-${{ github.sha }}" >> "$GITHUB_ENV"
echo "dep-cache-${{ env.hash }}" >> "$GITHUB_ENV"
echo "dep-cache" >> "$GITHUB_ENV"
echo "$EOF" >> "$GITHUB_ENV"
- name: Nx cache
uses: actions/cache@v4
id: cache_nx
with:
path: .nxcache
key: nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT }}
restore-keys: |
nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT }}
nx-Linux-${{ github.ref }}
nx-Linux
- name: Check dependency cache
uses: actions/cache@v4
id: cache_dependencies
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ env.cachekey }}
restore-keys: ${{ env.IS_DEVELOPMENT == 'false' && env.DEPENDENCY_CACHE_RESTORE_KEYS || 'dep-never-restore'}}
- name: Define Node test matrix
id: node_matrix
run: |
echo 'matrix=["22.13.1"]' >> $GITHUB_OUTPUT
- name: Set up Node
uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install dependencies
run: yarn install --prefer-offline --frozen-lockfile
outputs:
changed_admin: ${{ steps.changed.outputs.admin }}
changed_core: ${{ steps.changed.outputs.core }}
changed_admin_x_settings: ${{ steps.changed.outputs.admin-x-settings }}
changed_admin_x_activitypub: ${{ steps.changed.outputs.admin-x-activitypub }}
changed_announcement_bar: ${{ steps.changed.outputs.announcement-bar }}
changed_comments_ui: ${{ steps.changed.outputs.comments-ui }}
changed_portal: ${{ steps.changed.outputs.portal }}
changed_signup_form: ${{ steps.changed.outputs.signup-form }}
changed_sodo_search: ${{ steps.changed.outputs.sodo-search }}
changed_tinybird: ${{ steps.changed.outputs.tinybird }}
changed_any_code: ${{ steps.changed.outputs.any-code }}
changed_new_package: ${{ steps.added.outputs.new-package }}
base_commit: ${{ env.BASE_COMMIT }}
is_main: ${{ env.IS_MAIN }}
is_development: ${{ env.IS_DEVELOPMENT }}
is_six: ${{ env.IS_SIX }}
is_six_pr: ${{ env.IS_SIX_PR }}
member_is_in_org: ${{ steps.check_user_org_membership.outputs.is_member }}
has_browser_tests_label: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'browser-tests') }}
dependency_cache_key: ${{ env.cachekey }}
node_version: ${{ env.NODE_VERSION }}
node_test_matrix: ${{ steps.node_matrix.outputs.matrix }}
job_lint:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_any_code == 'true'
name: Lint
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1000
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- uses: actions/cache@v4
with:
path: ghost/**/.eslintcache
key: eslint-cache
- run: yarn nx affected -t lint --base=${{ needs.job_setup.outputs.BASE_COMMIT }}
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_i18n:
runs-on: ubuntu-latest
needs: [job_setup]
name: i18n
if: |
needs.job_setup.outputs.changed_comments_ui == 'true'
|| needs.job_setup.outputs.changed_signup_form == 'true'
|| needs.job_setup.outputs.changed_sodo_search == 'true'
|| needs.job_setup.outputs.changed_portal == 'true'
|| needs.job_setup.outputs.changed_core == 'true'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Run i18n tests
run: yarn nx run @tryghost/i18n:test
job_admin-tests:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_admin == 'true'
name: Admin tests - Chrome
env:
MOZ_HEADLESS: 1
JOBS: 1
CI: true
COVERAGE: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- run: yarn nx run ghost-admin:test
env:
BROWSER: Chrome
# Merge coverage reports and upload
- name: Merge Admin test coverage
run: yarn ember coverage-merge
working-directory: ghost/admin
- uses: actions/upload-artifact@v4
with:
name: admin-coverage
path: ghost/*/coverage/cobertura-coverage.xml
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_browser-tests:
name: Browser tests
timeout-minutes: 60
runs-on:
labels: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_any_code == 'true' && (needs.job_setup.outputs.is_six_pr == 'true' || needs.job_setup.outputs.is_development == 'true' || needs.job_setup.outputs.has_browser_tests_label == 'true')
concurrency:
group: ${{ github.workflow }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Check secrets
if: github.event_name == 'pull_request'
env:
STRIPE_PUBLISHABLE_KEY: ${{ secrets.STRIPE_PUBLISHABLE_KEY }}
run: |
if [ -z "${{ env.STRIPE_PUBLISHABLE_KEY }}" ]; then
echo "Stripe Publishable Key is not available. Did you open this PR from a fork?"
echo "If so, please re-open the PR from a branch in the upstream TryGhost/Ghost repository."
exit 1
fi
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
- name: Install Stripe-CLI
run: |
export VERSION=1.13.5
wget "https://github.com/stripe/stripe-cli/releases/download/v$VERSION/stripe_${VERSION}_linux_x86_64.tar.gz"
tar -zxvf "stripe_${VERSION}_linux_x86_64.tar.gz"
mv stripe /usr/local/bin
stripe -v
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Run migrations
working-directory: ghost/core
run: yarn knex-migrator init
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
- name: Build Admin
run: yarn nx run ghost-admin:build:dev
- name: Run Playwright tests locally
run: yarn test:browser
env:
CI: true
STRIPE_PUBLISHABLE_KEY: ${{ secrets.STRIPE_PUBLISHABLE_KEY }}
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: browser-tests-playwright-report
path: ghost/core/playwright-report
retention-days: 30
job_perf-tests:
runs-on:
labels: ubuntu-latest-4-cores
needs: [job_setup]
if: needs.job_setup.outputs.changed_core == 'true' && needs.job_setup.outputs.is_development == 'true'
name: Performance tests
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Install hyperfine
run: |
export HYPERFINE_VERSION=1.18.0
wget https://github.com/sharkdp/hyperfine/releases/download/v$HYPERFINE_VERSION/hyperfine-v$HYPERFINE_VERSION-x86_64-unknown-linux-gnu.tar.gz
tar -zxvf hyperfine-v$HYPERFINE_VERSION-x86_64-unknown-linux-gnu.tar.gz
mv hyperfine-v$HYPERFINE_VERSION-x86_64-unknown-linux-gnu/hyperfine /usr/local/bin
chmod +x /usr/local/bin/hyperfine
- name: Build TS code
run: yarn nx run-many -t build:tsc
- name: Run hyperfine on boot
working-directory: ghost/core
run: hyperfine --show-output --warmup 3 'GHOST_CI_SHUTDOWN_AFTER_BOOT=1 node index.js' --export-json boot-perf.json
- name: Convert data
working-directory: ghost/core
run: |
jq '[{ name: "Boot time", unit: "s", value: .results[0].median, range: ((.results[0].max - .results[0].min) | tostring) }]' < boot-perf.json > boot-perf-formatted.json
- name: Run analysis
uses: benchmark-action/[email protected]
with:
tool: 'customSmallerIsBetter'
output-file-path: ghost/core/boot-perf-formatted.json
benchmark-data-dir-path: ""
gh-repository: github.com/TryGhost/Ghost-Benchmarks
github-token: ${{ secrets.CANARY_DOCKER_BUILD }}
auto-push: true
job_unit-tests:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_any_code == 'true'
strategy:
matrix:
node: ${{ fromJSON(needs.job_setup.outputs.node_test_matrix) }}
name: Unit tests (Node ${{ matrix.node }})
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1000
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ matrix.node }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Set timezone (non-UTC)
uses: szenius/[email protected]
with:
timezoneLinux: "America/New_York"
# Ensure all built packages are built before running tests (admin is built in job_setup)
- name: Build remaining assets
run: yarn nx run-many -t build --exclude=ghost-admin
- run: yarn nx affected -t test:unit --base=${{ needs.job_setup.outputs.BASE_COMMIT }}
- uses: actions/upload-artifact@v4
if: matrix.node == env.NODE_VERSION
with:
name: unit-coverage
path: ghost/*/coverage/cobertura-coverage.xml
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_acceptance-tests:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_core == 'true'
strategy:
matrix:
node: ${{ fromJSON(needs.job_setup.outputs.node_test_matrix) }}
env:
- DB: mysql8
NODE_ENV: testing-mysql
include:
- node: ${{ needs.job_setup.outputs.node_version }}
env:
DB: sqlite3
NODE_ENV: testing
env:
DB: ${{ matrix.env.DB }}
NODE_ENV: ${{ matrix.env.NODE_ENV }}
name: Acceptance tests (Node ${{ matrix.node }}, ${{ matrix.env.DB }})
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ matrix.node }}
- name: Shutdown MySQL
run: sudo service mysql stop
if: matrix.env.DB == 'mysql8'
- name: Login to Docker Hub
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: tryghost/mysql-action@main
if: matrix.env.DB == 'mysql8'
timeout-minutes: 3
with:
authentication plugin: 'caching_sha2_password'
mysql version: '8.0'
mysql database: 'ghost_testing'
mysql root password: 'root'
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Set timezone (non-UTC)
uses: szenius/[email protected]
with:
timezoneLinux: "America/New_York"
- name: Set env vars (SQLite)
if: contains(matrix.env.DB, 'sqlite')
run: echo "database__connection__filename=/dev/shm/ghost-test.db" >> $GITHUB_ENV
- name: Set env vars (MySQL)
if: contains(matrix.env.DB, 'mysql')
run: echo "database__connection__password=root" >> $GITHUB_ENV
- name: E2E tests
working-directory: ghost/core
run: yarn test:ci:e2e
- name: Integration tests
working-directory: ghost/core
run: yarn test:ci:integration
- uses: actions/upload-artifact@v4
if: matrix.node == env.NODE_VERSION && contains(matrix.env.DB, 'mysql')
with:
name: e2e-coverage
path: |
ghost/*/coverage-e2e/cobertura-coverage.xml
ghost/*/coverage-integration/cobertura-coverage.xml
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_legacy-tests:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_core == 'true'
strategy:
matrix:
include:
- node: ${{ needs.job_setup.outputs.node_version }}
env:
DB: mysql8
NODE_ENV: testing-mysql
- node: ${{ needs.job_setup.outputs.node_version }}
env:
DB: sqlite3
NODE_ENV: testing
env:
DB: ${{ matrix.env.DB }}
NODE_ENV: ${{ matrix.env.NODE_ENV }}
name: Legacy tests (Node ${{ matrix.node }}, ${{ matrix.env.DB }})
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ matrix.node }}
- name: Shutdown MySQL
run: sudo service mysql stop
if: matrix.env.DB == 'mysql8'
- uses: tryghost/mysql-action@main
if: matrix.env.DB == 'mysql8'
timeout-minutes: 3
with:
authentication plugin: 'caching_sha2_password'
mysql version: '8.0'
mysql database: 'ghost_testing'
mysql root password: 'root'
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Set env vars (SQLite)
if: contains(matrix.env.DB, 'sqlite')
run: echo "database__connection__filename=/dev/shm/ghost-test.db" >> $GITHUB_ENV
- name: Set env vars (MySQL)
if: contains(matrix.env.DB, 'mysql')
run: echo "database__connection__password=root" >> $GITHUB_ENV
- name: Legacy tests
working-directory: ghost/core
run: yarn test:ci:legacy
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_admin_x_settings:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_admin_x_settings == 'true'
name: Admin-X Settings tests
env:
CI: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
- run: yarn nx run @tryghost/admin-x-settings:test:acceptance
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: admin-x-settings-playwright-report
path: apps/admin-x-settings/playwright-report
retention-days: 30
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_admin_x_activitypub:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_admin_x_activitypub == 'true'
name: ActivityPub tests
env:
CI: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
- run: yarn nx run @tryghost/admin-x-activitypub:test:acceptance
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: admin-x-activitypub-playwright-report
path: apps/admin-x-activitypub/playwright-report
retention-days: 30
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_comments_ui:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_comments_ui == 'true'
name: Comments-UI tests
env:
CI: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
- run: yarn nx run @tryghost/comments-ui:test
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: comments-ui-playwright-report
path: apps/comments-ui/playwright-report
retention-days: 30
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_signup_form:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_signup_form == 'true'
name: Signup-form tests
env:
CI: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
- run: yarn nx run @tryghost/signup-form:test:e2e
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: signup-form-playwright-report
path: apps/signup-form/playwright-report
retention-days: 30
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_e2e-tests:
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_any_code == 'true'
name: E2E tests
env:
CI: true
database__client: mysql2
database__connection__host: localhost
database__connection__port: 3306
database__connection__user: ghost
database__connection__password: ghost
database__connection__database: ghost_testing
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Configure Docker daemon for mirror.gcr.io
run: |
echo '{"registry-mirrors": ["https://mirror.gcr.io"]}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
docker logout || echo "No Docker Hub login found"
- name: Start E2E services
run: docker compose -f e2e/compose.e2e.yml up -d --wait
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
- name: Install Tinybird CLI
run: curl -fsSL https://tinybird.co/install.sh | sh
- name: Deploy Tinybird Schema
working-directory: ghost/core/core/server/data/tinybird
run: tb build
- name: Get Tinybird configuration
working-directory: ghost/core/core/server/data/tinybird
run: ./scripts/configure-ghost.sh
- name: Run migrations
working-directory: ghost/core
run: yarn knex-migrator init
- name: Build Admin
run: yarn nx run ghost-admin:build:dev
- name: Start Ghost
working-directory: ghost/core
run: node --import=tsx index.js &
- name: Wait for Ghost to be ready
run: |
timeout 120 bash -c 'until curl -f http://localhost:2368; do sleep 1; done'
- name: Run E2E tests
run: yarn test:e2e
env:
GHOST_BASE_URL: http://localhost:2368
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-playwright-report
path: e2e/test-results
retention-days: 30
- name: Stop E2E services
if: always()
run: docker compose -f e2e/compose.e2e.yml down
job_tinybird-tests:
name: Tinybird Tests
runs-on: ubuntu-latest
needs: [job_setup]
if: needs.job_setup.outputs.changed_tinybird == 'true'
defaults:
run:
working-directory: ghost/core/core/server/data/tinybird
services:
tinybird:
image: tinybirdco/tinybird-local:latest
ports:
- 7181:7181
env:
TINYBIRD_HOST: ${{ secrets.TINYBIRD_HOST }}
TINYBIRD_TOKEN: ${{ secrets.TINYBIRD_TOKEN }}
TINYBIRD_HOST_STAGING: ${{ secrets.TINYBIRD_HOST_STAGING }}
TINYBIRD_TOKEN_STAGING: ${{ secrets.TINYBIRD_TOKEN_STAGING }}
steps:
- uses: actions/checkout@v4
- name: Install Tinybird CLI
run: curl -fsSL https://tinybird.co/install.sh | sh
- name: Build project
run: tb build
- name: Test project
run: tb test run
- name: Deployment check - Staging
run: tb --cloud --host ${{ env.TINYBIRD_HOST_STAGING }} --token ${{ env.TINYBIRD_TOKEN_STAGING }} deploy --check
- name: Deployment check - Production
run: tb --cloud --host ${{ env.TINYBIRD_HOST }} --token ${{ env.TINYBIRD_TOKEN }} deploy --check
job_ghost-cli:
name: Ghost-CLI tests
needs: [job_setup]
if: needs.job_setup.outputs.changed_core == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install npm v8 # downgrade from v10 to v8 due to https://github.com/npm/cli/issues/6738
run: npm install -g npm@8
- name: Install Ghost-CLI
run: npm install -g ghost-cli@latest
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- run: node .github/scripts/bump-version.js canary
- run: yarn archive
- run: mv ghost-*.tgz ghost.tgz
working-directory: ghost/core
- name: Switch back to Node v16.14.0 (for v4)
uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: '16.14.0'
- name: Install latest v4
run: |
DIR=$(mktemp -d)
echo "V4_DIR=$DIR" >> $GITHUB_ENV
ghost install v4 --local -d $DIR
- name: Switch back to ${{ env.NODE_VERSION }}
uses: actions/setup-node@v4
env:
FORCE_COLOR: 0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Update from v4
run: |
ghost update -f -d $V4_DIR --archive $(pwd)/ghost/core/ghost.tgz
- name: Save Ghost CLI Debug Logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: ghost-cli-debug-logs
path: /home/runner/.ghost/logs/
- name: Clean Install
run: |
DIR=$(mktemp -d)
ghost install local -d $DIR --archive $(pwd)/ghost/core/ghost.tgz
- name: Latest Release
run: |
DIR=$(mktemp -d)
ghost install local -d $DIR
ghost update -d $DIR --archive $(pwd)/ghost/core/ghost.tgz
- name: Print debug logs
if: failure()
run: |
[ -f ~/.ghost/logs/*.log ] && cat ~/.ghost/logs/*.log
- uses: tryghost/actions/actions/slack-build@main
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
with:
status: ${{ job.status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
job_coverage:
name: Coverage
needs: [
job_admin-tests,
job_acceptance-tests,
job_unit-tests
]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Restore Admin coverage
if: contains(needs.job_admin-tests.result, 'success')
uses: actions/download-artifact@v4
with:
name: admin-coverage
- name: Move coverage
if: contains(needs.job_admin-tests.result, 'success')
run: |
rsync -av --remove-source-files admin/* ghost/admin
- name: Upload Admin test coverage
uses: codecov/codecov-action@v5
with:
flags: admin-tests
- name: Restore E2E coverage
if: contains(needs.job_acceptance-tests.result, 'success')
uses: actions/download-artifact@v4
with:
name: e2e-coverage
- name: Move coverage
if: contains(needs.job_acceptance-tests.result, 'success')
run: |
rsync -av --remove-source-files core/* ghost/core
- name: Upload E2E test coverage
if: contains(needs.job_acceptance-tests.result, 'success')
uses: codecov/codecov-action@v5
with:
flags: e2e-tests
job_required_tests:
name: All required tests passed or skipped
needs:
[
job_setup,
job_lint,
job_i18n,
job_ghost-cli,
job_admin-tests,
job_unit-tests,
job_acceptance-tests,
job_legacy-tests,
job_browser-tests,
job_admin_x_settings,
job_admin_x_activitypub,
job_comments_ui,
job_signup_form,
job_e2e-tests,
job_tinybird-tests
]
if: always()
runs-on: ubuntu-latest
steps:
- name: Output needs
run: echo "${{ toJson(needs) }}"
- name: Check if any required jobs failed or been cancelled
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: |
echo "One of the dependent jobs have failed or been cancelled. You may need to re-run it." && exit 1
canary:
needs: [
job_setup,
job_required_tests
]
name: Canary
runs-on: ubuntu-latest
if: |
always()
&& needs.job_setup.result == 'success'
&& needs.job_required_tests.result == 'success'
&& (
needs.job_setup.outputs.is_main == 'true'
|| needs.job_setup.outputs.is_six == 'true'
|| (
github.event_name == 'pull_request'
&& (
needs.job_setup.outputs.member_is_in_org == 'true'
|| github.event.pull_request.user.login == 'renovate[bot]'
)
&& contains(github.event.pull_request.labels.*.name, 'deploy-to-staging')
)
)
steps:
- name: Output needs (for debugging)
run: echo "${{ toJson(needs) }}"
- name: Compute branch name (push)
if: github.event_name == 'push'
run: echo "branch_name=${{ github.ref_name }}" >> $GITHUB_ENV
- name: Compute branch name (pull_request)
if: github.event_name == 'pull_request'
run: echo "branch_name=${{ github.ref }}" >> $GITHUB_ENV
- name: Set deployment parameters
run: |
if [[ "${{ needs.job_setup.outputs.is_main }}" == "true" ]]; then
echo "deploy_version=canary" >> $GITHUB_ENV
else
echo "deploy_version=six" >> $GITHUB_ENV
fi
- name: Invoke build
uses: aurelien-baudet/workflow-dispatch@v4
with:
token: ${{ secrets.CANARY_DOCKER_BUILD }}
workflow: .github/workflows/deploy.yml
ref: 'refs/heads/main' # this is the ref of Ghost-Moya
repo: TryGhost/Ghost-Moya
# env.branch_name is the branch of Ghost itself
inputs: '{"version":"${{ env.deploy_version }}","environment":"staging","version_extra":"${{ env.branch_name }}"}'
wait-for-completion-timeout: 25m
wait-for-completion-interval: 30s
publish_packages:
needs: [
job_setup,
job_lint,
job_unit-tests
]
name: Publish ${{ matrix.package_name }}
runs-on: ubuntu-latest
if: always() && needs.job_setup.result == 'success' && needs.job_lint.result == 'success' && needs.job_unit-tests.result == 'success' && needs.job_setup.outputs.is_main == 'true'
strategy:
matrix:
include:
- package_name: '@tryghost/admin-x-activitypub'
package_path: 'apps/admin-x-activitypub'
cdn_paths: 'https://cdn.jsdelivr.net/ghost/admin-x-activitypub@0/dist/admin-x-activitypub.js'
- package_name: '@tryghost/portal'
package_path: 'apps/portal'
cdn_paths: 'https://cdn.jsdelivr.net/ghost/portal@~CURRENT_MINOR/umd/portal.min.js'
- package_name: '@tryghost/sodo-search'
package_path: 'apps/sodo-search'
cdn_paths: |
https://cdn.jsdelivr.net/ghost/sodo-search@~CURRENT_MINOR/umd/sodo-search.min.js
https://cdn.jsdelivr.net/ghost/sodo-search@~CURRENT_MINOR/umd/main.css
- package_name: '@tryghost/comments-ui'
package_path: 'apps/comments-ui'
cdn_paths: 'https://cdn.jsdelivr.net/ghost/comments-ui@~CURRENT_MINOR/umd/comments-ui.min.js'
- package_name: '@tryghost/signup-form'
package_path: 'apps/signup-form'
cdn_paths: 'https://cdn.jsdelivr.net/ghost/signup-form@~CURRENT_MINOR/umd/signup-form.min.js'
- package_name: '@tryghost/announcement-bar'
package_path: 'apps/announcement-bar'
cdn_paths: 'https://cdn.jsdelivr.net/ghost/announcement-bar@~CURRENT_MINOR/umd/announcement-bar.min.js'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Restore caches
uses: ./.github/actions/restore-cache
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_setup.outputs.dependency_cache_key }}
- name: Check if version changed
id: version_check
working-directory: ${{ matrix.package_path }}
run: |
CURRENT_VERSION=$(cat package.json | jq -r .version)
PUBLISHED_VERSION=$(npm show ${{ matrix.package_name }} version || echo "0.0.0")
echo "Current version: $CURRENT_VERSION"
echo "Published version: $PUBLISHED_VERSION"
CURRENT_MINOR=$(cat package.json | jq -r .version | awk -F. '{print $1"."$2}')
echo "current_minor=$CURRENT_MINOR" >> $GITHUB_OUTPUT
if [ "$CURRENT_VERSION" = "$PUBLISHED_VERSION" ]; then
echo "Version is unchanged."
echo "version_changed=false" >> $GITHUB_OUTPUT
else
echo "Version has changed."
echo "version_changed=true" >> $GITHUB_OUTPUT
fi
- name: Build the package
if: steps.version_check.outputs.version_changed == 'true'
run: yarn run nx build ${{ matrix.package_name }}
- name: Configure .npmrc
if: steps.version_check.outputs.version_changed == 'true'
run: |
echo "@tryghost:registry=https://registry.npmjs.org/" >> ~/.npmrc
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
- name: Publish to npm
if: steps.version_check.outputs.version_changed == 'true'
working-directory: ${{ matrix.package_path }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish --access public
- name: Replace CURRENT_MINOR in cdn-paths
id: cdn_paths
if: steps.version_check.outputs.version_changed == 'true'
run: |
cdn_paths="${{ matrix.cdn_paths }}"
echo "cdn_paths<<EOF" >> $GITHUB_OUTPUT
echo "$cdn_paths" | sed 's/CURRENT_MINOR/${{ steps.version_check.outputs.current_minor }}/g' >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Print cdn_paths
if: steps.version_check.outputs.version_changed == 'true'
run: echo "${{ steps.cdn_paths.outputs.cdn_paths }}"
- name: Wait before purging jsDelivr cache
if: steps.version_check.outputs.version_changed == 'true' && matrix.package_name == '@tryghost/admin-x-activitypub'
run: |
echo "Purging jsDelivr cache immediately after publishing a new version on NPM is unreliable. Waiting 1 minute before purging cache..."
sleep 60
- name: Purge jsDelivr cache
if: steps.version_check.outputs.version_changed == 'true'
uses: gacts/purge-jsdelivr-cache@v1
with:
url: ${{ steps.cdn_paths.outputs.cdn_paths }}
deploy_tinybird_staging:
name: Deploy Tinybird - Staging
runs-on: ubuntu-latest
needs: [
job_setup,
job_tinybird-tests
]
if: always() && needs.job_setup.outputs.changed_tinybird == 'true' && needs.job_setup.result == 'success' && needs.job_tinybird-tests.result == 'success' && needs.job_setup.outputs.is_main == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Deploy to Staging
uses: ./.github/actions/deploy-tinybird
with:
host: ${{ secrets.TINYBIRD_HOST_STAGING }}
token: ${{ secrets.TINYBIRD_TOKEN_STAGING }}
workspace: 'Staging'
slack-webhook: ${{ secrets.ANALYTICS_SLACK_WEBHOOK_URL }}
deploy_tinybird_production:
name: Deploy Tinybird - Production
runs-on: ubuntu-latest
needs: [
job_setup,
job_tinybird-tests,
deploy_tinybird_staging
]
if: always() && needs.job_setup.outputs.changed_tinybird == 'true' && needs.job_setup.result == 'success' && needs.job_tinybird-tests.result == 'success' && needs.deploy_tinybird_staging.result == 'success' && needs.job_setup.outputs.is_main == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Deploy to Production
uses: ./.github/actions/deploy-tinybird
with:
host: ${{ secrets.TINYBIRD_HOST }}
token: ${{ secrets.TINYBIRD_TOKEN }}
workspace: 'Production'
slack-webhook: ${{ secrets.ANALYTICS_SLACK_WEBHOOK_URL }}