### What?
This PR introduces complete trash (soft-delete) support. When a
collection is configured with `trash: true`, documents can now be
soft-deleted and restored via both the API and the admin panel.
```
import type { CollectionConfig } from 'payload'
const Posts: CollectionConfig = {
slug: 'posts',
trash: true, // <-- New collection config prop @default false
fields: [
{
name: 'title',
type: 'text',
},
// other fields...
],
}
```
### Why
Soft deletes allow developers and admins to safely remove documents
without losing data immediately. This enables workflows like reversible
deletions, trash views, and auditing—while preserving compatibility with
drafts, autosave, and version history.
### How?
#### Backend
- Adds new `trash: true` config option to collections.
- When enabled:
- A `deletedAt` timestamp is conditionally injected into the schema.
- Soft deletion is performed by setting `deletedAt` instead of removing
the document from the database.
- Extends all relevant API operations (`find`, `findByID`, `update`,
`delete`, `versions`, etc.) to support a new `trash` param:
- `trash: false` → excludes trashed documents (default)
- `trash: true` → includes both trashed and non-trashed documents
- To query **only trashed** documents: use `trash: true` with a `where`
clause like `{ deletedAt: { exists: true } }`
- Enforces delete access control before allowing a soft delete via
update or updateByID.
- Disables version restoring on trashed documents (must be restored
first).
#### Admin Panel
- Adds a dedicated **Trash view**: `/collections/:collectionSlug/trash`
- Default delete action now soft-deletes documents when `trash: true` is
set.
- **Delete confirmation modal** includes a checkbox to permanently
delete instead.
- Trashed documents:
- Displays UI banner for better clarity of trashed document edit view vs
non-trashed document edit view
- Render in a read-only edit view
- Still allow access to **Preview**, **API**, and **Versions** tabs
- Updated Status component:
- Displays “Previously published” or “Previously a draft” for trashed
documents.
- Disables status-changing actions when documents are in trash.
- Adds new **Restore** bulk action to clear the `deletedAt` timestamp.
- New `Restore` and `Permanently Delete` buttons for
single-trashed-document restore and permanent deletion.
- **Restore confirmation modal** includes a checkbox to restore as
`published`, defaults to `draft`.
- Adds **Empty Trash** and **Delete permanently** bulk actions.
#### Notes
- This feature is completely opt-in. Collections without trash: true
behave exactly as before.
https://github.com/user-attachments/assets/00b83f8a-0442-441e-a89e-d5dc1f49dd37
733 lines
24 KiB
YAML
733 lines
24 KiB
YAML
name: ci
|
|
|
|
on:
|
|
pull_request:
|
|
types:
|
|
- opened
|
|
- reopened
|
|
- synchronize
|
|
- labeled
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
concurrency:
|
|
# <workflow_name>-<branch_name>-<true || commit_sha if branch is protected>
|
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref_protected && github.sha || ''}}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
DO_NOT_TRACK: 1 # Disable Turbopack telemetry
|
|
NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry
|
|
|
|
jobs:
|
|
changes:
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
pull-requests: read
|
|
outputs:
|
|
needs_build: ${{ steps.filter.outputs.needs_build }}
|
|
needs_tests: ${{ steps.filter.outputs.needs_tests }}
|
|
templates: ${{ steps.filter.outputs.templates }}
|
|
steps:
|
|
# https://github.com/actions/virtual-environments/issues/1187
|
|
- name: tune linux network
|
|
run: sudo ethtool -K eth0 tx off rx off
|
|
|
|
- uses: actions/checkout@v4
|
|
- uses: dorny/paths-filter@v3
|
|
id: filter
|
|
with:
|
|
filters: |
|
|
needs_build:
|
|
- '.github/workflows/main.yml'
|
|
- 'packages/**'
|
|
- 'test/**'
|
|
- 'pnpm-lock.yaml'
|
|
- 'package.json'
|
|
- 'templates/**'
|
|
needs_tests:
|
|
- '.github/workflows/main.yml'
|
|
- 'packages/**'
|
|
- 'test/**'
|
|
- 'pnpm-lock.yaml'
|
|
- 'package.json'
|
|
templates:
|
|
- 'templates/**'
|
|
- name: Log all filter results
|
|
run: |
|
|
echo "needs_build: ${{ steps.filter.outputs.needs_build }}"
|
|
echo "needs_tests: ${{ steps.filter.outputs.needs_tests }}"
|
|
echo "templates: ${{ steps.filter.outputs.templates }}"
|
|
|
|
lint:
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
|
|
- name: Lint
|
|
run: pnpm lint -- --quiet
|
|
|
|
build:
|
|
needs: changes
|
|
if: ${{ needs.changes.outputs.needs_build == 'true' }}
|
|
runs-on: ubuntu-24.04
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
|
|
- run: pnpm run build:all
|
|
env:
|
|
DO_NOT_TRACK: 1 # Disable Turbopack telemetry
|
|
|
|
- name: Cache build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
tests-unit:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: ${{ needs.changes.outputs.needs_tests == 'true' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Unit Tests
|
|
run: pnpm test:unit
|
|
env:
|
|
NODE_OPTIONS: --max-old-space-size=8096
|
|
|
|
tests-types:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: ${{ needs.changes.outputs.needs_tests == 'true' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Types Tests
|
|
run: pnpm test:types --target '>=5.7'
|
|
env:
|
|
NODE_OPTIONS: --max-old-space-size=8096
|
|
|
|
tests-int:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: ${{ needs.changes.outputs.needs_tests == 'true' }}
|
|
name: int-${{ matrix.database }}
|
|
timeout-minutes: 45
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
database:
|
|
- mongodb
|
|
- firestore
|
|
- postgres
|
|
- postgres-custom-schema
|
|
- postgres-uuid
|
|
- supabase
|
|
- sqlite
|
|
- sqlite-uuid
|
|
|
|
env:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: payloadtests
|
|
AWS_ENDPOINT_URL: http://127.0.0.1:4566
|
|
AWS_ACCESS_KEY_ID: localstack
|
|
AWS_SECRET_ACCESS_KEY: localstack
|
|
AWS_REGION: us-east-1
|
|
|
|
services:
|
|
postgres:
|
|
# Custom postgres 17 docker image that supports both pg-vector and postgis: https://github.com/payloadcms/postgis-vector
|
|
image: ${{ (startsWith(matrix.database, 'postgres') ) && 'ghcr.io/payloadcms/postgis-vector:latest' || '' }}
|
|
env:
|
|
# must specify password for PG Docker container image, see: https://registry.hub.docker.com/_/postgres?tab=description&page=1&name=10
|
|
POSTGRES_USER: ${{ env.POSTGRES_USER }}
|
|
POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }}
|
|
POSTGRES_DB: ${{ env.POSTGRES_DB }}
|
|
ports:
|
|
- 5432:5432
|
|
# needed because the postgres container does not provide a healthcheck
|
|
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Start LocalStack
|
|
run: pnpm docker:start
|
|
|
|
- name: Install Supabase CLI
|
|
uses: supabase/setup-cli@v1
|
|
with:
|
|
version: latest
|
|
if: matrix.database == 'supabase'
|
|
|
|
- name: Initialize Supabase
|
|
run: |
|
|
supabase init
|
|
supabase start
|
|
if: matrix.database == 'supabase'
|
|
|
|
- name: Configure PostgreSQL
|
|
run: |
|
|
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "CREATE ROLE runner SUPERUSER LOGIN;"
|
|
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "SELECT version();"
|
|
echo "POSTGRES_URL=postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" >> $GITHUB_ENV
|
|
if: startsWith(matrix.database, 'postgres')
|
|
|
|
- name: Configure PostgreSQL with custom schema
|
|
run: |
|
|
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "CREATE SCHEMA custom;"
|
|
if: matrix.database == 'postgres-custom-schema'
|
|
|
|
- name: Configure Supabase
|
|
run: |
|
|
echo "POSTGRES_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres" >> $GITHUB_ENV
|
|
if: matrix.database == 'supabase'
|
|
|
|
- name: Integration Tests
|
|
run: pnpm test:int
|
|
env:
|
|
NODE_OPTIONS: --max-old-space-size=8096
|
|
PAYLOAD_DATABASE: ${{ matrix.database }}
|
|
POSTGRES_URL: ${{ env.POSTGRES_URL }}
|
|
|
|
tests-e2e:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: ${{ needs.changes.outputs.needs_tests == 'true' }}
|
|
name: e2e-${{ matrix.suite }}
|
|
timeout-minutes: 45
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
# find test -type f -name 'e2e.spec.ts' | sort | xargs dirname | xargs -I {} basename {}
|
|
suite:
|
|
- _community
|
|
- access-control
|
|
- admin__e2e__general
|
|
- admin__e2e__list-view
|
|
- admin__e2e__document-view
|
|
- admin-bar
|
|
- admin-root
|
|
- auth
|
|
- auth-basic
|
|
- bulk-edit
|
|
- joins
|
|
- field-error-states
|
|
- fields-relationship
|
|
- fields__collections__Array
|
|
- fields__collections__Blocks
|
|
- fields__collections__Blocks#config.blockreferences.ts
|
|
- fields__collections__Checkbox
|
|
- fields__collections__Collapsible
|
|
- fields__collections__ConditionalLogic
|
|
- fields__collections__CustomID
|
|
- fields__collections__Date
|
|
- fields__collections__Email
|
|
- fields__collections__Indexed
|
|
- fields__collections__JSON
|
|
- fields__collections__Number
|
|
- fields__collections__Point
|
|
- fields__collections__Radio
|
|
- fields__collections__Relationship
|
|
- fields__collections__Row
|
|
- fields__collections__Select
|
|
- fields__collections__Tabs
|
|
- fields__collections__Tabs2
|
|
- fields__collections__Text
|
|
- fields__collections__UI
|
|
- fields__collections__Upload
|
|
- group-by
|
|
- folders
|
|
- hooks
|
|
- lexical__collections__Lexical__e2e__main
|
|
- lexical__collections__Lexical__e2e__blocks
|
|
- lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts
|
|
- lexical__collections__RichText
|
|
- query-presets
|
|
- form-state
|
|
- live-preview
|
|
- localization
|
|
- locked-documents
|
|
- i18n
|
|
- plugin-cloud-storage
|
|
- plugin-form-builder
|
|
- plugin-import-export
|
|
- plugin-multi-tenant
|
|
- plugin-nested-docs
|
|
- plugin-seo
|
|
- sort
|
|
- trash
|
|
- versions
|
|
- uploads
|
|
env:
|
|
SUITE_NAME: ${{ matrix.suite }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Start LocalStack
|
|
run: pnpm docker:start
|
|
if: ${{ matrix.suite == 'plugin-cloud-storage' }}
|
|
|
|
- name: Store Playwright's Version
|
|
run: |
|
|
# Extract the version number using a more targeted regex pattern with awk
|
|
PLAYWRIGHT_VERSION=$(pnpm ls @playwright/test --depth=0 | awk '/@playwright\/test/ {print $2}')
|
|
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
|
|
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
|
|
|
|
- name: Cache Playwright Browsers for Playwright's Version
|
|
id: cache-playwright-browsers
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}
|
|
|
|
- name: Setup Playwright - Browsers and Dependencies
|
|
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
|
|
run: pnpm exec playwright install --with-deps chromium
|
|
|
|
- name: Setup Playwright - Dependencies-only
|
|
if: steps.cache-playwright-browsers.outputs.cache-hit == 'true'
|
|
run: pnpm exec playwright install-deps chromium
|
|
|
|
- name: E2E Tests
|
|
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.suite }}.json pnpm test:e2e:prod:ci:noturbo ${{ matrix.suite }}
|
|
env:
|
|
PLAYWRIGHT_JSON_OUTPUT_NAME: results_${{ matrix.suite }}.json
|
|
NEXT_TELEMETRY_DISABLED: 1
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: test-results-${{ matrix.suite }}
|
|
path: test/test-results/
|
|
if-no-files-found: ignore
|
|
retention-days: 1
|
|
|
|
# Disabled until this is fixed: https://github.com/daun/playwright-report-summary/issues/156
|
|
# - uses: daun/playwright-report-summary@v3
|
|
# with:
|
|
# report-file: results_${{ matrix.suite }}.json
|
|
# report-tag: ${{ matrix.suite }}
|
|
# job-summary: true
|
|
|
|
tests-e2e-turbo:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: >-
|
|
needs.changes.outputs.needs_tests == 'true' &&
|
|
(
|
|
contains(github.event.pull_request.labels.*.name, 'run-e2e-turbo') ||
|
|
github.event.label.name == 'run-e2e-turbo'
|
|
)
|
|
name: e2e-turbo-${{ matrix.suite }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
# find test -type f -name 'e2e.spec.ts' | sort | xargs dirname | xargs -I {} basename {}
|
|
suite:
|
|
- _community
|
|
- access-control
|
|
- admin__e2e__general
|
|
- admin__e2e__list-view
|
|
- admin__e2e__document-view
|
|
- admin-bar
|
|
- admin-root
|
|
- auth
|
|
- auth-basic
|
|
- bulk-edit
|
|
- joins
|
|
- field-error-states
|
|
- fields-relationship
|
|
- fields__collections__Array
|
|
- fields__collections__Blocks
|
|
- fields__collections__Blocks#config.blockreferences.ts
|
|
- fields__collections__Checkbox
|
|
- fields__collections__Collapsible
|
|
- fields__collections__ConditionalLogic
|
|
- fields__collections__CustomID
|
|
- fields__collections__Date
|
|
- fields__collections__Email
|
|
- fields__collections__Indexed
|
|
- fields__collections__JSON
|
|
- fields__collections__Number
|
|
- fields__collections__Point
|
|
- fields__collections__Radio
|
|
- fields__collections__Relationship
|
|
- fields__collections__Row
|
|
- fields__collections__Select
|
|
- fields__collections__Tabs
|
|
- fields__collections__Tabs2
|
|
- fields__collections__Text
|
|
- fields__collections__UI
|
|
- fields__collections__Upload
|
|
- group-by
|
|
- folders
|
|
- hooks
|
|
- lexical__collections__Lexical__e2e__main
|
|
- lexical__collections__Lexical__e2e__blocks
|
|
- lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts
|
|
- lexical__collections__RichText
|
|
- query-presets
|
|
- form-state
|
|
- live-preview
|
|
- localization
|
|
- locked-documents
|
|
- i18n
|
|
- plugin-cloud-storage
|
|
- plugin-form-builder
|
|
- plugin-import-export
|
|
- plugin-multi-tenant
|
|
- plugin-nested-docs
|
|
- plugin-seo
|
|
- sort
|
|
- trash
|
|
- versions
|
|
- uploads
|
|
env:
|
|
SUITE_NAME: ${{ matrix.suite }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Start LocalStack
|
|
run: pnpm docker:start
|
|
if: ${{ matrix.suite == 'plugin-cloud-storage' }}
|
|
|
|
- name: Store Playwright's Version
|
|
run: |
|
|
# Extract the version number using a more targeted regex pattern with awk
|
|
PLAYWRIGHT_VERSION=$(pnpm ls @playwright/test --depth=0 | awk '/@playwright\/test/ {print $2}')
|
|
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
|
|
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
|
|
|
|
- name: Cache Playwright Browsers for Playwright's Version
|
|
id: cache-playwright-browsers
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}
|
|
|
|
- name: Setup Playwright - Browsers and Dependencies
|
|
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
|
|
run: pnpm exec playwright install --with-deps chromium
|
|
|
|
- name: Setup Playwright - Dependencies-only
|
|
if: steps.cache-playwright-browsers.outputs.cache-hit == 'true'
|
|
run: pnpm exec playwright install-deps chromium
|
|
|
|
- name: E2E Tests
|
|
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.suite }}.json pnpm test:e2e:prod:ci ${{ matrix.suite }}
|
|
env:
|
|
PLAYWRIGHT_JSON_OUTPUT_NAME: results_${{ matrix.suite }}.json
|
|
NEXT_TELEMETRY_DISABLED: 1
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: test-results-turbo${{ matrix.suite }}
|
|
path: test/test-results/
|
|
if-no-files-found: ignore
|
|
retention-days: 1
|
|
|
|
# Disabled until this is fixed: https://github.com/daun/playwright-report-summary/issues/156
|
|
# - uses: daun/playwright-report-summary@v3
|
|
# with:
|
|
# report-file: results_${{ matrix.suite }}.json
|
|
# report-tag: ${{ matrix.suite }}
|
|
# job-summary: true
|
|
|
|
# Build listed templates with packed local packages and then runs their int and e2e tests
|
|
build-and-test-templates:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: ${{ needs.changes.outputs.needs_build == 'true' }}
|
|
name: build-template-${{ matrix.template }}-${{ matrix.database }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- template: blank
|
|
database: mongodb
|
|
|
|
- template: website
|
|
database: mongodb
|
|
|
|
- template: with-payload-cloud
|
|
database: mongodb
|
|
|
|
- template: with-vercel-mongodb
|
|
database: mongodb
|
|
|
|
# Postgres
|
|
- template: with-postgres
|
|
database: postgres
|
|
|
|
- template: with-vercel-postgres
|
|
database: postgres
|
|
|
|
- template: plugin
|
|
|
|
# Re-enable once PG conncection is figured out
|
|
# - template: with-vercel-website
|
|
# database: postgres
|
|
|
|
env:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: payloadtests
|
|
MONGODB_VERSION: 6.0
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Start PostgreSQL
|
|
uses: CasperWA/postgresql-action@v1.2
|
|
with:
|
|
postgresql version: '14' # See https://hub.docker.com/_/postgres for available versions
|
|
postgresql db: ${{ env.POSTGRES_DB }}
|
|
postgresql user: ${{ env.POSTGRES_USER }}
|
|
postgresql password: ${{ env.POSTGRES_PASSWORD }}
|
|
if: matrix.database == 'postgres'
|
|
|
|
- name: Wait for PostgreSQL
|
|
run: sleep 30
|
|
if: matrix.database == 'postgres'
|
|
|
|
- name: Configure PostgreSQL
|
|
run: |
|
|
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "CREATE ROLE runner SUPERUSER LOGIN;"
|
|
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "SELECT version();"
|
|
echo "POSTGRES_URL=postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" >> $GITHUB_ENV
|
|
if: matrix.database == 'postgres'
|
|
|
|
# Avoid dockerhub rate-limiting
|
|
- name: Cache Docker images
|
|
uses: ScribeMD/docker-cache@0.5.0
|
|
with:
|
|
key: docker-${{ runner.os }}-mongo-${{ env.MONGODB_VERSION }}
|
|
|
|
- name: Start MongoDB
|
|
uses: supercharge/mongodb-github-action@1.12.0
|
|
with:
|
|
mongodb-version: 6.0
|
|
if: matrix.database == 'mongodb'
|
|
|
|
- name: Build Template
|
|
run: |
|
|
pnpm run script:pack --dest templates/${{ matrix.template }}
|
|
pnpm run script:build-template-with-local-pkgs ${{ matrix.template }} $POSTGRES_URL
|
|
env:
|
|
NODE_OPTIONS: --max-old-space-size=8096
|
|
|
|
- name: Store Playwright's Version
|
|
run: |
|
|
# Extract the version number using a more targeted regex pattern with awk
|
|
PLAYWRIGHT_VERSION=$(pnpm ls @playwright/test --depth=0 | awk '/@playwright\/test/ {print $2}')
|
|
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
|
|
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
|
|
|
|
- name: Cache Playwright Browsers for Playwright's Version
|
|
id: cache-playwright-browsers
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}
|
|
|
|
- name: Setup Playwright - Browsers and Dependencies
|
|
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
|
|
run: pnpm exec playwright install --with-deps chromium
|
|
|
|
- name: Setup Playwright - Dependencies-only
|
|
if: steps.cache-playwright-browsers.outputs.cache-hit == 'true'
|
|
run: pnpm exec playwright install-deps chromium
|
|
|
|
- name: Runs Template Int Tests
|
|
run: pnpm --filter ${{ matrix.template }} run test:int
|
|
env:
|
|
NODE_OPTIONS: --max-old-space-size=8096
|
|
PAYLOAD_DATABASE: ${{ matrix.database }}
|
|
POSTGRES_URL: ${{ env.POSTGRES_URL }}
|
|
MONGODB_URL: mongodb://localhost:27017/payloadtests
|
|
|
|
- name: Runs Template E2E Tests
|
|
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.template }}.json pnpm --filter ${{ matrix.template }} test:e2e
|
|
env:
|
|
NODE_OPTIONS: --max-old-space-size=8096
|
|
PAYLOAD_DATABASE: ${{ matrix.database }}
|
|
POSTGRES_URL: ${{ env.POSTGRES_URL }}
|
|
MONGODB_URL: mongodb://localhost:27017/payloadtests
|
|
NEXT_TELEMETRY_DISABLED: 1
|
|
|
|
tests-type-generation:
|
|
runs-on: ubuntu-24.04
|
|
needs: [changes, build]
|
|
if: ${{ needs.changes.outputs.needs_tests == 'true' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- name: Generate Payload Types
|
|
run: pnpm dev:generate-types fields
|
|
|
|
- name: Generate GraphQL schema file
|
|
run: pnpm dev:generate-graphql-schema graphql-schema-gen
|
|
|
|
all-green:
|
|
name: All Green
|
|
if: always()
|
|
runs-on: ubuntu-24.04
|
|
needs:
|
|
- lint
|
|
- build
|
|
- build-and-test-templates
|
|
- tests-unit
|
|
- tests-int
|
|
- tests-e2e
|
|
- tests-types
|
|
- tests-type-generation
|
|
|
|
steps:
|
|
- if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}
|
|
run: exit 1
|
|
|
|
publish-canary:
|
|
name: Publish Canary
|
|
runs-on: ubuntu-24.04
|
|
if: ${{ needs.all-green.result == 'success' && github.ref_name == 'main' }}
|
|
needs:
|
|
- all-green
|
|
|
|
steps:
|
|
# debug github.ref output
|
|
- run: |
|
|
echo github.ref: ${{ github.ref }}
|
|
echo isV3: ${{ github.ref == 'refs/heads/main' }}
|
|
analyze:
|
|
runs-on: ubuntu-latest
|
|
needs: [changes, build]
|
|
timeout-minutes: 5
|
|
permissions:
|
|
contents: read # for checkout repository
|
|
actions: read # for fetching base branch bundle stats
|
|
pull-requests: write # for comments
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Node setup
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
pnpm-run-install: false
|
|
pnpm-restore-cache: false # Full build is restored below
|
|
|
|
- name: Restore build
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ./*
|
|
key: ${{ github.sha }}-${{ github.run_number }}
|
|
|
|
- run: pnpm run build:bundle-for-analysis # Esbuild packages that haven't already been built in the build step for the purpose of analyzing bundle size
|
|
env:
|
|
DO_NOT_TRACK: 1 # Disable Turbopack telemetry
|
|
|
|
- name: Analyze esbuild bundle size
|
|
# Temporarily disable this for community PRs until this can be implemented in a separate workflow
|
|
if: github.event.pull_request.head.repo.fork == false
|
|
uses: exoego/esbuild-bundle-analyzer@v1
|
|
with:
|
|
metafiles: 'packages/payload/meta_index.json,packages/payload/meta_shared.json,packages/ui/meta_client.json,packages/ui/meta_shared.json,packages/next/meta_index.json,packages/richtext-lexical/meta_client.json'
|