From 6d3c1ed3cb7ffbf448886eb2c9d21abdefe2c285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Sch=C3=B6ldstr=C3=B6m?= Date: Mon, 7 Sep 2026 12:25:48 -0300 Subject: [PATCH] refactor(ci): move the scaffold onto the shared reusable workflows Every repo generated from this scaffold inherited a vendored setup action and PACKAGIST_GITHUB_TOKEN, which is why the generoi-deploy retirement has had to visit thirty-odd sites one at a time. Fixing it here stops the bleeding. test.yml -> test.yml@v2 deploy_production.yml -> deploy.yml@v2 (+ the local e2e wrapper) deploy_staging.yml -> deploy.yml@v2 (+ the local e2e wrapper) e2e.yml -> a thin wrapper over e2e.yml@v2, still workflow_dispatch + workflow_call vulnerability-scan.yml -> vulnerability-scan.yml@v2 .github/actions/setup deleted, superseded by setup@v2 .github/actions/install-wordpress deleted, the shared test workflow does it .github/workflows/deploy.yml deleted, a subset of deploy.yml@v2 Composer now authenticates as genero-composer-bot with no PAT anywhere, so new projects start on a per-run token that expires in an hour instead of a machine user's PAT. The vulnerability scan is the biggest behaviour change: it predated the shared scan entirely, running `wp vuln status` and notifying Microsoft Teams. The shared workflow runs `composer audit --locked`, notifies Google Chat, opens fix PRs via genero-vuln-bot, and gates on the repo's `maintenance` org property. That is what the rest of the fleet has been running for months; the scaffold was the last thing still on the old one. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PJ9rPCo5ZJbUPVS5dRGnZx --- .github/actions/install-wordpress/action.yml | 52 ----------- .github/actions/setup/action.yml | 48 ---------- .github/workflows/deploy.yml | 57 ------------ .github/workflows/deploy_production.yml | 14 ++- .github/workflows/deploy_staging.yml | 14 ++- .github/workflows/e2e.yml | 28 ++---- .github/workflows/test.yml | 40 ++------ .github/workflows/vulnerability-scan.yml | 98 +++----------------- 8 files changed, 51 insertions(+), 300 deletions(-) delete mode 100644 .github/actions/install-wordpress/action.yml delete mode 100644 .github/actions/setup/action.yml delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/actions/install-wordpress/action.yml b/.github/actions/install-wordpress/action.yml deleted file mode 100644 index e28ece74..00000000 --- a/.github/actions/install-wordpress/action.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: 'Install WordPress' - -inputs: - multisite: - required: false - default: 'false' - -runs: - using: 'composite' - steps: - - name: Start MySQL service - shell: bash - run: | - sudo /etc/init.d/mysql start - mysql -e 'CREATE DATABASE db;' -uroot -proot - mysql -e "CREATE USER 'db'@'localhost' IDENTIFIED BY 'db';" -uroot -proot - mysql -e "GRANT ALL PRIVILEGES ON db.* TO 'db'@'localhost' WITH GRANT OPTION;" -uroot -proot - - - name: Launch web server - shell: bash - run: ./vendor/bin/wp server & - - - name: Setup .env - shell: bash - run: | - cp .env.example .env - sed -i 's/.*WP_HOME=.*/WP_HOME=http:\/\/localhost:8080/g' .env - sed -i 's/.*DOMAIN_CURRENT_SITE=.*/DOMAIN_CURRENT_SITE=localhost:8080/g' .env - sed -i 's/.*DB_HOST=.*/DB_HOST=localhost/g' .env - cat .env - - - name: Install WordPress - if: ${{ inputs.multisite != 'true' }} - shell: bash - run: | - ./vendor/bin/wp core install \ - --url=http://localhost:8080 \ - --title="Bedrock" \ - --admin_user="admin" \ - --admin_email="bedrock@example.test" \ - --skip-email - - - name: Install WordPress (multisite) - if: ${{ inputs.multisite == 'true' }} - shell: bash - run: | - ./vendor/bin/wp core multisite-install \ - --url=http://localhost:8080 \ - --title="Bedrock" \ - --admin_email="bedrock@example.test" \ - --skip-config \ - --skip-email diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml deleted file mode 100644 index 42ebe537..00000000 --- a/.github/actions/setup/action.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: 'Build' - -inputs: - npm_fontawesome_auth_token: - required: true - packagist_github_token: - required: true - -runs: - using: 'composite' - steps: - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - - - name: Authenticate with Fontawesome NPM reposity - shell: bash - run: | - npm config set "//npm.fontawesome.com/:_authToken" ${{ inputs.npm_fontawesome_auth_token }} - - - name: Read PHP version from composer.json to env - shell: bash - run: | - echo "PHP_VERSION=$(cat ./composer.json | jq -r '.config.platform.php')" >> "$GITHUB_ENV" - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ env.PHP_VERSION }} - env: - COMPOSER_TOKEN: ${{ inputs.packagist_github_token }} - - - name: Get Composer Cache Directory - id: composer-cache - shell: bash - run: | - echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Composer Cache - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index aa6173e1..00000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: '__deploy' -on: - workflow_call: - inputs: - log_level: - required: true - type: string - environment: - required: true - type: string - - secrets: - KINSTA_DEPLOY_PRIVATE_KEY: - required: true - PACKAGIST_GITHUB_TOKEN: - required: true - NPM_FONTAWESOME_AUTH_TOKEN: - required: true -jobs: - build_deploy: - name: Build and deploy - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Start SSH agent - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: | - ${{ secrets.KINSTA_DEPLOY_PRIVATE_KEY }} - - - name: Setup project - uses: ./.github/actions/setup - with: - npm_fontawesome_auth_token: ${{ secrets.NPM_FONTAWESOME_AUTH_TOKEN }} - packagist_github_token: ${{ secrets.PACKAGIST_GITHUB_TOKEN }} - - - name: Install development packages to run tests - run: composer install:development - - - name: Run tests - run: composer test --no-interaction - - - name: Add remote public keys to known hosts - env: - DEPLOY_ENV: ${{ inputs.environment }} - # Read robo.yml directly rather than shelling out to `robo`, which - # prints PHP deprecation notices on stdout that command substitution - # would feed to ssh-keyscan as hostnames. Matches generoi/github-actions. - run: | - ssh-keyscan \ - -p $(yq ".env[\"@${DEPLOY_ENV}\"].port // 22" robo.yml) \ - $(yq ".env[\"@${DEPLOY_ENV}\"].host" robo.yml) >> ~/.ssh/known_hosts - - - name: Deploy - run: ./vendor/bin/dep deploy ${{ inputs.environment }} ${{ inputs.log_level }} diff --git a/.github/workflows/deploy_production.yml b/.github/workflows/deploy_production.yml index 4fc97587..1b619c07 100644 --- a/.github/workflows/deploy_production.yml +++ b/.github/workflows/deploy_production.yml @@ -1,4 +1,4 @@ -name: Deploy to Production +name: 'Deploy: Production' on: workflow_dispatch: inputs: @@ -7,10 +7,18 @@ on: required: true default: '-vv' +permissions: + contents: read + jobs: deploy: - uses: ./.github/workflows/deploy.yml - secrets: inherit + uses: generoi/github-actions/.github/workflows/deploy.yml@v2 + secrets: + # The shared workflow expects DEPLOY_SSH_PRIVATE_KEY; this repo's secret + # predates that name. + DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.KINSTA_DEPLOY_PRIVATE_KEY }} + NPM_FONTAWESOME_AUTH_TOKEN: ${{ secrets.NPM_FONTAWESOME_AUTH_TOKEN }} + COMPOSER_BOT_PRIVATE_KEY: ${{ secrets.COMPOSER_BOT_PRIVATE_KEY }} with: environment: 'production' log_level: ${{ inputs.log_level }} diff --git a/.github/workflows/deploy_staging.yml b/.github/workflows/deploy_staging.yml index 249eec8f..80af4020 100644 --- a/.github/workflows/deploy_staging.yml +++ b/.github/workflows/deploy_staging.yml @@ -1,4 +1,4 @@ -name: Deploy to Staging +name: 'Deploy: Staging' on: workflow_dispatch: inputs: @@ -7,10 +7,18 @@ on: required: true default: '-vv' +permissions: + contents: read + jobs: deploy: - uses: ./.github/workflows/deploy.yml - secrets: inherit + uses: generoi/github-actions/.github/workflows/deploy.yml@v2 + secrets: + # The shared workflow expects DEPLOY_SSH_PRIVATE_KEY; this repo's secret + # predates that name. + DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.KINSTA_DEPLOY_PRIVATE_KEY }} + NPM_FONTAWESOME_AUTH_TOKEN: ${{ secrets.NPM_FONTAWESOME_AUTH_TOKEN }} + COMPOSER_BOT_PRIVATE_KEY: ${{ secrets.COMPOSER_BOT_PRIVATE_KEY }} with: environment: 'staging' log_level: ${{ inputs.log_level }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index b6969aec..d99b9e95 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,4 +1,4 @@ -name: E2E tests +name: 'CI: E2E' on: workflow_dispatch: inputs: @@ -10,24 +10,12 @@ on: url: required: true type: string -jobs: - e2e: - name: Run E2E tests - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Set URL as environmnet variable so playwright uses it - run: echo "URL=${{ inputs.url }}" >> $GITHUB_ENV - - name: Install dependencies - run: npm run e2e:install +permissions: + contents: read - - name: Run E2E tests - run: npm run e2e:test - - - uses: actions/upload-artifact@v4 - with: - name: Screenshot - path: screenshot.jpg +jobs: + e2e: + uses: generoi/github-actions/.github/workflows/e2e.yml@v2 + with: + url: ${{ inputs.url }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c972b43e..b9ee23d8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,36 +1,16 @@ -name: Test +name: "CI: Test" on: pull_request: workflow_dispatch: +permissions: + contents: read + jobs: test: - name: Run tests - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup project - uses: ./.github/actions/setup - with: - npm_fontawesome_auth_token: ${{ secrets.NPM_FONTAWESOME_AUTH_TOKEN }} - packagist_github_token: ${{ secrets.PACKAGIST_GITHUB_TOKEN }} - - - name: Install development packages to run tests - run: composer install:development - - - name: Run CI tests - run: composer ci --no-interaction - - - name: Install WordPress - uses: ./.github/actions/install-wordpress - - - name: Optimize acorn - run: ./vendor/bin/wp acorn optimize - - - name: Load frontpage and verify app.js script is loaded - run: curl http://localhost:8080/ | grep '> $GITHUB_OUTPUT - exit 1 - else - echo "No vulnerabilities found" - exit 0 - fi - - - name: Microsoft Teams Notification - if: failure() - run: | - curl -H 'Content-Type: application/json' -d '{ - "type": "message", - "attachments": [ - { - "contentType": "application/vnd.microsoft.card.adaptive", - "content": { - "type": "AdaptiveCard", - "$schema": "https://adaptivecards.io/schemas/adaptive-card.json", - "version": "1.5", - "body": [ - { - "type": "TextBlock", - "size": "Large", - "weight": "Bolder", - "text": "⚠️ Vulnerability scan failed: ${{ github.event.repository.name }}", - "wrap": true - }, - { - "type": "TextBlock", - "size": "Small", - "text": "${{ steps.scan.outputs.formatted_plugins }}", - "wrap": true - }, - { - "type": "ActionSet", - "actions": [ - { - "type": "Action.OpenUrl", - "title": "Repository", - "url": "${{ github.server_url }}/${{ github.repository }}" - }, - { - "type": "Action.OpenUrl", - "title": "Job details", - "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - ], - "horizontalAlignment": "left" - } - ] - } - } - ] - }' "${{ env.MICROSOFT_TEAMS_FAUCET_WEBHOOK }}" + scan: + uses: generoi/github-actions/.github/workflows/vulnerability-scan.yml@v2 + secrets: + GOOGLE_CHAT_FAUCET_WEBHOOK: ${{ secrets.GOOGLE_CHAT_FAUCET_WEBHOOK }} + NPM_FONTAWESOME_AUTH_TOKEN: ${{ secrets.NPM_FONTAWESOME_AUTH_TOKEN }} + COMPOSER_BOT_PRIVATE_KEY: ${{ secrets.COMPOSER_BOT_PRIVATE_KEY }} + VULN_BOT_APP_ID: ${{ secrets.VULN_BOT_APP_ID }} + VULN_BOT_PRIVATE_KEY: ${{ secrets.VULN_BOT_PRIVATE_KEY }}