diff --git a/.github/workflows/php-transformer-dev-trunk.yml b/.github/workflows/php-transformer-dev-trunk.yml new file mode 100644 index 000000000..3ab57fac4 --- /dev/null +++ b/.github/workflows/php-transformer-dev-trunk.yml @@ -0,0 +1,33 @@ +name: PHP Transformer dev-trunk mirror + +on: + push: + branches: + - trunk + paths: + - "php-transformer/**" + - ".github/workflows/php-transformer-dev-trunk.yml" + +permissions: + contents: read + +concurrency: + 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: Extra-Chill/homeboy-action@v2.19.1 + with: + 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/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..d3a2f04cb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,101 @@ +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 + id-token: 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. 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.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 +# `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@v2.19.1 + with: + component: packages/blocks-engine + action-ref: v2.19.1 + extension-ref: nodejs-v3.7.4 + prepared-ref: trunk + dry-run: ${{ inputs.dry-run || false }} + release-branch: trunk + secrets: inherit + + php: + needs: javascript + if: ${{ !cancelled() }} + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2.19.1 + with: + component: php-transformer + action-ref: v2.19.1 + extension-ref: wordpress-v3.48.6 + prepared-ref: trunk + dry-run: ${{ inputs.dry-run || false }} + release-branch: trunk + 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: ${{ !cancelled() }} + uses: Extra-Chill/homeboy-action/.github/workflows/release.yml@v2.19.1 + with: + component: figma-transformer + action-ref: v2.19.1 + extension-ref: wordpress-v3.48.6 + 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 new file mode 100644 index 000000000..811e919a6 --- /dev/null +++ b/docs/release-components.md @@ -0,0 +1,80 @@ +# Component Releases + +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 + +- `@automattic/blocks-engine` publishes through the Node.js Homeboy extension. +- `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 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 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/figma-transformer/homeboy.json b/figma-transformer/homeboy.json index 36a743c1c..5eb10dd74 100644 --- a/figma-transformer/homeboy.json +++ b/figma-transformer/homeboy.json @@ -3,6 +3,12 @@ "changelog_target": "CHANGELOG.md", "id": "figma-transformer", "remote_path": "", + "extensions": { + "wordpress": {} + }, + "release": { + "publish": false + }, "version_targets": [ { "file": "VERSION", diff --git a/packages/blocks-engine/homeboy.json b/packages/blocks-engine/homeboy.json index e3c0c27d1..d03f129cf 100644 --- a/packages/blocks-engine/homeboy.json +++ b/packages/blocks-engine/homeboy.json @@ -3,6 +3,12 @@ "changelog_target": "CHANGELOG.md", "id": "blocks-engine", "remote_path": "", + "extensions": { + "nodejs": {} + }, + "release": { + "publish": true + }, "version_targets": [ { "file": "package.json", diff --git a/php-transformer/README.md b/php-transformer/README.md index 24917bce4..2ceea282f 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. @@ -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/homeboy.json b/php-transformer/homeboy.json index 7dadd9550..26de6befe 100644 --- a/php-transformer/homeboy.json +++ b/php-transformer/homeboy.json @@ -3,6 +3,22 @@ "changelog_target": "CHANGELOG.md", "id": "php-transformer", "remote_path": "", + "extensions": { + "wordpress": {} + }, + "release": { + "publish": true, + "subtree": [ + { + "prefix": "php-transformer", + "remote": "git@github.com:Automattic/blocks-engine-php-transformer.git", + "branch": "trunk", + "tag": true, + "tag_template": "v{version}", + "branch_policy": "fast_forward" + } + ] + }, "version_targets": [ { "file": "VERSION", 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"