revert: tea 1.0 rewrite (#1122–#1126) (#1146)

Reverts #1126, #1125, #1124, #1123 and #1122.

`go.mod` keeps the Go 1.26 line with toolchain `go1.26.9` (instead of the original `go1.26.6`) so the security fix from #1131 isn't lost.

reopens #69
reopens #141
reopens #162
reopens #172
reopens #197
reopens #232
reopens #240
reopens #246
reopens #323
reopens #325
reopens #326
reopens #328
reopens #344
reopens #351
reopens #373
reopens #403
reopens #406
reopens #417
reopens #430
reopens #457
reopens #480
reopens #482
reopens #489
reopens #490
reopens #498
reopens #500
reopens #504
reopens #510
reopens #516
reopens #523
reopens #556
reopens #560
reopens #569
reopens #571
reopens #602
reopens #632
reopens #633
reopens #643
reopens #666
reopens #670
reopens #672
reopens #677
reopens #683
reopens #697
reopens #726
reopens #737
reopens #770
reopens #779
reopens #804
reopens #817
reopens #831
reopens #833
reopens #834
reopens #908
reopens #966
reopens #1023
reopens #1029
reopens #1032
reopens #1050
reopens #1052
reopens #1069
reopens #1073
reopens #1087
reopens #1091
reopens #1094
reopens #1110
reopens #1115
reopens #1116
reopens #1118

Reviewed-on: https://gitea.com/gitea/tea/pulls/1146
Reviewed-by: TheFox0x7 <95654+thefox0x7@noreply.gitea.com>
This commit is contained in:
bircni committed 2026-10-18 20:56:33 +00:00
1 parent 33bb12729e
commit c5f674111a
604 files changed
+33711 -35545

No files matched your search

+2404
View File
File diff suppressed because it is too large. Load diff
+29
View File
@@ -0,0 +1,29 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:generates
package main
import (
"context"
"os"
docs "github.com/urfave/cli-docs/v3"
"github.com/urfave/cli/v3"
"gitea.dev/tea/cmd"
)
// CmdDocs generates markdown for tea
func main() {
cli := &cli.Command{
Name: "docs",
Hidden: true,
Description: "Generate CLI docs",
Flags: cmd.DocRenderFlags,
Action: func(ctx context.Context, params *cli.Command) error {
return cmd.RenderDocs(params, cmd.App(), docs.ToMarkdown)
},
}
cli.Run(context.Background(), os.Args)
}
+113 -23
View File
@@ -1,30 +1,120 @@
# Gitea Actions workflows
# Gitea actions workflows
Select a repository explicitly for scripts and supply a token scoped to its instance:
## Workflow management with tea
```sh
export TEA_HOST=https://gitea.example.org
export TEA_REPO=owner/repository
# Supply GITEA_TOKEN through your CI secret environment.
tea workflow list --no-input --json
tea workflow view deploy.yml --no-input --json
tea workflow run deploy.yml --ref main --field env=staging --field version=1.2.3 --no-input
tea workflow disable deploy.yml --yes --no-input
tea workflow enable deploy.yml --no-input
### List workflows
```bash
# List all workflows in the repository
tea actions workflows list
```
Workflow dispatch requires a `workflow_dispatch` trigger in the workflow. Dispatch
and watching are separate commands; find the run with `tea run list`, then use
`tea run watch RUN_ID --timeout 10m --no-input`. Unsuccessful completed runs return
a nonzero exit code.
### View workflow details
For an explicitly authorized merge in CI:
```sh
tea pr merge 123 --repo owner/repository --method rebase --no-input
```bash
# View details of a specific workflow by ID or filename
tea actions workflows view deploy.yml
```
Keep credentials in the secret environment or credential store. Never write a token
into `config.yml` or `hosts.yml`. Run `tea help <command>`, or see the command
reference in each release's docs archive, for supported flags and the
[README](../README.md) for fresh authentication.
### Dispatch (trigger) a workflow
```bash
# Dispatch a workflow on the current branch
tea actions workflows dispatch deploy.yml
# Dispatch on a specific branch
tea actions workflows dispatch deploy.yml --ref main
# Dispatch with workflow inputs
tea actions workflows dispatch deploy.yml --ref main --input env=staging --input version=1.2.3
# Dispatch and follow log output
tea actions workflows dispatch ci.yml --ref feature/my-pr --follow
```
### Enable / disable workflows
```bash
# Disable a workflow
tea actions workflows disable deploy.yml --confirm
# Enable a workflow
tea actions workflows enable deploy.yml
```
## Example: Re-trigger CI from an AI-driven PR flow
Use `tea actions workflows dispatch` to re-run a specific workflow after
pushing changes in an automated PR workflow:
```bash
# Push changes to a feature branch, then re-trigger CI
git push origin feature/auto-fix
tea actions workflows dispatch check-and-test --ref feature/auto-fix --follow
```
## Example: Dispatch a workflow with `workflow_dispatch` trigger
```yaml
name: deploy
on:
workflow_dispatch:
inputs:
env:
description: "Target environment"
required: true
default: "staging"
version:
description: "Version to deploy"
required: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Deploy
run: |
echo "Deploying version ${{ gitea.event.inputs.version }} to ${{ gitea.event.inputs.env }}"
```
Trigger this workflow from the CLI:
```bash
tea actions workflows dispatch deploy.yml --ref main --input env=production --input version=2.0.0
```
## Merge Pull request on approval
```yaml
---
name: Pull request
on:
pull_request_review:
types: [submitted, dismissed]
jobs:
approved:
name: Approved
if: gitea.event.review.type == 'pull_request_review_approved'
container:
image: docker.io/pysen/tea:latest
runs-on: ubuntu-latest
steps:
- name: Configure Tea
env:
# This is a tea config.yml with (service) account token
TEA_CREDENTIALS: ${{ secrets.TEA_CREDENTIALS }}
run: |
echo "$TEA_CREDENTIALS" > $HOME/.config/tea/config.yml
- name: Rebase then fast-forward merge Git
run: |
tea pr merge --repo ${{ gitea.event.repository.full_name }} --style rebase ${{ gitea.event.pull_request.number }}
dismissed:
name: Dismissed
if: gitea.event.review.type == 'pull_request_review_rejected'
runs-on: ubuntu-latest
steps:
- run: |
tea pr reject --repo ${{ gitea.event.repository.full_name }} ${{ gitea.event.pull_request.number }} "Dismissed"
```
-358
View File
@@ -1,358 +0,0 @@
# Migrating to tea 1.0
tea 1.0 rebuilds the CLI around explicit, singular `noun verb` commands (similar
to GitHub's `gh`), a split configuration, and per-instance accounts. There are no
compatibility aliases: old command names, plural groups and most short flags are
gone, and scripts need updating. This guide lists what changed and what to use
instead.
Quick checklist:
1. Make sure your instances run Gitea 28 or newer
([Server requirements](#server-requirements)).
2. Move the old configuration away, or point tea 1.0 at a new directory
([Configuration](#old-configuration-file)).
3. Log in again ([Logging in](#logging-in-again)).
4. Replace the old `!tea login helper` Git credential entries
([Git credential helper](#git-credential-helper)).
5. Regenerate shell completions ([Shell completion](#shell-completion)).
6. Update scripts: [global flags](#global-flags), [commands](#renamed-commands),
[arguments](#changed-positional-arguments) and [output](#output-formats).
Run `tea <command> --help` for the full flag list of any command.
## Server requirements
Requires Gitea 28 or newer. tea no longer probes `/api/v1/version` or
`/swagger.v1.json` to adapt to older servers: on an older instance, commands
that need a newer endpoint fail with the server's HTTP error instead of a
"not supported" message.
## Configuration and login
### Old configuration file
Older releases kept logins and preferences in one file, `config.yml` in the `tea`
directory under the platform configuration directory (`~/.config/tea/config.yml`
on Linux; very old releases used `~/.tea/tea.yml`). tea 1.0 stores preferences in
`config.yml` and instances and accounts in `hosts.yml`, in the same directory by
default; `tea config path` prints both paths. When it finds an old-format file it
stops with:
```text
legacy tea configuration: archive the old config.yml or select a separate TEA_CONFIG_DIR, then run tea auth login; existing files have not been changed
```
Nothing is imported automatically. Either archive the old file:
```sh
mv ~/.config/tea/config.yml ~/.config/tea/config.yml.old # adjust the path on macOS and Windows
```
or keep it and give tea 1.0 its own directory with `TEA_CONFIG_DIR`. Do not run
an old tea against a directory written by tea 1.0: it reads the new `config.yml`
as an empty login list and overwrites it on its next save.
`tea config list` shows effective preferences. Old settings map as follows:
| Old `config.yml` | tea 1.0 |
|---|---|
| `preferences.editor: true` | `tea config set editor "<command>"` (a command, not a switch) |
| `preferences.flag_defaults.remote` | `tea config set remote <name>` |
| login `default: true` | `tea config set default_host <url>` |
| login `insecure`, `ssh_host` | `tea config set --host <url> insecure true`, `... ssh_host <host[:port]>` |
| login `ssh_key`, `ssh_agent`, `ssh_certificate_principal`, `ssh_key_agent_pub` | `tea config set --host <url> --user <name> ssh_key …` (also `ssh_agent`, `ssh_certificate_principal`, `ssh_key_fingerprint`) |
### Logging in again
Accounts are identified by instance URL and username instead of a login name.
`tea auth login --host <url>` replaces `tea login add`:
| Old | tea 1.0 |
|---|---|
| `tea login add --url URL --token TOKEN` | `tea auth login --host URL --with-token < token-file` (the token is read from stdin) |
| `tea login add --oauth` | `tea auth login --host URL --oauth` |
| `tea login add --ssh-key PATH` / `-s` | `tea auth login --host URL --ssh-key PATH` |
| `--ssh-agent-key` / `-a`, `--ssh-agent-principal` / `-c` | same long flags, no shorthands |
| `--insecure` / `-i` | `--insecure` |
| `--user`, `--password`, `--otp`, `--scopes` (create a token with basic auth) | removed: create a token in the web UI (Settings → Applications) or use `--oauth` |
| `--name`, `--no-version-check` | removed |
| `--redirect-url` | removed: OAuth always listens on a random loopback port |
| `--git-credentials` / `--helper` / `-j` | `tea auth setup-git --host URL` |
Token logins of the old release kept the token in plain text under
`logins[].token` in the old `config.yml`, so you can pipe it straight into
`tea auth login --with-token` instead of creating a new one.
Credentials go to the operating-system keyring (service `tea-cli-v2`). Pass
`--credential-store file` to store them in private files under the configuration
directory instead. The old release's OAuth tokens (keyring service `tea-cli`, and
`credentials.json` in the old configuration directory) are not read; delete them once you
have logged in again.
Managing accounts:
| Old | tea 1.0 |
|---|---|
| `tea login list`, `tea login status`, `tea whoami` | `tea auth status` (`--verify` checks each credential) |
| `tea login default NAME` | `tea config set default_host URL`, and `tea auth switch USER --host URL` for the active account |
| `tea login edit` | `tea config set --host URL <key> <value>` |
| `tea login delete NAME`, `tea logout NAME` | `tea auth logout --host URL [--user USER]` |
| `tea login oauth-refresh` | `tea auth refresh` |
### Environment variables
| Variable | tea 1.0 |
|---|---|
| `GITEA_TOKEN`, `GITEA_INSTANCE_URL` | supported; `TEA_HOST` is an alternative to `GITEA_INSTANCE_URL` |
| `GITEA_INSTANCE_INSECURE`, `GITEA_INSTANCE_SSH_HOST` | supported |
| `GH_TOKEN` | no longer read: use `GITEA_TOKEN` |
| `GITEA_SERVER_URL`, `GITEA_SERVER_TOKEN`, `GITEA_SERVER_USER`, `GITEA_SERVER_PASSWORD`, `GITEA_SERVER_OTP`, `GITEA_SCOPES` | removed with `tea login add` |
New variables: `TEA_CONFIG_DIR`, `TEA_HOST`, `TEA_USER`, `TEA_REPO`, `TEA_EDITOR`,
`TEA_PAGER` and `TEA_COLOR`; see `tea config --help`. Environment credentials are
never written to disk.
### Git credential helper
`tea login helper setup` and `tea login add --git-credentials` wrote two entries
to `~/.gitconfig` for each instance: an empty `credential.<url>.helper` and
`!tea login helper`. tea 1.0 has no `login` command, so Git now gets an error
from that helper and falls back to prompting. Remove both entries, then register
the new helper:
```sh
git config --global --get-all credential.https://gitea.example.org.helper
git config --global --unset-all credential.https://gitea.example.org.helper '^!tea login helper$'
git config --global --unset-all credential.https://gitea.example.org.helper '^$'
tea auth setup-git --host https://gitea.example.org
```
`tea repo clone`, `tea pr checkout`, `tea pr clean`, `tea repo sync` and
`tea pr create --agit` authenticate Git without any helper; `tea auth setup-git`
is only needed for plain `git` commands. Add `--local` to configure only the
current repository.
## Global flags
| Old | tea 1.0 |
|---|---|
| `--repo` / `-r` | `--repo` / `-R` |
| `--remote` / `-R` | `--remote` (no shorthand) |
| `--login` / `-l` | `--host URL`, plus `--user NAME` when the instance has several accounts |
| `--output` / `-o`, `--fields` / `-f` | `--json [fields]` and `--jq <expression>` |
| `--debug` / `--vvv` | `--debug` |
| `--confirm` / `-y`, `--force` / `-f` on destructive commands | `--yes` |
`-R` now means `--repo`: `tea issue list -R origin` fails with
`invalid repository URL` instead of selecting the `origin` remote. Use
`--remote origin`.
New global flags: `--no-input` disables prompts, editors and browsers, `--yes`
accepts confirmations, `--cwd` selects the directory used for repository
discovery, and `--sudo USER` acts as another user (administrators only).
## Renamed commands
All command groups are singular, and the built-in aliases (`ls`, `rm`, `c`, `e`,
`i`, `ms`, `co`, `lgtm`, …) are gone. `tea alias set NAME EXPANSION` defines your
own top-level shortcuts, for example `tea alias set co 'pr checkout'`; aliases
for subcommands such as `issue ls` are not possible.
Top-level groups:
| Old | tea 1.0 |
|---|---|
| `issues`, `issue`, `i` | `issue` |
| `pulls`, `pull`, `pr` | `pr` |
| `labels` | `label` |
| `milestones`, `ms` | `milestone` |
| `releases`, `r` | `release` |
| `times`, `t` | `time` |
| `organizations`, `org` | `org` |
| `repos` | `repo` |
| `branches`, `b` | `branch` |
| `actions secrets` | `secret` |
| `actions variables` | `variable` |
| `actions runs` | `run` |
| `actions workflows` | `workflow` |
| `webhooks`, `hooks` | `webhook` |
| `comments`, `c` | `issue comment` / `pr comment` |
| `notifications`, `n` | `notification` |
| `ssh-keys` | `ssh-key` |
| `admin users`, `admin u` | `admin user` |
| `logins`, `login`, `logout`, `whoami` | `auth` (see [Logging in](#logging-in-again)) |
| `clone`, `C` | `repo clone` |
| `open`, `o` | removed (see [Removed features](#removed-features)) |
Groups no longer run a default action: `tea issues` listed issues and
`tea issues 5` showed issue 5; use `tea issue list` and `tea issue view 5`.
The same applies to `pulls`, `notifications` and the other groups.
Subcommands:
| Old | tea 1.0 |
|---|---|
| `issues reopen`, `pulls reopen` (alias `open`) | `issue reopen`, `pr reopen` |
| `pulls approve <n> [comment]` | `pr review <n> --event APPROVED [--body TEXT]` |
| `pulls reject <n> <comment>` | `pr review <n> --event REQUEST_CHANGES --body TEXT` |
| `pulls review <n>` | `pr review <n>` |
| `pulls review-comments` | `pr review comments` |
| `pulls reply`, `resolve`, `unresolve` | `pr review reply`, `pr review resolve`, `pr review unresolve` |
| `labels update --id ID` | `label edit ID` |
| `labels delete --id ID` | `label delete ID` |
| `labels list --save` | `label export` |
| `milestones issues <name>` | `milestone issue list <milestone-id>`, or `milestone issue list --by-name <name>` |
| `milestones issues add\|remove` | `milestone issue add\|remove <milestone-id> <number>...` (`--by-name` selects by title) |
| `releases assets create` | `release asset upload` |
| `times add` | `time create` |
| `times list [user\|#issue]` | `time list [--username USER\|--issue N]` |
| `repos search` | `search repo` |
| `repos create-from-template` | `repo create --template OWNER/REPO` |
| `actions secrets create` | `secret set` |
| `actions variables list --name NAME` | `variable view NAME` |
| `actions runs delete` (alias `cancel`) | `run delete`; `run cancel` cancels without deleting |
| `actions workflows dispatch` | `workflow run` |
| `webhooks update` | `webhook edit` |
| `comments add <n> [body]` | `issue comment create <n> --body TEXT` (also `pr comment create`) |
| `notifications read\|unread [all\|id]` | `notification mark-read\|mark-unread [id]...`; use `--all` for every filtered notification |
| `ssh-keys add` | `ssh-key create` |
| `login helper setup` | `auth setup-git` |
| `completion pwsh` | `completion powershell` |
Renamed flags that appear on many commands:
| Old | tea 1.0 |
|---|---|
| `--description` / `-d`, `--description-file` (issues, pulls, comments) | `--body`, `--body-file` |
| `--note` / `-n`, `--note-file` / `-f` (releases) | `--body`, `--body-file` |
| `--content` / `-c` (wiki) | `--body`, `--body-file` |
| `--labels` / `-L`, `--assignees` / `-a`, `--milestones` / `-m` | `--label`, `--assignee`, `--milestone` |
| `--referenced-version` / `-v` | `--ref` |
| `--keyword` / `-k` | `--search` |
| `--from` / `-F` (issue list) | `--since` |
| `--states` / `-s`, `--types` / `-t` (notifications) | `--status`, `--type` |
| `--page` / `-p`, `--limit` / `--lm` | `--page`, `--limit` |
| `--style` / `-s` (pr merge) | `--method` / `-s` |
| `--owner` / `-O`, `--init`, `--labels`, `--trustmodel`, `--branch`, `--template` (repo create) | `--org`, `--auto-init`, `--label-template`, `--trust-model`, `--default-branch`, `--as-template` |
| `--inactive` (webhook) | `--active=false` |
| `--out` (man) | `--output-file` / `-o` |
Most other short flags were dropped; the long names are unchanged unless listed
here. Two flags kept their name but changed meaning:
- `workflow run`: `-f` was `--follow` and now means `--field KEY=VALUE`;
`--follow` has no shorthand. `-r` (`--ref`) and `-i` (`--input`) are unchanged.
- `api`: `--field` (`-f`) sent a string and `--Field` (`-F`) a typed value. Now
`--raw-field` / `-f` sends a string and `--field` / `-F` a typed value, so the
shorthands behave as before. `--data` / `-d` became `--input FILE` (or `-` for
stdin), `--include` lost `-i`, and `--output` / `-o` became `--output-file`.
## Changed positional arguments
| Command | Old | tea 1.0 |
|---|---|---|
| `milestone close\|reopen\|delete\|edit\|view` | milestone name | milestone ID; add `--by-name` to select by exact title |
| `milestone issue list\|add\|remove` | milestone name | milestone ID; add `--by-name` to select by exact title |
| `release asset delete <tag>` | attachment name | asset ID; add `--by-name` to select by exact name |
| `label edit\|delete` | `--id ID` | `ID` |
| `repo delete` | `--name NAME --owner OWNER` | optional `OWNER/REPO` argument (or `--repo`) |
| `issue comment create` | optional body argument | `--body`, `--body-file` or `--editor` |
A milestone whose title is a number is now read as an ID unless you pass
`--by-name`. Destructive commands still ask for confirmation unless `--yes` is
given.
## Output formats
`--output` / `-o` (`table`, `simple`, `csv`, `tsv`, `yaml`, `json`) and `--fields`
are gone. Human output is plain text; scripts should use JSON:
```sh
# old: tea issues list --fields index,title -o csv
tea issue list --json number,title --jq '.[] | "\(.number),\(.title)"'
# old: tea notifications --mine -o simple | xargs notify-send
tea notification list --mine --json title --jq '.[].title' | xargs -n1 notify-send
```
`--json` alone prints every field; `--json a,b` selects fields and rejects unknown
names; `--jq` filters the result. Commands that produce no resource, such as
deletes, reject `--json` with a usage error instead of printing nothing.
Lists print aligned columns without a header row and with fewer columns than
before: the ID or number first, then the title or name, then the state and a few
details (`issue list` and `pr list` show number, title, state and author). Do not
parse them; the columns may change. On a color terminal the first column links to
the resource. Tabs and line breaks in list cells become spaces, and control
characters such as escape sequences are dropped from all human output, bodies
included. Commands that change several resources at once, such as
`issue close 1 2`, `issue edit`, `milestone close`, `release edit` or
`notification mark-read`, print one table of the changed items in the matching
list's columns. When a list continues past the requested page, tea prints a
`--page` hint on stderr.
Issue, pull request and other bodies are printed as raw Markdown instead of being
rendered. Long output on a terminal goes through a pager (`TEA_PAGER`, the
`pager` preference or `PAGER`). Each command starts the pager at most once.
## Removed features
| Feature | Replacement |
|---|---|
| `tea open [number\|issues\|pulls\|releases\|commits\|branches\|wiki\|labels\|milestones\|activity\|settings\|<ref>]` | `tea issue view N --web`, `tea pr view N --web`, `tea repo view --web`; for other pages open `$(tea repo view --json url --jq .url)/releases` and similar |
| Basic-auth token creation (`login add --user/--password/--otp/--scopes`) | create a token in the web UI, or `tea auth login --oauth` |
| `login edit` | `tea config set --host URL <key> <value>` |
| Output formats and `--fields` | `--json` and `--jq` |
| Markdown rendering of bodies | raw Markdown, optionally paged |
| `contrib/autocomplete.*` scripts and the `--generate-shell-completion` protocol | `tea completion <shell>` |
| `GH_TOKEN`, `GITEA_SERVER_*`, `GITEA_SCOPES` | `GITEA_TOKEN`, `tea auth login` |
| `--vvv` | `--debug` |
### Shell completion
Completion scripts saved from an older `tea completion` (or the removed
`contrib/autocomplete.*` files) call tea with `--generate-shell-completion`, which
tea 1.0 rejects, so completion silently stops working. Regenerate them:
```sh
source <(tea completion bash) # ~/.bashrc
source <(tea completion zsh) # ~/.zshrc
tea completion fish > ~/.config/fish/completions/tea.fish
tea completion powershell | Out-String | Invoke-Expression # PowerShell profile
```
Packagers can ship the pre-generated scripts and man pages from the release docs
archive, or run `make docs`.
## Behavior changes
- `pr checkout N` creates or reuses the local branch `pr/N`; it no longer
switches to another local branch that already points at the PR head. Use
`--branch NAME` to check out into a branch you choose (it must point at the PR
head; `--update` fast-forwards it) or `--detach` for a detached checkout.
`-b` now takes the branch name.
- `webhook edit` must be told what to do with the delivery authorization header
on every call, because Gitea replaces it: pass `--authorization-header`,
`--authorization-header-file` or `--clear-authorization`. The signing secret
cannot be edited; recreate the hook to rotate it.
- `notification mark-read`, `mark-unread`, `pin` and `unpin` act on the given IDs;
pass `--all` to apply them to every notification matching the filters.
- `--no-input` disables prompts, editors and browsers. With `--json`, tea never
prompts unless `--interactive` is given; required values must come from flags.
- Destructive commands confirm on a terminal and need `--yes` elsewhere.
- `--limit` accepts 1 to 100 and `--page` a positive number; other values are
usage errors instead of being passed to the server.
- In `--json` output, timestamps the server leaves unset print as `""`, or as
`null` for optional fields such as deadlines, instead of
`0001-01-01T00:00:00Z`.
- More input is checked before anything is sent: release titles, issue titles
and comment bodies cannot be empty, a review needs a body or inline comments
(unless it approves), team creation needs a permission, migrations from
GitHub, Gitea, GitLab and Gogs need an access token, and `workflow run` needs
a ref (`--ref` or a checked-out branch).
- `pr merge` merges the head it read and refuses when the branch moved in the
meantime; run it again to merge the new head.
- Preferences follow the git/gh order: an explicit `tea config set` value wins
over `VISUAL`/`EDITOR`, `PAGER` and `BROWSER`, which win over the defaults;
`TEA_EDITOR`, `TEA_PAGER` and `TEA_COLOR` override both.