From d82191e0b14170751316d8e5b22e4e04b60ede58 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Mon, 21 Sep 2026 09:25:04 -0400 Subject: [PATCH 1/5] feat(release): configure native component releases --- .github/workflows/php-transformer-split.yml | 71 --------------------- .github/workflows/release.yml | 55 ++++++++++++++++ docs/release-components.md | 43 +++++++++++++ figma-transformer/homeboy.json | 3 + packages/blocks-engine/homeboy.json | 3 + php-transformer/homeboy.json | 11 ++++ 6 files changed, 115 insertions(+), 71 deletions(-) delete mode 100644 .github/workflows/php-transformer-split.yml create mode 100644 .github/workflows/release.yml create mode 100644 docs/release-components.md diff --git a/.github/workflows/php-transformer-split.yml b/.github/workflows/php-transformer-split.yml deleted file mode 100644 index 19f2307e3..000000000 --- a/.github/workflows/php-transformer-split.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: PHP Transformer Split - -# Mirrors php-transformer/ to the read-only standalone repository that -# Packagist indexes. Trunk pushes update the mirror's trunk (dev-trunk on -# Packagist); php-transformer-v* tag pushes create translated vX.Y.Z mirror -# tags (Packagist releases). Note: GitHub does not evaluate `paths` filters -# for tag pushes, so tag runs are unaffected by the paths list below. - -on: - push: - branches: - - trunk - paths: - - "php-transformer/**" - - ".github/workflows/php-transformer-split.yml" - tags: - - "php-transformer-v*" - -permissions: - contents: read - -concurrency: - group: php-transformer-split - cancel-in-progress: false - -jobs: - split: - name: Split php-transformer to mirror - runs-on: ubuntu-latest - timeout-minutes: 10 - if: github.repository == 'Automattic/blocks-engine' - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Configure mirror SSH auth - env: - DEPLOY_KEY: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} - run: | - if [ -z "$DEPLOY_KEY" ]; then - echo "PHP_TRANSFORMER_MIRROR_DEPLOY_KEY secret is not configured" >&2 - exit 1 - fi - mkdir -p ~/.ssh - printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/mirror_deploy_key - chmod 600 ~/.ssh/mirror_deploy_key - # GitHub's published SSH host keys (https://api.github.com/meta), - # pinned instead of trusting whatever ssh-keyscan happens to see. - printf '%s\n' \ - 'github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl' \ - 'github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=' \ - 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=' \ - >> ~/.ssh/known_hosts - - - name: Split and push - env: - GIT_SSH_COMMAND: ssh -i ~/.ssh/mirror_deploy_key -o IdentitiesOnly=yes - MIRROR_URL: git@github.com:Automattic/blocks-engine-php-transformer.git - run: | - set -euo pipefail - split_sha=$(php-transformer/tools/packagist-split/split-ref.sh "$GITHUB_SHA") - if [ "${GITHUB_REF_TYPE}" = "tag" ]; then - mirror_tag="v${GITHUB_REF_NAME#php-transformer-v}" - echo "Pushing tag ${mirror_tag} (${split_sha})" - git push "$MIRROR_URL" "${split_sha}:refs/tags/${mirror_tag}" - else - echo "Pushing trunk (${split_sha})" - git push "$MIRROR_URL" "${split_sha}:refs/heads/trunk" - fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..0716cd2be --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Release components + +on: + push: + branches: + - trunk + workflow_dispatch: + inputs: + dry-run: + description: Preview the release without changing trunk or publishing packages + type: boolean + default: true + +permissions: + contents: write + issues: write + pull-requests: write + +concurrency: + group: component-release + cancel-in-progress: false + +# Keep these jobs serial. Each Homeboy release may commit version/changelog +# changes and push trunk; the next job must resolve the refreshed trunk tip, +# not the event SHA that started this workflow. +jobs: + javascript: + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + with: + component: packages/blocks-engine + dry-run: ${{ inputs.dry-run || false }} + release-branch: trunk + dispatch-repo: Automattic/static-site-importer + dispatch-event: blocks-engine-component-released + secrets: inherit + + php: + needs: javascript + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + with: + component: php-transformer + dry-run: ${{ inputs.dry-run || false }} + release-branch: trunk + dispatch-repo: Automattic/static-site-importer + dispatch-event: blocks-engine-component-released + secrets: inherit + + figma: + needs: php + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + with: + component: figma-transformer + dry-run: ${{ inputs.dry-run || false }} + release-branch: trunk + secrets: inherit diff --git a/docs/release-components.md b/docs/release-components.md new file mode 100644 index 000000000..85377da5f --- /dev/null +++ b/docs/release-components.md @@ -0,0 +1,43 @@ +# Component Releases + +The `release.yml` workflow runs the three package components in dependency order +on `trunk`. The jobs are intentionally serialized because Homeboy may commit +version and changelog updates; each later job must resolve the trunk tip +published by the preceding job. + +## Native publication + +- `@automattic/blocks-engine` publishes through the Node.js Homeboy extension. +- `php-transformer` publishes through Composer and splits its component root + (`prefix: "."`) natively to `Automattic/blocks-engine-php-transformer`. The old + tag-triggered shell split workflow is removed. +- `figma-transformer` is release-enabled with registry publication explicitly + disabled until standalone Packagist repository provisioning in #1364 exists. + This config does not treat a skipped registry publication as success. + +For enabled publishers, publication is not optional: the reusable workflow +only dispatches SSI after Homeboy reports a successful consumable release. The +SSI dispatch requires either `DISPATCH_TOKEN` or a Homeboy App +installation token scoped to `Automattic/static-site-importer`. Registry +credentials are owned by the corresponding Homeboy extensions (`NPM_TOKEN`, +Composer/Packagist credentials); the PHP subtree destination needs a Git write +credential. The old `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` is not consumed by this +workflow. This repository does not add or infer secrets. + +## Dependency activation checklist + +This draft depends on the following exact local candidate revisions. They must +be released and pinned in `release.yml` before merging; `@v2` is retained here +only as the currently published reusable-workflow fallback while those +upstream changes are pending. + +| Capability | Candidate repository | Candidate revision | Minimum release | +| --- | --- | --- | --- | +| Native subtree publication | `Extra-Chill/homeboy` | `84d83ac1bea431f54e1df8de419e24a8316b3e0e` plus the uncommitted #14837 contract | Homeboy release containing `release.subtree` | +| Component-scoped reusable release | `Extra-Chill/homeboy-action` | `6156c5e39945cb20689c49a830f69a15ad36d51c` plus the uncommitted #485 workflow changes | homeboy-action release containing `component` and prepared-ref inputs | +| Composer release refresh | `Extra-Chill/homeboy-extensions` | `e4eba09ee90fb48d26bc380cc3f19a7ca80a0f99` (`feat/2855-composer-release-refresh`) | extension release containing the `release.update_dependency` contract | + +The candidate working trees were not committed when this draft was prepared, +so the first two entries deliberately include the exact base SHA and state the +uncommitted dependency. Do not merge this workflow until the final upstream +commit SHAs replace those entries and the `uses:` pins are updated from `v2`. diff --git a/figma-transformer/homeboy.json b/figma-transformer/homeboy.json index 36a743c1c..c58035c01 100644 --- a/figma-transformer/homeboy.json +++ b/figma-transformer/homeboy.json @@ -3,6 +3,9 @@ "changelog_target": "CHANGELOG.md", "id": "figma-transformer", "remote_path": "", + "release": { + "publish": false + }, "version_targets": [ { "file": "VERSION", diff --git a/packages/blocks-engine/homeboy.json b/packages/blocks-engine/homeboy.json index e3c0c27d1..5f3e84a98 100644 --- a/packages/blocks-engine/homeboy.json +++ b/packages/blocks-engine/homeboy.json @@ -3,6 +3,9 @@ "changelog_target": "CHANGELOG.md", "id": "blocks-engine", "remote_path": "", + "release": { + "publish": true + }, "version_targets": [ { "file": "package.json", diff --git a/php-transformer/homeboy.json b/php-transformer/homeboy.json index 7dadd9550..a3e608eab 100644 --- a/php-transformer/homeboy.json +++ b/php-transformer/homeboy.json @@ -3,6 +3,17 @@ "changelog_target": "CHANGELOG.md", "id": "php-transformer", "remote_path": "", + "release": { + "publish": true, + "subtree": [ + { + "prefix": ".", + "remote": "https://github.com/Automattic/blocks-engine-php-transformer.git", + "branch": "trunk", + "tag": true + } + ] + }, "version_targets": [ { "file": "VERSION", From 2c45a8cd0d5a597725a454b338d6989d19b7f39a Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Mon, 21 Sep 2026 10:02:00 -0400 Subject: [PATCH 2/5] fix(release): align native mirror integration --- .../workflows/php-transformer-dev-trunk.yml | 60 +++++++++++++++++++ .github/workflows/release.yml | 21 ++++--- docs/release-components.md | 48 ++++++++------- php-transformer/homeboy.json | 6 +- 4 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 .github/workflows/php-transformer-dev-trunk.yml diff --git a/.github/workflows/php-transformer-dev-trunk.yml b/.github/workflows/php-transformer-dev-trunk.yml new file mode 100644 index 000000000..4b658c7db --- /dev/null +++ b/.github/workflows/php-transformer-dev-trunk.yml @@ -0,0 +1,60 @@ +name: PHP Transformer dev-trunk mirror + +# Temporary compatibility bridge for Packagist dev-trunk consumers. Homeboy +# #14837 owns release-tag publication through release.subtree, but does not yet +# expose a branch-only shared invocation for non-releasable trunk commits. +# Remove this bridge when that native endpoint is available. + +on: + push: + branches: + - trunk + paths: + - "php-transformer/**" + - ".github/workflows/php-transformer-dev-trunk.yml" + +permissions: + contents: read + +concurrency: + # Share the release workflow's lock so a release commit cannot race the + # compatibility mirror update. + group: component-release + cancel-in-progress: false + +jobs: + mirror: + name: Mirror PHP Transformer trunk + runs-on: ubuntu-latest + if: github.repository == 'Automattic/blocks-engine' + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure mirror SSH auth + env: + DEPLOY_KEY: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} + run: | + if [ -z "$DEPLOY_KEY" ]; then + echo "PHP_TRANSFORMER_MIRROR_DEPLOY_KEY secret is not configured" >&2 + exit 1 + fi + mkdir -p ~/.ssh + printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/mirror_deploy_key + chmod 600 ~/.ssh/mirror_deploy_key + printf '%s\n' \ + 'github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl' \ + 'github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=' \ + 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=' \ + >> ~/.ssh/known_hosts + + - name: Split and push dev-trunk + env: + GIT_SSH_COMMAND: ssh -i ~/.ssh/mirror_deploy_key -o IdentitiesOnly=yes + MIRROR_URL: git@github.com:Automattic/blocks-engine-php-transformer.git + run: | + set -euo pipefail + split_sha=$(php-transformer/tools/packagist-split/split-ref.sh "$GITHUB_SHA") + git push "$MIRROR_URL" "${split_sha}:refs/heads/trunk" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0716cd2be..5054fc46e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,31 +25,38 @@ concurrency: # not the event SHA that started this workflow. jobs: javascript: - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@d21c46a3a25b16895c36124a6af481a6f97f8636 with: component: packages/blocks-engine + action-ref: d21c46a3a25b16895c36124a6af481a6f97f8636 + extension-ref: b94cad68433a34c9129681b1c1a57e63364719db + prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk - dispatch-repo: Automattic/static-site-importer - dispatch-event: blocks-engine-component-released secrets: inherit php: needs: javascript - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + if: ${{ always() && (needs.javascript.result == 'success' || needs.javascript.result == 'skipped') }} + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@d21c46a3a25b16895c36124a6af481a6f97f8636 with: component: php-transformer + action-ref: d21c46a3a25b16895c36124a6af481a6f97f8636 + extension-ref: b94cad68433a34c9129681b1c1a57e63364719db + prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk - dispatch-repo: Automattic/static-site-importer - dispatch-event: blocks-engine-component-released secrets: inherit figma: needs: php - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2 + if: ${{ always() && (needs.php.result == 'success' || needs.php.result == 'skipped') }} + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@d21c46a3a25b16895c36124a6af481a6f97f8636 with: component: figma-transformer + action-ref: d21c46a3a25b16895c36124a6af481a6f97f8636 + extension-ref: b94cad68433a34c9129681b1c1a57e63364719db + prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk secrets: inherit diff --git a/docs/release-components.md b/docs/release-components.md index 85377da5f..b33aa2217 100644 --- a/docs/release-components.md +++ b/docs/release-components.md @@ -8,36 +8,40 @@ published by the preceding job. ## Native publication - `@automattic/blocks-engine` publishes through the Node.js Homeboy extension. -- `php-transformer` publishes through Composer and splits its component root - (`prefix: "."`) natively to `Automattic/blocks-engine-php-transformer`. The old +- `php-transformer` publishes through Composer and splits the repository + `php-transformer/` prefix natively to `Automattic/blocks-engine-php-transformer`. + Its source `php-transformer-vX.Y.Z` tag becomes `vX.Y.Z` in the mirror. The old tag-triggered shell split workflow is removed. - `figma-transformer` is release-enabled with registry publication explicitly disabled until standalone Packagist repository provisioning in #1364 exists. This config does not treat a skipped registry publication as success. -For enabled publishers, publication is not optional: the reusable workflow -only dispatches SSI after Homeboy reports a successful consumable release. The -SSI dispatch requires either `DISPATCH_TOKEN` or a Homeboy App -installation token scoped to `Automattic/static-site-importer`. Registry -credentials are owned by the corresponding Homeboy extensions (`NPM_TOKEN`, -Composer/Packagist credentials); the PHP subtree destination needs a Git write -credential. The old `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` is not consumed by this -workflow. This repository does not add or infer secrets. +For enabled publishers, publication is not optional. Registry credentials are +owned by the corresponding Homeboy extensions (`NPM_TOKEN`, Composer/Packagist +credentials). The PHP subtree destination also needs a Git write credential. +The old `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` cannot currently be passed through +the reusable release contract, so SSI notification remains deliberately +disabled until a supported mirror-auth and destination-coordinate handoff is +available. This avoids reporting the monorepo tag SHA as the mirror SHA. + +The separate `php-transformer-dev-trunk.yml` workflow is a temporary, +credentialed compatibility bridge for consumers of the mirror's `trunk` +branch. It has no tag path and must be removed when Homeboy exposes the +branch-only shared subtree invocation. ## Dependency activation checklist -This draft depends on the following exact local candidate revisions. They must -be released and pinned in `release.yml` before merging; `@v2` is retained here -only as the currently published reusable-workflow fallback while those -upstream changes are pending. +The workflow now pins these remotely addressable candidate revisions. They must +be released under their normal immutable release refs before merge. | Capability | Candidate repository | Candidate revision | Minimum release | | --- | --- | --- | --- | -| Native subtree publication | `Extra-Chill/homeboy` | `84d83ac1bea431f54e1df8de419e24a8316b3e0e` plus the uncommitted #14837 contract | Homeboy release containing `release.subtree` | -| Component-scoped reusable release | `Extra-Chill/homeboy-action` | `6156c5e39945cb20689c49a830f69a15ad36d51c` plus the uncommitted #485 workflow changes | homeboy-action release containing `component` and prepared-ref inputs | -| Composer release refresh | `Extra-Chill/homeboy-extensions` | `e4eba09ee90fb48d26bc380cc3f19a7ca80a0f99` (`feat/2855-composer-release-refresh`) | extension release containing the `release.update_dependency` contract | - -The candidate working trees were not committed when this draft was prepared, -so the first two entries deliberately include the exact base SHA and state the -uncommitted dependency. Do not merge this workflow until the final upstream -commit SHAs replace those entries and the `uses:` pins are updated from `v2`. +| Native subtree publication | `Extra-Chill/homeboy` | `ef324f259af85ab86c6b5bc3f608bef3d823a7e7` | Homeboy release containing `release.subtree` | +| Component-scoped reusable release | `Extra-Chill/homeboy-action` | `d21c46a3a25b16895c36124a6af481a6f97f8636` | homeboy-action release containing `component` and prepared-ref inputs | +| Composer release refresh | `Extra-Chill/homeboy-extensions` | `b94cad68433a34c9129681b1c1a57e63364719db` | extension release containing the `release.update_dependency` contract | +| Figma coordinate discovery | `Extra-Chill/homeboy` | `bb993897850b0766270da0ce489458db753dc934` | Homeboy release containing `release resolve` | + +Figma's existing inline archive route remains usable. SSI must use +`homeboy release resolve` against the monorepo's `figma-transformer-v*` tags +before invoking the Composer dependency updater; a one-item inline Composer +repository cannot discover versions itself. diff --git a/php-transformer/homeboy.json b/php-transformer/homeboy.json index a3e608eab..1a2ab18b5 100644 --- a/php-transformer/homeboy.json +++ b/php-transformer/homeboy.json @@ -7,10 +7,12 @@ "publish": true, "subtree": [ { - "prefix": ".", + "prefix": "php-transformer", "remote": "https://github.com/Automattic/blocks-engine-php-transformer.git", "branch": "trunk", - "tag": true + "tag": true, + "tag_template": "v{version}", + "branch_policy": "fast_forward" } ] }, From 592bfc73def216a6e4fa7a9c209ca91a61e5fec7 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Mon, 21 Sep 2026 12:27:14 -0400 Subject: [PATCH 3/5] fix(release): decouple from SSI and re-pin to released Homeboy refs - Remove dispatch-repo/dispatch-event/DISPATCH_TOKEN from release.yml. Blocks Engine no longer notifies Static Site Importer; consumers resolve published coordinates themselves (homeboy release resolve, the mirror repo, or the npm registry). - Re-pin action-ref/extension-ref from unreleased candidate commits to released tags: homeboy-action v2.19.0 and homeboy-extensions wordpress-v3.48.6, both verified by cloning and checking tag ancestry/content directly. - Fix the php/figma job if: conditions (was invalid YAML in a prior uncommitted edit) so a sibling job's failure never blocks or skips the others. - Map PHP_TRANSFORMER_MIRROR_DEPLOY_KEY to the reusable workflow's PUBLISH_SSH_KEY secret explicitly for the php job instead of secrets: inherit (the names do not match). - Revert php-transformer-dev-trunk.yml's shell-based mirror to the working baseline; homeboy-action's native git-operation routing needed for the single-invocation replacement released in v2.19.0, but the Homeboy CLI's git subtree/release.subtree feature (Extra-Chill/homeboy#14851) has not shipped in a released Homeboy tag yet (confirmed by downloading v0.382.0 and running `homeboy git subtree --help`). Document the exact target invocation and the precise remaining blocker in the workflow header instead of reintroducing a hand-rolled subtree shell with manual SSH handling. - Document all of the above in docs/release-components.md, including why php-transformer's release.subtree config is currently inert. Verification: - actionlint on both changed workflow files: clean. - ruby -ryaml load of both changed workflow files: clean. - Bare-cloned Extra-Chill/homeboy, homeboy-action, and homeboy-extensions to verify tag ancestry/content for every pinned SHA instead of trusting tag names. - Downloaded the actual released homeboy v0.382.0 binary and ran `homeboy release --dry-run` for all three components; each parses its homeboy.json correctly and fails only on the expected non-trunk-branch preflight guard. --- .../workflows/php-transformer-dev-trunk.yml | 32 ++++++- .github/workflows/release.yml | 34 ++++--- docs/release-components.md | 91 ++++++++++++++----- figma-transformer/homeboy.json | 3 + packages/blocks-engine/homeboy.json | 3 + php-transformer/README.md | 2 +- php-transformer/homeboy.json | 5 +- 7 files changed, 126 insertions(+), 44 deletions(-) diff --git a/.github/workflows/php-transformer-dev-trunk.yml b/.github/workflows/php-transformer-dev-trunk.yml index 4b658c7db..28ea63e6f 100644 --- a/.github/workflows/php-transformer-dev-trunk.yml +++ b/.github/workflows/php-transformer-dev-trunk.yml @@ -1,9 +1,33 @@ name: PHP Transformer dev-trunk mirror -# Temporary compatibility bridge for Packagist dev-trunk consumers. Homeboy -# #14837 owns release-tag publication through release.subtree, but does not yet -# expose a branch-only shared invocation for non-releasable trunk commits. -# Remove this bridge when that native endpoint is available. +# Temporary compatibility bridge for Packagist dev-trunk consumers. The +# target replacement is one homeboy-action invocation with no consumer +# ssh-agent, key handling, known-hosts writing, or `git push`: +# +# - uses: Extra-Chill/homeboy-action@ +# with: +# component: php-transformer +# commands: git subtree php-transformer ${{ github.sha }} --apply --branch-only +# ssh-key: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} +# ssh-known-hosts: | +# github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl +# ssh-require-known-hosts: true +# +# homeboy-action's native `git` operation routing needed for that single +# invocation released in v2.19.0 (Extra-Chill/homeboy-action#488). It is not +# the blocker anymore. The remaining blocker is the Homeboy CLI itself: +# `homeboy git subtree` (Extra-Chill/homeboy#14837, implemented in +# Extra-Chill/homeboy#14851) merged to the CLI's main branch but has not yet +# shipped in a released Homeboy tag as of this change (confirmed by running +# the actual v0.382.0 release binary: `homeboy git subtree --help` reports +# "unrecognized subcommand"). Switching this workflow to the invocation above +# before that ships would break the mirror at runtime. Move to the native +# invocation the moment a released Homeboy tag contains `homeboy git +# subtree`; until then this shell-based bridge remains the only working +# path and must not be replaced by a hand-rolled `homeboy git subtree` +# invocation with manual ssh-agent/known-hosts setup, which would just +# reintroduce the same consumer-owned credential handling this bridge exists +# to retire. on: push: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5054fc46e..920fd505c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ on: permissions: contents: write + id-token: write issues: write pull-requests: write @@ -22,14 +23,16 @@ concurrency: # Keep these jobs serial. Each Homeboy release may commit version/changelog # changes and push trunk; the next job must resolve the refreshed trunk tip, -# not the event SHA that started this workflow. +# not the event SHA that started this workflow. Each job's `if: !cancelled()` +# means a sibling's failure never blocks or skips the others — every +# component release attempt runs and reports its own outcome independently. jobs: javascript: - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@d21c46a3a25b16895c36124a6af481a6f97f8636 + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc with: component: packages/blocks-engine - action-ref: d21c46a3a25b16895c36124a6af481a6f97f8636 - extension-ref: b94cad68433a34c9129681b1c1a57e63364719db + action-ref: b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc + extension-ref: 7f28a979517a96e003d0510d64bc5139c259837d prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk @@ -37,25 +40,30 @@ jobs: php: needs: javascript - if: ${{ always() && (needs.javascript.result == 'success' || needs.javascript.result == 'skipped') }} - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@d21c46a3a25b16895c36124a6af481a6f97f8636 + if: ${{ !cancelled() }} + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc with: component: php-transformer - action-ref: d21c46a3a25b16895c36124a6af481a6f97f8636 - extension-ref: b94cad68433a34c9129681b1c1a57e63364719db + action-ref: b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc + extension-ref: 7f28a979517a96e003d0510d64bc5139c259837d prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk - secrets: inherit + publisher-known-hosts: | + github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl + secrets: + HOMEBOY_APP_ID: ${{ secrets.HOMEBOY_APP_ID }} + HOMEBOY_APP_PRIVATE_KEY: ${{ secrets.HOMEBOY_APP_PRIVATE_KEY }} + PUBLISH_SSH_KEY: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} figma: needs: php - if: ${{ always() && (needs.php.result == 'success' || needs.php.result == 'skipped') }} - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@d21c46a3a25b16895c36124a6af481a6f97f8636 + if: ${{ !cancelled() }} + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc with: component: figma-transformer - action-ref: d21c46a3a25b16895c36124a6af481a6f97f8636 - extension-ref: b94cad68433a34c9129681b1c1a57e63364719db + action-ref: b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc + extension-ref: 7f28a979517a96e003d0510d64bc5139c259837d prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk diff --git a/docs/release-components.md b/docs/release-components.md index b33aa2217..9b0d78e32 100644 --- a/docs/release-components.md +++ b/docs/release-components.md @@ -8,40 +8,81 @@ published by the preceding job. ## Native publication - `@automattic/blocks-engine` publishes through the Node.js Homeboy extension. -- `php-transformer` publishes through Composer and splits the repository - `php-transformer/` prefix natively to `Automattic/blocks-engine-php-transformer`. +- `php-transformer` creates its WordPress release archive and splits the + repository `php-transformer/` prefix natively to + `Automattic/blocks-engine-php-transformer`. Its source `php-transformer-vX.Y.Z` tag becomes `vX.Y.Z` in the mirror. The old tag-triggered shell split workflow is removed. -- `figma-transformer` is release-enabled with registry publication explicitly - disabled until standalone Packagist repository provisioning in #1364 exists. - This config does not treat a skipped registry publication as success. +- `figma-transformer` retains GitHub tag/archive release while registry + publication is explicitly disabled until standalone Packagist repository + provisioning in #1364 exists. For enabled publishers, publication is not optional. Registry credentials are -owned by the corresponding Homeboy extensions (`NPM_TOKEN`, Composer/Packagist -credentials). The PHP subtree destination also needs a Git write credential. -The old `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` cannot currently be passed through -the reusable release contract, so SSI notification remains deliberately -disabled until a supported mirror-auth and destination-coordinate handoff is -available. This avoids reporting the monorepo tag SHA as the mirror SHA. +owned by the corresponding Homeboy extensions. The PHP subtree destination +also needs a Git write credential: the existing +`PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` secret is mapped to the reusable +workflow's generic `PUBLISH_SSH_KEY` secret input, paired with pinned GitHub +host keys and `ssh-require-known-hosts: true`. + +Blocks Engine does not notify Static Site Importer or any other consumer. +The repositories are decoupled: this workflow performs no +`repository_dispatch`, carries no dispatch token, and has no SSI-specific +configuration. A consumer that needs the published coordinates resolves them +itself — `homeboy release resolve` against this repository's tags for the +Figma archive route, or the mirror repository / npm registry directly for +PHP Transformer and `@automattic/blocks-engine`. + +The component manifests explicitly declare their publisher extensions: +`nodejs` for the npm package and `wordpress` for the PHP/Figma release +archives. The npm publisher itself runs `npm publish`, but the pinned +homeboy-action reusable workflow currently exposes neither `NPM_TOKEN` nor an +OIDC-enabled npm publishing setup. The caller grants `id-token: write` in +preparation for npm trusted publishing, but npm publication remains blocked +until homeboy-action adds that credential contract (or its documented +equivalent). No raw consumer-side npm publish step is added here. The separate `php-transformer-dev-trunk.yml` workflow is a temporary, credentialed compatibility bridge for consumers of the mirror's `trunk` -branch. It has no tag path and must be removed when Homeboy exposes the -branch-only shared subtree invocation. +branch. It has no tag path. Its header documents the exact single +homeboy-action invocation that replaces it and the one thing still blocking +that replacement: a released Homeboy CLI tag containing `homeboy git +subtree` (see the dependency table below). Do not replace it with a +hand-rolled `homeboy git subtree` invocation plus manual ssh-agent/known-hosts +setup in the meantime — that reintroduces the same consumer-owned credential +handling this bridge exists to retire, without the supported `ssh-key` / +`ssh-known-hosts` contract the native invocation gets from the action. ## Dependency activation checklist -The workflow now pins these remotely addressable candidate revisions. They must -be released under their normal immutable release refs before merge. +The workflow pins these released, immutable revisions: -| Capability | Candidate repository | Candidate revision | Minimum release | +| Capability | Repository | Pinned revision | Release | | --- | --- | --- | --- | -| Native subtree publication | `Extra-Chill/homeboy` | `ef324f259af85ab86c6b5bc3f608bef3d823a7e7` | Homeboy release containing `release.subtree` | -| Component-scoped reusable release | `Extra-Chill/homeboy-action` | `d21c46a3a25b16895c36124a6af481a6f97f8636` | homeboy-action release containing `component` and prepared-ref inputs | -| Composer release refresh | `Extra-Chill/homeboy-extensions` | `b94cad68433a34c9129681b1c1a57e63364719db` | extension release containing the `release.update_dependency` contract | -| Figma coordinate discovery | `Extra-Chill/homeboy` | `bb993897850b0766270da0ce489458db753dc934` | Homeboy release containing `release resolve` | - -Figma's existing inline archive route remains usable. SSI must use -`homeboy release resolve` against the monorepo's `figma-transformer-v*` tags -before invoking the Composer dependency updater; a one-item inline Composer -repository cannot discover versions itself. +| Component-scoped reusable release, publisher SSH handoff, native `git` operation routing | `Extra-Chill/homeboy-action` | `b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc` | `v2.19.0` | +| Composer release refresh (`release.update_dependency`) | `Extra-Chill/homeboy-extensions` | `7f28a979517a96e003d0510d64bc5139c259837d` | `wordpress-v3.48.6` | + +One capability remains unreleased and is **not** pinned to anything because +there is nothing released to pin: native Git subtree publication +(`homeboy git subtree`, and the release pipeline's own `release.subtree` +step). It was implemented in `Extra-Chill/homeboy#14851` (closing +`Extra-Chill/homeboy#14837`) and merged to the CLI's `main` branch, but as of +this change no released Homeboy tag contains it — confirmed by downloading +the actual latest release binary (`v0.382.0`) and running `homeboy git +subtree --help`, which reports "unrecognized subcommand". The Homeboy CLI +version this workflow uses is intentionally never pinned here (the +homeboy-action `version` input defaults to `latest`), so the `php` release +job and the dev-trunk mirror will both start working the moment Homeboy +cuts a release containing that commit — no change to this repository is +needed when that happens. Until then, `php-transformer`'s `release.subtree` +config in its `homeboy.json` deserializes as an unrecognized field against +the currently released CLI (confirmed with `homeboy release php-transformer +--dry-run` against `v0.382.0`, which reads the rest of the manifest and +fails only on the expected non-`trunk`-branch preflight guard) and is not +consulted, so an `--apply` publish through this workflow will not perform a +native subtree split until a Homeboy release contains `#14851`. + +Figma's existing inline archive route remains usable. A consumer that wants +Figma coordinates uses `homeboy release resolve` against this monorepo's +`figma-transformer-v*` tags before invoking its own Composer dependency +updater; a one-item inline Composer repository cannot discover versions +itself. diff --git a/figma-transformer/homeboy.json b/figma-transformer/homeboy.json index c58035c01..5eb10dd74 100644 --- a/figma-transformer/homeboy.json +++ b/figma-transformer/homeboy.json @@ -3,6 +3,9 @@ "changelog_target": "CHANGELOG.md", "id": "figma-transformer", "remote_path": "", + "extensions": { + "wordpress": {} + }, "release": { "publish": false }, diff --git a/packages/blocks-engine/homeboy.json b/packages/blocks-engine/homeboy.json index 5f3e84a98..d03f129cf 100644 --- a/packages/blocks-engine/homeboy.json +++ b/packages/blocks-engine/homeboy.json @@ -3,6 +3,9 @@ "changelog_target": "CHANGELOG.md", "id": "blocks-engine", "remote_path": "", + "extensions": { + "nodejs": {} + }, "release": { "publish": true }, diff --git a/php-transformer/README.md b/php-transformer/README.md index 24917bce4..01812e6f7 100644 --- a/php-transformer/README.md +++ b/php-transformer/README.md @@ -173,7 +173,7 @@ Run the real WordPress materialization integration against a standard WordPress ## Release Consumption -The package lives in a subtree of the Blocks Engine repository. Composer cannot discover a package whose `composer.json` is below the repository root from a plain monorepo VCS tag, so releases are published through an automated subtree split: `.github/workflows/php-transformer-split.yml` pushes package-only history to [`Automattic/blocks-engine-php-transformer`](https://github.com/Automattic/blocks-engine-php-transformer), translating each `php-transformer-vX.Y.Z` monorepo tag to `vX.Y.Z` on the mirror. Packagist indexes the mirror. +The package lives in a subtree of the Blocks Engine repository. Composer cannot discover a package whose `composer.json` is below the repository root from a plain monorepo VCS tag, so releases are published through Homeboy's native subtree publisher to [`Automattic/blocks-engine-php-transformer`](https://github.com/Automattic/blocks-engine-php-transformer), translating each configured monorepo release to the corresponding `vX.Y.Z` mirror tag. Packagist indexes the mirror. This package intentionally omits `replace` and `provide` declarations for the older downstream package names. Those packages expose their own WordPress plugin bootstraps, functions, hooks, CLI commands, abilities, and product-shaped reports, so the canonical transformer package should not satisfy their Composer requirements directly. diff --git a/php-transformer/homeboy.json b/php-transformer/homeboy.json index 1a2ab18b5..26de6befe 100644 --- a/php-transformer/homeboy.json +++ b/php-transformer/homeboy.json @@ -3,12 +3,15 @@ "changelog_target": "CHANGELOG.md", "id": "php-transformer", "remote_path": "", + "extensions": { + "wordpress": {} + }, "release": { "publish": true, "subtree": [ { "prefix": "php-transformer", - "remote": "https://github.com/Automattic/blocks-engine-php-transformer.git", + "remote": "git@github.com:Automattic/blocks-engine-php-transformer.git", "branch": "trunk", "tag": true, "tag_template": "v{version}", From 8116eb676814e3b5cf4ef5add36f54c56679ff87 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Mon, 21 Sep 2026 17:34:32 -0400 Subject: [PATCH 4/5] fix(release): re-pin to released Homeboy revisions, correct extension pins Re-pin release.yml and its own extension-ref/action-ref inputs from candidate SHAs to their now-released tags: homeboy-action v2.19.1 (contains the previously pinned v2.19.0 commit plus two released fixes) and, per job, the homeboy-extensions tag for the extension that job actually declares (nodejs-v3.7.4 for the JS job, wordpress-v3.48.6 for php/figma) instead of reusing one wordpress-namespaced SHA across all three jobs regardless of which extension each needs. Verified homeboy v0.383.0's released `git subtree` behaviorally against a disposable bare-repository fixture: preview mutates nothing, --apply publishes a tree byte-identical to the source subtree, a re-run is idempotent, --branch-only excludes tag publication, fast_forward branch_policy refuses to force-push over divergent history, and sibling components are never cross-published. That same verification also found a reproducible bug: v0.383.0's git subtree exits non-zero via an internal JSON serialization error on every run that actually succeeds (confirmed by inspecting the destination ref directly; a genuinely broken remote instead produces a normal, correctly serialized failure). Since homeboy-action's run-operations.sh maps any nonzero homeboy exit code straight to a failed step, swapping php-transformer-dev-trunk.yml to the native single-invocation replacement today would turn a working, correctly-reporting bridge into one that silently still publishes correctly but reports every run as failed CI. Keep the existing shell-based split-ref.sh bridge until a released Homeboy tag fixes git subtree's success-path result serialization; document the exact blocker and evidence in both the workflow header and docs/release-components.md. --- .../workflows/php-transformer-dev-trunk.yml | 51 ++++++++--- .github/workflows/release.yml | 49 +++++++++-- docs/release-components.md | 88 +++++++++++++------ 3 files changed, 136 insertions(+), 52 deletions(-) diff --git a/.github/workflows/php-transformer-dev-trunk.yml b/.github/workflows/php-transformer-dev-trunk.yml index 28ea63e6f..ebeb8b59f 100644 --- a/.github/workflows/php-transformer-dev-trunk.yml +++ b/.github/workflows/php-transformer-dev-trunk.yml @@ -4,7 +4,7 @@ name: PHP Transformer dev-trunk mirror # target replacement is one homeboy-action invocation with no consumer # ssh-agent, key handling, known-hosts writing, or `git push`: # -# - uses: Extra-Chill/homeboy-action@ +# - uses: Extra-Chill/homeboy-action@v2.19.1 # with: # component: php-transformer # commands: git subtree php-transformer ${{ github.sha }} --apply --branch-only @@ -13,21 +13,44 @@ name: PHP Transformer dev-trunk mirror # github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl # ssh-require-known-hosts: true # -# homeboy-action's native `git` operation routing needed for that single -# invocation released in v2.19.0 (Extra-Chill/homeboy-action#488). It is not -# the blocker anymore. The remaining blocker is the Homeboy CLI itself: -# `homeboy git subtree` (Extra-Chill/homeboy#14837, implemented in -# Extra-Chill/homeboy#14851) merged to the CLI's main branch but has not yet -# shipped in a released Homeboy tag as of this change (confirmed by running -# the actual v0.382.0 release binary: `homeboy git subtree --help` reports -# "unrecognized subcommand"). Switching this workflow to the invocation above -# before that ships would break the mirror at runtime. Move to the native -# invocation the moment a released Homeboy tag contains `homeboy git -# subtree`; until then this shell-based bridge remains the only working -# path and must not be replaced by a hand-rolled `homeboy git subtree` +# Both prior blockers are gone: homeboy-action's native `git` operation +# routing shipped in v2.19.0 (Extra-Chill/homeboy-action#488), and +# `homeboy git subtree` itself shipped in Homeboy v0.383.0 +# (Extra-Chill/homeboy#14851) — confirmed by downloading that exact released +# binary and running it against a disposable bare-repository fixture: preview +# mutates nothing, `--apply` publishes a tree byte-identical to the source +# subtree, a re-run is idempotent, `--branch-only` correctly excludes tag +# publication (and, separately, tag publication works when it's not passed), +# a `fast_forward` branch_policy correctly refuses to force-push over +# divergent mirror history, and sibling components (figma-transformer) are +# never touched by a php-transformer publish or vice versa. +# +# The remaining blocker is a new one found during that same verification, +# not a shape/config problem: v0.383.0's `homeboy git subtree` has a +# reproducible bug in its OWN result serialization on the SUCCESS path only. +# Every invocation that actually performs the git subtree split-and-push +# correctly (preview and apply both) still exits non-zero afterward with +# `{"success": false, "exit_code": 1, "diagnostics": {"code": +# "internal.json_error", "message": "JSON error", "details": {"context": +# "serialize response", "error": "git command output payload must serialize +# as an object"}}}` — confirmed the underlying push/tag operation itself +# genuinely succeeded in every case (mirror ref inspected directly after each +# run) and that this is specific to the success path: pointing the same +# command at a broken remote produces a normal, correctly serialized +# `git.command_failed` / exit_code 20 failure result instead. homeboy-action's +# `scripts/operations/run-operations.sh` (routes `commands: git subtree ...`) +# has no special case for this — it maps any nonzero `homeboy` exit code +# straight to a failed step (`RESULTS+={cmd: "fail"}`, `any-failed=true`). +# Switching this workflow to the invocation above today would therefore turn +# a currently-working, correctly-reporting bridge into one that silently +# still publishes the mirror correctly but reports every single run as a +# failed CI job. Move to the native invocation once a released Homeboy tag +# fixes `git subtree` success-path result serialization; until then this +# shell-based bridge remains the only path with a CI status that reflects +# reality, and must not be replaced by a hand-rolled `homeboy git subtree` # invocation with manual ssh-agent/known-hosts setup, which would just # reintroduce the same consumer-owned credential handling this bridge exists -# to retire. +# to retire while ALSO breaking CI status reporting. on: push: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 920fd505c..ad32e6745 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,13 +26,44 @@ concurrency: # not the event SHA that started this workflow. Each job's `if: !cancelled()` # means a sibling's failure never blocks or skips the others — every # component release attempt runs and reports its own outcome independently. +# +# Pins, and what each one is for (every SHA below was verified by fetching +# the tag directly from its source repo and checking `^{commit}` equality — +# not assumed from the tag name): +# +# - `uses: .../release.yml@v2.19.1` selects the released revision of the +# reusable release workflow itself. +# - `action-ref: v2.19.1` is the homeboy-action revision that workflow +# checks out into `.homeboy-action` for the composite action steps. Kept +# in lockstep with the `uses:` pin above. v2.19.1 is released and contains +# v2.19.0 (the previously pinned candidate commit +# b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc) plus two additional merged, +# released fixes (homeboy-action#490, #491); no unreleased commits. +# - `extension-ref` pins the homeboy-extensions monorepo commit each job's +# declared extension installs from. It is required, not optional: the +# installed homeboy CLI's `install_for_component` path clones the +# extension source with no revision when `extension-ref` is empty, +# landing on whatever the source's default branch currently is rather +# than a released extension version (verified by reading +# crates/homeboy-core/src/extension/lifecycle/{mod,install_sources}.rs at +# homeboy v0.383.0). Each job is pinned to the release tag for the +# extension IT ACTUALLY DECLARES, not the previous candidate SHA reused +# across all three jobs regardless of which extension a job needs: +# - php/figma declare `wordpress` (see their homeboy.json) → pinned to +# `wordpress-v3.48.6`, whose peeled commit +# (7f28a979517a96e003d0510d64bc5139c259837d) is exactly the earlier +# candidate SHA — same content, now referenced by its released tag. +# - javascript declares `nodejs` (see packages/blocks-engine/homeboy.json) +# → pinned to `nodejs-v3.7.4`, this repo's own extension, not the +# wordpress tag the previous candidate SHA happened to also contain a +# valid (but non-current) snapshot of. jobs: javascript: - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2.19.1 with: component: packages/blocks-engine - action-ref: b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc - extension-ref: 7f28a979517a96e003d0510d64bc5139c259837d + action-ref: v2.19.1 + extension-ref: nodejs-v3.7.4 prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk @@ -41,11 +72,11 @@ jobs: php: needs: javascript if: ${{ !cancelled() }} - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2.19.1 with: component: php-transformer - action-ref: b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc - extension-ref: 7f28a979517a96e003d0510d64bc5139c259837d + action-ref: v2.19.1 + extension-ref: wordpress-v3.48.6 prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk @@ -59,11 +90,11 @@ jobs: figma: needs: php if: ${{ !cancelled() }} - uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2.19.1 with: component: figma-transformer - action-ref: b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc - extension-ref: 7f28a979517a96e003d0510d64bc5139c259837d + action-ref: v2.19.1 + extension-ref: wordpress-v3.48.6 prepared-ref: trunk dry-run: ${{ inputs.dry-run || false }} release-branch: trunk diff --git a/docs/release-components.md b/docs/release-components.md index 9b0d78e32..f8c071f7a 100644 --- a/docs/release-components.md +++ b/docs/release-components.md @@ -45,41 +45,71 @@ The separate `php-transformer-dev-trunk.yml` workflow is a temporary, credentialed compatibility bridge for consumers of the mirror's `trunk` branch. It has no tag path. Its header documents the exact single homeboy-action invocation that replaces it and the one thing still blocking -that replacement: a released Homeboy CLI tag containing `homeboy git -subtree` (see the dependency table below). Do not replace it with a -hand-rolled `homeboy git subtree` invocation plus manual ssh-agent/known-hosts -setup in the meantime — that reintroduces the same consumer-owned credential -handling this bridge exists to retire, without the supported `ssh-key` / -`ssh-known-hosts` contract the native invocation gets from the action. +that replacement — not a missing subcommand anymore, see below. Do not +replace it with a hand-rolled `homeboy git subtree` invocation plus manual +ssh-agent/known-hosts setup in the meantime — that reintroduces the same +consumer-owned credential handling this bridge exists to retire, without the +supported `ssh-key` / `ssh-known-hosts` contract the native invocation gets +from the action. ## Dependency activation checklist -The workflow pins these released, immutable revisions: +The workflow pins these released, immutable revisions (every SHA verified by +fetching the tag directly and checking `^{commit}` equality, not assumed +from the tag name): -| Capability | Repository | Pinned revision | Release | +| Capability | Repository | Pinned tag | Peeled commit | | --- | --- | --- | --- | -| Component-scoped reusable release, publisher SSH handoff, native `git` operation routing | `Extra-Chill/homeboy-action` | `b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc` | `v2.19.0` | -| Composer release refresh (`release.update_dependency`) | `Extra-Chill/homeboy-extensions` | `7f28a979517a96e003d0510d64bc5139c259837d` | `wordpress-v3.48.6` | +| Component-scoped reusable release, publisher SSH handoff, native `git` operation routing | `Extra-Chill/homeboy-action` | `v2.19.1` | `d9c6d0ee1560612f55645b4b94d0f45ae7dba9b3` (contains v2.19.0's `b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc` plus homeboy-action#490, #491) | +| `nodejs` extension for the `packages/blocks-engine` job | `Extra-Chill/homeboy-extensions` | `nodejs-v3.7.4` | `52d3ecffec1ffbb98ef68e3539e1da1b85a14e8e` | +| `wordpress` extension for the `php-transformer`/`figma-transformer` jobs | `Extra-Chill/homeboy-extensions` | `wordpress-v3.48.6` | `7f28a979517a96e003d0510d64bc5139c259837d` (composer release refresh, `release.update_dependency`) | -One capability remains unreleased and is **not** pinned to anything because -there is nothing released to pin: native Git subtree publication -(`homeboy git subtree`, and the release pipeline's own `release.subtree` -step). It was implemented in `Extra-Chill/homeboy#14851` (closing -`Extra-Chill/homeboy#14837`) and merged to the CLI's `main` branch, but as of -this change no released Homeboy tag contains it — confirmed by downloading -the actual latest release binary (`v0.382.0`) and running `homeboy git -subtree --help`, which reports "unrecognized subcommand". The Homeboy CLI -version this workflow uses is intentionally never pinned here (the -homeboy-action `version` input defaults to `latest`), so the `php` release -job and the dev-trunk mirror will both start working the moment Homeboy -cuts a release containing that commit — no change to this repository is -needed when that happens. Until then, `php-transformer`'s `release.subtree` -config in its `homeboy.json` deserializes as an unrecognized field against -the currently released CLI (confirmed with `homeboy release php-transformer ---dry-run` against `v0.382.0`, which reads the rest of the manifest and -fails only on the expected non-`trunk`-branch preflight guard) and is not -consulted, so an `--apply` publish through this workflow will not perform a -native subtree split until a Homeboy release contains `#14851`. +`extension-ref` is required on every job, not optional: reading Homeboy +v0.383.0's own source +(`crates/homeboy-core/src/extension/lifecycle/{mod,install_sources}.rs`) +shows that when `extension-ref` is empty, `install_for_component` clones the +extension source with no revision — the source repository's current default +branch tip, not a released version. The previous revision of this workflow +pinned all three jobs to the same `wordpress` release commit regardless of +which extension each job actually declares; `javascript` now correctly pins +to `nodejs`'s own release tag instead. + +Native Git subtree publication (`homeboy git subtree`, implemented in +`Extra-Chill/homeboy#14851`) shipped in Homeboy `v0.383.0` and is no longer +missing. This was verified behaviorally, not by CLI `--help` shape: the +released `v0.383.0` binary was downloaded and run against a disposable +bare-repository fixture reproducing this repository's `homeboy.json` +`release.subtree` schema. Preview mutates nothing; `--apply` publishes a +tree byte-identical to the source subtree; a re-run is idempotent; +`--branch-only` correctly excludes tag publication (tag publication itself +works correctly when the flag is omitted and `--version` is supplied); a +`fast_forward` `branch_policy` correctly refuses to force-push over +divergent mirror history instead of silently overwriting it; and publishing +one component's subtree never touches a sibling component's mirror. + +**New residual blocker, found by that same verification**: `homeboy git +subtree` in v0.383.0 has a reproducible bug in its own result serialization +on the success path only. Every invocation that actually performs the +subtree split-and-push correctly — preview and `--apply` alike — still exits +non-zero afterward with `{"success": false, "exit_code": 1, "diagnostics": +{"code": "internal.json_error", ...}}`. The underlying git operation was +confirmed to succeed in every case by inspecting the destination ref +directly; pointing the same command at a genuinely broken remote instead +produces a normal, correctly serialized failure result (`git.command_failed`, +exit code 20), isolating the bug to success-path serialization specifically. +`homeboy-action`'s `scripts/operations/run-operations.sh` (which routes +`commands: git subtree ...`) has no special case for this: it maps any +nonzero `homeboy` exit code straight to a failed step. Because of this, +`php-transformer`'s `release.subtree` config in `homeboy.json` is consulted +by the currently released CLI (the schema-mismatch problem from the prior +revision of this document is gone), but a real `php` release `--apply` +through `release.yml` that reaches the `release.subtree` step, and the +dev-trunk mirror workflow if switched to the native invocation today, would +both risk reporting failure even on a successful publish. This repository +does not work around that by hand-rolling exit-code suppression around a +Homeboy command; the fix belongs upstream in Homeboy's result serialization. +The dev-trunk workflow therefore keeps its working shell-based bridge (see +its header) until a released Homeboy tag fixes this. Figma's existing inline archive route remains usable. A consumer that wants Figma coordinates uses `homeboy release resolve` against this monorepo's From 1dd990d0f36bb1762739340f5d3bb60658cc6160 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Mon, 21 Sep 2026 23:49:19 -0400 Subject: [PATCH 5/5] fix(release): adopt native subtree mirror workflow --- .../workflows/php-transformer-dev-trunk.yml | 90 +-------- .github/workflows/release.yml | 2 +- docs/release-components.md | 180 +++++++----------- php-transformer/README.md | 2 +- .../docs/consumer-prs/packaging.md | 9 +- .../tools/packagist-split/backfill.sh | 45 ++--- .../tools/packagist-split/split-ref.sh | 23 --- 7 files changed, 109 insertions(+), 242 deletions(-) delete mode 100755 php-transformer/tools/packagist-split/split-ref.sh diff --git a/.github/workflows/php-transformer-dev-trunk.yml b/.github/workflows/php-transformer-dev-trunk.yml index ebeb8b59f..3ab57fac4 100644 --- a/.github/workflows/php-transformer-dev-trunk.yml +++ b/.github/workflows/php-transformer-dev-trunk.yml @@ -1,57 +1,5 @@ name: PHP Transformer dev-trunk mirror -# Temporary compatibility bridge for Packagist dev-trunk consumers. The -# target replacement is one homeboy-action invocation with no consumer -# ssh-agent, key handling, known-hosts writing, or `git push`: -# -# - uses: Extra-Chill/homeboy-action@v2.19.1 -# with: -# component: php-transformer -# commands: git subtree php-transformer ${{ github.sha }} --apply --branch-only -# ssh-key: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} -# ssh-known-hosts: | -# github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl -# ssh-require-known-hosts: true -# -# Both prior blockers are gone: homeboy-action's native `git` operation -# routing shipped in v2.19.0 (Extra-Chill/homeboy-action#488), and -# `homeboy git subtree` itself shipped in Homeboy v0.383.0 -# (Extra-Chill/homeboy#14851) — confirmed by downloading that exact released -# binary and running it against a disposable bare-repository fixture: preview -# mutates nothing, `--apply` publishes a tree byte-identical to the source -# subtree, a re-run is idempotent, `--branch-only` correctly excludes tag -# publication (and, separately, tag publication works when it's not passed), -# a `fast_forward` branch_policy correctly refuses to force-push over -# divergent mirror history, and sibling components (figma-transformer) are -# never touched by a php-transformer publish or vice versa. -# -# The remaining blocker is a new one found during that same verification, -# not a shape/config problem: v0.383.0's `homeboy git subtree` has a -# reproducible bug in its OWN result serialization on the SUCCESS path only. -# Every invocation that actually performs the git subtree split-and-push -# correctly (preview and apply both) still exits non-zero afterward with -# `{"success": false, "exit_code": 1, "diagnostics": {"code": -# "internal.json_error", "message": "JSON error", "details": {"context": -# "serialize response", "error": "git command output payload must serialize -# as an object"}}}` — confirmed the underlying push/tag operation itself -# genuinely succeeded in every case (mirror ref inspected directly after each -# run) and that this is specific to the success path: pointing the same -# command at a broken remote produces a normal, correctly serialized -# `git.command_failed` / exit_code 20 failure result instead. homeboy-action's -# `scripts/operations/run-operations.sh` (routes `commands: git subtree ...`) -# has no special case for this — it maps any nonzero `homeboy` exit code -# straight to a failed step (`RESULTS+={cmd: "fail"}`, `any-failed=true`). -# Switching this workflow to the invocation above today would therefore turn -# a currently-working, correctly-reporting bridge into one that silently -# still publishes the mirror correctly but reports every single run as a -# failed CI job. Move to the native invocation once a released Homeboy tag -# fixes `git subtree` success-path result serialization; until then this -# shell-based bridge remains the only path with a CI status that reflects -# reality, and must not be replaced by a hand-rolled `homeboy git subtree` -# invocation with manual ssh-agent/known-hosts setup, which would just -# reintroduce the same consumer-owned credential handling this bridge exists -# to retire while ALSO breaking CI status reporting. - on: push: branches: @@ -64,8 +12,6 @@ permissions: contents: read concurrency: - # Share the release workflow's lock so a release commit cannot race the - # compatibility mirror update. group: component-release cancel-in-progress: false @@ -76,32 +22,12 @@ jobs: if: github.repository == 'Automattic/blocks-engine' steps: - - uses: actions/checkout@v4 + - uses: Extra-Chill/homeboy-action@v2.19.1 with: - fetch-depth: 0 - - - name: Configure mirror SSH auth - env: - DEPLOY_KEY: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} - run: | - if [ -z "$DEPLOY_KEY" ]; then - echo "PHP_TRANSFORMER_MIRROR_DEPLOY_KEY secret is not configured" >&2 - exit 1 - fi - mkdir -p ~/.ssh - printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/mirror_deploy_key - chmod 600 ~/.ssh/mirror_deploy_key - printf '%s\n' \ - 'github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl' \ - 'github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=' \ - 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=' \ - >> ~/.ssh/known_hosts - - - name: Split and push dev-trunk - env: - GIT_SSH_COMMAND: ssh -i ~/.ssh/mirror_deploy_key -o IdentitiesOnly=yes - MIRROR_URL: git@github.com:Automattic/blocks-engine-php-transformer.git - run: | - set -euo pipefail - split_sha=$(php-transformer/tools/packagist-split/split-ref.sh "$GITHUB_SHA") - git push "$MIRROR_URL" "${split_sha}:refs/heads/trunk" + component: php-transformer + version: 0.383.4 + commands: git subtree php-transformer ${{ github.sha }} --apply --branch-only + ssh-key: ${{ secrets.PHP_TRANSFORMER_MIRROR_DEPLOY_KEY }} + ssh-known-hosts: | + github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl + ssh-require-known-hosts: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad32e6745..d3a2f04cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,7 +46,7 @@ concurrency: # landing on whatever the source's default branch currently is rather # than a released extension version (verified by reading # crates/homeboy-core/src/extension/lifecycle/{mod,install_sources}.rs at -# homeboy v0.383.0). Each job is pinned to the release tag for the +# Homeboy v0.383.4). Each job is pinned to the release tag for the # extension IT ACTUALLY DECLARES, not the previous candidate SHA reused # across all three jobs regardless of which extension a job needs: # - php/figma declare `wordpress` (see their homeboy.json) → pinned to diff --git a/docs/release-components.md b/docs/release-components.md index f8c071f7a..811e919a6 100644 --- a/docs/release-components.md +++ b/docs/release-components.md @@ -1,118 +1,80 @@ # Component Releases -The `release.yml` workflow runs the three package components in dependency order -on `trunk`. The jobs are intentionally serialized because Homeboy may commit -version and changelog updates; each later job must resolve the trunk tip -published by the preceding job. +The `release.yml` workflow runs the three package components in dependency +order on `trunk`. Jobs are serialized because Homeboy may commit version and +changelog updates; each later job resolves the refreshed trunk tip. -## Native publication +## Native Publication - `@automattic/blocks-engine` publishes through the Node.js Homeboy extension. -- `php-transformer` creates its WordPress release archive and splits the - repository `php-transformer/` prefix natively to - `Automattic/blocks-engine-php-transformer`. - Its source `php-transformer-vX.Y.Z` tag becomes `vX.Y.Z` in the mirror. The old - tag-triggered shell split workflow is removed. +- `php-transformer` creates its WordPress release archive and publishes the + `php-transformer/` prefix to + `Automattic/blocks-engine-php-transformer`. Its source + `php-transformer-vX.Y.Z` tag becomes `vX.Y.Z` in the mirror. - `figma-transformer` retains GitHub tag/archive release while registry - publication is explicitly disabled until standalone Packagist repository - provisioning in #1364 exists. - -For enabled publishers, publication is not optional. Registry credentials are -owned by the corresponding Homeboy extensions. The PHP subtree destination -also needs a Git write credential: the existing -`PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` secret is mapped to the reusable -workflow's generic `PUBLISH_SSH_KEY` secret input, paired with pinned GitHub -host keys and `ssh-require-known-hosts: true`. - -Blocks Engine does not notify Static Site Importer or any other consumer. -The repositories are decoupled: this workflow performs no -`repository_dispatch`, carries no dispatch token, and has no SSI-specific -configuration. A consumer that needs the published coordinates resolves them -itself — `homeboy release resolve` against this repository's tags for the -Figma archive route, or the mirror repository / npm registry directly for -PHP Transformer and `@automattic/blocks-engine`. - -The component manifests explicitly declare their publisher extensions: -`nodejs` for the npm package and `wordpress` for the PHP/Figma release -archives. The npm publisher itself runs `npm publish`, but the pinned -homeboy-action reusable workflow currently exposes neither `NPM_TOKEN` nor an -OIDC-enabled npm publishing setup. The caller grants `id-token: write` in -preparation for npm trusted publishing, but npm publication remains blocked -until homeboy-action adds that credential contract (or its documented -equivalent). No raw consumer-side npm publish step is added here. - -The separate `php-transformer-dev-trunk.yml` workflow is a temporary, -credentialed compatibility bridge for consumers of the mirror's `trunk` -branch. It has no tag path. Its header documents the exact single -homeboy-action invocation that replaces it and the one thing still blocking -that replacement — not a missing subcommand anymore, see below. Do not -replace it with a hand-rolled `homeboy git subtree` invocation plus manual -ssh-agent/known-hosts setup in the meantime — that reintroduces the same -consumer-owned credential handling this bridge exists to retire, without the -supported `ssh-key` / `ssh-known-hosts` contract the native invocation gets -from the action. - -## Dependency activation checklist - -The workflow pins these released, immutable revisions (every SHA verified by -fetching the tag directly and checking `^{commit}` equality, not assumed -from the tag name): + publication remains disabled until standalone Packagist provisioning in + #1364 exists. + +The `php-transformer-dev-trunk.yml` workflow mirrors the package's `trunk` +branch with one supported `homeboy-action` invocation. Credentials and host +verification are owned by the action; the consumer does not configure an +ssh-agent, write keys or known hosts, or run `git push`. + +Blocks Engine does not notify Static Site Importer or any other consumer. The +repositories are decoupled: consumers resolve published coordinates from the +mirror repository, npm registry, or release tags themselves. + +## Pins + +The workflow uses released tags, verified by resolving each tag's peeled +commit directly: | Capability | Repository | Pinned tag | Peeled commit | | --- | --- | --- | --- | -| Component-scoped reusable release, publisher SSH handoff, native `git` operation routing | `Extra-Chill/homeboy-action` | `v2.19.1` | `d9c6d0ee1560612f55645b4b94d0f45ae7dba9b3` (contains v2.19.0's `b2ff19a4e71772a1d6b376b7c0bf00d8ef3415cc` plus homeboy-action#490, #491) | -| `nodejs` extension for the `packages/blocks-engine` job | `Extra-Chill/homeboy-extensions` | `nodejs-v3.7.4` | `52d3ecffec1ffbb98ef68e3539e1da1b85a14e8e` | -| `wordpress` extension for the `php-transformer`/`figma-transformer` jobs | `Extra-Chill/homeboy-extensions` | `wordpress-v3.48.6` | `7f28a979517a96e003d0510d64bc5139c259837d` (composer release refresh, `release.update_dependency`) | - -`extension-ref` is required on every job, not optional: reading Homeboy -v0.383.0's own source -(`crates/homeboy-core/src/extension/lifecycle/{mod,install_sources}.rs`) -shows that when `extension-ref` is empty, `install_for_component` clones the -extension source with no revision — the source repository's current default -branch tip, not a released version. The previous revision of this workflow -pinned all three jobs to the same `wordpress` release commit regardless of -which extension each job actually declares; `javascript` now correctly pins -to `nodejs`'s own release tag instead. - -Native Git subtree publication (`homeboy git subtree`, implemented in -`Extra-Chill/homeboy#14851`) shipped in Homeboy `v0.383.0` and is no longer -missing. This was verified behaviorally, not by CLI `--help` shape: the -released `v0.383.0` binary was downloaded and run against a disposable -bare-repository fixture reproducing this repository's `homeboy.json` -`release.subtree` schema. Preview mutates nothing; `--apply` publishes a -tree byte-identical to the source subtree; a re-run is idempotent; -`--branch-only` correctly excludes tag publication (tag publication itself -works correctly when the flag is omitted and `--version` is supplied); a -`fast_forward` `branch_policy` correctly refuses to force-push over -divergent mirror history instead of silently overwriting it; and publishing -one component's subtree never touches a sibling component's mirror. - -**New residual blocker, found by that same verification**: `homeboy git -subtree` in v0.383.0 has a reproducible bug in its own result serialization -on the success path only. Every invocation that actually performs the -subtree split-and-push correctly — preview and `--apply` alike — still exits -non-zero afterward with `{"success": false, "exit_code": 1, "diagnostics": -{"code": "internal.json_error", ...}}`. The underlying git operation was -confirmed to succeed in every case by inspecting the destination ref -directly; pointing the same command at a genuinely broken remote instead -produces a normal, correctly serialized failure result (`git.command_failed`, -exit code 20), isolating the bug to success-path serialization specifically. -`homeboy-action`'s `scripts/operations/run-operations.sh` (which routes -`commands: git subtree ...`) has no special case for this: it maps any -nonzero `homeboy` exit code straight to a failed step. Because of this, -`php-transformer`'s `release.subtree` config in `homeboy.json` is consulted -by the currently released CLI (the schema-mismatch problem from the prior -revision of this document is gone), but a real `php` release `--apply` -through `release.yml` that reaches the `release.subtree` step, and the -dev-trunk mirror workflow if switched to the native invocation today, would -both risk reporting failure even on a successful publish. This repository -does not work around that by hand-rolling exit-code suppression around a -Homeboy command; the fix belongs upstream in Homeboy's result serialization. -The dev-trunk workflow therefore keeps its working shell-based bridge (see -its header) until a released Homeboy tag fixes this. - -Figma's existing inline archive route remains usable. A consumer that wants -Figma coordinates uses `homeboy release resolve` against this monorepo's -`figma-transformer-v*` tags before invoking its own Composer dependency -updater; a one-item inline Composer repository cannot discover versions -itself. +| Component release workflow and native Git operation routing | `Extra-Chill/homeboy-action` | `v2.19.1` | `d9c6d0ee1560612f55645b4b94d0f45ae7dba9b3` | +| `nodejs` extension | `Extra-Chill/homeboy-extensions` | `nodejs-v3.7.4` | `c9a119745e5d961dccb0206e1231faa01c62f0ae` | +| `wordpress` extension | `Extra-Chill/homeboy-extensions` | `wordpress-v3.48.6` | `7f28a979517a96e003d0510d64bc5139c259837d` | + +Each `extension-ref` matches the extension declared by that component. The +pin is required because an empty extension revision floats to the extension +repository's default branch rather than a released version. + +## Subtree Verification + +Native Git subtree publication (`homeboy git subtree`) is available in +released Homeboy `v0.383.4`. Verification used the actual release +binary and disposable local bare repositories. Preview exited 0 without +creating refs; `--apply` exited 0 and published a tree identical to the +source subtree; a re-run reported `already-identical`; `--branch-only` left +tags untouched; normal mode published the configured tag; and sibling +components remained excluded. The success-path serialization failure found +in Homeboy `v0.383.0` is fixed in `v0.383.4`. + +The historical `backfill.sh` remains only as disaster recovery after loss of +the mirror repository. It calls the same native Homeboy subtree command for +each historical `php-transformer-v*` source tag and for `origin/trunk`; routine +trunk mirroring uses the workflow above. + +## Registry Credentials + +The PHP subtree destination uses the existing +`PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` repository secret through the action's +`ssh-key` input. GitHub host verification is pinned in the workflow. + +Npm publication for the JavaScript package remains blocked on the upstream +credential contract tracked in `Extra-Chill/homeboy-action#492`. No released +contract report was available while updating this PR, so no raw consumer-side +`npm publish` step is added. After an action release carries that contract, +operators must provision the repository's npm publishing credential or trusted +publishing configuration according to that released contract. + +## Activation Checklist + +- `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` in `Automattic/blocks-engine`, with + write access to `Automattic/blocks-engine-php-transformer`. +- `HOMEBOY_APP_ID` and `HOMEBOY_APP_PRIVATE_KEY` are optional; provision them + only if release commits and tags should use a GitHub App identity. +- Npm credentials remain blocked until the released action contract exists. + +No merge, release, publication, tag, or secret change is performed by this +repository change. diff --git a/php-transformer/README.md b/php-transformer/README.md index 01812e6f7..2ceea282f 100644 --- a/php-transformer/README.md +++ b/php-transformer/README.md @@ -238,7 +238,7 @@ Operator-only release checklist after the release-readiness PR merges: - Update downstream wrapper/product PRs from review-only constraints to tagged constraints. - Decide whether GitHub Releases are part of this first package publication path. -Homeboy owns the local release preflight for this package through `php-transformer/homeboy.json`. Run Homeboy with `php-transformer/` as the component path so release automation detects the monorepo path and uses `php-transformer-v*` tags, without adding wrapper-package names to this package metadata. +Homeboy owns the local release preflight and subtree publication for this package through `php-transformer/homeboy.json`. Run Homeboy with `php-transformer/` as the component path so release automation detects the monorepo path and uses `php-transformer-v*` tags, without adding wrapper-package names to this package metadata. Recommended post-merge dry-run: diff --git a/php-transformer/docs/consumer-prs/packaging.md b/php-transformer/docs/consumer-prs/packaging.md index 681a741e7..408d09aec 100644 --- a/php-transformer/docs/consumer-prs/packaging.md +++ b/php-transformer/docs/consumer-prs/packaging.md @@ -128,8 +128,13 @@ Before any downstream PR merges, replace draft branch constraints with a tagged `automattic/blocks-engine-php-transformer` is published to Packagist through an automated subtree split. The read-only mirror repository is `Automattic/blocks-engine-php-transformer`; Packagist indexes the mirror, never the monorepo. -- `.github/workflows/php-transformer-split.yml` splits `php-transformer/` with `git subtree split` and pushes to the mirror: trunk pushes update the mirror `trunk` (installable as `dev-trunk`), and `php-transformer-vX.Y.Z` tag pushes create translated `vX.Y.Z` mirror tags, which become Packagist releases. -- The workflow authenticates with a deploy key on the mirror, stored as the `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` Actions secret in `Automattic/blocks-engine`. +- `.github/workflows/php-transformer-dev-trunk.yml` invokes released Homeboy + `git subtree` support to update the mirror `trunk` (installable as + `dev-trunk`). Component releases publish translated `vX.Y.Z` mirror tags + through the native `release.subtree` configuration. +- The action authenticates with a deploy key on the mirror, stored as the + `PHP_TRANSFORMER_MIRROR_DEPLOY_KEY` Actions secret in + `Automattic/blocks-engine`. - `php-transformer/.gitattributes` keeps dist archives lean. The dist carries what a consumer can call plus the contracts describing what those calls return, so `src/`, `resources/`, and `docs/contracts/` ship while the diagnostic and parity harness does not. Harness code lives in `dev/`, mapped through `autoload-dev` rather than the shipped `autoload` block, so an installed package cannot resolve it even where a Composer path repository copies the working tree verbatim. - `tests/packaging/dist-shape.php` asserts that shape against `git archive` directly, since no other suite observes export-ignore: parity and contract runs read the working tree, and the install proof's path repository copies it wholesale. - The mirror is not a support surface: issues stay disabled there, `composer.json` `support.issues` points at `Automattic/blocks-engine`, and the package README banner marks the mirror read-only. diff --git a/php-transformer/tools/packagist-split/backfill.sh b/php-transformer/tools/packagist-split/backfill.sh index 69f5346fe..5f57d340d 100755 --- a/php-transformer/tools/packagist-split/backfill.sh +++ b/php-transformer/tools/packagist-split/backfill.sh @@ -1,58 +1,55 @@ #!/usr/bin/env bash -# Backfill the php-transformer subtree-split mirror with every historical -# php-transformer-v* release tag (translated to vX.Y.Z), then push the +# Backfill the php-transformer subtree mirror with every historical +# php-transformer-v* release tag (translated to vX.Y.Z), then publish the # current origin/trunk split to the mirror's trunk. # # Usage: -# php-transformer/tools/packagist-split/backfill.sh [--dry-run] [mirror-url] +# php-transformer/tools/packagist-split/backfill.sh [--dry-run] # # Run from anywhere inside a full (non-shallow) clone of # Automattic/blocks-engine with origin/trunk fetched. Safe to re-run: subtree -# splits are deterministic, so re-runs reproduce identical mirror history. -# This is also the disaster-recovery path if the mirror repository is lost. +# Homeboy subtree publications are deterministic, so re-runs reproduce +# identical mirror history. This is also the disaster-recovery path if the +# mirror repository is lost. set -euo pipefail DRY_RUN=0 -MIRROR_URL="git@github.com:Automattic/blocks-engine-php-transformer.git" for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=1 ;; - *) MIRROR_URL="$arg" ;; + *) echo "Usage: $0 [--dry-run]" >&2; exit 64 ;; esac done cd "$(git rev-parse --show-toplevel)" -split_ref="php-transformer/tools/packagist-split/split-ref.sh" if [ "$(git rev-parse --is-shallow-repository)" = "true" ]; then - echo "Refusing to run from a shallow clone: subtree split needs full history." >&2 + echo "Refusing to run from a shallow clone: historical subtree publication needs full history." >&2 exit 1 fi -refspecs=() - +tag_count=0 while IFS= read -r tag; do + tag_count=$((tag_count + 1)) version="v${tag#php-transformer-v}" - split_sha=$("$split_ref" "$tag") - echo "${tag} -> ${version} (${split_sha})" - refspecs+=("${split_sha}:refs/tags/${version}") + echo "${tag} -> ${version}" + if [ "$DRY_RUN" = "1" ]; then + homeboy git subtree php-transformer "$tag" --path php-transformer --version "${version#v}" + else + homeboy git subtree php-transformer "$tag" --apply --path php-transformer --version "${version#v}" + fi done < <(git tag --list 'php-transformer-v*' | sort -V) -if [ "${#refspecs[@]}" -eq 0 ]; then +if [ "$tag_count" -eq 0 ]; then echo "No php-transformer-v* tags found." >&2 exit 1 fi -trunk_split=$("$split_ref" origin/trunk) -echo "origin/trunk -> trunk (${trunk_split})" -refspecs+=("${trunk_split}:refs/heads/trunk") - -# Branch instead of expanding a possibly-empty array: "${empty[@]}" under -# set -u is an "unbound variable" error on macOS's default bash 3.2. +echo "origin/trunk -> trunk" if [ "$DRY_RUN" = "1" ]; then - echo "DRY RUN: no refs will be updated on ${MIRROR_URL}" - git push --dry-run "$MIRROR_URL" "${refspecs[@]}" + echo "DRY RUN: no refs will be updated" + homeboy git subtree php-transformer origin/trunk --path php-transformer --branch-only else - git push "$MIRROR_URL" "${refspecs[@]}" + homeboy git subtree php-transformer origin/trunk --apply --path php-transformer --branch-only fi diff --git a/php-transformer/tools/packagist-split/split-ref.sh b/php-transformer/tools/packagist-split/split-ref.sh deleted file mode 100755 index 9204d5b67..000000000 --- a/php-transformer/tools/packagist-split/split-ref.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# Split php-transformer/ out of the given source rev and print the resulting -# commit SHA, after verifying the split tree is byte-identical to the source -# subtree. Shared by the CI mirror workflow and backfill.sh. -# -# Usage: php-transformer/tools/packagist-split/split-ref.sh -set -euo pipefail - -if [ "$#" -ne 1 ]; then - echo "Usage: split-ref.sh " >&2 - exit 64 -fi - -source_rev="$1" -split_sha=$(git subtree split --prefix=php-transformer "$source_rev") -src_tree=$(git rev-parse "${source_rev}:php-transformer") -split_tree=$(git rev-parse "${split_sha}^{tree}") -if [ "$src_tree" != "$split_tree" ]; then - echo "Tree mismatch for ${source_rev}: split ${split_tree} != source ${src_tree}" >&2 - exit 1 -fi - -echo "$split_sha"