Added experimental background job queue #13658
Workflow file for this run
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
name: CI | |
on: | |
pull_request: | |
types: [opened, synchronize, reopened, labeled, unlabeled] | |
push: | |
branches: | |
- main | |
- 'v5.*' | |
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 | |
~/.cache/ms-playwright/ | |
CACHED_BUILD_PATHS: | | |
${{ github.workspace }}/ghost/*/build | |
NX_REJECT_UNKNOWN_LOCAL_CACHE: 0 | |
NODE_VERSION: 20.11.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' }} | |
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 | |
run: echo "$GITHUB_CONTEXT" | |
env: | |
GITHUB_CONTEXT: ${{ toJson(github) }} | |
- 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.event.pull_request.user.login }}" | |
ENCODED_USERNAME=$(printf '%s' '${{ github.event.pull_request.user.login }}' | 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/**' | |
admin: | |
- *shared | |
- 'ghost/admin/**' | |
admin-x-settings: | |
- *shared | |
- 'apps/admin-x-settings/**' | |
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/**' | |
any-code: | |
- '!**/*.md' | |
- name: 'Checkout current commit' | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ env.HEAD_COMMIT }} | |
- 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_MAIN == 'false' && env.DEPENDENCY_CACHE_RESTORE_KEYS || 'dep-never-restore'}} | |
- name: Check build cache | |
uses: actions/cache@v4 | |
id: cache_built_packages | |
with: | |
path: ${{ env.CACHED_BUILD_PATHS }} | |
key: ${{ env.HEAD_COMMIT }} | |
- name: Set up Node | |
uses: actions/setup-node@v4 | |
env: | |
FORCE_COLOR: 0 | |
with: | |
node-version: ${{ env.NODE_VERSION }} | |
cache: yarn | |
- name: Install dependencies | |
run: yarn install --prefer-offline --frozen-lockfile | |
- name: Build packages | |
if: steps.cache_built_packages.outputs.cache-hit != 'true' | |
run: yarn nx run-many -t build:ts | |
outputs: | |
changed_admin: ${{ steps.changed.outputs.admin }} | |
changed_core: ${{ steps.changed.outputs.core }} | |
changed_admin_x_settings: ${{ steps.changed.outputs.admin-x-settings }} | |
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_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 }} | |
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 }} | |
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_main == 'true' || needs.job_setup.outputs.has_browser_tests_label == 'true') | |
concurrency: | |
group: ${{ github.workflow }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
submodules: true | |
- 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: Get Playwright version | |
id: playwright-version | |
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> $GITHUB_OUTPUT | |
- uses: actions/cache@v4 | |
name: Check if Playwright browser is cached | |
id: playwright-cache | |
with: | |
path: ~/.cache/ms-playwright | |
key: ${{ runner.os }}-Playwright-${{steps.playwright-version.outputs.version}} | |
- name: Install Playwright browser if not cached | |
if: steps.playwright-cache.outputs.cache-hit != 'true' | |
run: npx playwright install --with-deps | |
- name: Install OS dependencies of Playwright if cache hit | |
if: steps.playwright-cache.outputs.cache-hit == 'true' | |
run: npx playwright install-deps | |
- 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_main == '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: 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: [ '18.12.1', '20.11.1' ] | |
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" | |
- run: yarn nx affected -t test:unit --base=${{ needs.job_setup.outputs.BASE_COMMIT }} | |
- uses: actions/upload-artifact@v4 | |
if: startsWith(matrix.node, '18') | |
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_database-tests: | |
runs-on: ubuntu-latest | |
needs: [job_setup] | |
if: needs.job_setup.outputs.changed_core == 'true' | |
strategy: | |
matrix: | |
node: [ '18.12.1', '20.11.1' ] | |
env: | |
- DB: mysql8 | |
NODE_ENV: testing-mysql | |
include: | |
- node: 20.11.1 | |
env: | |
DB: sqlite3 | |
NODE_ENV: testing | |
env: | |
DB: ${{ matrix.env.DB }} | |
NODE_ENV: ${{ matrix.env.NODE_ENV }} | |
name: Database 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' | |
- uses: daniellockyer/mysql-action@main | |
if: matrix.env.DB == 'mysql8' | |
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: Record start time | |
run: date +%s > ${{ runner.temp }}/startTime # Get start time for test suite | |
- 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 | |
# Get runtime in seconds for test suite | |
- name: Record test duration | |
run: | | |
startTime="$(cat ${{ runner.temp }}/startTime)" | |
endTime="$(date +%s)" | |
echo "test_time=$(($endTime-$startTime))" >> $GITHUB_ENV | |
- uses: actions/upload-artifact@v4 | |
if: startsWith(matrix.node, '18') && contains(matrix.env.DB, 'mysql') | |
with: | |
name: e2e-coverage | |
path: | | |
ghost/*/coverage-e2e/cobertura-coverage.xml | |
ghost/*/coverage-integration/cobertura-coverage.xml | |
ghost/*/coverage-regression/cobertura-coverage.xml | |
# Continue on error if TailScale service is down | |
- name: Tailscale Action | |
timeout-minutes: 2 | |
continue-on-error: true | |
if: (github.event_name == 'push' && github.repository_owner == 'TryGhost') || (github.event_name == 'pull_request' && startsWith(github.head_ref, 'TryGhost/')) | |
uses: tailscale/github-action@v1 | |
with: | |
authkey: ${{ secrets.TAILSCALE_AUTHKEY }} | |
# Report time taken to metrics service | |
# Continue on error if previous TailScale step fails | |
- name: Store test duration | |
uses: tryghost/actions/actions/trigger-metric@main | |
timeout-minutes: 1 | |
continue-on-error: true | |
if: (github.event_name == 'push' && github.repository_owner == 'TryGhost') || (github.event_name == 'pull_request' && startsWith(github.head_ref, 'TryGhost/')) | |
with: | |
metricName: 'test-time' | |
metricValue: ${{ env.test_time }} | |
configuration: | | |
{ | |
"metrics": { | |
"transports": ["elasticsearch"], | |
"metadata": { | |
"database": "${{ matrix.env.DB }}", | |
"node": "${{ matrix.node }}" | |
} | |
}, | |
"elasticsearch": { | |
"host": "${{ secrets.ELASTICSEARCH_HOST }}", | |
"username": "${{ secrets.ELASTICSEARCH_USERNAME }}", | |
"password": "${{ secrets.ELASTICSEARCH_PASSWORD }}" | |
} | |
} | |
- 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_regression-tests: | |
runs-on: ubuntu-latest | |
needs: [job_setup] | |
if: needs.job_setup.outputs.changed_core == 'true' | |
strategy: | |
matrix: | |
include: | |
- node: 20.11.1 | |
env: | |
DB: mysql8 | |
NODE_ENV: testing-mysql | |
- node: 20.11.1 | |
env: | |
DB: sqlite3 | |
NODE_ENV: testing | |
env: | |
DB: ${{ matrix.env.DB }} | |
NODE_ENV: ${{ matrix.env.NODE_ENV }} | |
name: Regression 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: daniellockyer/mysql-action@main | |
if: matrix.env.DB == 'mysql8' | |
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: Regression tests | |
working-directory: ghost/core | |
run: yarn test:ci:regression | |
- 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: Get Playwright version | |
id: playwright-version | |
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> $GITHUB_OUTPUT | |
- uses: actions/cache@v4 | |
name: Check if Playwright browser is cached | |
id: playwright-cache | |
with: | |
path: ~/.cache/ms-playwright | |
key: ${{ runner.os }}-Playwright-${{steps.playwright-version.outputs.version}} | |
- name: Install Playwright browser if not cached | |
if: steps.playwright-cache.outputs.cache-hit != 'true' | |
run: npx playwright install --with-deps | |
- name: Install OS dependencies of Playwright if cache hit | |
if: steps.playwright-cache.outputs.cache-hit == 'true' | |
run: npx playwright install-deps | |
- 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_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: Get Playwright version | |
id: playwright-version | |
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> $GITHUB_OUTPUT | |
- uses: actions/cache@v4 | |
name: Check if Playwright browser is cached | |
id: playwright-cache | |
with: | |
path: ~/.cache/ms-playwright | |
key: ${{ runner.os }}-Playwright-${{steps.playwright-version.outputs.version}} | |
- name: Install Playwright browser if not cached | |
if: steps.playwright-cache.outputs.cache-hit != 'true' | |
run: npx playwright install --with-deps | |
- name: Install OS dependencies of Playwright if cache hit | |
if: steps.playwright-cache.outputs.cache-hit == 'true' | |
run: npx playwright install-deps | |
- 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: Get Playwright version | |
id: playwright-version | |
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> $GITHUB_OUTPUT | |
- uses: actions/cache@v4 | |
name: Check if Playwright browser is cached | |
id: playwright-cache | |
with: | |
path: ~/.cache/ms-playwright | |
key: ${{ runner.os }}-Playwright-${{steps.playwright-version.outputs.version}} | |
- name: Install Playwright browser if not cached | |
if: steps.playwright-cache.outputs.cache-hit != 'true' | |
run: npx playwright install --with-deps | |
- name: Install OS dependencies of Playwright if cache hit | |
if: steps.playwright-cache.outputs.cache-hit == 'true' | |
run: npx playwright install-deps | |
- 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_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: '16.14.0' | |
- 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: npm pack | |
working-directory: ghost/core | |
- run: mv ghost-*.tgz ghost.tgz | |
working-directory: ghost/core | |
- name: Install latest v4 | |
run: | | |
DIR=$(mktemp -d) | |
echo "V4_DIR=$DIR" >> $GITHUB_ENV | |
ghost install v4 --local -d $DIR | |
- 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@v3 | |
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_database-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@v3 | |
with: | |
flags: admin-tests | |
move_coverage_to_trash: true | |
- name: Restore E2E coverage | |
if: contains(needs.job_database-tests.result, 'success') | |
uses: actions/download-artifact@v4 | |
with: | |
name: e2e-coverage | |
- name: Move coverage | |
if: contains(needs.job_database-tests.result, 'success') | |
run: | | |
rsync -av --remove-source-files core/* ghost/core | |
- name: Upload E2E test coverage | |
if: contains(needs.job_database-tests.result, 'success') | |
uses: codecov/codecov-action@v3 | |
with: | |
flags: e2e-tests | |
move_coverage_to_trash: true | |
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_database-tests, | |
job_regression-tests, | |
job_browser-tests, | |
job_admin_x_settings, | |
job_comments_ui, | |
job_signup_form, | |
] | |
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' | |
|| ( | |
github.event_name == 'pull_request' | |
&& needs.job_setup.outputs.member_is_in_org == 'true' | |
&& 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: Invoke build | |
uses: aurelien-baudet/workflow-dispatch@v2 | |
with: | |
token: ${{ secrets.CANARY_DOCKER_BUILD }} | |
workflow: .github/workflows/deploy.yml | |
ref: 'refs/heads/main' | |
repo: TryGhost/Ghost-Moya | |
inputs: '{"version":"canary","environment":"staging","version_extra":"${{ env.branch_name }}"}' | |
wait-for-completion-timeout: 25m | |
wait-for-completion-interval: 30s | |
publish_admin_x_activitypub: | |
needs: [ | |
job_setup, | |
job_lint, | |
job_unit-tests | |
] | |
name: Publish @tryghost/admin-x-activitypub | |
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' | |
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: Build the package | |
run: yarn run nx build @tryghost/admin-x-activitypub | |
- name: Check if version changed | |
id: version_check | |
working-directory: apps/admin-x-activitypub | |
run: | | |
CURRENT_VERSION=$(cat package.json | jq -r .version) | |
PUBLISHED_VERSION=$(npm show @tryghost/admin-x-activitypub version || echo "0.0.0") | |
echo "Current version: $CURRENT_VERSION" | |
echo "Published version: $PUBLISHED_VERSION" | |
if [ "$CURRENT_VERSION" = "$PUBLISHED_VERSION" ]; then | |
echo "Version is unchanged." | |
echo "version_changed=false" >> $GITHUB_ENV | |
else | |
echo "Version has changed." | |
echo "version_changed=true" >> $GITHUB_ENV | |
fi | |
- name: Configure .npmrc | |
run: | | |
echo "@tryghost:registry=https://registry.npmjs.org/" >> ~/.npmrc | |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc | |
- name: Publish to npm | |
if: env.version_changed == 'true' | |
working-directory: apps/admin-x-activitypub | |
env: | |
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
run: npm publish --access public | |
- name: Purge jsdelivr cache | |
if: env.version_changed == 'true' | |
uses: gacts/purge-jsdelivr-cache@v1 | |
with: | |
url: | | |
https://cdn.jsdelivr.net/ghost/admin-x-activitypub@0/dist/admin-x-activitypub.js |