Commit graph

633 commits

Author SHA1 Message Date
Ross Golder 976a60dc2b Merge branch 'main' into feature/deploy-keys-https 2026-09-09 22:36:52 +00:00
Ross Golder 3e96e3deb5
feat: use upstream gitea.dev/sdk, remove fork replace directive
Upstream gitea/go-sdk#846 added deploy token support to the main
branch, so the fork-specific replace directive is no longer needed.

Co-authored-by: rossigee <ross@golder.org>
2026-09-10 05:36:22 +07:00
Jan Baer 4d09587d4c fix(pulls): report the real reason when a merge is refused (#1107)
Some checks are pending
goreleaser / goreleaser (push) Waiting to run
goreleaser / release-image (push) Waiting to run
## Problem

`tea pr merge <index>` reports the same misleading error for every refusal:

```
failed to merge PR, is it still open?
```

The PR usually *is* still open — `tea pr <index>` shows it as open and lists `Conflicting files` — so the message sends users looking in the wrong direction.

## Root cause

Gitea answers an unmergeable PR with a 405 and a body naming the actual cause. The SDK's `MergePullRequest` is built on `getStatusCode`, which returns only the status code and never calls `statusCodeToErr`, so the body is discarded. tea receives `success=false, err=nil` with no server explanation to pass on, and fell back to guessing that the PR might be closed.

## Changes

- Derive the refusal reason from the pull request when a merge fails: already merged, closed, draft, or not mergeable.
- When the PR looks mergeable but was refused anyway, name the conditions tea cannot observe (required status checks, requested reviews, branch protection) instead of guessing.
- Include the PR index in the error.
- Add table-driven tests for every reason, plus the case where the follow-up PR lookup fails.

The extra API call happens only on the failure path.

Fixes #1022

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1107
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Jan Baer <jan.s.baer@googlemail.com>
2026-09-09 19:15:46 +00:00
Lunny Xiao 16896b5046 Merge branch 'main' into feature/deploy-keys-https 2026-09-08 19:20:49 +00:00
ongolk b2bab268d7 Make tea pulls create honor --output json (#1111)
Some checks failed
goreleaser / goreleaser (push) Has been cancelled
goreleaser / release-image (push) Has been cancelled
## Problem

`tea pulls create` accepts `--output` (the flag parses successfully) but never reads it — the action always prints glamour-rendered markdown regardless of the requested format. That is a trap for anyone scripting the CLI: `tea pr create --output json | jq .url` quietly feeds jq a markdown document.

The current output is also hostile to URL-scraping consumers even without `--output`: glamour autolinks the bare PR URL into an OSC 8 terminal hyperlink, so piped stdout contains

```
\x1b]8;;https://host/owner/repo/pulls/33\x1b\\https://host/owner/repo/pulls/33\x1b]8;;\x1b\\
```

instead of a plain URL (repro: `tea pr create ... | cat -v`).

## Why the flag parses but does nothing

`create` itself does not declare `--output`: its flag set (`IssuePRCreateFlags`) carries no `OutputFlag`. The flag parses anyway because urfave/cli v3 resolves flags through `Command.lookupAppliedFlag`, which searches `appliedFlags` — "local flags for current command **or persistent flags from ancestors**". The parent `pulls` command carries `--output` via `AllDefaultFlags`, so the flag reaches the subcommand's parser while being absent from `create --help` — and was never consulted by the action.

## What this changes

- `task.CreatePull` now returns the created `*gitea.PullRequest` instead of printing it.
- `runPullsCreate` switches on `--output`, mirroring the existing detail-command precedent (`RunPullsDetails` in `cmd/pulls.go`): `--output json` emits a lean JSON object; any other value (or no flag at all) falls through to the previous `print.PullDetails` rendering, byte-identical to before.
- Lean JSON shape, since a freshly created PR has no reviews/comments/CI yet: `index`, `title`, `url`, `state`, `base`, `head`.
- `--agit` combined with `--output` now fails fast with an explicit error before any API call or `git push`: the agit flow creates the PR server-side via push and returns no object to print.
- The interactive path is untouched — it only triggers when zero flags are set, so `--output` can never be active there.

Example:

```
$ tea pr create --output json --title "fix: thing" | jq -r .url
https://gitea.example.com/owner/repo/pulls/33
```

---------

Co-authored-by: Danilo Sousa <code@danilosousa.net>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1111
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: ongolk <238961+ongolk@noreply.gitea.com>
2026-09-08 19:20:40 +00:00
Ross Golder 3dc843ca1a
chore: regenerate CLI documentation for deploy-tokens command
The deploy-tokens command was added but the auto-generated CLI documentation was not updated. Regenerated docs/CLI.md to include the new deploy-tokens, dt, deploy-token command with list, create, and delete subcommands.
2026-09-08 12:32:52 +07:00
Ross Golder e5dfe86193
Add deploy-tokens to CHANGELOG and README, fix lint comments 2026-09-08 12:26:17 +07:00
Ross Golder dfb08abe2a
chore: use ListDeployTokens SDK method instead of manual filtering 2026-09-08 11:21:16 +07:00
Ross Golder 803aeab5db
feat: Add 'tea deploy-tokens' command for repository deploy token management
- Add deploy-tokens subcommand with list, create, delete
- Create deploy token print helpers with token display (shown once only)
- Add unit tests for all commands
- Update SDK dependency to use fork with deploy token support

Relates to gitea/go-sdk#846
2026-09-08 11:05:40 +07:00
Ross Golder e499d0843c
feat: Add 'tea deploy-keys' command for repository deploy key management
Adds a top-level 'tea deploy-keys' command under ENTITIES, providing
list, create, delete, and detail-by-id operations over the existing
Gitea REST API at /repos/{owner}/{repo}/keys.

- New CmdDeployKeys registered alongside tea webhooks/branches/etc.
- Subcommands: list (with pagination + --fingerprint filter),
  create (<title> --key|--key-file [--read-only|--read-write]),
  delete (<key-id> --confirm|-y), and a default <key-id> detail view.
- The Gitea API has no edit endpoint; 'change' is documented as
  delete+create. No update subcommand is added.
- modules/print/deploy_key.go: DeployKeysList and DeployKeyDetails.
- Unit tests covering command metadata, flag wiring, key-material
  resolution (--key vs --key-file, mutual exclusion, missing file),
  delete confirmation logic, key-id parsing, and prompt formatting.
- README/CHANGELOG/CLI.md updated.

All four Gitea SDK methods used (CreateDeployKey, DeleteDeployKey,
GetDeployKey, ListDeployKeys) are already present in
code.gitea.io/sdk/gitea v0.23.2; no go.mod changes.

Refs #1066.

Signed-off-by: Ross Golder <ross@golder.org>
(cherry picked from commit 384540c91f9703d1e1b37dd6a8e51f502cc5f216)
2026-09-05 09:52:56 +07:00
Renovate Bot 58931b5d17 fix(deps): update module golang.org/x/crypto to v0.56.0 [security] (#1109)
Some checks failed
goreleaser / goreleaser (push) Has been cancelled
goreleaser / release-image (push) Has been cancelled
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) | [`v0.55.0` → `v0.56.0`](https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.55.0...refs/tags/v0.56.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fcrypto/v0.56.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fcrypto/v0.55.0/v0.56.0?slim=true) |

---

### Prevent DoS on deadlocked undecided channel in golang.org/x/crypto/ssh
[CVE-2026-78662](https://nvd.nist.gov/vuln/detail/CVE-2026-78662) / [GO-2026-6354](https://pkg.go.dev/vuln/GO-2026-6354)

<details>
<summary>More information</summary>

#### Details
Previously, a channel registered in the mux's chanList is not usable until it is established. A malicious peer was able flood the channel's incomingRequests, deadlocking the entire connection.

Now, we add an atomic established state, set when a channel becomes usable. Until such a time, handlePacket drops every packet other than the open confirmation/failure, without blocking and without tearing down the connection.

#### Severity
Unknown

#### References
- [https://go.dev/issue/81316](https://go.dev/issue/81316)
- [https://go.dev/cl/826504](https://go.dev/cl/826504)
- [https://groups.google.com/g/golang-announce/c/1y3fb2np35U](https://groups.google.com/g/golang-announce/c/1y3fb2np35U)

This data is provided by [OSV](https://osv.dev/vulnerability/GO-2026-6354) and the [Go Vulnerability Database](https://github.com/golang/vulndb) ([CC-BY 4.0](https://github.com/golang/vulndb#license)).
</details>

---

### Prevent DoS on deadlocked established channel in golang.org/x/crypto/ssh
[CVE-2026-56855](https://nvd.nist.gov/vuln/detail/CVE-2026-56855) / [GO-2026-6355](https://pkg.go.dev/vuln/GO-2026-6355)

<details>
<summary>More information</summary>

#### Details
Previously, after a channel has been established, a malicious peer could send crafted messages that would deadlock the entire connection.

Now, we handle all RFC 4254 channel messages; global requests are handled explicitly. Then, treat all other messages as a protocol error and tear the connection down instead of buffering and blocking.

#### Severity
Unknown

#### References
- [https://go.dev/issue/81317](https://go.dev/issue/81317)
- [https://go.dev/cl/826524](https://go.dev/cl/826524)
- [https://groups.google.com/g/golang-announce/c/1y3fb2np35U](https://groups.google.com/g/golang-announce/c/1y3fb2np35U)

This data is provided by [OSV](https://osv.dev/vulnerability/GO-2026-6355) and the [Go Vulnerability Database](https://github.com/golang/vulndb) ([CC-BY 4.0](https://github.com/golang/vulndb#license)).
</details>

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1109
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-09-03 06:40:04 +00:00
Renovate Bot c2947c23d9 fix(deps): update module golang.org/x/crypto to v0.55.0 [security] (#1106)
Some checks failed
goreleaser / goreleaser (push) Has been cancelled
goreleaser / release-image (push) Has been cancelled
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) | [`v0.54.0` → `v0.55.0`](https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.54.0...refs/tags/v0.55.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fcrypto/v0.55.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fcrypto/v0.54.0/v0.55.0?slim=true) |

---

### Source-address critical option not enforced for non-public-key auth callbacks in golang.org/x/crypto/ssh
[CVE-2026-56854](https://nvd.nist.gov/vuln/detail/CVE-2026-56854) / [GO-2026-6303](https://pkg.go.dev/vuln/GO-2026-6303)

<details>
<summary>More information</summary>

#### Details
The source-address critical option in the Permissions returned by an authentication callback was only enforced for the PublicKeyCallback and VerifiedPublicKeyCallback paths, extending the fix for CVE-2026-46595. Permissions returned by the PasswordCallback, KeyboardInteractiveCallback, NoClientAuthCallback, and GSSAPIWithMICConfig.AllowLogin callbacks were not validated against the client's remote address, so a source-address restriction set by those callbacks was silently ignored. The check is now applied to the Permissions returned by any authentication callback.

#### Severity
Unknown

#### References
- [https://go.dev/issue/80213](https://go.dev/issue/80213)
- [https://go.dev/cl/797040](https://go.dev/cl/797040)

This data is provided by [OSV](https://osv.dev/vulnerability/GO-2026-6303) and the [Go Vulnerability Database](https://github.com/golang/vulndb) ([CC-BY 4.0](https://github.com/golang/vulndb#license)).
</details>

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1106
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-08-29 04:46:28 +00:00
Lunny Xiao 8bfdec40c6 feat(login): add status command (#1087) (#1105)
Implements #1087.

Adds `tea login status [<login name>] [-o <format>]`, which verifies the stored token for one or all configured logins and reports:

- login name/URL and default status
- whether the token is valid (via `GET /api/v1/user`)
- auth method and token expiry
- whether the git credential helper is configured

Machine-readable output is available via the usual `-o` formats with fields `name`, `url`, `user`, `valid`, `auth_method`, `token_expiry`, `helper`, and `default`.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1105
Reviewed-by: bircni <bircni@icloud.com>
2026-08-28 23:55:13 +00:00
Lunny Xiao 22d43ec9b6 fix(login): avoid panic when parsing auto-discovered SSH keys (#1100)
Some checks are pending
goreleaser / goreleaser (push) Waiting to run
goreleaser / release-image (push) Waiting to run
## Problem

`tea login add` can panic while auto-discovering SSH keys. The interactive login flow calls `regexp.FindStringSubmatch` and immediately indexes `[1]` without checking whether the regex matched. When the selected key display string does not have the expected format, the returned slice is `nil` and tea crashes with:

```
panic: runtime error: index out of range [1] with length 0
```

This is the crash reported in #527.

## Root cause

`regexp.Regexp.FindStringSubmatch` returns `nil` when the input does not match. Indexing that result with `[1]` assumes a match and causes the panic. The same unchecked pattern exists for SSH certificates and plain public keys in `modules/interact/login.go`.

## Changes

- Extract auto-discovered SSH key/certificate display parsing into `parseSSHPubkeySelection`.
- Add a `regexpSubmatch` helper that returns an error when a regex does not match, so login fails with a descriptive error instead of panicking.
- Add table-driven tests for local/agent keys, local/agent certificates, and malformed input.

Fixes #527

---------

Co-authored-by: bircni <bircni@icloud.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1100
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-08-23 19:20:19 +00:00
Lunny Xiao bfda25be63 Read issue/PR description from stdin or a file (#1096)
Closes #1095.

`tea issues create` and `tea pulls create` now resolve the description in the same way as comments: when stdin is piped and neither `--description` nor `--description-file` is given, the body is read from stdin. Both create and edit commands also accept:

```text
--description-file <path>   # '-' reads stdin
```

This avoids the PowerShell 5.1 argument mangling and ANSI code page issues described in #1095.

## Changes

- Add `--description-file` to `issues create`, `issues edit`, `pulls create`, and `pulls edit`.
- Create commands fall back to piped stdin when no description flag is set.
- Add unit tests for the new body resolution.

---------

Co-authored-by: bircni <bircni@icloud.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1096
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-08-23 12:46:22 +00:00
Renovate Bot dfe89dfb6b fix(deps): update go toolchain directive to v1.26.6 [security] (#1103)
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-08-23 12:44:52 +00:00
Renovate Bot ee531914cd chore(deps): update docker/login-action digest to dbcb813 (#1082)
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-08-16 13:01:15 +00:00
James Braid 276a4b735a fix(oauth): don't wait for the browser opener to exit (#1093)
Fixes `tea login add --oauth` hanging after the user authenticates in the
browser.

`xdg-open` (at least on Debian) runs the browser in the foreground, so it does
not exit until the browser does. `open.Run` waits for it, so tea is blocked and
doesn't get the oAuth callback from the browser.

This only happens when `xdg-open` has to start the browser. With one already
running, the new process hands off and exits immediately.

`open.Start` launches the opener and returns. The test mocks `xdg-open` with a
script that holds the foreground and fails if `openBrowser` waits on it.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1093
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: James Braid <jamesb@loreland.org>
2026-08-16 12:57:47 +00:00
Lunny Xiao 943d4c1512 Drop AWS S3 release upload, keep only Cloudflare R2 (#1092)
The release pipeline uploaded artifacts to both AWS S3 (goreleaser `blobs:`) and Cloudflare R2 (custom publisher) during the migration period. The migration is done, so this removes the S3 half:

- drop the `blobs:` block from `.goreleaser.yaml`
- drop the `AWS_*` / `S3_*` env from the nightly and tag release workflows
- update the comments in `.goreleaser.yaml` and `scripts/upload-r2.sh` accordingly

Cloudflare R2 upload (including the early `--check-config` preflight step) is unchanged, and the `AWS_*` repo secrets are no longer used.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1092
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-08-15 20:34:32 +00:00
Lunny Xiao 4233ebcbb1 ci: Drop AWS S3 release upload, keep only Cloudflare R2 (#1092)
The release pipeline uploaded artifacts to both AWS S3 (goreleaser `blobs:`) and Cloudflare R2 (custom publisher) during the migration period. The migration is done, so this removes the S3 half:

- drop the `blobs:` block from `.goreleaser.yaml`
- drop the `AWS_*` / `S3_*` env from the nightly and tag release workflows
- update the comments in `.goreleaser.yaml` and `scripts/upload-r2.sh` accordingly

Cloudflare R2 upload (including the early `--check-config` preflight step) is unchanged, and the `AWS_*` repo secrets are no longer used.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1092
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-08-15 20:17:51 +00:00
silverwind 12726f4c9b chore: align go version handling with gitea (#1088)
Aligns Go version handling with gitea, see https://github.com/go-gitea/gitea/pull/38559. `toolchain` names the build version, `go` stays the minimum.

The renovate extends match the other repos now. `security` is an empty preset, and `go-deps` only fast-tracked the toolchain bump into its own PR, which the weekly group carries instead.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1088
Reviewed-by: techknowlogick <9+techknowlogick@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-08-05 22:50:47 +00:00
Bo-Yi Wu f34697c5ed chore(config): replace authgate SDK with signet (#1081)
## Summary

- Replace `github.com/go-authgate/sdk-go` with `github.com/go-signet/sdk-go v1.1.0`.
- Update the credential-store import while retaining the existing `credstore` API and OAuth token persistence
behavior.

## Related issues

- GitHub/Gitea: fixed https://gitea.com/gitea/tea/issues/1058

Reviewed-on: https://gitea.com/gitea/tea/pulls/1081
Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2026-08-02 14:38:25 +00:00
Ross Golder a613a344de fix(test): disable gpg signing in worktree test repo (#1072)
Fixes #1071

`TestRepoFromPath_Worktree` creates a throwaway temp repo and commits to it. On machines with `commit.gpgsign=true` in global git config, the commit fails with `No secret key`.

Override the global setting by setting `commit.gpgsign=false` in the temp repo's local config so the test is environment-independent.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1072
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Ross Golder <ross@golder.org>
2026-07-30 00:29:29 +00:00
Renovate Bot 6435b12202 chore(deps): pin dependencies (#1064)
chore(deps): pin dependencies (gitea/tea#1064)

Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-07-27 22:02:00 +00:00
Lunny Xiao 61b8536e4a ci(goreleaser): mirror release artifacts to Cloudflare R2 (#1063)
Ports the Cloudflare R2 release mirror from [gitea.com/gitea/runner](https://gitea.com/gitea/runner) to `tea`, so release artifacts land in R2 alongside S3 for the duration of the migration away from S3.

Two commits, meant to be reviewed in order.

## 1. `ci(goreleaser): migrate release config to goreleaser v2`

A purely mechanical migration, no behaviour change intended:

- add `version: 2`
- `blobs.folder` -> `blobs.directory`
- `snapshot.name_template` -> `snapshot.version_template`
- `nightly.name_template` -> `nightly.version_template`
- `version: "~> v1"` -> `"~> v2"` in both release workflows

This is a prefactor rather than scope creep. Under goreleaser v1 the custom-publisher pipe runs *4th*, before the `release` pipe; under v2 it runs *last*. That ordering difference matters for the change below: on v1 a failed R2 upload would abort the publish after every artifact had already gone to S3 but **before** the Gitea release was created, leaving a half-finished release. On v2 the R2 mirror runs after the release exists, which matches the behaviour the runner repo already has in production.

The pre-existing `archives.format` deprecation warning is deliberately left alone; it is orthogonal to this change and the runner repo has not addressed it either.

## 2. `ci(goreleaser): mirror release artifacts to Cloudflare R2`

- **`scripts/upload-r2.sh`** — uploads one local file to one R2 object key using curl's built-in AWS SigV4 signer (R2 is S3-API compatible). Credentials are fed through `curl --config -` so they never appear in `ps` output. Also provides a `--check-config` preflight mode. This file is byte-identical to the runner repo's copy.
- **`.goreleaser.yaml`** — a `publishers:` entry mirroring the existing S3 `blobs:` upload into R2. A second `blobs:` entry is not usable here: the blob pipe authenticates from the global `AWS_*` environment and has no per-entry credentials, whereas `publishers:` supports per-entry `env:`.
- **Both release workflows** — forward the R2 secrets, plus an early `check R2 configuration` step. Custom publishers run as the very last step of goreleaser's publish pipeline, so without a preflight a missing secret would only surface after the release had been created and every artifact already uploaded to S3.

### Deviation from the runner implementation

The publisher here also sets `signature: true` in addition to `checksum: true`. `tea` has a `signs:` block that GPG-signs the checksum file, and the S3 blob pipe uploads the resulting `checksums.txt.sig`; without `signature: true` the R2 mirror would carry the artifacts and their checksums but no signature to verify them against.

The object key prefix is `tea/{{ .Version }}/...`, matching the existing S3 `directory: "tea/{{.Version}}"`.

## Required repository secrets

This PR is inert until these are configured. The preflight step will fail the release loudly if they are missing:

- `R2_ENDPOINT` — e.g. `https://<account>.r2.cloudflarestorage.com`
- `R2_BUCKET`
- `R2_ACCESS_KEY_ID`
- `R2_SECRET_ACCESS_KEY`

## Verification

- `goreleaser check` against the migrated config (with the pro-only `nightly:` block temporarily stripped, since the check ran with the OSS v2 binary): *configuration is valid*, the only deprecation being the pre-existing `archives.format`.
- A real `goreleaser build --snapshot --clean --single-target` against the v2 config: succeeded, including the `xz` and `.goreleaser.checksum.sh` post-hooks.
- `scripts/upload-r2.sh`: clean under `sh -n` and `shellcheck`; all four `--check-config` cases exercised (all vars unset, one missing, all set, wrong argument count).
- The actual upload path was not exercised end to end, since that needs live R2 credentials.

Reviewed-on: https://gitea.com/gitea/tea/pulls/1063
Reviewed-by: Zettat123 <39446+zettat123@noreply.gitea.com>
2026-07-26 03:21:03 +00:00
Zach Winter 73b6bf3e23 fix(context): clarify the fallback login prompt wording (#1061)
The prompt shown when no login matches the current repository reads:

```
NOTE: no gitea login detected, whether falling back to login 'X'?
```

Two problems, both raised by @magistra-aria in #817:

- **"whether"** is a conjunction that needs two stated alternatives, so it doesn't parse in front of a yes/no confirm.
- **"no gitea login detected"** is misleading. The condition is that no *configured login matched this repository's remote* — not that a Gitea instance is missing. Read literally it suggests the CLI expects gitea.com specifically, which is how at least one user (me) first misread it.

Reworded to say what actually happened, for both the interactive prompt and its non-interactive counterpart:

```
NOTE: no login matched this repository. Fall back to login 'X'?
```

Strings only, no logic change.

Refs #817

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Zach Winter <contact@zachwinter.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1061
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Zach Winter <222839+zachwinter@noreply.gitea.com>
2026-07-26 01:38:10 +00:00
Lunny Xiao 993eb37b57 Fix notifications --mine outside git repositories (#1056)
Fixes #1055.

## Root cause
`tea notifications --mine` still initialized full repository context before checking the global notification scope, so it probed the current working directory with git and could select or fail on repository-derived context even though repository data is not needed.

## Changes
- Add an InitCommand option to skip local git repository discovery when a command does not need repository context.
- Use that option for notification list and mark-as operations when `--mine` is set.
- Add a regression test that makes `git` fail if invoked and verifies `notifications --mine` still uses the global notifications API.

## Tests
- `go test ./cmd/notifications ./modules/context`

Reviewed-on: https://gitea.com/gitea/tea/pulls/1056
2026-07-26 01:37:33 +00:00
Zach Winter cd93d8561b ci: wait for the gitea service to be ready before integration tests (#1062)
The `Integration Test` job is currently failing repo-wide, on unrelated PRs and on `main`:

```
curl: (7) Failed to connect to gitea port 3000 after 7 ms
```

It fails at the health check, before any Go test runs. Recent examples: #1056 (7/18), #1059, #1060, #1061.

### Cause

The health check was a single bare curl fired as soon as `setup-go` finished — there was never a readiness wait. The job has been depending on gitea binding port 3000 within however long `checkout` + `setup-go` happened to take. Timings from the job logs, container start → curl:

| run | gap | result |
|---|---|---|
| #1021 (2026-06-21) | 7.4s | pass |
| #1056 (2026-07-18) | 6.3s | fail |
| #1060 (2026-07-25) | 6.3s | fail |

Two failures a week apart with an identical gap, and curl giving up in single-digit **milliseconds** with nothing listening, points at the service still starting rather than crashing.

### What I could not determine

Two things landed in the same window and I can't separate them from outside: the service image bump 1.26.2 → 1.27.0 (d664c01) and the hosted runner fleet going v1.0.3 → v2.0.0 (visible in the log header). The service container's own stdout isn't exposed by the job log endpoint, so **"still running migrations" is inferred from timing, not observed.** Happy to be corrected by anyone who can see the container logs.

### Why this fix regardless

The missing readiness wait is the actual bug class, independent of what shifted the timing. If the service is merely slower to boot, this fixes it permanently. If it is genuinely broken, this converts a cryptic 7ms connection refusal into an explicit 60s timeout with a clear error.

Locally I verified the YAML parses and exercised both loop paths in a shell (success exits immediately; exhaustion emits `::error::` and exits 1). I can't run Gitea Actions locally, so this workflow's first real execution is the CI run on this PR — a passing `Integration Test` here is the fix demonstrating itself.

---------

Co-authored-by: Zach Winter <contact@zachwinter.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1062
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Zach Winter <222839+zachwinter@noreply.gitea.com>
2026-07-25 04:47:09 +00:00
Minjie Fang d664c01e18 feat(assignees): add set, add, and remove assignees APIs (#1045)
Implemented set, add, and remove assignees APIs.
Closes https://gitea.com/gitea/tea/issues/965 and https://gitea.com/gitea/tea/issues/966Reviewed-on: https://gitea.com/gitea/tea/pulls/1045
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Minjie Fang <wingsallen@gmail.com>
2026-07-18 00:20:03 +00:00
Renovate Bot 2d6dcd062f fix(deps): update go dependencies (#1057)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) | [`v0.53.0` → `v0.54.0`](https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.53.0...refs/tags/v0.54.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fcrypto/v0.54.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fcrypto/v0.53.0/v0.54.0?slim=true) |
| [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) | [`v0.44.0` → `v0.45.0`](https://cs.opensource.google/go/x/term/+/refs/tags/v0.44.0...refs/tags/v0.45.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fterm/v0.45.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fterm/v0.44.0/v0.45.0?slim=true) |

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->Reviewed-on: https://gitea.com/gitea/tea/pulls/1057
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-07-16 13:18:16 +00:00
Renovate Bot 7f0213940d fix(deps): update go dependencies (#1051)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) | `v2.0.4` → `v2.0.5` | ![age](https://developer.mend.io/api/mc/badges/age/go/charm.land%2flipgloss%2fv2/v2.0.5?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/charm.land%2flipgloss%2fv2/v2.0.4/v2.0.5?slim=true) |
| [github.com/urfave/cli/v3](https://github.com/urfave/cli) | `v3.10.0` → `v3.10.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2furfave%2fcli%2fv3/v3.10.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2furfave%2fcli%2fv3/v3.10.0/v3.10.1?slim=true) |
| [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) | [`v0.46.0` → `v0.47.0`](https://cs.opensource.google/go/x/sys/+/refs/tags/v0.46.0...refs/tags/v0.47.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fsys/v0.47.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fsys/v0.46.0/v0.47.0?slim=true) |

---

### Release Notes

<details>
<summary>charmbracelet/lipgloss (charm.land/lipgloss/v2)</summary>

### [`v2.0.5`](https://github.com/charmbracelet/lipgloss/releases/tag/v2.0.5)

[Compare Source](https://github.com/charmbracelet/lipgloss/compare/v2.0.4...v2.0.5)

### Graphemes, Schmraphemes

If you’re using emojis in the terminal you're in for a rough ride. That said, we do what we can. This release brings some in some very specific edge case rendering improvements. Enjoy.

Enjoy!

#### Changelog

- [`10f9584`](10f9584edb): chore(deps): bump ultraviolet for emoji-related improvements

***

<a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a>

Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@&#8203;charmcli), [Bluesky](https://bsky.app/profile/charm.land).

</details>

<details>
<summary>urfave/cli (github.com/urfave/cli/v3)</summary>

### [`v3.10.1`](https://github.com/urfave/cli/releases/tag/v3.10.1)

[Compare Source](https://github.com/urfave/cli/compare/v3.10.0...v3.10.1)

#### What's Changed

- chore(deps): bump actions/checkout from 6 to 7 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2371](https://github.com/urfave/cli/pull/2371)
- fix: align gfmrun example counter with actual runnable count by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2369](https://github.com/urfave/cli/pull/2369)
- v3: yield the version flag's -v alias to a user-defined flag by [@&#8203;c-tonneslan](https://github.com/c-tonneslan) in [#&#8203;2330](https://github.com/urfave/cli/pull/2330)
- fix: keep completion subcommand order deterministic in help output by [@&#8203;suzuki-shunsuke](https://github.com/suzuki-shunsuke) in [#&#8203;2374](https://github.com/urfave/cli/pull/2374)
- fix: allow DefaultCommand to handle its own flags by [@&#8203;lihan3238](https://github.com/lihan3238) in [#&#8203;2322](https://github.com/urfave/cli/pull/2322)

#### New Contributors

- [@&#8203;lihan3238](https://github.com/lihan3238) made their first contribution in [#&#8203;2322](https://github.com/urfave/cli/pull/2322)

**Full Changelog**: <https://github.com/urfave/cli/compare/v3.10.0...v3.10.1>

</details>

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1051
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
2026-07-15 01:41:25 +00:00
Willem Kokke 3b5703177d fix(theme): don't query the terminal at start-up (#1054)
Fixes https://gitea.com/gitea/tea/issues/1053

## What

tea hangs forever on Windows when it is started by something that owns a console but redirects
tea's stdio: a Windows service, a CI runner, an automation harness. Every command is affected,
`tea --version` included.

## Root cause

`modules/theme` imported `charm.land/lipgloss/v2/compat` for one struct type,
`compat.AdaptiveColor`. But compat detects the terminal background from package-level vars:

```go
var (
    HasDarkBackground = lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
    Profile           = colorprofile.Detect(os.Stdout, os.Environ())
)
```

Go initialises every package in the import graph before `main()` runs, and every file in package
`cmd` imports `modules/context`, which imports `modules/theme`. So tea queried the terminal on
every invocation, before urfave/cli had even looked at the arguments — which is why `--version`
hung.

On Windows that query opens `CONIN$`/`CONOUT$` and asks the console directly instead of giving up
when stdio is redirected, then waits for a reply that never comes. The read has a 2 second timeout,
but it does not fire, because the cancel it relies on is a no-op for that handle. Full trace in the
issue.

## Changes

- `modules/theme/theme.go` — drop the `compat` import and use `lipgloss.LightDark`, a plain
  function that touches no terminal. `TeaTheme.Theme` is already handed the `isDark` it needs.

  This also fixes a bug hiding in plain sight: `compat.AdaptiveColor` resolves against a
  process-wide value detected at init, so the title color ignored the `isDark` argument huh passed
  in. `Theme(true)` and `Theme(false)` returned the same color.

- `modules/theme/background.go` — new `HasDarkBackground()` helper that only asks the terminal when
  stdin and stdout are both terminals, and otherwise assumes dark, which is the default lipgloss
  itself falls back to. This is the same rule lipgloss already applies on Unix.

- `modules/interact/print.go` — `printTitleAndContent` called
  `lipgloss.HasDarkBackground(os.Stdin, os.Stdout)` directly, so it hit the same wait on the
  interactive paths, `tea login add` among them. It now goes through the helper.

## Why fix this in tea

The underlying bug is upstream and I have opened PRs for both halves of it: https://github.com/charmbracelet/ultraviolet/pull/138 and
https://github.com/charmbracelet/lipgloss/pull/713. But it is not fixed in any released version — lipgloss v2.0.5 is byte-identical to
v2.0.4 in the relevant files — so upgrading dependencies does not help, and tea would stay broken on
Windows until Charm cuts a release and tea bumps `go.mod`.

Separately, these changes stand on their own. tea should not query the terminal in order to print a
version string, whatever upstream does.

Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Willem Kokke <mail@willem.net>
2026-07-13 04:31:26 +00:00
Lunny Xiao 2a9c8ff6fd upgrade go sdk and add test (#1048)
Some checks failed
goreleaser / goreleaser (push) Has been cancelled
goreleaser / release-image (push) Has been cancelled
Fix #1046Reviewed-on: https://gitea.com/gitea/tea/pulls/1048
2026-07-01 18:06:19 +00:00
Brien Coffield 12947f068a feat(comments): accept -d/--description for comment body (#1043)
Closes #1042.

### What

`tea issue create`, `tea issue edit` and `tea pr create` all take the body via
`-d` / `--description`, but `tea comments add` and `tea comments edit` only
accepted it positionally — passing `-d` errored with
`flag provided but not defined: -d`.

This adds `-d` / `--description` to both `comments` subcommands so every
body-bearing command shares one flag.

### Behaviour / precedence

Unchanged for existing usage. Body resolution is now:

1. positional argument (kept first for back-compat),
2. `-d` / `--description`,
3. piped stdin,
4. `$EDITOR` (interactive only).

### Testing

- `go build`, `go vet ./...`, `go test -short ./cmd/... ./modules/...` all pass.
- Manually verified `tea comments add --help` / `edit --help` list the flag,
  and that `-d` resolves the body (reaches the API, no parse error, no editor
  prompt, no stdin block).

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1043
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Brien Coffield <coffbr01@gmail.com>
Co-committed-by: Brien Coffield <coffbr01@gmail.com>
2026-06-29 00:52:24 +00:00
Lunny Xiao d4545d8ed7 Add reply to code review (#978)
Follow https://gitea.com/gitea/go-sdk/pulls/784

Reviewed-on: https://gitea.com/gitea/tea/pulls/978
2026-06-26 21:40:31 +00:00
dinsmoor 885381e3e4 fix(http): add transport timeouts so tea fails fast on stalled servers (#1020)
Fixes #1018

Co-authored-by: dinsmoor <204368+dinsmoor@noreply.gitea.com>
Co-committed-by: dinsmoor <204368+dinsmoor@noreply.gitea.com>
2026-06-26 19:59:05 +00:00
techknowlogick 6a57af24ad fix(config): write to keychain before config (#1044)
Reviewed-on: https://gitea.com/gitea/tea/pulls/1044
Co-authored-by: techknowlogick <techknowlogick@gitea.com>
Co-committed-by: techknowlogick <techknowlogick@gitea.com>
2026-06-26 19:53:59 +00:00
Minjie Fang 88f5cdcafa fix(labels): add org label for ls and pr (#1017)
Fix https://gitea.com/gitea/tea/issues/634, https://gitea.com/gitea/tea/issues/669

Reviewed-on: https://gitea.com/gitea/tea/pulls/1017
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Minjie Fang <wingsallen@gmail.com>
Co-committed-by: Minjie Fang <wingsallen@gmail.com>
2026-06-24 17:46:12 +00:00
Renovate Bot 5cfee362c8 chore(deps): update actions/checkout action to v7 (#1041)
Reviewed-on: https://gitea.com/gitea/tea/pulls/1041
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-23 00:18:41 +00:00
Renovate Bot fff82ac723 fix(deps): update module github.com/urfave/cli/v3 to v3.10.0 (#1040)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/urfave/cli/v3](https://github.com/urfave/cli) | `v3.9.1` → `v3.10.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2furfave%2fcli%2fv3/v3.10.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2furfave%2fcli%2fv3/v3.9.1/v3.10.0?slim=true) |

---

### Release Notes

<details>
<summary>urfave/cli (github.com/urfave/cli/v3)</summary>

### [`v3.10.0`](https://github.com/urfave/cli/releases/tag/v3.10.0)

[Compare Source](https://github.com/urfave/cli/compare/v3.9.1...v3.10.0)

#### What's Changed

- feat: add Flag.SchemaType() and Flag.SchemaItemsType() for JSON Schema introspection by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2368](https://github.com/urfave/cli/pull/2368)
- feat: add Command.Walk() and Command.Path() convenience methods by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2353](https://github.com/urfave/cli/pull/2353)
- fix: let --help flag take precedence over parse errors by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2360](https://github.com/urfave/cli/pull/2360)
- fix: resolve remaining help invocation inconsistencies by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2361](https://github.com/urfave/cli/pull/2361)
- fix: skip After hook when help is displayed on subcommand by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2363](https://github.com/urfave/cli/pull/2363)
- fix: show GLOBAL OPTIONS in SubcommandHelpTemplate by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2359](https://github.com/urfave/cli/pull/2359)
- fix: resolve broken links in CHANGELOG.md by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2357](https://github.com/urfave/cli/pull/2357)
- docs: document what happened to build tags in v3 migration guide by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2358](https://github.com/urfave/cli/pull/2358)
- Various docs updates and dependency bumps

**Full Changelog**: <https://github.com/urfave/cli/compare/v3.9.1...v3.10.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

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

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1040
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-20 20:04:37 +00:00
Daniel Bankmann b11d991d1e fix(oauth): pass resolved redirect_uri to token exchange (#1019)
When --redirect-url is omitted, the local callback listener binds to a
free port and opts.RedirectURL is rewritten with it. oauth2Config.RedirectURL
was never updated, so Exchange() sent the stale http://127.0.0.1:0 while
the authorize step had sent the real port. RFC-6749-compliant servers
(Gitea >= #37704, current Forgejo) reject the mismatch.

Propagate the resolved URL back into oauth2Config before Exchange. Add a
regression test using httptest that drives the flow end-to-end and asserts
the redirect_uri values match.

---------

Co-authored-by: dbankmann <204984+dbankmann@users.noreply.gitea.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1019
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Daniel Bankmann <204984+dbankmann@noreply.gitea.com>
Co-committed-by: Daniel Bankmann <204984+dbankmann@noreply.gitea.com>
2026-06-20 20:03:34 +00:00
Renovate Bot 4b209d68de fix(deps): update go dependencies (#1039)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [charm.land/glamour/v2](https://github.com/charmbracelet/glamour) | `v2.0.0` → `v2.0.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/charm.land%2fglamour%2fv2/v2.0.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/charm.land%2fglamour%2fv2/v2.0.0/v2.0.1?slim=true) |
| [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) | `v2.0.3` → `v2.0.4` | ![age](https://developer.mend.io/api/mc/badges/age/go/charm.land%2flipgloss%2fv2/v2.0.4?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/charm.land%2flipgloss%2fv2/v2.0.3/v2.0.4?slim=true) |

---

### Release Notes

<details>
<summary>charmbracelet/glamour (charm.land/glamour/v2)</summary>

### [`v2.0.1`](https://github.com/charmbracelet/glamour/releases/tag/v2.0.1)

[Compare Source](https://github.com/charmbracelet/glamour/compare/v2.0.0...v2.0.1)

#### Changelog

##### Bug fixes

- [`975a0f3`](975a0f30cc): fix: close wrap writer before its downstream chain ([#&#8203;575](https://github.com/charmbracelet/glamour/issues/575)) ([@&#8203;taciturnaxolotl](https://github.com/taciturnaxolotl))

##### Other work

- [`c293649`](c293649244): chore: fix pre-existing lint failures ([#&#8203;575](https://github.com/charmbracelet/glamour/issues/575)) ([@&#8203;taciturnaxolotl](https://github.com/taciturnaxolotl))
- [`95c93db`](95c93db044): chore: bump lipgloss to v2.0.4 ([@&#8203;taciturnaxolotl](https://github.com/taciturnaxolotl))
- [`600b93a`](600b93a40b): chore: remove CODEOWNERS ([@&#8203;aymanbagabas](https://github.com/aymanbagabas))
- [`253da61`](253da61fcb): fix(ci): use local golangci config ([@&#8203;aymanbagabas](https://github.com/aymanbagabas))

***

<a href="https://charm.sh/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-badge.jpg"
width="400"></a>

Thoughts? Questions? We love hearing from you. Feel free to reach out on [Twitter](https://twitter.com/charmcli), [The Fediverse](https://mastodon.social/@&#8203;charm), or on [Discord](https://charm.sh/chat).

</details>

<details>
<summary>charmbracelet/lipgloss (charm.land/lipgloss/v2)</summary>

### [`v2.0.4`](https://github.com/charmbracelet/lipgloss/releases/tag/v2.0.4)

[Compare Source](https://github.com/charmbracelet/lipgloss/compare/v2.0.3...v2.0.4)

### Mini Crash Patch

Hi! This is a small patch to fix a writer-related panic. Thanks for using Lip Gloss!

#### Changelog

##### Fixed

- [`fefa41d`](https://github.com/charmbracelet/lipgloss/commit/fefa41d): fix: prevent crash when writing to a closed wrap writer ([#&#8203;699](https://github.com/charmbracelet/lipgloss/issues/699)) ([@&#8203;taciturnaxolotl](https://github.com/taciturnaxolotl))

##### Docs

- [`40ec0e6`](https://github.com/charmbracelet/lipgloss/commit/40ec0e6): docs: fix typo in table comment ([#&#8203;641](https://github.com/charmbracelet/lipgloss/issues/641)) ([@&#8203;aymanbagabas](https://github.com/aymanbagabas))
- [`a4d0b40`](https://github.com/charmbracelet/lipgloss/commit/a4d0b40): docs: restore missing diaereses ([#&#8203;664](https://github.com/charmbracelet/lipgloss/issues/664)) ([@&#8203;meowgorithm](https://github.com/meowgorithm))

##### Chore

- [`aa91b99`](https://github.com/charmbracelet/lipgloss/commit/aa91b99): chore: remove CODEOWNERS ([@&#8203;aymanbagabas](https://github.com/aymanbagabas))
- [`9cbfe8b`](https://github.com/charmbracelet/lipgloss/commit/9cbfe8b): chore(lint): exclude revive naming linter ([@&#8203;aymanbagabas](https://github.com/aymanbagabas))

***

<a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a>

Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@&#8203;charmcli), [Bluesky](https://bsky.app/profile/charm.land).

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1039
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-18 02:32:16 +00:00
Renovate Bot 2b844786f0 fix(deps): update go dependencies (#1037)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/go-authgate/sdk-go](https://github.com/go-authgate/sdk-go) | `v0.12.0` → `v0.14.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-authgate%2fsdk-go/v0.14.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgo-authgate%2fsdk-go/v0.12.0/v0.14.0?slim=true) |
| [github.com/urfave/cli/v3](https://github.com/urfave/cli) | `v3.9.0` → `v3.9.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2furfave%2fcli%2fv3/v3.9.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2furfave%2fcli%2fv3/v3.9.0/v3.9.1?slim=true) |

---

### Release Notes

<details>
<summary>go-authgate/sdk-go (github.com/go-authgate/sdk-go)</summary>

### [`v0.14.0`](https://github.com/go-authgate/sdk-go/releases/tag/v0.14.0)

[Compare Source](https://github.com/go-authgate/sdk-go/compare/v0.13.0...v0.14.0)

#### Changelog

##### Features

- [`1e9404e`](1e9404eea6): feat(credstore): add DefaultStorePath path helper ([@&#8203;appleboy](https://github.com/appleboy))
- [`3498105`](34981059ec): feat(credstore): add DefaultTokenStorePath shorthand ([@&#8203;appleboy](https://github.com/appleboy))

### [`v0.13.0`](https://github.com/go-authgate/sdk-go/releases/tag/v0.13.0)

[Compare Source](https://github.com/go-authgate/sdk-go/compare/v0.12.0...v0.13.0)

#### Changelog

##### Others

- [`fc432e3`](fc432e3da2): feat(credstore)!: add encrypted file store with keyring master key ([#&#8203;35](https://github.com/go-authgate/sdk-go/issues/35)) ([@&#8203;appleboy](https://github.com/appleboy))

</details>

<details>
<summary>urfave/cli (github.com/urfave/cli/v3)</summary>

### [`v3.9.1`](https://github.com/urfave/cli/releases/tag/v3.9.1)

[Compare Source](https://github.com/urfave/cli/compare/v3.9.0...v3.9.1)

#### What's Changed

- fix: inherit Reader/Writer/ErrWriter from parent on subcommand setup by [@&#8203;c-tonneslan](https://github.com/c-tonneslan) in [#&#8203;2329](https://github.com/urfave/cli/pull/2329)
- fix: correct greedy colon parsing in bash completion script by [@&#8203;TimSoethout](https://github.com/TimSoethout) in [#&#8203;2336](https://github.com/urfave/cli/pull/2336)
- fix: Honor env sources on duplicated flags by [@&#8203;ibobgunardi](https://github.com/ibobgunardi) in [#&#8203;2355](https://github.com/urfave/cli/pull/2355)
- fix: Remove incorrect flag check by [@&#8203;MohitPanchariya](https://github.com/MohitPanchariya) in [#&#8203;2280](https://github.com/urfave/cli/pull/2280)
- fix: let completion command use normal flag parsing pipeline by [@&#8203;suzuki-shunsuke](https://github.com/suzuki-shunsuke) in [#&#8203;2279](https://github.com/urfave/cli/pull/2279)
- fix: bash completion spacing by [@&#8203;cyphercodes](https://github.com/cyphercodes) in [#&#8203;2337](https://github.com/urfave/cli/pull/2337)
- fix: fish custom completion arguments by [@&#8203;puneetdixit200](https://github.com/puneetdixit200) in [#&#8203;2338](https://github.com/urfave/cli/pull/2338)
- fix: empty positional arg after a flag regression test by [@&#8203;c-tonneslan](https://github.com/c-tonneslan) in [#&#8203;2328](https://github.com/urfave/cli/pull/2328)
- docs: document build tags in v3 migration guide by [@&#8203;dearchap](https://github.com/dearchap) in [#&#8203;2358](https://github.com/urfave/cli/pull/2358)
- chore(deps): bump mkdocs-git-revision-date-localized-plugin by [@&#8203;dependabot](https://github.com/dependabot) in [#&#8203;2347](https://github.com/urfave/cli/pull/2347)
- Fix typos by [@&#8203;myfloss](https://github.com/myfloss) in [#&#8203;2339](https://github.com/urfave/cli/pull/2339)

**Full Changelog**: <https://github.com/urfave/cli/compare/v3.9.0...v3.9.1>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1037
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-16 21:09:11 +00:00
LeonM 67bb0e7789 feat(pulls): show PR URL in detail view (#1036)
Fixes #1035.

## Summary
- include the pull request URL in `tea pr <number>` detail output
- keep `tea pr create` output to one URL by relying on the shared detail renderer
- add a focused regression test

## Tests
- `go test ./modules/print`
- `go test ./...`

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Leon Müller <mueller4leon@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1036
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: LeonM <206012+leonm@noreply.gitea.com>
Co-committed-by: LeonM <206012+leonm@noreply.gitea.com>
2026-06-15 20:35:21 +00:00
Renovate Bot 6de58b2223 fix(deps): update go dependencies (#1034)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) | [`v0.52.0` → `v0.53.0`](https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.52.0...refs/tags/v0.53.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fcrypto/v0.53.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fcrypto/v0.52.0/v0.53.0?slim=true) |
| [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) | [`v0.43.0` → `v0.44.0`](https://cs.opensource.google/go/x/term/+/refs/tags/v0.43.0...refs/tags/v0.44.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fterm/v0.44.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fterm/v0.43.0/v0.44.0?slim=true) |

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1034
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-15 20:30:27 +00:00
Renovate Bot 27bcbf80ae fix(deps): update module golang.org/x/sys to v0.46.0 (#1028)
Reviewed-on: https://gitea.com/gitea/tea/pulls/1028
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-09 16:02:18 +00:00
Renovate Bot dfbbda83f3 fix(deps): update module gitea.dev/sdk to v1.1.0 (#1027)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| gitea.dev/sdk | `v1.0.1` → `v1.1.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/gitea.dev%2fsdk/v1.1.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/gitea.dev%2fsdk/v1.0.1/v1.1.0?slim=true) |

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

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

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1027
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-08 22:42:38 +00:00
Renovate Bot df320c74ca fix(deps): update module github.com/go-authgate/sdk-go to v0.12.0 (#1024)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/go-authgate/sdk-go](https://github.com/go-authgate/sdk-go) | `v0.11.0` → `v0.12.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-authgate%2fsdk-go/v0.12.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgo-authgate%2fsdk-go/v0.11.0/v0.12.0?slim=true) |

---

### Release Notes

<details>
<summary>go-authgate/sdk-go (github.com/go-authgate/sdk-go)</summary>

### [`v0.12.0`](https://github.com/go-authgate/sdk-go/releases/tag/v0.12.0)

[Compare Source](https://github.com/go-authgate/sdk-go/compare/v0.11.0...v0.12.0)

#### Changelog

##### Bug fixes

- [`506ff28`](506ff28e68): fix: authenticate confidential clients and harden token handling ([#&#8203;33](https://github.com/go-authgate/sdk-go/issues/33)) ([@&#8203;appleboy](https://github.com/appleboy))

##### Refactor

- [`81b51e2`](81b51e244f): refactor: simplify control flow across sdk packages ([#&#8203;30](https://github.com/go-authgate/sdk-go/issues/30)) ([@&#8203;appleboy](https://github.com/appleboy))
- [`7fcdb3c`](7fcdb3cde0): refactor(oauth): use error-code constants at all sites ([#&#8203;31](https://github.com/go-authgate/sdk-go/issues/31)) ([@&#8203;appleboy](https://github.com/appleboy))
- [`4407ea6`](4407ea621e): refactor(middleware): split token scope once for required-scope checks ([#&#8203;32](https://github.com/go-authgate/sdk-go/issues/32)) ([@&#8203;appleboy](https://github.com/appleboy))

##### Documentation updates

- [`f8b8b28`](f8b8b28fd7): docs(jwksauth): document UID across remaining godoc and test comments ([@&#8203;appleboy](https://github.com/appleboy))

##### Others

- [`a90443e`](a90443e622): fix(discovery,middleware): coalesce concurrent discovery fetches via singleflight with per-caller cancellation; route scope errors through the error handler ([#&#8203;16](https://github.com/go-authgate/sdk-go/issues/16)) ([@&#8203;appleboy](https://github.com/appleboy))

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch 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 PR becomes conflicted, or you tick the rebase/retry checkbox.

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

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/tea/pulls/1024
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Renovate Bot <renovate-bot@gitea.com>
Co-committed-by: Renovate Bot <renovate-bot@gitea.com>
2026-06-05 03:55:19 +00:00
dinsmoor 09fc09c2f7 feat(comments): add list/edit/delete subcommands to tea comment (#1015)
## Why

Today `tea comment` can only *add* a comment. Editing or deleting requires falling back to `tea api`. This came up while I was iterating on PRs in this same repo earlier today and had to correct a couple of comments by hand. Every comparable forge CLI (gh, glab, etc.) exposes these operations as first-class commands.

## What

Restructures `tea comment` from a single-action command into a parent with four subcommands. The parent's default action remains the existing "add" behavior, so the historical shorthand keeps working.

| Command | Purpose |
|---|---|
| `tea comment add <idx> [<body>]` | Add a comment (explicit subcommand) |
| `tea comment list <idx>` | Tabular listing including comment IDs |
| `tea comment edit <id> [<body>]` | Replace the body of one comment |
| `tea comment delete <id> [<id>...]` | Delete one or more comments |
| `tea comment <idx> [<body>]` | Unchanged — still routes to `add` |

The `list` command exists specifically so users can discover the IDs that `edit` and `delete` accept.

## Backward compatibility

The whole point of routing the parent's default `Action` through `add` is to preserve every existing invocation. `tea comment 1 "body"` still does what it did before. No flag or arg names change.

## Input forms (for add and edit)

Same pattern as the original `tea comment`:

1. Positional body (`tea comment edit <id> "new body"`) — wins if present.
2. Piped stdin if no positional body is given.
3. External `$EDITOR` (pre-populated with the current body, on `edit`) if neither.

This matches the stdin-handling fix in #1011 — positional body wins over a non-TTY stdin so the command doesn't hang in CI/subshells.

## Verification

All four subcommands were exercised live against `https://gitea.com/dinsmoor/tea-testing` issue #1. The test artifacts and a summary log are visible on that issue right now. Specifically:

- The annotated summary comment lists every operation tested and the comment IDs each one acted on.
- Comments 1197162 (legacy add), 1197163 (subcommand add, later edited), 1197164 (stdin add) are still there to be inspected.
- Comment 1197166 was created and then deleted; its absence from `tea comment list` output is evidence that delete works.

## New files

- `cmd/comments/add.go` — extracted from the old `cmd/comment.go`
- `cmd/comments/list.go`
- `cmd/comments/edit.go`
- `cmd/comments/delete.go`
- `modules/print/comment.go` — adds `CommentsList` helper for the tabular output

`cmd/comment.go` is rewritten as a thin parent that wires these together.

## Open questions for the reviewer

- **Naming**: should the top-level command be `comments` (plural) or stay `comment` (singular)? I kept it singular with `comments` as an alias to match the existing user-visible name.
- **Delete confirmation**: I did not add a confirmation prompt — `delete` just deletes. Some projects gate this behind `--yes` / interactive `[y/N]`. I'd rather follow whatever convention the maintainers prefer.
- **Output format on list**: currently uses the existing `print.tableWithHeader` helper, matching `tea organizations list` etc. Other tea listings support `--output json` / `--output csv` via the shared `--output` flag, which works here automatically through the same helper.

---

This patch was authored interactively with an AI assistant, driven and reviewed by a human (Tyler / @dinsmoor) every step.

*pull request created by Tyler's lovingly wrangled demon machine <3*

Reviewed-on: https://gitea.com/gitea/tea/pulls/1015
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: dinsmoor <204368+dinsmoor@noreply.gitea.com>
Co-committed-by: dinsmoor <204368+dinsmoor@noreply.gitea.com>
2026-05-31 22:20:48 +00:00
Tyler 5fa24b9a65 feat(pulls): add --draft to create and --draft/--ready to edit (#1008)
Closes #979. An alternative to the approach in #980 — this one is purely client-side title-mangling, no SDK changes needed.

Gitea already treats any PR with a `WIP:` or `[WIP]` title prefix (case-insensitive) as a draft. This patch wires three flags around that behavior:

- `tea pulls create --draft` — prepend `WIP: ` to the title at creation time
- `tea pulls edit --draft <idx>` — add `WIP: ` to an existing PR's title
- `tea pulls edit --ready <idx>` — strip any recognized draft prefix

All three are idempotent. `--draft` and `--ready` on edit are mutually exclusive. If the user also passes `--title` on edit, the toggle applies to the supplied title; otherwise the current title is fetched from the server first.

Why this approach over a server-payload-based one: Gitea's draft state is *defined* as the title-prefix convention (see the Gitea source for `HasWIPPrefix`). Modeling it server-side would either duplicate or fight that. A small string helper covers it without needing the SDK to add a `Draft` field.

Verified against `gitea.com` (1.26.0+dev) with a throwaway repo:
- create with `--draft` → server reports `draft: true` ✓
- `edit --ready` strips → `draft: false` ✓
- `edit --draft` adds back → `draft: true` ✓
- second `edit --draft` is idempotent ✓
- `edit --draft --ready` errors ✓

Unit tests for the prefix detection live in `modules/utils/draft_test.go`.

---

This patch was authored interactively with an AI assistant, driven and reviewed by a human (Tyler / @dinsmoor) every step. Reproduction, design decisions, and the choice not to follow #980's payload approach were mine — happy to discuss any of it.

*pull request created by Tyler's lovingly wrangled demon machine <3*

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/1008
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Tyler <tyler@dinsmoor.us>
Co-committed-by: Tyler <tyler@dinsmoor.us>
2026-05-31 02:50:32 +00:00