Skip to content

[AI-6917] Smarter ddev release branch tag command#23860

Open
AAraKKe wants to merge 11 commits into
masterfrom
aarakke/ddev-release-tag-smarter
Open

[AI-6917] Smarter ddev release branch tag command#23860
AAraKKe wants to merge 11 commits into
masterfrom
aarakke/ddev-release-tag-smarter

Conversation

@AAraKKe
Copy link
Copy Markdown
Collaborator

@AAraKKe AAraKKe commented May 28, 2026

What does this PR do?

Adds --release/-r, --ref, --rc N, and --yes/-y to ddev release branch tag. The command can now target any release branch from anywhere, tag an arbitrary commit instead of the branch tip, pin the RC number explicitly, and skip yes/no prompts. Tagging operates against origin/<branch> directly — the user's local branches and worktree are never touched.

Motivation

The previous command required the user to be on the release branch and only chose between --rc and --final. Tagging a specific commit (e.g. when later backports should not be included), filling in a missed RC number, or releasing from a different branch all required manual git work outside the tool.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Add `qa/required` if this PR needs QA validation, or `qa/skip-qa` if it does not. Exactly one of the two is required.
  • If you need to backport this PR to another branch, you can add the `backport/` label to the PR and it will automatically open a backport PR once this one is merged

This PR has been created and validated using the paired-review skill from agent-integrations. Ready for human review.

…`--yes`

The command previously required the user to be on the release branch and only
let them pick between `--rc` and `--final`. The new flags make it possible to
tag a release branch from anywhere, pin or auto-suggest the RC number, and tag
an arbitrary commit instead of the branch tip:

- `--release/-r <X.Y[.x]>` selects the target release branch; if not on it, a
  worktree is created at `.worktrees/release-tag/<branch>` from
  `origin/<branch>` and torn down on success.
- `--ref <commit>` tags the given commit (must be an ancestor of
  `origin/<branch>`) instead of the branch tip.
- `--rc` accepts an optional value: `--rc` alone auto-suggests, `--rc N` pins.
  Warns when N skips ahead of the next available RC.
- `--yes/-y` skips all yes/no confirms.
@AAraKKe AAraKKe added the qa/skip-qa Automatically skip this PR for the next QA label May 28, 2026
@dd-octo-sts dd-octo-sts Bot added the ddev label May 28, 2026
@datadog-prod-us1-3
Copy link
Copy Markdown

datadog-prod-us1-3 Bot commented May 28, 2026

Pipelines  Tests  Code Coverage

Fix all issues with BitsAI

⚠️ Warnings

🚦 6 Pipeline jobs failed

PR All | test / j06ca546 / SNMP   View in Datadog   GitHub Actions

🔄 Retry job. This looks flaky and may succeed on retry. NameResolutionError: Failed to resolve 'ddintegrations.blob.core.windows.net' during SNMP test execution.

PR All | test / j46da136 / JBoss_WildFly   View in Datadog   GitHub Actions

🔄 Retry job. This looks flaky and may succeed on retry. Could not resolve hostname: ddintegrations.blob.core.windows.net

PR All | test / j5a9585a / IBM ACE   View in Datadog   GitHub Actions

🔄 Retry job. This looks flaky and may succeed on retry. Could not resolve host: ddintegrations.blob.core.windows.net, which caused tar extraction to fail due to missing files.

View all 6 failed jobs.

🧪 20 Tests failed in 1 job

PR All | run   GitHub Actions

