diff --git a/skills/example-skill/SKILL.md b/skills/example-skill/SKILL.md deleted file mode 100644 index eb1217b..0000000 --- a/skills/example-skill/SKILL.md +++ /dev/null @@ -1,19 +0,0 @@ -# Example Skill - -Use this directory as a template for new skills. - -## When To Use - -Use this skill when you want to demonstrate the expected shape of a skill in this -repository. - -## Workflow - -1. State why the skill applies. -2. Read only the files needed for the current task. -3. Follow the documented workflow. -4. Verify the outcome before reporting completion. - -## Notes - -Replace this example with real skills over time, or keep it as a reference. diff --git a/skills/gitea-tea/SKILL.md b/skills/gitea-tea/SKILL.md new file mode 100644 index 0000000..b8df4b1 --- /dev/null +++ b/skills/gitea-tea/SKILL.md @@ -0,0 +1,60 @@ +--- +name: gitea-tea +description: "Use this skill when working with Gitea instances through the official `tea` CLI: logging in to one or more Gitea servers, inspecting repositories, creating or editing issues, commenting on issues or pull requests, creating/checking out/reviewing/merging pull requests, creating releases, or making authenticated Gitea API calls from the terminal. Use it for Gitea/Forgejo-style collaboration workflows when the user mentions `tea`, Gitea CLI, Gitea issues, Gitea pull requests, Gitea releases, or Gitea instance automation." +--- + +# Gitea Tea + +## What This Skill Does + +Use `tea`, the official Gitea CLI, for terminal-driven work against one or more Gitea instances. Tea can infer repository context from `$PWD`, but for automation prefer explicit `--repo`, `--login`, or `--remote` arguments. + +Tea versions differ across package managers. Before running a mutating command in an unfamiliar environment, check the installed surface with `tea --version` and `tea --help`. + +## Fast Workflow + +1. Confirm authentication and context: + ```bash + tea login list + tea whoami --login + tea repos --login --owner -o table + ``` +2. For repository-scoped tasks, prefer `--repo owner/name --login login-name` unless you are already inside the correct local checkout. +3. For reads, use Tea's structured output when possible: + ```bash + tea issues --repo owner/name --login work --state open -o json + tea pulls --repo owner/name --login work --state all -o json + ``` +4. For writes, compose the exact command, verify required fields, then run it. Do not print tokens or passwords. +5. If Tea lacks a narrow command for the task, use `tea api`; see [references/api-fallbacks.md](references/api-fallbacks.md). + +## Common Scripts + +The scripts are in `scripts/` and are designed as small, predictable wrappers around Tea: + +- `tea-login-add.sh`: add a named login from environment variables or flags. +- `tea-issue-create.sh`: create an issue with title/body, labels, milestone, assignees, deadline. +- `tea-comment.sh`: add a comment to an issue or pull request, with body from an argument, file, or stdin. +- `tea-pr-create.sh`: create a pull request from published branches. +- `tea-pr-review.sh`: approve, reject, comment on, or merge a pull request. +- `tea-release-create.sh`: create a release and optionally attach assets. +- `tea-api.sh`: make authenticated API calls with `tea api`. + +Run any script with `--help` for exact arguments. + +## References + +Read only the reference needed for the current request: + +- [references/command-recipes.md](references/command-recipes.md): daily issue, PR, release, repo, branch, and notification commands. +- [references/auth-and-context.md](references/auth-and-context.md): login profiles, token handling, repo detection, CI setup, troubleshooting. +- [references/api-fallbacks.md](references/api-fallbacks.md): Gitea API patterns via `tea api` when the first-class CLI command is missing. + +## Operating Notes + +- `tea` is the Gitea client CLI. The separate `gitea` binary is the server/admin CLI; use it only for server administration when the user asks for instance maintenance. +- Tea stores configuration under `$XDG_CONFIG_HOME/tea` when set, otherwise the platform default config location. +- `tea issue` and `tea issues` are aliases. `tea pull`, `tea pulls`, and `tea pr` are aliases. +- Issue and pull request numbers are repository-local indexes. +- For PR creation, Tea assumes the local Git state has already been pushed to the remote. Publish the branch first unless the user explicitly wants only a draft command. +- For CI or unattended work, use `GITEA_SERVER_URL`, `GITEA_SERVER_TOKEN`, and `GITEA_SCOPES` for login setup, and prefer `--output json` for machine-readable reads. diff --git a/skills/gitea-tea/agents/openai.yaml b/skills/gitea-tea/agents/openai.yaml new file mode 100644 index 0000000..28072c6 --- /dev/null +++ b/skills/gitea-tea/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Gitea Tea" + short_description: "Use tea CLI for Gitea workflows" + default_prompt: "Use $gitea-tea to create an issue and comment on it with the Tea CLI." diff --git a/skills/gitea-tea/references/api-fallbacks.md b/skills/gitea-tea/references/api-fallbacks.md new file mode 100644 index 0000000..051da70 --- /dev/null +++ b/skills/gitea-tea/references/api-fallbacks.md @@ -0,0 +1,66 @@ +# API Fallbacks With `tea api` + +Use `tea api` when a first-class Tea command cannot express the required Gitea operation. Tea prefixes endpoints with `/api/v1/` unless the endpoint starts with `/api/` or a full URL. + +Inside a repository, placeholders such as `{owner}` and `{repo}` are replaced from context. Outside a checkout, pass `--repo owner/name --login login`. + +## Basic Forms + +```bash +tea api --login work --repo owner/name '/repos/{owner}/{repo}/issues?state=open' + +tea api --login work --repo owner/name \ + -X POST '/repos/{owner}/{repo}/issues/42/comments' \ + -f body='Thanks, I can reproduce this.' + +tea api --login work --repo owner/name \ + -X PATCH '/repos/{owner}/{repo}/issues/42' \ + -F state='"closed"' +``` + +Use `-f key=value` for string fields. Use `-F key=value` for typed JSON values such as booleans, numbers, arrays, objects, and `null`. + +## Raw JSON Body + +```bash +tea api --login work --repo owner/name \ + -X POST '/repos/{owner}/{repo}/issues' \ + --data @issue.json +``` + +Use `--data @-` to read JSON from stdin. Do not combine `--data` with `-f` or `-F`. + +## Common Endpoints + +Issue comments: + +```bash +tea api --login work --repo owner/name \ + '/repos/{owner}/{repo}/issues/42/comments' +``` + +Pull request files: + +```bash +tea api --login work --repo owner/name \ + '/repos/{owner}/{repo}/pulls/128/files' +``` + +Labels: + +```bash +tea api --login work --repo owner/name \ + '/repos/{owner}/{repo}/labels' +``` + +Repository metadata: + +```bash +tea api --login work '/repos/owner/name' +``` + +## Safety + +- Quote endpoints containing `?` or `&` to prevent shell expansion. +- For destructive methods such as `DELETE`, confirm the target owner, repo, and numeric index first. +- For scripted calls, capture output to a file with `--output response.json` or pipe to a JSON parser. diff --git a/skills/gitea-tea/references/auth-and-context.md b/skills/gitea-tea/references/auth-and-context.md new file mode 100644 index 0000000..d36ba15 --- /dev/null +++ b/skills/gitea-tea/references/auth-and-context.md @@ -0,0 +1,67 @@ +# Auth And Context + +## Login Profiles + +Tea supports multiple named Gitea instance logins: + +```bash +tea login add --name work --url https://git.example.com --token "$GITEA_TOKEN" +tea login add --name personal --url https://gitea.com --oauth +tea login default work +tea login list +``` + +For unattended use, set environment variables and run a non-interactive login: + +```bash +export GITEA_SERVER_URL=https://git.example.com +export GITEA_SERVER_TOKEN=... +export GITEA_SCOPES=write:repo,write:issue +tea login add --name ci --url "$GITEA_SERVER_URL" --token "$GITEA_SERVER_TOKEN" +``` + +Never echo tokens in final answers, logs, or scripts. When a user provides a token, use it only in the command environment. + +## Token Scopes + +Exact scope names can vary by Gitea version. Common needs: + +- Read repositories/issues/PRs: repo and issue read scopes. +- Create issues/comments/PRs/releases: write scopes for repo and issue areas. +- Admin commands: admin user or site scopes, depending on instance configuration. + +When scope failures occur, inspect the Gitea web UI under user Settings > Applications or the instance API documentation page. + +## Repository Detection + +Tea can infer context from the current local Git repository and its remotes. That is convenient for humans but risky in automation. + +Use this decision rule: + +- Known repo and login: pass `--repo owner/name --login login`. +- Current checkout should determine repo: pass `--remote origin` or `--remote upstream` if more than one Gitea remote exists. +- User asks for a local PR workflow: inspect `git remote -v`, current branch, upstream tracking, and whether the branch has been pushed. + +## CI Pattern + +```bash +tea login add --name ci \ + --url "$GITEA_SERVER_URL" \ + --token "$GITEA_SERVER_TOKEN" \ + --no-version-check + +tea comment --login ci --repo "$GITEA_REPOSITORY" "$GITEA_PULL_REQUEST_INDEX" \ + "Build passed for $GITEA_SHA." +``` + +Use CI-provided repository and issue/PR index variables when available. If the CI system does not provide an index, parse it from the event payload or use `tea api`. + +## Troubleshooting + +- Wrong repository: rerun with explicit `--repo owner/name --login login`. +- Login not found: run `tea login list`; add or set default login. +- TLS issues on private instances: only use `--insecure` when the user explicitly accepts the risk. +- Version mismatch: run `tea --version` and `tea --help`. +- Non-interactive hangs: avoid commands that prompt. Provide required flags such as `--title`, `--description`, `--token`, `--repo`, and `--login`. +- PR creation fails: verify the source branch has been pushed and `--head` refers to the published branch or `user:branch`. +- Comment body lost formatting: pass a file or stdin through `scripts/tea-comment.sh`. diff --git a/skills/gitea-tea/references/command-recipes.md b/skills/gitea-tea/references/command-recipes.md new file mode 100644 index 0000000..65cf61b --- /dev/null +++ b/skills/gitea-tea/references/command-recipes.md @@ -0,0 +1,131 @@ +# Tea Command Recipes + +Commands below are based on Tea `0.14.1`; check `tea --help` if a user's installation differs. + +## Login And Context + +```bash +tea login list +tea login default +tea login add --name work --url https://git.example.com --token "$GITEA_TOKEN" +tea whoami --login work +``` + +Repository context choices: + +- Inside a checkout with a Gitea remote: omit `--repo` and let Tea infer context. +- Outside a checkout: use `--repo owner/name --login work`. +- In a checkout with multiple remotes: use `--remote upstream` or `--remote origin`. + +## Issues + +List and inspect: + +```bash +tea issues --repo owner/name --login work --state open -o table +tea issues --repo owner/name --login work --state all --fields index,state,title,labels,assignees,url -o json +tea issue --repo owner/name --login work 42 --comments +``` + +Create: + +```bash +tea issue create --repo owner/name --login work \ + --title "Fix flaky deployment status" \ + --description "Observed in staging after the latest runner update." \ + --labels "bug,ci" \ + --assignees "alice" \ + --milestone "v1.4" +``` + +Edit, label, assign, close, reopen: + +```bash +tea issue edit --repo owner/name --login work 42 --add-labels "bug" --add-assignees "alice" +tea issue edit --repo owner/name --login work 42 --remove-labels "needs triage" +tea issue close --repo owner/name --login work 42 +tea issue reopen --repo owner/name --login work 42 +``` + +## Comments + +`tea comment` works for both issues and pull requests: + +```bash +tea comment --repo owner/name --login work 42 "I can reproduce this on main." +tea comment --repo owner/name --login work 128 "$(cat /tmp/review-note.md)" +``` + +Prefer the `tea-comment.sh` script when the comment body may contain newlines or shell-sensitive characters. + +## Pull Requests + +List and inspect: + +```bash +tea pulls --repo owner/name --login work --state open -o table +tea pull --repo owner/name --login work 128 --comments +tea pull checkout --repo owner/name --login work 128 +``` + +Create after pushing the source branch: + +```bash +git push -u origin feature-branch +tea pull create --repo owner/name --login work \ + --head feature-branch \ + --base main \ + --title "Add deployment health checks" \ + --description "Adds health probes and status reporting." \ + --labels "enhancement" \ + --allow-maintainer-edits +``` + +For fork workflows, use `:` for `--head`: + +```bash +tea pull create --repo upstream-owner/project --login work --head myuser:feature-branch --base main +``` + +Review and merge: + +```bash +tea pull approve --repo owner/name --login work 128 "LGTM" +tea pull reject --repo owner/name --login work 128 "Please add a regression test." +tea pull merge --repo owner/name --login work 128 --style squash --title "Add deployment health checks" +tea pull close --repo owner/name --login work 128 +``` + +## Releases + +```bash +tea releases --repo owner/name --login work -o table +tea release create --repo owner/name --login work \ + --tag v1.4.0 \ + --title "v1.4.0" \ + --note-file ./CHANGELOG.md \ + --asset ./dist/app.tar.gz \ + --asset ./dist/checksums.txt +``` + +Use `--draft` for staged releases and `--prerelease` for pre-release tags. + +## Repositories And Branches + +```bash +tea repos --login work --owner owner -o table +tea repos search --login work "project name" +tea repo owner/name --login work +tea branches --repo owner/name --login work +``` + +## Notifications + +```bash +tea notifications --login work --mine -o table +tea notifications --login work --repo owner/name -o json +``` + +## Output Formats + +Many list/show commands support `--output simple|table|csv|tsv|yaml|json`. Prefer `json` for scripts, `table` for human-facing terminal output, and `simple` for compact status summaries. diff --git a/skills/gitea-tea/scripts/tea-api.sh b/skills/gitea-tea/scripts/tea-api.sh new file mode 100755 index 0000000..99759a4 --- /dev/null +++ b/skills/gitea-tea/scripts/tea-api.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/tea-common.sh" + +usage() { + cat <<'EOF' +Make an authenticated Gitea API request through tea. + +Usage: + tea-api.sh ENDPOINT [--method METHOD] [--field key=value ...] [--typed-field key=value ...] [--data JSON_OR_@FILE] + +Examples: + tea-api.sh '/repos/{owner}/{repo}/issues?state=open' --repo owner/name --login work + tea-api.sh '/repos/{owner}/{repo}/issues/42/comments' --method POST --field body='Thanks' --repo owner/name +EOF + tea_usage_context +} + +endpoint="" +method="" +data="" +output="" +fields=() +typed_fields=() +headers=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --method|-X) method=${2:?}; shift 2 ;; + --field|-f) fields+=("${2:?}"); shift 2 ;; + --typed-field|-F) typed_fields+=("${2:?}"); shift 2 ;; + --header|-H) headers+=("${2:?}"); shift 2 ;; + --data|-d) data=${2:?}; shift 2 ;; + --output|-o) output=${2:?}; shift 2 ;; + --repo|-r) TEA_REPO=${2:?}; shift 2 ;; + --login|-l) TEA_LOGIN=${2:?}; shift 2 ;; + --remote|-R) TEA_REMOTE=${2:?}; shift 2 ;; + --help|-h) usage; exit 0 ;; + *) + if [[ -z "$endpoint" ]]; then + endpoint=$1 + shift + else + echo "error: unknown argument: $1" >&2 + usage >&2 + exit 2 + fi + ;; + esac +done + +tea_require +[[ -n "$endpoint" ]] || { echo "error: ENDPOINT is required" >&2; exit 2; } +if [[ -n "$data" && (${#fields[@]} -gt 0 || ${#typed_fields[@]} -gt 0) ]]; then + echo "error: --data cannot be combined with --field or --typed-field" >&2 + exit 2 +fi + +args=(api) +tea_append_context_args args +[[ -n "$method" ]] && args+=(--method "$method") +[[ -n "$data" ]] && args+=(--data "$data") +[[ -n "$output" ]] && args+=(--output "$output") +for field in "${fields[@]}"; do + args+=(--field "$field") +done +for field in "${typed_fields[@]}"; do + args+=(--Field "$field") +done +for header in "${headers[@]}"; do + args+=(--header "$header") +done +args+=("$endpoint") + +exec tea "${args[@]}" diff --git a/skills/gitea-tea/scripts/tea-comment.sh b/skills/gitea-tea/scripts/tea-comment.sh new file mode 100755 index 0000000..c6240cc --- /dev/null +++ b/skills/gitea-tea/scripts/tea-comment.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/tea-common.sh" + +usage() { + cat <<'EOF' +Add a comment to a Gitea issue or pull request. + +Usage: + tea-comment.sh INDEX [--body TEXT | --body-file FILE] + command-producing-body | tea-comment.sh INDEX +EOF + tea_usage_context +} + +index="" +body="" +body_file="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --body|-b) body=${2:?}; shift 2 ;; + --body-file|-F) body_file=${2:?}; shift 2 ;; + --repo|-r) TEA_REPO=${2:?}; shift 2 ;; + --login|-l) TEA_LOGIN=${2:?}; shift 2 ;; + --remote|-R) TEA_REMOTE=${2:?}; shift 2 ;; + --help|-h) usage; exit 0 ;; + *) + if [[ -z "$index" ]]; then + index=$1 + shift + else + echo "error: unknown argument: $1" >&2 + usage >&2 + exit 2 + fi + ;; + esac +done + +tea_require +[[ -n "$index" ]] || { echo "error: INDEX is required" >&2; exit 2; } +[[ -z "$body" || -z "$body_file" ]] || { echo "error: use --body or --body-file, not both" >&2; exit 2; } + +comment_body="$(tea_read_body "$body" "$body_file")" +[[ -n "$comment_body" ]] || { echo "error: comment body is empty" >&2; exit 2; } + +args=(comment) +tea_append_context_args args +args+=("$index" "$comment_body") +exec tea "${args[@]}" diff --git a/skills/gitea-tea/scripts/tea-common.sh b/skills/gitea-tea/scripts/tea-common.sh new file mode 100755 index 0000000..fc1e65e --- /dev/null +++ b/skills/gitea-tea/scripts/tea-common.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -euo pipefail + +tea_require() { + if ! command -v tea >/dev/null 2>&1; then + echo "error: tea CLI is not installed or not on PATH" >&2 + exit 127 + fi +} + +tea_append_context_args() { + local -n _out=$1 + local repo=${TEA_REPO:-} + local login=${TEA_LOGIN:-} + local remote=${TEA_REMOTE:-} + + if [[ -n "$repo" ]]; then + _out+=(--repo "$repo") + fi + if [[ -n "$login" ]]; then + _out+=(--login "$login") + fi + if [[ -n "$remote" ]]; then + _out+=(--remote "$remote") + fi +} + +tea_read_body() { + local inline=${1:-} + local file=${2:-} + + if [[ -n "$inline" ]]; then + printf '%s' "$inline" + elif [[ -n "$file" ]]; then + [[ -r "$file" ]] || { echo "error: cannot read body file: $file" >&2; exit 2; } + sed -n '1,$p' "$file" + else + cat + fi +} + +tea_read_optional_body() { + local inline=${1:-} + local file=${2:-} + + if [[ -n "$inline" || -n "$file" ]]; then + tea_read_body "$inline" "$file" + elif [[ ! -t 0 ]]; then + cat + else + printf '' + fi +} + +tea_usage_context() { + cat <<'EOF' +Context flags: + --repo OWNER/REPO Repository slug. Can also be set with TEA_REPO. + --login NAME Tea login profile. Can also be set with TEA_LOGIN. + --remote NAME Git remote for context discovery. Can also be set with TEA_REMOTE. +EOF +} diff --git a/skills/gitea-tea/scripts/tea-issue-create.sh b/skills/gitea-tea/scripts/tea-issue-create.sh new file mode 100755 index 0000000..d20193f --- /dev/null +++ b/skills/gitea-tea/scripts/tea-issue-create.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/tea-common.sh" + +usage() { + cat <<'EOF' +Create a Gitea issue with tea. + +Usage: + tea-issue-create.sh --title TITLE [--body TEXT | --body-file FILE] [options] + +Options: + --labels CSV Comma-separated labels. + --assignees CSV Comma-separated usernames. + --milestone NAME Milestone name. + --deadline DATE Deadline timestamp accepted by Gitea. + --version REF Referenced commit hash or tag. +EOF + tea_usage_context +} + +title="" +body="" +body_file="" +labels="" +assignees="" +milestone="" +deadline="" +version="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --title|-t) title=${2:?}; shift 2 ;; + --body|--description|-d) body=${2:?}; shift 2 ;; + --body-file|--description-file) body_file=${2:?}; shift 2 ;; + --labels|-L) labels=${2:?}; shift 2 ;; + --assignees|-a) assignees=${2:?}; shift 2 ;; + --milestone|-m) milestone=${2:?}; shift 2 ;; + --deadline|-D) deadline=${2:?}; shift 2 ;; + --version|--referenced-version|-v) version=${2:?}; shift 2 ;; + --repo|-r) TEA_REPO=${2:?}; shift 2 ;; + --login|-l) TEA_LOGIN=${2:?}; shift 2 ;; + --remote|-R) TEA_REMOTE=${2:?}; shift 2 ;; + --help|-h) usage; exit 0 ;; + *) echo "error: unknown argument: $1" >&2; usage >&2; exit 2 ;; + esac +done + +tea_require +[[ -n "$title" ]] || { echo "error: --title is required" >&2; exit 2; } +[[ -z "$body" || -z "$body_file" ]] || { echo "error: use --body or --body-file, not both" >&2; exit 2; } + +description="$(tea_read_optional_body "$body" "$body_file")" +args=(issue create --title "$title" --description "$description") +tea_append_context_args args +[[ -n "$labels" ]] && args+=(--labels "$labels") +[[ -n "$assignees" ]] && args+=(--assignees "$assignees") +[[ -n "$milestone" ]] && args+=(--milestone "$milestone") +[[ -n "$deadline" ]] && args+=(--deadline "$deadline") +[[ -n "$version" ]] && args+=(--referenced-version "$version") + +exec tea "${args[@]}" diff --git a/skills/gitea-tea/scripts/tea-login-add.sh b/skills/gitea-tea/scripts/tea-login-add.sh new file mode 100755 index 0000000..35968e5 --- /dev/null +++ b/skills/gitea-tea/scripts/tea-login-add.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat <<'EOF' +Add a named Gitea login for tea. + +Usage: + tea-login-add.sh --name NAME --url URL [--token TOKEN] [--scopes SCOPES] [--no-version-check] [--insecure] + +Environment: + GITEA_SERVER_URL Used when --url is omitted. + GITEA_SERVER_TOKEN Used when --token is omitted. + GITEA_SCOPES Used when --scopes is omitted. + +Examples: + GITEA_SERVER_TOKEN=... tea-login-add.sh --name work --url https://git.example.com + tea-login-add.sh --name ci --url "$GITEA_SERVER_URL" --token "$GITEA_SERVER_TOKEN" --no-version-check +EOF +} + +name="" +url="${GITEA_SERVER_URL:-}" +token="${GITEA_SERVER_TOKEN:-}" +scopes="${GITEA_SCOPES:-}" +no_version_check=0 +insecure=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --name|-n) name=${2:?}; shift 2 ;; + --url|-u) url=${2:?}; shift 2 ;; + --token|-t) token=${2:?}; shift 2 ;; + --scopes) scopes=${2:?}; shift 2 ;; + --no-version-check|--nv) no_version_check=1; shift ;; + --insecure|-i) insecure=1; shift ;; + --help|-h) usage; exit 0 ;; + *) echo "error: unknown argument: $1" >&2; usage >&2; exit 2 ;; + esac +done + +[[ -n "$name" ]] || { echo "error: --name is required" >&2; exit 2; } +[[ -n "$url" ]] || { echo "error: --url or GITEA_SERVER_URL is required" >&2; exit 2; } +[[ -n "$token" ]] || { echo "error: --token or GITEA_SERVER_TOKEN is required" >&2; exit 2; } + +args=(login add --name "$name" --url "$url" --token "$token") +[[ -n "$scopes" ]] && args+=(--scopes "$scopes") +[[ "$no_version_check" -eq 1 ]] && args+=(--no-version-check) +[[ "$insecure" -eq 1 ]] && args+=(--insecure) + +exec tea "${args[@]}" diff --git a/skills/gitea-tea/scripts/tea-pr-create.sh b/skills/gitea-tea/scripts/tea-pr-create.sh new file mode 100755 index 0000000..b897d60 --- /dev/null +++ b/skills/gitea-tea/scripts/tea-pr-create.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/tea-common.sh" + +usage() { + cat <<'EOF' +Create a Gitea pull request with tea. + +Usage: + tea-pr-create.sh --title TITLE [--body TEXT | --body-file FILE] [--head BRANCH] [--base BRANCH] [options] + +Options: + --allow-maintainer-edits Allow maintainers to push to the source branch. + --labels CSV Comma-separated labels. + --assignees CSV Comma-separated usernames. + --milestone NAME Milestone name. + --deadline DATE Deadline timestamp accepted by Gitea. +EOF + tea_usage_context +} + +title="" +body="" +body_file="" +head="" +base="" +labels="" +assignees="" +milestone="" +deadline="" +edits=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --title|-t) title=${2:?}; shift 2 ;; + --body|--description|-d) body=${2:?}; shift 2 ;; + --body-file|--description-file) body_file=${2:?}; shift 2 ;; + --head) head=${2:?}; shift 2 ;; + --base|-b) base=${2:?}; shift 2 ;; + --allow-maintainer-edits|--edits) edits=1; shift ;; + --labels|-L) labels=${2:?}; shift 2 ;; + --assignees|-a) assignees=${2:?}; shift 2 ;; + --milestone|-m) milestone=${2:?}; shift 2 ;; + --deadline|-D) deadline=${2:?}; shift 2 ;; + --repo|-r) TEA_REPO=${2:?}; shift 2 ;; + --login|-l) TEA_LOGIN=${2:?}; shift 2 ;; + --remote|-R) TEA_REMOTE=${2:?}; shift 2 ;; + --help|-h) usage; exit 0 ;; + *) echo "error: unknown argument: $1" >&2; usage >&2; exit 2 ;; + esac +done + +tea_require +[[ -n "$title" ]] || { echo "error: --title is required" >&2; exit 2; } +[[ -z "$body" || -z "$body_file" ]] || { echo "error: use --body or --body-file, not both" >&2; exit 2; } + +description="$(tea_read_optional_body "$body" "$body_file")" +args=(pull create --title "$title" --description "$description") +tea_append_context_args args +[[ -n "$head" ]] && args+=(--head "$head") +[[ -n "$base" ]] && args+=(--base "$base") +[[ "$edits" -eq 1 ]] && args+=(--allow-maintainer-edits) +[[ -n "$labels" ]] && args+=(--labels "$labels") +[[ -n "$assignees" ]] && args+=(--assignees "$assignees") +[[ -n "$milestone" ]] && args+=(--milestone "$milestone") +[[ -n "$deadline" ]] && args+=(--deadline "$deadline") + +exec tea "${args[@]}" diff --git a/skills/gitea-tea/scripts/tea-pr-review.sh b/skills/gitea-tea/scripts/tea-pr-review.sh new file mode 100755 index 0000000..df86141 --- /dev/null +++ b/skills/gitea-tea/scripts/tea-pr-review.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/tea-common.sh" + +usage() { + cat <<'EOF' +Review or merge a Gitea pull request. + +Usage: + tea-pr-review.sh approve INDEX [--body TEXT | --body-file FILE] + tea-pr-review.sh reject INDEX [--body TEXT | --body-file FILE] + tea-pr-review.sh comment INDEX [--body TEXT | --body-file FILE] + tea-pr-review.sh merge INDEX [--style merge|rebase|squash|rebase-merge] [--title TITLE] [--message MESSAGE] +EOF + tea_usage_context +} + +action="${1:-}" +if [[ "$action" == "--help" || "$action" == "-h" ]]; then + usage + exit 0 +fi +[[ -n "$action" ]] || { usage >&2; exit 2; } +shift || true + +index="" +body="" +body_file="" +style="" +title="" +message="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --body|-b) body=${2:?}; shift 2 ;; + --body-file|-F) body_file=${2:?}; shift 2 ;; + --style|-s) style=${2:?}; shift 2 ;; + --title|-t) title=${2:?}; shift 2 ;; + --message|-m) message=${2:?}; shift 2 ;; + --repo|-r) TEA_REPO=${2:?}; shift 2 ;; + --login|-l) TEA_LOGIN=${2:?}; shift 2 ;; + --remote|-R) TEA_REMOTE=${2:?}; shift 2 ;; + --help|-h) usage; exit 0 ;; + *) + if [[ -z "$index" ]]; then + index=$1 + shift + else + echo "error: unknown argument: $1" >&2 + usage >&2 + exit 2 + fi + ;; + esac +done + +tea_require +[[ -n "$index" ]] || { echo "error: INDEX is required" >&2; exit 2; } +[[ -z "$body" || -z "$body_file" ]] || { echo "error: use --body or --body-file, not both" >&2; exit 2; } + +args=() +case "$action" in + approve) + comment="$(tea_read_optional_body "$body" "$body_file")" + args=(pull approve) + ;; + reject) + reason="$(tea_read_body "$body" "$body_file")" + [[ -n "$reason" ]] || { echo "error: reject requires --body, --body-file, or stdin" >&2; exit 2; } + args=(pull reject) + ;; + comment) + comment="$(tea_read_body "$body" "$body_file")" + [[ -n "$comment" ]] || { echo "error: comment requires --body, --body-file, or stdin" >&2; exit 2; } + args=(comment) + ;; + merge) + args=(pull merge) + [[ -n "$style" ]] && args+=(--style "$style") + [[ -n "$title" ]] && args+=(--title "$title") + [[ -n "$message" ]] && args+=(--message "$message") + ;; + *) + echo "error: action must be approve, reject, comment, or merge" >&2 + usage >&2 + exit 2 + ;; +esac + +tea_append_context_args args +case "$action" in + approve) + args+=("$index") + [[ -n "$comment" ]] && args+=("$comment") + ;; + reject) + args+=("$index" "$reason") + ;; + comment) + args+=("$index" "$comment") + ;; + merge) + args+=("$index") + ;; +esac +exec tea "${args[@]}" diff --git a/skills/gitea-tea/scripts/tea-release-create.sh b/skills/gitea-tea/scripts/tea-release-create.sh new file mode 100755 index 0000000..5e74727 --- /dev/null +++ b/skills/gitea-tea/scripts/tea-release-create.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/tea-common.sh" + +usage() { + cat <<'EOF' +Create a Gitea release with tea. + +Usage: + tea-release-create.sh --tag TAG [--title TITLE] [--note TEXT | --note-file FILE] [--asset FILE ...] [--draft] [--prerelease] +EOF + tea_usage_context +} + +tag="" +title="" +note="" +note_file="" +target="" +draft=0 +prerelease=0 +assets=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --tag) tag=${2:?}; shift 2 ;; + --title|-t) title=${2:?}; shift 2 ;; + --note|-n) note=${2:?}; shift 2 ;; + --note-file|-f) note_file=${2:?}; shift 2 ;; + --target) target=${2:?}; shift 2 ;; + --asset|-a) assets+=("${2:?}"); shift 2 ;; + --draft|-d) draft=1; shift ;; + --prerelease|-p) prerelease=1; shift ;; + --repo|-r) TEA_REPO=${2:?}; shift 2 ;; + --login|-l) TEA_LOGIN=${2:?}; shift 2 ;; + --remote|-R) TEA_REMOTE=${2:?}; shift 2 ;; + --help|-h) usage; exit 0 ;; + *) echo "error: unknown argument: $1" >&2; usage >&2; exit 2 ;; + esac +done + +tea_require +[[ -n "$tag" ]] || { echo "error: --tag is required" >&2; exit 2; } +[[ -z "$note" || -z "$note_file" ]] || { echo "error: use --note or --note-file, not both" >&2; exit 2; } + +args=(release create --tag "$tag") +tea_append_context_args args +[[ -n "$title" ]] && args+=(--title "$title") +[[ -n "$note" ]] && args+=(--note "$note") +[[ -n "$note_file" ]] && args+=(--note-file "$note_file") +[[ -n "$target" ]] && args+=(--target "$target") +[[ "$draft" -eq 1 ]] && args+=(--draft) +[[ "$prerelease" -eq 1 ]] && args+=(--prerelease) +for asset in "${assets[@]}"; do + args+=(--asset "$asset") +done + +exec tea "${args[@]}"