diff --git a/.forgejo/workflows/typo3-build-frontend.yaml b/.forgejo/workflows/typo3-build-frontend.yaml new file mode 100644 index 0000000..0ebb269 --- /dev/null +++ b/.forgejo/workflows/typo3-build-frontend.yaml @@ -0,0 +1,258 @@ +# Cloonar TYPO3 Staged Deployment Workflow +# +# Staged deployment: build → deploy to stage → run E2E tests → switch release +# +# Usage in project's .forgejo/workflows/deploy.yaml: +# name: Deploy +# on: +# push: +# branches: [main] +# jobs: +# deploy: +# uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main +# with: +# stage_url: https://myproject.cloonar.dev +# php_version: '8.3' +# 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: 'Also deploy to production after stage succeeds' + 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: ${{ fromJSON(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 + + - uses: actions/upload-artifact@v4 + with: + name: build-${{ github.sha }} + path: build.tar.gz + retention-days: 1 + + + # =========================================================================== + # Deploy to Stage (release:create only) + # =========================================================================== + deploy-stage: + name: Upload to Stage + runs-on: ubuntu-latest + needs: [build] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Upload release + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:create stage + private-key: ${{ secrets.stage_key }} + + + # =========================================================================== + # Switch Stage Release + # =========================================================================== + switch-stage: + name: Activate Stage Release + runs-on: ubuntu-latest + needs: [deploy-stage] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Switch release + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:switch stage + private-key: ${{ secrets.stage_key }} + + + # =========================================================================== + # E2E Tests with Playwright + # =========================================================================== + 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 + + + # =========================================================================== + # Deploy to Production + # =========================================================================== + deploy-production: + name: Deploy Production + runs-on: ubuntu-latest + needs: [test-stage] + if: ${{ inputs.deploy_production && (needs.test-stage.result == 'success' || needs.test-stage.result == 'skipped') }} + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Deploy to production + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:create production + private-key: ${{ secrets.prod_key }} diff --git a/.forgejo/workflows/typo3-build.yaml b/.forgejo/workflows/typo3-build.yaml new file mode 100644 index 0000000..0b56f67 --- /dev/null +++ b/.forgejo/workflows/typo3-build.yaml @@ -0,0 +1,66 @@ +# Cloonar TYPO3 Staged Deployment Workflow +# +# Staged deployment: build → deploy to stage → run E2E tests → switch release +# +# Usage in project's .forgejo/workflows/deploy.yaml: +# name: Deploy +# on: +# push: +# branches: [main] +# jobs: +# deploy: +# uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main +# with: +# stage_url: https://myproject.cloonar.dev +# php_version: '8.3' +# secrets: +# stage_key: ${{ secrets.STAGE_KEY }} +# prod_key: ${{ secrets.PROD_KEY }} + +name: TYPO3 Staged Deploy + +on: + workflow_call: + inputs: + php_version: + description: 'PHP version' + required: false + type: string + default: '8.3' + +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: Install PHP dependencies + run: composer install --prefer-dist --no-progress --no-dev --ignore-platform-reqs + + - 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 + + - uses: actions/upload-artifact@v4 + with: + name: build-${{ github.sha }} + path: build.tar.gz + retention-days: 1 diff --git a/.forgejo/workflows/typo3-deploy-stage.yml b/.forgejo/workflows/typo3-deploy-stage.yml new file mode 100644 index 0000000..3ca2212 --- /dev/null +++ b/.forgejo/workflows/typo3-deploy-stage.yml @@ -0,0 +1,207 @@ +# Cloonar TYPO3 Staged Deployment Workflow +# +# Staged deployment: build → deploy to stage → run E2E tests → switch release +# +# Usage in project's .forgejo/workflows/deploy.yaml: +# name: Deploy +# on: +# push: +# branches: [main] +# jobs: +# deploy: +# uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main +# with: +# stage_url: https://myproject.cloonar.dev +# php_version: '8.3' +# 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' + 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: 'Also deploy to production after stage succeeds' + 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: + # =========================================================================== + # Deploy to Stage (release:create only) + # =========================================================================== + deploy-stage: + name: Upload to Stage + runs-on: ubuntu-latest + needs: [build] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Upload release + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:create stage + private-key: ${{ secrets.stage_key }} + + + # =========================================================================== + # Switch Stage Release + # =========================================================================== + switch-stage: + name: Activate Stage Release + runs-on: ubuntu-latest + needs: [deploy-stage] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Switch release + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:switch stage + private-key: ${{ secrets.stage_key }} + + + # =========================================================================== + # E2E Tests with Playwright + # =========================================================================== + 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 + + + # =========================================================================== + # Deploy to Production + # =========================================================================== + deploy-production: + name: Deploy Production + runs-on: ubuntu-latest + needs: [test-stage] + if: ${{ inputs.deploy_production && (needs.test-stage.result == 'success' || needs.test-stage.result == 'skipped') }} + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Deploy to production + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:create production + private-key: ${{ secrets.prod_key }} diff --git a/.forgejo/workflows/typo3-release-prod.yml b/.forgejo/workflows/typo3-release-prod.yml new file mode 100644 index 0000000..0ebb269 --- /dev/null +++ b/.forgejo/workflows/typo3-release-prod.yml @@ -0,0 +1,258 @@ +# Cloonar TYPO3 Staged Deployment Workflow +# +# Staged deployment: build → deploy to stage → run E2E tests → switch release +# +# Usage in project's .forgejo/workflows/deploy.yaml: +# name: Deploy +# on: +# push: +# branches: [main] +# jobs: +# deploy: +# uses: infrastructure/ci-templates/.forgejo/workflows/typo3-staged-deploy.yaml@main +# with: +# stage_url: https://myproject.cloonar.dev +# php_version: '8.3' +# 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: 'Also deploy to production after stage succeeds' + 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: ${{ fromJSON(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 + + - uses: actions/upload-artifact@v4 + with: + name: build-${{ github.sha }} + path: build.tar.gz + retention-days: 1 + + + # =========================================================================== + # Deploy to Stage (release:create only) + # =========================================================================== + deploy-stage: + name: Upload to Stage + runs-on: ubuntu-latest + needs: [build] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Upload release + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:create stage + private-key: ${{ secrets.stage_key }} + + + # =========================================================================== + # Switch Stage Release + # =========================================================================== + switch-stage: + name: Activate Stage Release + runs-on: ubuntu-latest + needs: [deploy-stage] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Switch release + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:switch stage + private-key: ${{ secrets.stage_key }} + + + # =========================================================================== + # E2E Tests with Playwright + # =========================================================================== + 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 + + + # =========================================================================== + # Deploy to Production + # =========================================================================== + deploy-production: + name: Deploy Production + runs-on: ubuntu-latest + needs: [test-stage] + if: ${{ inputs.deploy_production && (needs.test-stage.result == 'success' || needs.test-stage.result == 'skipped') }} + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php_version }} + + - uses: actions/download-artifact@v4 + with: + name: build-${{ github.sha }} + + - run: tar xf build.tar.gz && rm build.tar.gz + + - run: apt-get update && apt-get install -y openssh-client rsync + + - name: Deploy to production + uses: deployphp/action@v1 + with: + deployer-binary: "./bin/dep" + dep: --file=${{ inputs.deployer_file }} release:create production + private-key: ${{ secrets.prod_key }}