Skip to content

Commit 0771ce1

Browse files
Consolidate backport workflow onto ddev release port-commit (#24470)
* Consolidate backport workflow onto ddev release port-commit Replace the tibdex/backport action with a ddev-driven backport that cherry-picks the merged commit per backport/<base> label and resets per-branch regenerated files (.in-toto and now .deps/) to the target branch, so dependency lockfiles don't carry over from the source branch. - Generalize port-commit's .in-toto handling to a path list covering .deps/. - Guard the interactive confirm prompts with app.interactive so the tool runs unattended in CI. - Rework backport-pr.yml to loop the backport/* labels and call ddev --no-interactive release port-commit per base. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add changelog entry Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Anchor .deps/ match to repo root and extract port-commit confirm helper - Match `.deps/` with startswith so nested paths (e.g. vendor/foo.deps/) are not treated as regenerated; `.in-toto` stays a substring match for its *.in-toto.link files. - Extract `confirm_or_abort` so the interactive confirmation guard lives in one place instead of being duplicated at both prompt sites. - Rename the preserve-step tests to `generated_files` and parametrize the in-toto/deps reset case. * Pass merge SHA directly to port-commit in backport workflow We already have the merge commit SHA from the triggering event; passing it directly avoids resolving PR-<n> back through the GitHub API to the same commit, and drops the dependency on the API's lazily-computed merge_commit_sha. * Minimize ambient token scope and tighten backport label gate The backport job's branch push, PR creation, and PR comments all authenticate with the scoped octo-sts token, so the ambient GITHUB_TOKEN no longer needs contents/pull-requests write; drop it to read to shrink blast radius under pull_request_target. Gate the labeled-event run on startsWith('backport/') instead of contains('backport') so unrelated labels that merely include the substring (e.g. no-backport) don't spin up the privileged job. * Guard per-base fetch and empty PR-URL default in backport workflow A backport/<base> label pointing at a branch that does not exist on origin made the per-base git fetch fail under set -e, aborting the whole step so no other backport/* label was processed. Guard the fetch: comment, mark the run failed, and continue to the next base. When port-commit succeeds but the new PR is not yet listed, gh pr list --jq '.[0].url' printed the literal 'null', which is non-empty and produced an 'opened: null' comment. Default the jq expression to an empty string so the comment is skipped instead. * Condense backport workflow comments to one line each Compress the multi-line inline comments in backport-pr.yml to single lines per the repo's one-line-comment convention. No behavioral change. * Extract comment_pr helper in backport workflow Collapse the three near-identical gh pr comment call sites into a single comment_pr helper, centralizing the best-effort (|| true) semantics in one place. No behavioral change. * Document stale backport branch cleanup in workflow The open-PR pre-check only detects an OPEN backport PR, so a branch left by a run that failed before opening the PR (or whose PR was later closed) is not auto-cleaned and port-commit's push is rejected non-fast-forward. Document the limitation at the pre-check and, in the failure comment, tell the operator to delete the stale branch and retry. Manual cleanup is the accepted remedy. * Redesign backport automation around port-commit --from-pr Move all backport label parsing, per-base looping, idempotency, and error aggregation into ddev release port-commit --from-pr, backed by unit tests. Slim backport-pr.yml to a should_run gate job plus a gated backport job, and use ddev config override in place of the repo-pointing config set calls. * Group port-commit options and type the backport results Carry the shared CLI knobs (branch prefix/suffix, labels, no-pr, draft, verify, dry-run) in a frozen PortOptions instead of threading them through build_port_plan, resolve_port_plan, and run_backport_from_pr as a repeated seven-parameter tail. Replace the stringly-typed per-base result tuple with a BackportStatus StrEnum and a BackportResult dataclass, so the overall pass/fail check is an enum comparison rather than a string match. Extract the per-base loop into _port_to_each_base, collapse target_branch plus its explicit flag into a single override_base, and drop run_backport_from_pr's token check in favour of a message override on _resolve_pr. Add a summary-panel test covering the mixed ported/skipped/failed case and register the not-found PR mock explicitly. * Rename check_github_user to require_github_user and tighten fake client typing require_github_user names the get-or-abort contract accurately whether the returned user is used or discarded. Document that the existing-backport-PR check filters on head=owner:branch and therefore relies on the branch being pushed to origin, as PushStep does; a fork-based push flow would silently stop matching. Mirror the real client's Literal['open','closed','all'] on the fake's list_pull_requests state param so test call sites get the same type feedback. * Reject --branch-suffix in multi-base --from-pr and mark dry-run ports as planned An explicit --branch-suffix is shared across every base derived from --from-pr, so all bases resolve to the same head branch. After the first opens a PR, the rest are silently skipped as already-ported. Reject the combination unless --target-branch pins a single base. Dry-run ports recorded BackportStatus.PORTED even though nothing was pushed, so the summary implied work happened. Add a PLANNED status used only under --dry-run. * Pin backport workflow checkout to master so ddev has --from-pr Under pull_request_target the default checkout ref is the PR's base branch. A PR merged into an older release branch would install a local ddev lacking --from-pr. Pinning ref: master decouples the ddev version from the target branch; port-commit still fetches origin/<base> per target for the cherry-pick. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> 6fd380c
1 parent 190c7df commit 0771ce1

2 files changed

Lines changed: 3 additions & 3 deletions

File tree

ddev/cli/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@
144144
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--message</code>, <code>-m</code></td> <td>text</td> <td>The changelog text</td> <td>None</td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h4 id=ddev-release-changelog-show>ddev release changelog show<a class=headerlink href=#ddev-release-changelog-show title="Permanent link">&para;</a></h4> <p>Print the section of TARGET's CHANGELOG.md that corresponds to VERSION.</p> <p>The output is the markdown content between the <code>## VERSION</code> heading and the next <code>##</code> heading, with surrounding blank lines stripped. Useful for populating GitHub release notes from the just-built changelog.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release changelog show [OPTIONS] TARGET VERSION
145145
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--file</code>, <code>-f</code></td> <td>file</td> <td>Write the extracted section to this file (overwrites if it exists) instead of stdout</td> <td>None</td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-list>ddev release list<a class=headerlink href=#ddev-release-list title="Permanent link">&para;</a></h3> <p>Show all versions of an integration.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release list [OPTIONS] INTEGRATION
146146
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-make>ddev release make<a class=headerlink href=#ddev-release-make title="Permanent link">&para;</a></h3> <p>Perform a set of operations needed to release checks:</p> <ul> <li>update the version in <code>__about__.py</code></li> <li>update the changelog</li> <li>update the <code>requirements-agent-release.txt</code> file</li> <li>update in-toto metadata</li> <li>commit the above changes</li> </ul> <p>You can release everything at once by setting the check to <code>all</code>.</p> <p>If you run into issues signing: - Ensure you did <code>gpg --import &lt;YOUR_KEY_ID&gt;.gpg.pub</code></p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release make [OPTIONS] CHECKS...
147-
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--version</code></td> <td>text</td> <td>N/A</td> <td>None</td> </tr> <tr> <td><code>--end</code></td> <td>text</td> <td>N/A</td> <td>None</td> </tr> <tr> <td><code>--new</code></td> <td>boolean</td> <td>Ensure versions are at 1.0.0</td> <td><code>False</code></td> </tr> <tr> <td><code>--skip-sign</code></td> <td>boolean</td> <td>Skip the signing of release metadata</td> <td><code>False</code></td> </tr> <tr> <td><code>--sign-only</code></td> <td>boolean</td> <td>Only sign release metadata</td> <td><code>False</code></td> </tr> <tr> <td><code>--exclude</code></td> <td>text</td> <td>Comma-separated list of checks to skip</td> <td>None</td> </tr> <tr> <td><code>--allow-master</code></td> <td>boolean</td> <td>Allow ddev to commit directly to master. Forbidden for core.</td> <td><code>False</code></td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-port-commit>ddev release port-commit<a class=headerlink href=#ddev-release-port-commit title="Permanent link">&para;</a></h3> <p>Backport a commit onto a target branch.</p> <p>Cherry-picks COMMIT_OR_PR onto <code>--target-branch</code> (default <code>master</code>) on a new branch named <code>&lt;github-user&gt;/&lt;prefix&gt;-&lt;sha[:10]&gt;-&lt;suffix&gt;</code>, preserving <code>.in-toto</code> files from the target branch so package signatures stay intact. Pushes the branch and, unless <code>--no-pr</code> is set, opens a pull request titled <code>[Backport] &lt;subject&gt;</code> and labeled with <code>--pr-labels</code>.</p> <p>COMMIT_OR_PR accepts: a full 40-character commit SHA, a PR number (e.g. <code>23703</code>), an explicit <code>PR-&lt;number&gt;</code> token, or a GitHub PR URL. Pure-digit inputs are tried as a PR first when a GitHub token is configured, and fall back to commit resolution on 404. If omitted, the current HEAD commit is used after confirmation.</p> <p>The GitHub user for the branch prefix is taken from <code>ddev config</code> (<code>github.user</code>) or the <code>DD_GITHUB_USER</code> / <code>GITHUB_USER</code> / <code>GITHUB_ACTOR</code> environment variables.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release port-commit [OPTIONS] COMMIT_OR_PR
148-
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>-t</code>, <code>--target-branch</code></td> <td>text</td> <td>Target branch to port to.</td> <td><code>master</code></td> </tr> <tr> <td><code>-p</code>, <code>--branch-prefix</code></td> <td>text</td> <td>Branch name prefix.</td> <td><code>port</code></td> </tr> <tr> <td><code>-s</code>, <code>--branch-suffix</code></td> <td>text</td> <td>Branch name suffix. Defaults to <code>to-&lt;target-branch&gt;</code>.</td> <td>None</td> </tr> <tr> <td><code>-l</code>, <code>--pr-labels</code></td> <td>text</td> <td>Comma-separated PR labels.</td> <td><code>qa/skip-qa</code></td> </tr> <tr> <td><code>--no-pr</code></td> <td>boolean</td> <td>Don't create a pull request.</td> <td><code>False</code></td> </tr> <tr> <td><code>--draft</code></td> <td>boolean</td> <td>Open the PR as a draft.</td> <td><code>False</code></td> </tr> <tr> <td><code>--verify</code></td> <td>boolean</td> <td>Run commit hooks (skipped by default).</td> <td><code>False</code></td> </tr> <tr> <td><code>--dry-run</code></td> <td>boolean</td> <td>Print every step instead of executing it.</td> <td><code>False</code></td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-show>ddev release show<a class=headerlink href=#ddev-release-show title="Permanent link">&para;</a></h3> <p>To avoid GitHub's public API rate limits, you need to set <code>github.user</code>/<code>github.token</code> in your config file or use the <code>DD_GITHUB_USER</code>/<code>DD_GITHUB_TOKEN</code> environment variables.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release show [OPTIONS] COMMAND [ARGS]...
147+
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--version</code></td> <td>text</td> <td>N/A</td> <td>None</td> </tr> <tr> <td><code>--end</code></td> <td>text</td> <td>N/A</td> <td>None</td> </tr> <tr> <td><code>--new</code></td> <td>boolean</td> <td>Ensure versions are at 1.0.0</td> <td><code>False</code></td> </tr> <tr> <td><code>--skip-sign</code></td> <td>boolean</td> <td>Skip the signing of release metadata</td> <td><code>False</code></td> </tr> <tr> <td><code>--sign-only</code></td> <td>boolean</td> <td>Only sign release metadata</td> <td><code>False</code></td> </tr> <tr> <td><code>--exclude</code></td> <td>text</td> <td>Comma-separated list of checks to skip</td> <td>None</td> </tr> <tr> <td><code>--allow-master</code></td> <td>boolean</td> <td>Allow ddev to commit directly to master. Forbidden for core.</td> <td><code>False</code></td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-port-commit>ddev release port-commit<a class=headerlink href=#ddev-release-port-commit title="Permanent link">&para;</a></h3> <p>Backport a commit onto a target branch.</p> <p>Cherry-picks COMMIT_OR_PR onto <code>--target-branch</code> (default <code>master</code>) on a new branch named <code>&lt;github-user&gt;/&lt;prefix&gt;-&lt;sha[:10]&gt;-&lt;suffix&gt;</code>, preserving <code>.in-toto</code> and <code>.deps/</code> files from the target branch so package signatures stay intact. Pushes the branch and, unless <code>--no-pr</code> is set, opens a pull request titled <code>[Backport] &lt;subject&gt;</code> and labeled with <code>--pr-labels</code>.</p> <p>COMMIT_OR_PR accepts: a full 40-character commit SHA, a PR number (e.g. <code>23703</code>), an explicit <code>PR-&lt;number&gt;</code> token, or a GitHub PR URL. Pure-digit inputs are tried as a PR first when a GitHub token is configured, and fall back to commit resolution on 404. If omitted, the current HEAD commit is used after confirmation.</p> <p>Pass <code>--from-pr &lt;number&gt;</code> instead of COMMIT_OR_PR to backport a merged PR to every <code>backport/&lt;base&gt;</code> label on it, deriving the commit and target branches from the PR. A base whose backport PR already exists (open, merged, or closed) is skipped, so re-runs are idempotent. Give <code>--target-branch</code> alongside <code>--from-pr</code> to restrict the backport to that one branch.</p> <p>The GitHub user for the branch prefix is taken from <code>ddev config</code> (<code>github.user</code>) or the <code>DD_GITHUB_USER</code> / <code>GITHUB_USER</code> / <code>GITHUB_ACTOR</code> environment variables.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release port-commit [OPTIONS] COMMIT_OR_PR
148+
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>-t</code>, <code>--target-branch</code></td> <td>text</td> <td>Target branch to port to.</td> <td><code>master</code></td> </tr> <tr> <td><code>-p</code>, <code>--branch-prefix</code></td> <td>text</td> <td>Branch name prefix.</td> <td><code>port</code></td> </tr> <tr> <td><code>-s</code>, <code>--branch-suffix</code></td> <td>text</td> <td>Branch name suffix. Defaults to <code>to-&lt;target-branch&gt;</code>.</td> <td>None</td> </tr> <tr> <td><code>-l</code>, <code>--pr-labels</code></td> <td>text</td> <td>Comma-separated PR labels.</td> <td><code>qa/skip-qa</code></td> </tr> <tr> <td><code>--no-pr</code></td> <td>boolean</td> <td>Don't create a pull request.</td> <td><code>False</code></td> </tr> <tr> <td><code>--draft</code></td> <td>boolean</td> <td>Open the PR as a draft.</td> <td><code>False</code></td> </tr> <tr> <td><code>--verify</code></td> <td>boolean</td> <td>Run commit hooks (skipped by default).</td> <td><code>False</code></td> </tr> <tr> <td><code>--dry-run</code></td> <td>boolean</td> <td>Print every step instead of executing it.</td> <td><code>False</code></td> </tr> <tr> <td><code>--from-pr</code></td> <td>integer</td> <td>Backport a merged PR to every <code>backport/&lt;base&gt;</code> label on it, deriving the commit and target branches from the PR. Mutually exclusive with COMMIT_OR_PR.</td> <td>None</td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-show>ddev release show<a class=headerlink href=#ddev-release-show title="Permanent link">&para;</a></h3> <p>To avoid GitHub's public API rate limits, you need to set <code>github.user</code>/<code>github.token</code> in your config file or use the <code>DD_GITHUB_USER</code>/<code>DD_GITHUB_TOKEN</code> environment variables.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release show [OPTIONS] COMMAND [ARGS]...
149149
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h4 id=ddev-release-show-changes>ddev release show changes<a class=headerlink href=#ddev-release-show-changes title="Permanent link">&para;</a></h4> <p>Show all the pending PRs for a given check.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release show changes [OPTIONS] CHECK
150150
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--tag-pattern</code></td> <td>text</td> <td>The regex pattern for the format of the tag. Required if the tag doesn't follow semver</td> <td>None</td> </tr> <tr> <td><code>--tag-prefix</code></td> <td>text</td> <td>Specify the prefix of the tag to use if the tag doesn't follow semver</td> <td>None</td> </tr> <tr> <td><code>--dry-run</code>, <code>-n</code></td> <td>boolean</td> <td>Run the command in dry-run mode</td> <td><code>False</code></td> </tr> <tr> <td><code>--since</code></td> <td>text</td> <td>The git ref to use instead of auto-detecting the tag to view changes since</td> <td>None</td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h4 id=ddev-release-show-ready>ddev release show ready<a class=headerlink href=#ddev-release-show-ready title="Permanent link">&para;</a></h4> <p>Show all the checks that can be released.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release show ready [OPTIONS]
151151
</code></pre></div> <p><strong>Options:</strong></p> <table> <thead> <tr> <th>Name</th> <th>Type</th> <th>Description</th> <th>Default</th> </tr> </thead> <tbody> <tr> <td><code>--quiet</code>, <code>-q</code></td> <td>boolean</td> <td>N/A</td> <td><code>False</code></td> </tr> <tr> <td><code>--help</code></td> <td>boolean</td> <td>Show this message and exit.</td> <td><code>False</code></td> </tr> </tbody> </table> <h3 id=ddev-release-stats>ddev release stats<a class=headerlink href=#ddev-release-stats title="Permanent link">&para;</a></h3> <p>A collection of tasks to generate reports about releases.</p> <p><strong>Usage:</strong></p> <div class=highlight><pre><span></span><code>ddev release stats [OPTIONS] COMMAND [ARGS]...

search/search_index.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)