diff --git a/.github/workflows/update-wordpress-js-dependencies-orchestrator.yml b/.github/workflows/update-wordpress-js-dependencies-orchestrator.yml new file mode 100644 index 00000000..80395297 --- /dev/null +++ b/.github/workflows/update-wordpress-js-dependencies-orchestrator.yml @@ -0,0 +1,60 @@ +name: Update WordPress JS Dependencies Orchestrator +on: + workflow_call: + inputs: + WP_DIST_TAG: + description: The dist tag to update the dependencies to, e.g., `wp-6.7` + required: true + type: string + PACKAGES: + description: Comma-separated list of additional `owner/repo`s to be updated. + required: false + type: string + secrets: + GH_TOKEN: + description: A personal access token (classic) with `repo` and `workflow` permissions, used to authenticate when calling GitHub APIs in target repositories. + required: true + +jobs: + update-dependencies-orchestrator: + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + WP_DIST_TAG: ${{ inputs.WP_DIST_TAG }} + PACKAGES: ${{ inputs.PACKAGES }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Gather packages and call the individual workflows. + run: | + # Initialize an array for packages + packages=() + + # Add packages from composer.json if it exists + if [ -f composer.json ]; then + composer_packages=$(cat composer.json | jq -r '.require | keys[]') + for pkg in $composer_packages; do + packages+=("$pkg") + done + fi + + # Add packages from the PACKAGES environment variable + IFS=',' read -r -a env_packages <<< "$PACKAGES" + for pkg in "${env_packages[@]}"; do + packages+=("$pkg") + done + + # Process all unique packages + unique_packages=$(echo "${packages[@]}" | tr ' ' '\n' | sort -u) + + for package in ${unique_packages[@]}; do + echo "Processing package: $package" + gh workflow run update-wordpress-js-dependencies.yml \ + --repo $package \ + --field WP_DIST_TAG=${{ env.WP_DIST_TAG }} + done diff --git a/.github/workflows/update-wordpress-js-dependencies.yml b/.github/workflows/update-wordpress-js-dependencies.yml new file mode 100644 index 00000000..c1055e7c --- /dev/null +++ b/.github/workflows/update-wordpress-js-dependencies.yml @@ -0,0 +1,144 @@ +name: Update WordPress JS Dependencies +on: + workflow_call: + inputs: + WP_DIST_TAG: + description: The dist tag to update the dependencies to, e.g., `wp-6.7`. + required: true + type: string + NPM_REGISTRY_DOMAIN: + description: Domain of the private npm registry. + default: https://npm.pkg.github.com/ + required: false + type: string + secrets: + GITHUB_USER_EMAIL: + description: Email address for the GitHub user configuration. + required: false + GITHUB_USER_NAME: + description: Username for the GitHub user configuration. + required: false + GITHUB_USER_SSH_KEY: + description: Private SSH key associated with the GitHub user for the token passed as `GITHUB_USER_TOKEN`. + required: false + GITHUB_USER_SSH_PUBLIC_KEY: + description: Public SSH key associated with the GitHub user for the token passed as `GITHUB_USER_TOKEN`. + required: false + NPM_REGISTRY_TOKEN: + description: Authentication for the private npm registry. + required: false + +jobs: + update-dependencies: + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + PACKAGE_MANAGER: npm + WP_DIST_TAG: ${{ inputs.WP_DIST_TAG }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.GITHUB_USER_SSH_KEY }} + + - name: Set global variables + run: | + echo "TEMP_BRANCH_NAME=update/${{ env.WP_DIST_TAG }}" >> $GITHUB_ENV + echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + + - name: Set up SSH + env: + GITHUB_USER_SSH_KEY: ${{ secrets.GITHUB_USER_SSH_KEY }} + if: ${{ env.GITHUB_USER_SSH_KEY != '' }} + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ env.GITHUB_USER_SSH_KEY }} + + - name: Set up Git + env: + GITHUB_USER_EMAIL: ${{ secrets.GITHUB_USER_EMAIL }} + GITHUB_USER_NAME: ${{ secrets.GITHUB_USER_NAME }} + run: | + git config --global user.email "${{ env.GITHUB_USER_EMAIL }}" + git config --global user.name "${{ env.GITHUB_USER_NAME }}" + git config --global advice.addIgnoredFile false + git config --global push.autoSetupRemote true + + - name: Set up signing commits + env: + GITHUB_USER_SSH_PUBLIC_KEY: ${{ secrets.GITHUB_USER_SSH_PUBLIC_KEY }} + if: ${{ env.GITHUB_USER_SSH_PUBLIC_KEY != '' }} + run: | + : # Create empty SSH private key file so Git does not complain. + touch "${{ runner.temp }}/signingkey" + echo "${{ env.GITHUB_USER_SSH_PUBLIC_KEY }}" > "${{ runner.temp }}/signingkey.pub" + git config --global commit.gpgsign true + git config --global gpg.format ssh + git config --global user.signingkey "${{ runner.temp }}/signingkey.pub" + + - name: Checkout to temporary branch + run: | + git show-ref -q refs/remotes/origin/${{ env.TEMP_BRANCH_NAME }} && git checkout ${{ env.TEMP_BRANCH_NAME }} || git checkout -b ${{ env.TEMP_BRANCH_NAME }} + + - name: Set up node cache mode + run: | + if [ "${{ env.PACKAGE_MANAGER }}" == 'npm' ] && { [ -f "${GITHUB_WORKSPACE}/package-lock.json" ] || [ -f "${GITHUB_WORKSPACE}/npm-shrinkwrap.json" ]; }; then + echo "NODE_CACHE_MODE=npm" >> $GITHUB_ENV + else + echo "No lock files found or unknown package manager" + fi + + - name: Set up node + env: + NPM_REGISTRY_DOMAIN: ${{ inputs.NPM_REGISTRY_DOMAIN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + registry-url: ${{ env.NPM_REGISTRY_DOMAIN }} + cache: ${{ env.NODE_CACHE_MODE }} + + - name: Install dependencies + env: + ARGS: ${{ env.NODE_CACHE_MODE == 'npm' && 'ci' || 'install' }} + NPM_REGISTRY_DOMAIN: ${{ inputs.NPM_REGISTRY_DOMAIN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }} + run: ${{ format('{0} {1} --ignore-scripts', env.PACKAGE_MANAGER, env.ARGS) }} + + - name: Update dependencies + env: + SCRIPT_START: ${{ env.PACKAGE_MANAGER == 'npm' && 'npm run' }} + NPM_REGISTRY_DOMAIN: ${{ inputs.NPM_REGISTRY_DOMAIN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }} + run: | + ./node_modules/.bin/wp-scripts packages-update --dist-tag=${{ env.WP_DIST_TAG }} + + - name: Git add, commit + run: | + git add -A + git commit -m "[BOT] Add dependencies changes for #${{ github.ref }}" --no-verify || ((echo "NO_CHANGES=yes" >> $GITHUB_ENV) && (echo "No changes to commit")) + + - name: Git push + if: ${{ env.NO_CHANGES != 'yes' }} + run: git push + + - name: Create pull request + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr create \ + --base ${{ github.event.repository.default_branch }} \ + --head ${{ env.TEMP_BRANCH_NAME }} \ + --title "Align WP Dependencies to meet dist tag ${{ env.WP_DIST_TAG }} - ${{ env.CURRENT_DATE }}" \ + --body "This PR updates the WordPress dependencies to meet the version ${{ env.WP_DIST_TAG }}." \ + --label "dependencies" + + - name: Delete signing key files + env: + GITHUB_USER_SSH_PUBLIC_KEY: ${{ secrets.GITHUB_USER_SSH_PUBLIC_KEY }} + if: ${{ always() && env.GITHUB_USER_SSH_PUBLIC_KEY != '' }} + run: | + rm -f "${{ runner.temp }}/signingkey" + rm -f "${{ runner.temp }}/signingkey.pub" diff --git a/docs/update-wp-dependencies.md b/docs/update-wp-dependencies.md new file mode 100644 index 00000000..10def1d1 --- /dev/null +++ b/docs/update-wp-dependencies.md @@ -0,0 +1,106 @@ + + +# Update WordPress JS Dependencies + +This documentation describes two closely related reusable workflows for updating JavaScript dependencies that use [WordPress packages](https://www.npmjs.com/search?q=%40wordpress%2F). These workflows handle automatic updates of the `@wordpress/*` packages to a specified WordPress version (dist tag) and can optionally create a pull request with all necessary changes. + +1. **Update WordPress JS Dependencies Workflow**: + This workflow lives in an individual repository (the one containing the WordPress JS dependencies to update). It checks out the repository, updates the `@wordpress/*` dependencies to a specific tag, and opens a pull request if changes are found. + +2. **Update WordPress JS Dependencies Orchestrator Workflow**: + This workflow can be placed in a single "orchestrator" repository (e.g., a website repository). It triggers the "Update WordPress JS Dependencies Workflow" in multiple other repositories. This is accomplished by sending a [workflow\_dispatch](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_dispatch) event to each of the target repositories. + +## Update WordPress JS Dependencies Workflow + +This workflow updates the `@wordpress/*` dependencies in the current repository to a specified WordPress version tag (e.g., `wp-6.7`) and creates a pull request containing all modified files. + +### Configuration parameters + +#### Inputs + +| Name | Default | Description | +|-----------------------|---------------------------------|------------------------------------------------------------| +| `WP_DIST_TAG` | `'wp-6.7'` | The dist tag to update the dependencies to, e.g., `wp-6.7` | +| `NPM_REGISTRY_DOMAIN` | `'https://npm.pkg.github.com/'` | Domain of the private npm registry | + +#### Secrets + +| Name | Description | +|------------------------------|------------------------------------------------------------------------------| +| `NPM_REGISTRY_TOKEN` | Authentication for the private npm registry | +| `GITHUB_USER_EMAIL` | Email address for the GitHub user configuration | +| `GITHUB_USER_NAME` | Username for the GitHub user configuration | +| `GITHUB_USER_SSH_KEY` | Private SSH key associated with the GitHub user passed as `GITHUB_USER_NAME` | +| `GITHUB_USER_SSH_PUBLIC_KEY` | Public SSH key associated with the GitHub user passed as `GITHUB_USER_NAME` | + +### Usage example + +```yml +name: Update WordPress JS Dependencies + +on: + workflow_dispatch: + inputs: + WP_DIST_TAG: + description: The dist tag to update the dependencies to, e.g., `wp-6.7`. + default: 'wp-6.7' + required: true + type: string + +jobs: + update-dependencies: + uses: inpsyde/reusable-workflows/.github/workflows/update-wordpress-js-dependencies.yml@main + secrets: + GITHUB_USER_EMAIL: ${{ secrets.DEPLOYBOT_EMAIL }} + GITHUB_USER_NAME: ${{ secrets.DEPLOYBOT_USER }} + GITHUB_USER_SSH_KEY: ${{ secrets.DEPLOYBOT_SSH_PRIVATE_KEY }} + GITHUB_USER_SSH_PUBLIC_KEY: ${{ secrets.DEPLOYBOT_SSH_PUBLIC_KEY }} + NPM_REGISTRY_TOKEN: ${{ secrets.DEPLOYBOT_PACKAGES_READ_ACCESS_TOKEN }} + with: + WP_DIST_TAG: ${{ inputs.WP_DIST_TAG }} +``` + +## Update WordPress JS Dependencies Orchestrator Workflow + +This workflow triggers the “Update WordPress JS Dependencies Workflow” in multiple external repositories by sending a `repository_dispatch` event to each target repository. This allows you to maintain a centralized list of repositories needing consistent WordPress JS dependency versions. + +### Configuration parameters + +#### Inputs + +| Name | Default | Description | +|---------------|------------|----------------------------------------------------------------| +| `WP_DIST_TAG` | `'wp-6.7'` | The dist tag to update the dependencies to, e.g., `wp-6.7` | +| `PACKAGES` | `''` | Comma-separated list of additional `owner/repo`s to be updated | + +#### Secrets + +| Name | Description | +|------------|-------------------------------------------------------------------------------------------------------------------------| +| `GH_TOKEN` | A personal access token (classic) with `repo` and `workflow` permissions, used to authenticate when calling GitHub APIs | + +### Usage example + +```yml +name: Update WordPress JS Dependencies Orchestrator + +on: + workflow_dispatch: + inputs: + WP_DIST_TAG: + description: The dist tag to update the dependencies to, e.g., `wp-6.7` + required: true + PACKAGES: + description: 'Comma-separated list of additional `owner/repo`s to be updated.' + required: false + type: string + +jobs: + update-dependency-orchestrator: + uses: inpsyde/reusable-workflows/.github/workflows/update-wordpress-js-dependencies-orchestrator.yml@main + with: + WP_DIST_TAG: ${{ inputs.WP_DIST_TAG }} + PACKAGES: ${{ inputs.PACKAGES }} + secrets: + GH_TOKEN: ${{ secrets.DEPLOYBOT_REPO_READ_WRITE_TOKEN }} +```