diff --git a/.forgejo/workflows/test.yaml b/.forgejo/workflows/test.yaml deleted file mode 100644 index 94d8f91..0000000 --- a/.forgejo/workflows/test.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# .forgejo/workflows/self-test.yaml -name: Self Test -on: [push, workflow_dispatch] -jobs: - test: - runs-on: ubuntu-latest - steps: - - run: echo "ci-templates works" diff --git a/.forgejo/workflows/typo3-e2e-test.yaml b/.forgejo/workflows/typo3-e2e-test.yaml index 6ccc6c3..a66ddc9 100644 --- a/.forgejo/workflows/typo3-e2e-test.yaml +++ b/.forgejo/workflows/typo3-e2e-test.yaml @@ -30,11 +30,6 @@ on: required: false type: boolean default: true - visual_tests_continue_on_error: - description: 'Continue if visual tests fail' - required: false - type: boolean - default: true jobs: e2e-test: @@ -62,7 +57,6 @@ jobs: env: TEST_URL: ${{ inputs.test_url }} run: npx playwright test visual - continue-on-error: ${{ inputs.visual_tests_continue_on_error }} - name: Upload test report if: always() diff --git a/.forgejo/workflows/typo3-staged-deploy.yaml b/.forgejo/workflows/typo3-staged-deploy.yaml deleted file mode 100644 index b7dce0f..0000000 --- a/.forgejo/workflows/typo3-staged-deploy.yaml +++ /dev/null @@ -1,302 +0,0 @@ -# TYPO3 Staged Deployment Workflow (Convenience Wrapper) -# -# All-in-one workflow: build → deploy to stage → test → optionally deploy to production -# For more control and visibility, use the composable workflows directly: -# - typo3-build.yaml -# - deployer-release-create.yaml -# - deployer-release-switch.yaml -# - typo3-e2e-test.yaml -# -# Usage: -# jobs: -# deploy: -# uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main -# with: -# stage_url: https://myproject.cloonar.dev -# secrets: -# stage_key: ${{ secrets.STAGE_KEY }} -# prod_key: ${{ secrets.PROD_KEY }} - -name: TYPO3 Staged Deploy - -on: - workflow_call: - inputs: - stage_url: - description: 'Staging URL for E2E tests' - required: true - type: string - php_version: - description: 'PHP version' - required: false - type: string - default: '8.3' - node_version: - description: 'Node.js version' - required: false - type: string - default: '20' - build_frontend: - description: 'Run npm build' - required: false - type: boolean - default: false - run_e2e_tests: - description: 'Run Playwright E2E tests' - required: false - type: boolean - default: true - e2e_path: - description: 'Path to E2E tests' - required: false - type: string - default: 'tests/e2e' - deployer_file: - description: 'Path to deploy.php' - required: false - type: string - default: './build/deploy.php' - deploy_production: - description: 'Deploy to production after tests pass' - required: false - type: boolean - default: true - secrets: - stage_key: - description: 'SSH key for staging' - required: true - prod_key: - description: 'SSH key for production' - required: false - -env: - COMPOSER_ALLOW_SUPERUSER: 1 - -jobs: - # =========================================================================== - # Build - # =========================================================================== - build: - name: Build - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ inputs.php_version }} - tools: composer - - - name: Setup Node.js - if: ${{ inputs.build_frontend }} - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node_version }} - - - name: Install PHP dependencies - run: composer install --prefer-dist --no-progress --no-dev --ignore-platform-reqs - - - name: Install Node dependencies & build - if: ${{ inputs.build_frontend }} - run: | - npm ci - npm run build - - - name: Create artifact - run: | - tar -czf build.tar.gz \ - bin public packages config vendor build composer.json composer.lock \ - $([ -d "node_modules" ] && echo "node_modules") \ - $([ -d "dist" ] && echo "dist") \ - 2>/dev/null || true - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: build-${{ github.sha }} - path: build.tar.gz - retention-days: 1 - - - # =========================================================================== - # Create Stage Release - # =========================================================================== - create-stage: - name: Create Release (stage) - runs-on: ubuntu-latest - needs: [build] - - steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ inputs.php_version }} - - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: build-${{ github.sha }} - - - name: Extract artifact - run: tar xf build.tar.gz && rm build.tar.gz - - - name: Install system dependencies - run: apt-get update -qq && apt-get install -y -qq openssh-client rsync - - - name: Create release - uses: deployphp/action@v1 - with: - deployer-binary: "./bin/dep" - dep: -q --file=${{ inputs.deployer_file }} release:create stage - private-key: ${{ secrets.stage_key }} - - - # =========================================================================== - # Switch Stage Release - # =========================================================================== - switch-stage: - name: Switch Release (stage) - runs-on: ubuntu-latest - needs: [create-stage] - - steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ inputs.php_version }} - - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: build-${{ github.sha }} - - - name: Extract artifact - run: tar xf build.tar.gz && rm build.tar.gz - - - name: Install system dependencies - run: apt-get update -qq && apt-get install -y -qq openssh-client rsync - - - name: Switch release - uses: deployphp/action@v1 - with: - deployer-binary: "./bin/dep" - dep: -q --file=${{ inputs.deployer_file }} release:switch stage - private-key: ${{ secrets.stage_key }} - - - # =========================================================================== - # E2E Tests - # =========================================================================== - test-stage: - name: E2E Tests - runs-on: ubuntu-latest - needs: [switch-stage] - if: ${{ inputs.run_e2e_tests }} - container: - image: mcr.microsoft.com/playwright:v1.50.0-noble - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - working-directory: ${{ inputs.e2e_path }} - run: npm ci - - - name: Run smoke tests - working-directory: ${{ inputs.e2e_path }} - env: - TEST_URL: ${{ inputs.stage_url }} - run: npx playwright test smoke - - - name: Run visual regression tests - working-directory: ${{ inputs.e2e_path }} - env: - TEST_URL: ${{ inputs.stage_url }} - run: npx playwright test visual - continue-on-error: true - - - name: Upload test report - if: always() - uses: actions/upload-artifact@v4 - with: - name: playwright-report - path: ${{ inputs.e2e_path }}/playwright-report/ - retention-days: 7 - - - name: Upload diff screenshots - if: failure() - uses: actions/upload-artifact@v4 - with: - name: visual-diff - path: ${{ inputs.e2e_path }}/test-results/ - retention-days: 7 - - - # =========================================================================== - # Create Production Release - # =========================================================================== - create-production: - name: Create Release (production) - runs-on: ubuntu-latest - needs: [switch-stage, test-stage] - if: ${{ always() && inputs.deploy_production && needs.switch-stage.result == 'success' && needs.test-stage.result != 'failure' }} - - steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ inputs.php_version }} - - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: build-${{ github.sha }} - - - name: Extract artifact - run: tar xf build.tar.gz && rm build.tar.gz - - - name: Install system dependencies - run: apt-get update -qq && apt-get install -y -qq openssh-client rsync - - - name: Create release - uses: deployphp/action@v1 - with: - deployer-binary: "./bin/dep" - dep: -q --file=${{ inputs.deployer_file }} release:create production - private-key: ${{ secrets.prod_key }} - - - # =========================================================================== - # Switch Production Release - # =========================================================================== - switch-production: - name: Switch Release (production) - runs-on: ubuntu-latest - needs: [create-production] - if: ${{ always() && needs.create-production.result == 'success' }} - - steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ inputs.php_version }} - - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: build-${{ github.sha }} - - - name: Extract artifact - run: tar xf build.tar.gz && rm build.tar.gz - - - name: Install system dependencies - run: apt-get update -qq && apt-get install -y -qq openssh-client rsync - - - name: Switch release - uses: deployphp/action@v1 - with: - deployer-binary: "./bin/dep" - dep: -q --file=${{ inputs.deployer_file }} release:switch production - private-key: ${{ secrets.prod_key }} diff --git a/README.md b/README.md index f8940d0..e98ed78 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,23 @@ Shared CI/CD templates for Cloonar projects. ``` .forgejo/workflows/ - typo3-deploy.yaml # Simple deployment workflow - typo3-staged-deploy.yaml # Staged deployment with E2E tests + # TYPO3-specific workflows + typo3-build.yaml # Build PHP/Node artifacts + typo3-e2e-test.yaml # Run Playwright E2E tests + typo3-staged-deploy.yaml # Convenience wrapper (all-in-one) + + # Generic Deployer workflows + deployer-release-create.yaml # Upload release without switching + deployer-release-switch.yaml # Activate a previously uploaded release deployer/ - typo3-recipe.php # Shared Deployer configuration + typo3-recipe.php # Shared Deployer configuration examples/ - project-deploy.php # Example project deploy.php - project-servers.yaml # Example servers.yaml - project-workflow-*.yaml # Example workflow files + project-workflow-staged.yaml # Composable pattern (recommended) + project-workflow-simple.yaml # Wrapper pattern + project-deploy.php # Example project deploy.php + project-servers.yaml # Example servers.yaml ``` ## Quick Start @@ -48,30 +55,72 @@ hosts: # ... rest of config ``` -### 3. Update your workflow +### 3. Choose your workflow pattern -Replace `.forgejo/workflows/deploy.yaml` with: +#### Option A: Composable Pattern (Recommended) + +Full control and visibility. Each job appears separately in the pipeline UI. -**Simple deployment:** ```yaml -name: Deploy +name: Build and Deploy + on: push: branches: [main] jobs: - deploy: - uses: infrastructure/ci-templates/.forgejo/workflows/typo3-deploy.yaml@main + build: + uses: infrastructure/ci-templates/.forgejo/workflows/typo3-build.yaml@main with: - target: stage php_version: '8.3' + build_frontend: true + + create-stage: + needs: build + uses: infrastructure/ci-templates/.forgejo/workflows/deployer-release-create.yaml@main + with: + server: stage secrets: - deploy_key: ${{ secrets.STAGE_KEY }} + ssh_key: ${{ secrets.STAGE_KEY }} + + switch-stage: + needs: create-stage + uses: infrastructure/ci-templates/.forgejo/workflows/deployer-release-switch.yaml@main + with: + server: stage + secrets: + ssh_key: ${{ secrets.STAGE_KEY }} + + test: + needs: switch-stage + uses: infrastructure/ci-templates/.forgejo/workflows/typo3-e2e-test.yaml@main + with: + test_url: https://myproject.cloonar.dev + + create-production: + needs: test + uses: infrastructure/ci-templates/.forgejo/workflows/deployer-release-create.yaml@main + with: + server: production + secrets: + ssh_key: ${{ secrets.PROD_KEY }} + + switch-production: + needs: create-production + uses: infrastructure/ci-templates/.forgejo/workflows/deployer-release-switch.yaml@main + with: + server: production + secrets: + ssh_key: ${{ secrets.PROD_KEY }} ``` -**Staged deployment with tests:** +#### Option B: Wrapper Pattern (Simple) + +All-in-one convenience workflow. Less visible but simpler to set up. + ```yaml name: Deploy + on: push: branches: [main] @@ -81,46 +130,97 @@ jobs: uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main with: stage_url: https://myproject.cloonar.dev + php_version: '8.3' run_e2e_tests: true secrets: stage_key: ${{ secrets.STAGE_KEY }} prod_key: ${{ secrets.PROD_KEY }} ``` -## Workflow Options +## Workflow Reference -### typo3-deploy.yaml +### typo3-build.yaml + +Builds PHP and optionally Node artifacts, uploads as build artifact. | Input | Default | Description | |-------|---------|-------------| -| `target` | required | `stage` or `production` | -| `task` | `deploy` | Deployer task (`deploy`, `release:create`, `release:switch`) | | `php_version` | `8.3` | PHP version | -| `run_tests` | `false` | Run PHPStan/Psalm before deploy | +| `node_version` | `20` | Node.js version | | `build_frontend` | `false` | Run `npm ci && npm run build` | -### typo3-staged-deploy.yaml +### deployer-release-create.yaml + +Downloads build artifact and runs `release:create ` without switching. + +| Input | Default | Description | +|-------|---------|-------------| +| `server` | required | Target server (e.g., `stage`, `production`) | +| `php_version` | `8.3` | PHP version | +| `deployer_file` | `./build/deploy.php` | Path to deploy.php | +| `artifact_name` | `build-` | Build artifact name | + +| Secret | Description | +|--------|-------------| +| `ssh_key` | SSH private key for deployment | + +### deployer-release-switch.yaml + +Downloads build artifact and runs `release:switch ` to activate a release. + +| Input | Default | Description | +|-------|---------|-------------| +| `server` | required | Target server (e.g., `stage`, `production`) | +| `php_version` | `8.3` | PHP version | +| `deployer_file` | `./build/deploy.php` | Path to deploy.php | +| `artifact_name` | `build-` | Build artifact name | + +| Secret | Description | +|--------|-------------| +| `ssh_key` | SSH private key for deployment | + +### typo3-e2e-test.yaml + +Runs Playwright E2E tests against a deployed environment. + +| Input | Default | Description | +|-------|---------|-------------| +| `test_url` | required | URL to test against | +| `e2e_path` | `tests/e2e` | Path to E2E test directory | +| `run_visual_tests` | `true` | Run visual regression tests | +| `visual_tests_continue_on_error` | `true` | Continue if visual tests fail | + +### typo3-staged-deploy.yaml (Wrapper) + +All-in-one workflow: build → stage deploy → E2E tests → production deploy. | Input | Default | Description | |-------|---------|-------------| | `stage_url` | required | URL for E2E tests | | `php_version` | `8.3` | PHP version | -| `run_e2e_tests` | `true` | Run Playwright tests after stage deploy | -| `e2e_path` | `tests/e2e` | Path to E2E test directory | -| `deploy_production` | `false` | Auto-deploy to prod after tests pass | +| `node_version` | `20` | Node.js version | +| `build_frontend` | `false` | Run npm build | +| `run_e2e_tests` | `true` | Run Playwright tests | +| `e2e_path` | `tests/e2e` | Path to E2E tests | +| `deployer_file` | `./build/deploy.php` | Path to deploy.php | +| `deploy_production` | `true` | Deploy to prod after tests pass | + +| Secret | Description | +|--------|-------------| +| `stage_key` | SSH key for staging | +| `prod_key` | SSH key for production | ## Deployer Tasks The shared recipe provides these tasks: -- `release:create ` - Upload release without switching (for staged deploys) -- `release:switch ` - Switch to uploaded release -- `deploy ` - Full deploy (create + switch) +- `release:create ` - Upload release without switching (for staged deploys) +- `release:switch ` - Switch to uploaded release +- `deploy ` - Full deploy (create + switch) ## Migration Checklist -- [ ] Create `infrastructure/ci-templates` repo with these files - [ ] Update project's `build/deploy.php` to use shared recipe - [ ] Update project's `.forgejo/workflows/` to use reusable workflows -- [ ] Delete old `.drone.yml` files -- [ ] Test on one project first (e.g., gbv-aktuell) +- [ ] Choose composable or wrapper pattern +- [ ] Test on staging first diff --git a/examples/project-deploy.php b/examples/project-deploy.php index aa26385..5491667 100644 --- a/examples/project-deploy.php +++ b/examples/project-deploy.php @@ -8,11 +8,7 @@ namespace Deployer; -// Option 1: Require from git raw URL (works immediately, no composer) -require 'https://git.cloonar.com/infrastructure/ci-templates/raw/branch/main/deployer/typo3-recipe.php'; - -// Option 2: Via composer (after adding to require-dev) -// require __DIR__ . '/../vendor/cloonar/ci-templates/deployer/typo3-recipe.php'; +require __DIR__ . '/../deployer-lib.php'; // Import project-specific server config import(__DIR__ . '/servers.yaml'); diff --git a/examples/project-servers.yaml b/examples/project-servers.yaml deleted file mode 100644 index d38c635..0000000 --- a/examples/project-servers.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Example project servers.yaml -# Rename PROJECTNAME to your actual project - -hosts: - stage: - stage: staging - hostname: web-arm.cloonar.com - remote_user: PROJECTNAME_cloonar_dev - writable_mode: chmod - forward_agent: true - deploy_path: ~/ - keep_releases: 1 - - production: - stage: production - hostname: web-arm.cloonar.com - remote_user: PROJECTNAME_TLD - writable_mode: chmod - forward_agent: true - deploy_path: ~/ - keep_releases: 5 diff --git a/examples/project-workflow-staged.yaml b/examples/project-workflow-staged.yaml deleted file mode 100644 index 845a5ea..0000000 --- a/examples/project-workflow-staged.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Example: Staged deployment with E2E tests (like gbv-aktuell) -# Place in your project's .forgejo/workflows/deploy.yaml - -name: Build and Deploy - -on: - push: - branches: [main] - paths-ignore: - - '**.md' - - 'renovate.json' - workflow_dispatch: - -jobs: - deploy: - uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main - with: - stage_url: https://PROJECTNAME.cloonar.dev - php_version: '8.3' - run_e2e_tests: true - e2e_path: tests/e2e - deploy_production: false # Set true for auto-deploy to prod after tests pass - secrets: - stage_key: ${{ secrets.STAGE_KEY }} - prod_key: ${{ secrets.PROD_KEY }}