gitea_client

This commit is contained in:
2025-09-05 10:42:55 +03:00
parent dd1a0c0c51
commit b87f898468

213
gitea-client.zsh Executable file
View File

@@ -0,0 +1,213 @@
#!/usr/bin/env zsh
# ==============================================================================
# Gitea Client Wrapper (gitea-client.zsh) - FULLY FEATURED
#
# PURPOSE:
# Высокоуровневая, отказоустойчивая обертка над 'tea' для
# использования AI-агентами. Абстрагирует сложность управления
# контекстом, предоставляет атомарные операции и прозрачный вывод.
#
# VERSION: 1.4
# CHANGE LOG:
# - v1.4: Добавлены критически важные функции 'create-task' и 'create-pr',
# чтобы полностью соответствовать архитектуре системы
# 'AI_Dev_System_Ivanov_Gemini_v1.1'.
# - v1.3: Исправлена критическая ошибка парсинга remote URL,
# когда в SSH адресе присутствует номер порта.
# Логика `initialize` полностью переработана для надежности.
# ==============================================================================
# --- ОБРАБОТКА ОШИБОК И ВЫХОД ---
set -e
set -u
set -o pipefail
# --- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ И НАСТРОЙКИ ---
ROLE_NAME=""
REPO_SLUG=""
VERBOSE="true"
# --- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ---
log_info() {
if [[ "$VERBOSE" == "true" ]]; then
echo -e "\033[34m[INFO]\033[0m $1" >&2
fi
}
error_exit() {
echo -e "\033[31m[ОШИБКА ЛОГИКИ]\033[0m $1" >&2
exit 1
}
# --- ЦЕНТРАЛИЗОВАННЫЙ ИСПОЛНИТЕЛЬ КОМАНД ---
run_command() {
log_info "Выполняется команда:"
echo -e "\033[33m[CMD]\033[0m $@" >&2
local output
local exit_code
output=$("$@" 2>&1)
exit_code=$?
if [[ $exit_code -ne 0 ]]; then
echo -e "\033[31m[ОШИБКА ВЫПОЛНЕНИЯ]\033[0m Команда завершилась с кодом $exit_code." >&2
echo "------------------------- ВЫВОД КОМАНДЫ -------------------------" >&2
echo "$output" >&2
echo "-----------------------------------------------------------------" >&2
exit $exit_code
fi
echo "$output"
}
# --- ИНИЦИАЛИЗАЦИЯ И ПРОВЕРКИ ---
initialize() {
log_info "Инициализация клиента..."
for cmd in git tea jq; do
command -v "$cmd" >/dev/null 2>&1 || error_exit "Зависимость не найдена: $cmd. Пожалуйста, установите ее."
done
local git_remote_url
git_remote_url=$(run_command git remote get-url origin) || error_exit "Не удалось определить remote URL."
# Надежная логика парсинга для SSH и HTTPS URL
local path_part=$(echo "$git_remote_url" | sed -n 's|.*//[^/]*/\(.*\)|\1|p')
if [[ -z "$path_part" ]]; then
path_part=$(echo "$git_remote_url" | sed -n 's|.*:\(.*\)|
\1|p')
fi
REPO_SLUG=$(echo "$path_part" | sed 's/\.git$//')
[[ -z "$REPO_SLUG" ]] && error_exit "Не удалось извлечь 'owner/repo' из URL: $git_remote_url"
log_info "Репозиторий определен как: $REPO_SLUG"
[[ -z "$ROLE_NAME" ]] && error_exit "Имя роли (ROLE_NAME) не было предоставлено."
log_info "Роль установлена: $ROLE_NAME"
}
# --- ФУНКЦИИ КОМАНД ---
create_task() {
local title="" body="" assignee="" labels=""
while [[ $# -gt 0 ]]; do case $1 in
--title) title="$2"; shift 2;;
--body) body="$2"; shift 2;;
--assignee) assignee="$2"; shift 2;;
--labels) labels="$2"; shift 2;;
*) shift;;
esac; done
[[ -z "$title" || -z "$body" || -z "$assignee" || -z "$labels" ]] && error_exit "Для 'create-task' требуются флаги --title, --body, --assignee, --labels."
log_info "Создание задачи для '$assignee'..."
run_command tea issues create --repo "$REPO_SLUG" \
--title "$title" \
--description "$body" \
--assignees "$assignee" \
--labels "$labels"
log_info "Задача успешно создана."
}
create_pr() {
local title="" body="" head="" base="main"
while [[ $# -gt 0 ]]; do case $1 in
--title) title="$2"; shift 2;;
--body) body="$2"; shift 2;;
--head) head="$2"; shift 2;;
--base) base="$2"; shift 2;;
*) shift;;
esac; done
[[ -z "$title" || -z "$body" || -z "$head" ]] && error_exit "Для 'create-pr' требуются флаги --title, --body, --head."
log_info "Создание Pull Request из ветки '$head' в '$base' ભા"
run_command tea pr create --repo "$REPO_SLUG" \
--title "$title" \
--description "$body" \
--head "$head" \
--base "$base"
log_info "Pull Request успешно создан."
}
find_tasks() {
local task_type=""
while [[ $# -gt 0 ]]; do case $1 in --type) task_type="$2"; shift 2;; *) shift;; esac; done
[[ -z "$task_type" ]] && error_exit "Для 'find-tasks' требуется флаг --type."
local issues_json
issues_json=$(run_command tea issues list --output json --repo "$REPO_SLUG" --labels "$task_type" --state "open")
if [[ -z "$issues_json" || "$issues_json" == "[]" ]]; then
echo "[]"
else
echo "$issues_json" | jq -c '.[] | select(.labels[]?.name == "status::pending")'
fi
}
update_task_status() {
local issue_id="" old_status="" new_status=""
while [[ $# -gt 0 ]]; do case $1 in --issue-id) issue_id="$2"; shift 2;; --old) old_status="$2"; shift 2;; --new) new_status="$2"; shift 2;; *) shift;; esac; done
[[ -z "$issue_id" || -z "$old_status" || -z "$new_status" ]] && error_exit "Для 'update-task-status' требуются флаги --issue-id, --old, --new."
run_command tea issues edit "$issue_id" --repo "$REPO_SLUG" --remove-labels "$old_status" --add-labels "$new_status"
log_info "Статус задачи #$issue_id успешно обновлен на '$new_status'."
}
merge_and_complete() {
local issue_id="" pr_id="" branch_name=""
while [[ $# -gt 0 ]]; do case $1 in --issue-id) issue_id="$2"; shift 2;; --pr-id) pr_id="$2"; shift 2;; --branch) branch_name="$2"; shift 2;; *) shift;; esac; done
[[ -z "$issue_id" || -z "$pr_id" || -z "$branch_name" ]] && error_exit "Для 'merge-and-complete' требуются флаги --issue-id, --pr-id, --branch."
log_info "Слияние PR #$pr_id..."
run_command tea pr merge "$pr_id" --repo "$REPO_SLUG"
log_info "Удаление ветки '$branch_name'..."
run_command git push origin --delete "$branch_name"
log_info "Закрытие задачи #$issue_id..."
run_command tea issues close "$issue_id" --repo "$REPO_SLUG"
log_info "Процесс успешно завершен."
}
return_to_dev() {
local issue_id="" pr_id="" report=""
while [[ $# -gt 0 ]]; do case $1 in --issue-id) issue_id="$2"; shift 2;; --pr-id) pr_id="$2"; shift 2;; --report) report="$2"; shift 2;; *) shift;; esac; done
[[ -z "$issue_id" || -z "$pr_id" || -z "$report" ]] && error_exit "Для 'return-to-dev' требуются флаги --issue-id, --pr-id, --report."
log_info "Отклонение PR #$pr_id..."
run_command tea pr close "$pr_id" --repo "$REPO_SLUG"
log_info "Добавление отчета о дефектах в задачу #$issue_id..."
run_command tea issues comment create "$issue_id" --repo "$REPO_SLUG" --comment "$report"
log_info "Возврат задачи #$issue_id разработчику..."
run_command tea issues edit "$issue_id" --repo "$REPO_SLUG" \
--title "[QA -> DEV] FAILED: Fix Defects in PR #$pr_id" \
--assignee "agent-developer" \
--remove-labels "status::in-progress,type::quality-assurance" \
--add-labels "status::failed,type::development"
log_info "Задача возвращена."
}
# --- ГЛАВНЫЙ ДИСПЕТЧЕР КОМАНД ---
main() {
[[ $# -lt 2 ]] && error_exit "Неверное использование. Требуется: ./gitea-client.zsh <ROLE_NAME> <COMMAND> [OPTIONS]"
ROLE_NAME="$1"; shift
local COMMAND="$1"; shift
initialize
case "$COMMAND" in
create-task) create_task "$@";;
create-pr) create_pr "$@";;
find-tasks) find_tasks "$@";;
update-task-status) update_task_status "$@";;
merge-and-complete) merge_and_complete "$@";;
return-to-dev) return_to_dev "$@";;
*) error_exit "Неизвестная команда: '$COMMAND'";;
esac
}
# --- ТОЧКА ВХОДА ---
main "$@"