test_bulk_table from test_check.py   View in Datadog (Fix with Cursor)
HTTPSConnectionPool(host=&#39;ddintegrations.blob.core.windows.net&#39;, port=443): Max retries exceeded with url: /snmp/cisco-3850.snmprec (Caused by NameResolutionError(&#34;HTTPSConnection(host=&#39;ddintegrations.blob.core.windows.net&#39;, port=443): Failed to resolve &#39;ddintegrations.blob.core.windows.net&#39; ([Errno -2] Name or service not known)&#34;))
test_cast_metrics from test_check.py   View in Datadog (Fix with Cursor)
HTTPSConnectionPool(host=&#39;ddintegrations.blob.core.windows.net&#39;, port=443): Max retries exceeded with url: /snmp/cisco-3850.snmprec (Caused by NameResolutionError(&#34;HTTPSConnection(host=&#39;ddintegrations.blob.core.windows.net&#39;, port=443): Failed to resolve &#39;ddintegrations.blob.core.windows.net&#39; ([Errno -2] Name or service not known)&#34;))

View all 20 test failures

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 93.36%
Overall Coverage: 87.51% (+0.12%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: ed3825b | Docs | Datadog PR Page | Give us feedback!

AAraKKe added 2 commits May 28, 2026 16:22
- `GitRepository.tag()` now uses its `message` parameter instead of the
  tag name (pre-existing bug: `--message` was always set to `value`).
- Compute `current_branch` once and thread it into `_resolve_target_branch`
  to avoid the duplicate `git rev-parse` subprocess call.
- Move worktree setup inside the try/finally so any failure between
  worktree creation and teardown still triggers the inspection warning.
- Narrow the OSError catch to just `git.tag` / `git.push` so other failures
  surface with their own attributable messages.
- `_branch_exists_on_origin` no longer swallows OSError as "branch missing"
  — split into `_ensure_branch_on_origin` that distinguishes a real
  ls-remote failure from an empty result.
- Confirmation prompt for `--ref` shows the resolved commit SHA, not the
  raw user input, so the user can verify what `rev-parse` resolved to.
- Renamed `_create_or_refresh_worktree` to `_create_worktree` (it only
  adds) and the failure message now hints at the manual cleanup command.
- Added an `exit_code` assertion to `test_no_worktree_when_already_on_target_branch`.
- Input-validation helpers now raise `click.UsageError` so mypy follows
  the `NoReturn` semantics; updated the two affected tests to assert
  non-zero exit instead of exit code 1 (UsageError exits with 2).
- Drop unused `app` arg from `_parse_rc_value` (it raises `click.UsageError`
  directly and never needed application state).
- Include the underlying git error text in the `--ref` failure messages
  for both `rev-parse` and `merge-base --is-ancestor`.
- Remove dead post-`range` guard in `_warn_on_rc_gap`.
- Annotate `_check_open_prs` return as `list[PullRequest]`.
- Rename changelog entry from `.added` to `.changed`: the new confirm
  prompt on a release branch is a behavior change for non-interactive
  callers that piped a single `y`.
- Replace the `capture.return_value` fixture default with a side_effect
  callable that dispatches on the first argument, so new code paths that
  call `capture()` without an explicit override don't silently inherit
  the `ls-remote` payload.
- Use a `_make_ref_dispatcher` helper in `--ref` tests so the mocked
  responses are keyed by subcommand instead of call order.
- Extract `_worktree_subcommands(git, sub)` helper to dedupe the
  worktree-call assertions.
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Major version bump
The changelog type changed or removed was used in this Pull Request, so the next release will bump major version. Please make sure this is a breaking change, or use the fixed or added type instead.

AAraKKe added 3 commits May 28, 2026 17:09
- `--final` + `--rc` now raises `click.UsageError` (exit code 2) to match
  the other CLI-validation errors in the command.
- Change the `RC_AUTO` sentinel to a private, unguessable string so
  `--rc auto` is no longer silently equivalent to bare `--rc`.
- Merge `_resolve_tag_ref`'s two try/except blocks; the branch that
  picks the abort message keys off whether `commit_sha` was bound,
  which avoids the possibly-unbound warning some type-checkers emit.
- `_warn_on_rc_gap` now uses `app.display_warning` to match the other
  new helpers in this PR.
- Test additions: full call-shape assertions on the `worktree add` /
  `worktree remove` invocations, plus a new test that covers the
  `_create_worktree` abort path and its manual-cleanup hint.
The command body had four logical phases interleaved with the worktree
lifecycle. Each phase is now its own helper:

- `_prepare_working_dir` decides between pull-in-place and worktree creation,
  returns `(git, working_dir, worktree_created)`.
- `_warn_if_build_agent_yaml_stale` surfaces the recovery warning and
  returns whether the workflow dispatch is needed.
- `_compute_new_tag` owns the existing-tag collection, RC resolution,
  and all RC validations (bounds, exists, gap, backward move).
- `_confirm_and_push_tag` owns the open-PR check, the final confirm
  prompt, and the `git tag` / `git push` pair.

The main `tag()` body shrinks from ~108 to ~35 lines and reads top-to-bottom
as the steps of a tagging operation. The worktree `try/finally` stays in
the main body — a future change can replace it with a context manager once
worktree management is consolidated across the codebase.
@AAraKKe AAraKKe marked this pull request as ready for review May 28, 2026 17:26
@AAraKKe AAraKKe requested a review from a team as a code owner May 28, 2026 17:26
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c1f88891e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ddev/src/ddev/cli/release/branch/tag.py Outdated
app.display_waiting(f'Creating worktree at `{worktree_path}` from `origin/{branch}`...')
worktree_path.parent.ensure_dir_exists()
try:
app.repo.git.run('worktree', 'add', '-B', branch, str(worktree_path), f'origin/{branch}')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid resetting the user's local release branch

When --release is run from any branch other than the release branch and the user already has a local 7.56.x branch that is not checked out, this git worktree add -B ... origin/7.56.x resets that local branch to the remote tip before tagging. I checked git worktree add -h, where -B <branch> is described as “create or reset a branch”, so local-only commits on that branch lose their branch ref even though the command is only preparing a temporary worktree; use a detached worktree or a throwaway branch name instead.

Useful? React with 👍 / 👎.

The previous design checked out the target branch in a worktree
under `.worktrees/release-tag/<branch>/` and ran the tag command
from there. The worktree was only ever needed to read
`.gitlab/build_agent.yaml` from the right commit, since every
other step (listing tags, validating `--ref`, creating and pushing
the tag) keys off ref/object names that any clone resolves the
same way.

Read the YAML via `git show <ref>:.gitlab/build_agent.yaml` and
pass an explicit `ref` to `git tag` (`origin/<target>` by default,
the resolved commit when `--ref` is supplied). The user's local
checkout and branches are never touched.

Side effects:
- Drops `WORKTREE_BASE`, `_create_worktree`, `_remove_worktree`,
  `_prepare_working_dir`, and the worktree `try/finally`.
- Closes a silent-data-loss bug: `git worktree add -B <branch>`
  force-resets a pre-existing local `<branch>` to the remote tip,
  orphaning any local-only commits on it.
- Reads the YAML at the actual commit being tagged when `--ref` is
  supplied, rather than at the branch tip.
- Removes the implicit `git pull origin <branch>` that the
  no-worktree path used to do — tagging no longer mutates local
  branch state under any flag combination.
@AAraKKe
Copy link
Copy Markdown
Collaborator Author

AAraKKe commented May 28, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

AAraKKe added 2 commits May 28, 2026 20:14
- Move the `< 1` guard into `_parse_rc_value` so `--rc 0` is rejected
  via `click.UsageError` (exit code 2) like every other `--rc` parse
  failure, instead of via `app.abort` (exit code 1) after the prompt
  branch. The interactive-prompt branch still aborts on `< 1`, which
  is now the only path that reaches that check.
- Add `git` as an explicit parameter to `_ensure_branch_on_origin` to
  match the other git-using helpers.
- Tighten the worktree-regression guard in tests: filter both `run`
  and `capture` calls, since `git worktree` operations can go through
  either entry point.
- `_make_ref_dispatcher` now delegates to `_capture_dispatch` for
  subcommands it doesn't explicitly handle, removing the duplicated
  `ls-remote` literal.
@dd-octo-sts
Copy link
Copy Markdown
Contributor

dd-octo-sts Bot commented May 29, 2026

Validation Report

All 21 validations passed.

Show details
Validation Description Status
agent-reqs Verify check versions match the Agent requirements file
ci Validate CI configuration and code coverage settings
codeowners Validate every integration has a CODEOWNERS entry
config Validate default configuration files against spec.yaml
dep Verify dependency pins are consistent and Agent-compatible
http Validate integrations use the HTTP wrapper correctly
imports Validate check imports do not use deprecated modules
integration-style Validate check code style conventions
jmx-metrics Validate JMX metrics definition files and config
labeler Validate PR labeler config matches integration directories
legacy-signature Validate no integration uses the legacy Agent check signature
license-headers Validate Python files have proper license headers
licenses Validate third-party license attribution list
metadata Validate metadata.csv metric definitions
models Validate configuration data models match spec.yaml
openmetrics Validate OpenMetrics integrations disable the metric limit
package Validate Python package metadata and naming
qa-label Validate the pull request declares whether it needs QA for the next Agent release
readmes Validate README files have required sections
saved-views Validate saved view JSON file structure and fields
version Validate version consistency between package and changelog

View full run

@AAraKKe AAraKKe changed the title Smarter ddev release branch tag command [AI-6917] Smarter ddev release branch tag command May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ddev qa/skip-qa Automatically skip this PR for the next QA team/agent-integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant