8000 Issue commands should parse args early by williammartin · Pull Request #10811 · cli/cli · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Issue commands should parse args early #10811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 22, 2025

Conversation

williammartin
Copy link
Member
@williammartin williammartin commented Apr 16, 2025

Description

Relates to: #10714

While working on #10785 I was frequently getting tripped up by the fact that we don't know which host the feature detector should be targeting, because we don't know the repo that is being targeted. This becomes a lot easier if we host arg parsing up to where it normally lives (PreRun) and give the run what it actually needs (IssueNumbers and a BaseRepo).

It also hoists conditionals up the stack (i.e. is there a base repo or not) so they don't have to be carried around mentally.

This should also free us from passing the detector through in many commands that need no feature detection because they don't use projects, since we can hoist that up too: https://github.com/cli/cli/pull/10785/files. For an example of this see: da1e788#diff-a408a9bdb3a5377b3d4f319497bbdfd42b739de41e6ff3645c2698dde0cc3e8aR129-R132

"github.com/cli/cli/v2/pkg/set"
"golang.org/x/sync/errgroup"
)

func ParseIssuesFromArgs(args []string) ([]int, o.Option[ghrepo.Interface], error) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is really the same logic as IssueFromArgWithFields without actually fetching the PR, and trying to indicate a little bit more with the types what valid states exist.

@@ -142,6 +221,37 @@ type PartialLoadError struct {
error
}

func FindIssuesOrPRs(httpClient *http.Client, repo ghrepo.Interface, issueNumbers []int, fields []string) ([]*api.Issue, error) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the content of IssuesFromArgWithFields without the parse step, so it operates directly on issue numbers and an already determined repo.

@@ -72,7 +72,19 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman
// support `-R, --repo` override
opts.BaseRepo = f.BaseRepo

opts.SelectorArgs = args
issueNumbers, baseRepo, err := shared.ParseIssuesFromArgs(args)
Copy link
Member Author

Choose a reason for hiding this comment

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

This is really where the magic happens, we move arg parsing into the pre-run, which means we can inject the correct issue numbers and base repo.

Since we now have the base repo, we are able to construct a featuredetection.Detector early to address things like https://github.com/cli/cli/pull/10785/files#r2046543890

Copy link
Member

Choose a reason for hiding this comment

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

thought: looking at this, I was wondering how gh issue edit handled multiple URLs from different repositories, which apparently raises an error they need to be in the same repo:

$ gh issue edit https://github.com/tinyfists/gh-nonsense-internal/issues/37 https://github.com/tinyfists/gh-nonsense/issues/7 --title "Same same but different"
multiple issues must be in same repo: found "tinyfists/gh-nonsense", expected "tinyfists/gh-nonsense-internal"

that really isn't apparent from the --help usage docs.

return issueNumber, o.None[ghrepo.Interface](), nil
}

type issueLocator struct {
Copy link
Member Author

Choose a reason for hiding this comment

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

Bit meh. Might remove in favour of two returns, it's just that I don't want to indicate a valid state that one might be present but the other isn't.

Copy link
Member

Choose a reason for hiding this comment

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

thought: if this was exported, then I might feel differently, but as-is I think I'm in favor of 2 returns just because of its limited use in parseIssueFromArg. 🤷

}

// tryParseIssueFromURL tries to parse an issue number and repo from a URL.
func tryParseIssueFromURL(maybeURL string) o.Option[issueLocator] {
Copy link
Member Author

Choose a reason for hiding this comment

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

tryParseIssueLocator maybe. Might just remove the type though.

return o.None[issueLocator]()
}

if u.Scheme != "https" && u.Scheme != "http" {
Copy link
Member Author

Choose a reason for hiding this comment

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

Bare numbers parse as valid URL, so I guess this is checking against that. Probably needs a comment.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, please.

Comment on lines +182 to +186
baseRepo, err := opts.BaseRepo()
if err != nil {
return err
}

Copy link
Member
@andyfeller andyfeller Apr 16, 2025

Choose a reason for hiding this comment

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

question: how do these changes reduce the need for passing featuredetection down to findIssueOrPR for GHES v1 projects fetching?

making sure I'm connecting the dots, all of the RunE changes before we get here potentially allow us to resolve the base repo, which is needed for featuredetection initialization as mentioned here in cli/cli#10785.

however, I'm having difficulty imagining how this reduces the work required to pass it down the stack to get to shared.findIssueOrPR() 🤔

Copy link
Member Author
@williammartin williammartin Apr 16, 2025

Choose a reason for hiding this comment

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

That's a great question, which is lead by what's on the branch. I want to push the decision about inclusion of projects and projectCards up the stack so that instead of "adding it and then later removing it deep down in the stack", we just don't add it.

The advantage to this is that all uses of v1 projects become very clear when we come to remove them. It also avoids having some dependencies passed around that are only used in rare cases, and the mental load of carrying that round.

I think it'll become clearer if I take this work just a little further.

Copy link
Member Author

Choose a reason for hiding this comment

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

The advantage to this is that all uses of v1 projects become very clear when we come to remove them. It also avoids having some dependencies passed around that are only used in rare cases, and the mental load of carrying that round.

Driving home this point, while looking at the work on this branch from November, I had to work my way back up each call stack to be sure that I understood all the places feature detection was being wired through, and whether it was having some kind of effect.

Copy link
Member

Choose a reason for hiding this comment

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

I think it'll become clearer if I take this work just a little further.

Yeah, I would like to see the changes as I'm having a hard time imagining how we avoid passing anything new down the stack.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ack, will do.

Copy link
Member Author

Choose a reason for hiding this comment

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

629A
Copy link
Member

Choose a reason for hiding this comment

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

Oh yeah, muuuuuuuuch better! ✨ 💯

Copy link
Member

Choose a reason for hiding this comment

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

thought: I wonder if there should be an initializer for fd instead of copy pasta the same logic everywhere.

Comment on lines +49 to +52
// add the issue number to the list
issueNumbers[i] = issueNumber
Copy link
Member

Choose a reason for hiding this comment

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

General question; what about duplicate issue numbers? We can drop them here, or let the invoked command handle it. I think the latter is the current behaviour.

Copy link
Member Author

Choose a reason for hiding this comment

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

With regards this PR I have no opinion. Currently I think you'll just end up editing the same issue twice, interactively, for issue edit.

@williammartin williammartin force-pushed the wm/issue-pr-base-repo-resolution branch 4 times, most recently from 1558a93 to 112701e Compare April 17, 2025 13:26
@williammartin williammartin force-pushed the wm/issue-pr-base-repo-resolution branch from 112701e to cfa90a2 Compare April 17, 2025 13:27
@williammartin williammartin marked this pull request as ready for review April 17, 2025 13:28
@williammartin williammartin requested a review from a team as a code owner April 17, 2025 13:28
@williammartin williammartin requested a review from babakks April 17, 2025 13:28
@@ -37,15 +38,41 @@ func NewCmdComment(f *cmdutil.Factory, runF func(*prShared.CommentableOptions) e
Args: cobra.ExactArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) error {
opts.RetrieveCommentable = func() (prShared.Commentable, ghrepo.Interface, error) {
// TODO wm: more testing
Copy link
Member Author

Choose a reason for hiding this comment

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

This block is totally untested. No BA4A t sure how much I want to tackle this for the extra confidence. TBD.

@williammartin williammartin changed the title Issue edit early arg parsing Issue commands should parse args early Apr 17, 2025
Copy link
Member
@babakks babakks left a comment

Choose a reason for hiding this comment

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

Great PR! Thanks for changes/improvements. 🙏

tests := []struct {
name string
input string
expectedissueNumber int
Copy link
Member

Choose a reason for hiding this comment

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

s/issue/Issue?

Comment on lines +82 to +83
// TODO: remember why we do this
cmd.Flags().BoolP("help", "x", false, "")
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather see an explanation like: "this is to avoid collision with -h usage for anything other than --help; like -h for hostname". Also, what if the command under test had an x flag/option? Can't we use a safer shorthand instead of x, like _ or ?? I haven't tested these chars with Cobra but as I checked its code, seems like there's no restriction on the chars.

Copy link
Member Author

Choose a reason for hiding this comment

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

Tbh I just didn't remember why we were doing this, but I think you've remembered for me. I think we should probably extract something shared like avoidHelpCollision(cmd).


func issueNumberFromOpts(t *testing.T, v any) int {
rv := reflect.ValueOf(v)
field := rv.FieldByName("IssueNumber")
Copy link
Member

Choose a reason for hiding this comment

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

I know this probably is the best way of doing this, so I'm just thinking out loud and these are just half-baked and over-engineered solutions. Feel free to ignore with no reply.

I'm thinking of two possible solutions to avoid binding to field names

1. Field tags

We can loop through the fields and pick the one with the right tag. We're still binding to a string literal, but the field name is free of any restriction.

type FooOption struct {
    BaseRepo    func() (ghrepo.Interface, error) `ghopt:"baseRepo"`
    IssueNumber int                              `ghopt:"issueNumber"`
}

2. Custom funcs

We can to add two func parameters to TestArgParsing to be responsible for extracting issue number and base repo:

  • extractIssueNumber: func(opt T) int
  • extractBaseRepo: func(opt T) ghrepo.Interface

If the passed argument is nil, we can use the current PR's implementation as a fallback. This way TestArgParsing is flexible enough for various situations.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't like 1 at all because it makes changes to production code to satisfy the test.

Re: 2, I don't really want commands to deviate from the pattern without good reason, so having configurability isn't an advantage to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

Note because Go generics are not very powerful, we can't constrain T to struct { IssueNumber int }, so there's no way to get type safety through this. Reflection is the only way.

Copy link
Member

Choose a reason for hiding this comment

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

True. Unless we introduce a getter function that we can abstract behind an interface (like IssueNumberRequired, or something).

Copy link
Member Author

Choose a reason for hiding this comment

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

Totally, and I don't want to do that either for the same reason as 1.

Comment on lines +24 to +26
func TestNewCmdDelete(t *testing.T) {
argparsetest.TestArgParsing(t, NewCmdDelete)
}
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for this!

Comment on lines +47 to +73
{
name: "issue number argument",
args: "451 --repo owner/repo",
want: LockOptions{
IssueNumber: 451,
},
},
{
name: "argument is hash prefixed number",
// Escaping is required here to avoid what I think is shellex treating it as a comment.
args: "\\#451 --repo owner/repo",
want: LockOptions{
IssueNumber: 451,
},
},
{
name: "argument is a URL",
args: "https://github.com/cli/cli/issues/451",
want: LockOptions{
IssueNumber: 451,
},
},
{
name: "argument cannot be parsed to an issue",
args: "unparseable",
wantErr: "invalid issue format: \"unparseable\"",
},
Copy link
Member

Choose a reason for hiding this comment

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

Why not re-using TestArgParsing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably can, I think I didn't because unlock requires parentCmd to be set: https://github.com/cli/cli/pull/10811/files/55d3b1eaa4e27acad346707ab91c9eb0e4a32a71#diff-c341e36bd18bb73313231c0bda8d126954f03bd766117351db33a1dba406a185R467.

Happy to revisit lock and keep unlock separate.

return o.None[issueLocator]()
}

if u.Scheme != "https" && u.Scheme != "http" {
Copy link
Member

Choose a reason for hiding this comment

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

Yes, please.

wantIssue: 13,
wantProjects: "",
wantRepo: "https://example.org/OWNER/REPO",
behavior: "when given a URL that isn't an issue or PR url, errors",
Copy link
Member

Choose a reason for hiding this comment

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

we need one more test case to verify inputs like /cli/cli/issues/999 cause error (url.Parse parses that successfully).

@williammartin
Copy link
Member Author

In light of the fact that this PR sits at the base of a large stack that I don't want to rebase, after talking with @babakks, I am going to merge this PR and address the comment in a follow up.

@williammartin williammartin merged commit 3fc362b into trunk Apr 22, 2025
16 checks passed
@williammartin williammartin deleted the wm/issue-pr-base-repo-resolution branch April 22, 2025 13:02
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request May 10, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [cli/cli](https://github.com/cli/cli) | minor | `v2.69.0` -> `v2.72.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>cli/cli (cli/cli)</summary>

### [`v2.72.0`](https://github.com/cli/cli/releases/tag/v2.72.0): GitHub CLI 2.72.0

[Compare Source](cli/cli@v2.71.2...v2.72.0)

#### :accessibility: Accessibility public preview

This release marks the public preview of several accessibility improvements to the GitHub CLI that have been under development over the past year in partnership with our friends at [Charm](https://github.com/charmbracelet) including:

-   customizable and contrasting colors
-   non-interactive user input prompting
-   text-based spinners

These new experiences are captured in a new `gh a11y` help topic command, which goes into greater detail into the motivation behind each of them as well as opt-in configuration settings / environment variables.

We would like you to share your feedback and join us on this journey through one of [GitHub Accessibility feedback channels](https://accessibility.github.com/feedback)! 🙌

#### What's Changed

##### ✨ Features

-   Introduce `gh accessibility` help topic highlighting GitHub CLI accessibility experiences by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10890
-   \[gh pr view] Support `closingIssuesReferences` JSON field by [@&#8203;iamazeem](https://github.com/iamazeem) in cli/cli#10544

##### 🐛 Fixes

-   Fix expected error output of `TestRepo/repo-set-default` by [@&#8203;aconsuegra](https://github.com/aconsuegra) in cli/cli#10884
-   Ensure accessible password and auth token prompters disable echo mode by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10885
-   Fix: Accessible multiselect prompt respects default selections by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10901

#### New Contributors

-   [@&#8203;aconsuegra](https://github.com/aconsuegra) made their first contribution in cli/cli#10884

**Full Changelog**: cli/cli@v2.71.2...v2.72.0

### [`v2.71.2`](https://github.com/cli/cli/releases/tag/v2.71.2): GitHub CLI 2.71.2

[Compare Source](cli/cli@v2.71.1...v2.71.2)

#### What's Changed

-   Fix pr create when push.default tracking and no merge ref by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10863

**Full Changelog**: cli/cli@v2.71.1...v2.71.2

### [`v2.71.1`](https://github.com/cli/cli/releases/tag/v2.71.1): GitHub CLI 2.71.1

[Compare Source](cli/cli@v2.71.0...v2.71.1)

#### What's Changed

-   Fix pr create when branch name contains slashes by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10859

**Full Changelog**: cli/cli@v2.71.0...v2.71.1

### [`v2.71.0`](https://github.com/cli/cli/releases/tag/v2.71.0): GitHub CLI 2.71.0

[Compare Source](cli/cli@v2.70.0...v2.71.0)

#### What's Changed

##### ✨ Features

-   `gh pr create`: Support Git's `@{push}` revision syntax for determining head ref by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10513
-   Introduce option to opt-out of spinners by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10773
-   Update configuration support for accessible colors by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10820
-   `gh config`: add config settings for accessible prompter and disabling spinner by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10846

##### 🐛 Fixes

-   Fix multi pages search for gh search by [@&#8203;leudz](https://github.com/leudz) in cli/cli#10767
-   Fix: `project` commands use shared progress indicator by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10817
-   Issue commands should parse args early by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10811
-   Feature detect v1 projects on `issue view` by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10813
-   Feature detect v1 projects on non web-mode `issue create` by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10815
-   Feature detect v1 projects on web mode issue create by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10818
-   Feature detect v1 projects on issue edit by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10819

##### 📚 Docs & Chores

-   Refactor Sigstore verifier logic by [@&#8203;malancas](https://github.com/malancas) in cli/cli#10750

##### :dependabot: Dependencies

-   chore(deps): bump github.com/sigstore/sigstore-go from 0.7.1 to 0.7.2 by [@&#8203;dependabot](https://github.com/dependabot) in cli/cli#10787
-   Bump google.golang.org/grpc from 1.71.0 to 1.71.1 by [@&#8203;dependabot](https://github.com/dependabot) in cli/cli#10758

#### New Contributors

-   [@&#8203;leudz](https://github.com/leudz) made their first contribution in cli/cli#10767

**Full Changelog**: cli/cli@v2.70.0...v2.71.0

### [`v2.70.0`](https://github.com/cli/cli/releases/tag/v2.70.0): GitHub CLI 2.70.0

[Compare Source](cli/cli@v2.69.0...v2.70.0)

#### Accessibility

This release contains dark shipped changes that are part of a larger GitHub CLI accessibility preview still under development.  More information about these will be announced later this month including various channels to work with GitHub and GitHub CLI maintainers on shaping these experiences.

##### Ensure table headers are thematically contrasting

[#&#8203;8292](cli/cli#8292) is a long time issue where table headers were difficult to see in terminals with light background.  Ahead of the aforementioned preview, `v2.70.0` has shipped changes that improve the out-of-the-box experience based on terminal background detection.

The following screenshots demonstrate the Mac Terminal using the Basic profile, which responds to user's appearance preferences:

<img width="1512" alt="Screenshot of gh repo list in light background terminal" src="https://github.com/user-attachments/assets/87413dde-eec8-43eb-9c16-dc84f8249ddf" />

<img width="1512" alt="Screenshot of gh repo list in dark background terminal" src="https://github.com/user-attachments/assets/7430b42c-7267-402b-b565-a296beb4d5ea" />

For more information including demos from various official distributions, see [#&#8203;10649](cli/cli#10649).

#### What's Changed

##### ✨ Features

-   Update go-gh and document available sprig funcs by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10680
-   Introducing experimental support for rendering markdown with customizable, accessible colors by [@&#8203;andyfeller](https://github.com/andyfeller) [@&#8203;jtmcg](https://github.com/jtmcg) in cli/cli#10680
-   Ensure table datetime columns have thematic, customizable muted text by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10709
-   Ensure table headers are thematically contrasting by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10649
-   Introduce configuration setting for displaying issue and pull request labels in rich truecolor by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10720
-   Ensure muted text is thematic and customizable by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10737
-   \[gh repo create] Show host name in repo creation prompts by [@&#8203;iamazeem](https://github.com/iamazeem) in cli/cli#10516
-   Introduce accessible prompter for screen readers (preview) by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10710

##### 🐛 Fixes

-   `run list`: do not fail on organization/enterprise ruleset imposed workflows by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10660
-   Implement safeguard for `gh alias delete` test, prevent wiping out GitHub CLI configuration by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#10683
-   Pin third party actions to commit sha by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#10731
-   Fallback to job run logs when step logs are missing by [@&#8203;babakks](https://github.com/babakks) in cli/cli#10740
-   \[gh ext] Fix `GitKind` extension directory path by [@&#8203;iamazeem](https://github.com/iamazeem) in cli/cli#10609
-   Fix job log resolution to skip legacy logs in favour of normal/new ones by [@&#8203;babakks](https://github.com/babakks) in cli/cli#10769

##### 📚 Docs & Chores

-   `./script/sign` cleanup by [@&#8203;iamazeem](https://github.com/iamazeem) in cli/cli#10599
-   Fix typos in CONTRIBUTING.md by [@&#8203;rylwin](https://github.com/rylwin) in cli/cli#10657
-   Improve `gh at verify --help`, document json output by [@&#8203;phillmv](https://github.com/phillmv) in cli/cli#10685
-   Acceptance test issue/pr create/edit with project by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10707
-   Escape dots in regexp pattern in `README.md` by [@&#8203;babakks](https://github.com/babakks) in cli/cli#10742
-   Simplify cosign verification example by not using a regex. by [@&#8203;kommendorkapten](https://github.com/kommendorkapten) in cli/cli#10759
-   Document UNKNOWN STEP in run view by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#10770

##### :dependabot: Dependencies

-   Update github.com/sigstore/sigstore-go to 0.7.1 and fix breaking function change by [@&#8203;malancas](https://github.com/malancas) in cli/cli#10749

#### New Contributors

-   [@&#8203;rylwin](https://github.com/rylwin) made their first contribution in cli/cli#10657

**Full Changelog**: cli/cli@v2.69.0...v2.70.0

</details>

---

### Configuration

📅 **Schedule**: Bran
7CEE
ch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNTkuMCIsInVwZGF0ZWRJblZlciI6IjM5LjI2NC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0