gitea-client
This commit is contained in:
504
gitea-client-mock.zsh
Normal file
504
gitea-client-mock.zsh
Normal file
@@ -0,0 +1,504 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Mock curl function
|
||||
function curl() {
|
||||
echo "MOCK_CURL_CALL: $*" >&2
|
||||
# Simulate a successful response for GET requests, especially for issue data
|
||||
if [[ "$1" == "-s" && "$3" == "GET" ]]; then
|
||||
if [[ "$6" == *"issues/"* ]]; then
|
||||
# Simulate issue data for update_task_status
|
||||
echo '{"labels": [{"name": "status::pending"}, {"name": "type::development"}], "id": 123}'
|
||||
else
|
||||
echo '[]' # Empty array for find_tasks
|
||||
fi
|
||||
elif [[ "$1" == "-s" && "$3" == "POST" && "$6" == *"pulls/"* ]]; then
|
||||
echo '{"merged": true}' # Simulate successful PR merge
|
||||
else
|
||||
echo '{}' # Generic successful response for other POST/PATCH/DELETE
|
||||
fi
|
||||
}
|
||||
|
||||
#!/usr/bin/env zsh
|
||||
# [PACKAGE: 'homebox_lens']
|
||||
# [FILE: 'gitea-client.zsh']
|
||||
# [SEMANTICS]
|
||||
# [ENTITY: 'File'('gitea-client.zsh')]
|
||||
# [ENTITY: 'Function'('api_request')]
|
||||
# [ENTITY: 'Function'('find_tasks')]
|
||||
# [ENTITY: 'Function'('update_task_status')]
|
||||
# [ENTITY: 'Function'('create_pr')]
|
||||
# [ENTITY: 'Function'('create_task')]
|
||||
# [ENTITY: 'Function'('add_comment')]
|
||||
# [ENTITY: 'Function'('merge_and_complete')]
|
||||
# [ENTITY: 'Function'('return_to_dev')]
|
||||
# [ENTITY: 'EntryPoint'('main_dispatch')]
|
||||
# [ENTITY: 'Configuration'('GITEA_URL')]
|
||||
# [ENTITY: 'Configuration'('GITEA_TOKEN')]
|
||||
# [ENTITY: 'Configuration'('GITEA_OWNER')]
|
||||
# [ENTITY: 'Configuration'('GITEA_REPO')]
|
||||
# [ENTITY: 'ExternalCommand'('jq')]
|
||||
# [ENTITY: 'ExternalCommand'('curl')]
|
||||
# [RELATION: 'File'('gitea-client.zsh')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'File'('gitea-client.zsh')] -> [DEPENDS_ON] -> ['ExternalCommand'('curl')]
|
||||
# [RELATION: 'Function'('api_request')] -> [DEPENDS_ON] -> ['ExternalCommand'('curl')]
|
||||
# [RELATION: 'Function'('api_request')] -> [READS_FROM] -> ['Configuration'('GITEA_URL')]
|
||||
# [RELATION: 'Function'('api_request')] -> [READS_FROM] -> ['Configuration'('GITEA_TOKEN')]
|
||||
# [RELATION: 'Function'('find_tasks')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('update_task_status')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('update_task_status')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('create_pr')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('create_pr')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('create_task')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('create_task')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('add_comment')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('add_comment')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('merge_and_complete')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('merge_and_complete')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('return_to_dev')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('return_to_dev')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('find_tasks')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('update_task_status')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('create_pr')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('create_task')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('add_comment')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('merge_and_complete')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('return_to_dev')]
|
||||
# [END_SEMANTICS]
|
||||
|
||||
set -x
|
||||
|
||||
# [DEPENDENCIES]
|
||||
# Gitea Client Script
|
||||
# Version: 1.0
|
||||
if ! command -v jq &> /dev/null;
|
||||
then
|
||||
echo "jq could not be found. Please install jq to use this script."
|
||||
exit 1
|
||||
fi
|
||||
# [END_DEPENDENCIES]
|
||||
|
||||
# [CONFIGURATION]
|
||||
# IMPORTANT: Replace with your Gitea URL, API Token, repository owner and repository name.
|
||||
# You can also set these as environment variables: GITEA_URL, GITEA_TOKEN, GITEA_OWNER, GITEA_REPO
|
||||
: ${GITEA_URL:="https://gitea.bebesh.ru"}
|
||||
: ${GITEA_TOKEN:="c6fb6d73a18b2b4ddf94b67f2da6b6bb832164ce"}
|
||||
: ${GITEA_OWNER:="busya"}
|
||||
: ${GITEA_REPO:="homebox_lens"}
|
||||
# [END_CONFIGURATION]
|
||||
|
||||
|
||||
# [HELPERS]
|
||||
|
||||
# [ENTITY: 'Function'('api_request')]
|
||||
# [CONTRACT]
|
||||
# Generic function to make requests to the Gitea API.
|
||||
# This is the central communication point with the Gitea instance.
|
||||
#
|
||||
# @param $1: method - The HTTP method (GET, POST, PATCH).
|
||||
# @param $2: endpoint - The API endpoint (e.g., "repos/owner/repo/issues").
|
||||
# @param $3: json_data - The JSON payload for POST/PATCH requests.
|
||||
#
|
||||
# @stdout The body of the API response on success.
|
||||
# @stderr Error messages on failure.
|
||||
#
|
||||
# @returns 0 on success, 1 on unsupported method. Curl exit code on curl failure.
|
||||
# [/CONTRACT]
|
||||
function api_request() {
|
||||
local method="$1"
|
||||
local endpoint="$2"
|
||||
local data="$3"
|
||||
local url="$GITEA_URL/api/v1/$endpoint"
|
||||
|
||||
local -a curl_opts
|
||||
curl_opts=("-s" "-H" "Authorization: token $GITEA_TOKEN" "-H" "Content-Type: application/json")
|
||||
|
||||
case "$method" in
|
||||
GET)
|
||||
curl "${curl_opts[@]}" "$url"
|
||||
;;
|
||||
POST|PATCH)
|
||||
curl "${curl_opts[@]}" -X "$method" -d @- "$url" <<< "$data"
|
||||
;; *)
|
||||
echo "Unsupported HTTP method: $method" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
# [END_ENTITY: 'Function'('api_request')]
|
||||
|
||||
# [END_HELPERS]
|
||||
|
||||
|
||||
# [COMMANDS]
|
||||
|
||||
# [ENTITY: 'Function'('find_tasks')]
|
||||
# [CONTRACT]
|
||||
# Finds open issues with a specific type and 'status::pending' label.
|
||||
#
|
||||
# @param --type: The label to filter issues by (e.g., "type::development").
|
||||
#
|
||||
# @stdout A JSON array of Gitea issues matching the criteria.
|
||||
# [/CONTRACT]
|
||||
function find_tasks() {
|
||||
local type=""
|
||||
# Parsing arguments like --type "type::development"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--type) type="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# In Gitea, we can filter issues by labels.
|
||||
# The protocol uses "type::development" and "status::pending"
|
||||
# We will treat these as labels.
|
||||
local labels="type::development,status::pending"
|
||||
if [[ -n "$type" ]]; then
|
||||
labels="status::pending,${type}"
|
||||
fi
|
||||
|
||||
api_request "GET" "repos/$GITEA_OWNER/$GITEA_REPO/issues?labels=$labels&state=open"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('find_tasks')]
|
||||
|
||||
# [ENTITY: 'Function'('update_task_status')]
|
||||
# [CONTRACT]
|
||||
# Atomically changes the status of a task by removing an old status label and adding a new one.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue to update.
|
||||
# @param --old: The old status label to remove (e.g., "status::pending").
|
||||
# @param --new: The new status label to add (e.g., "status::in-progress").
|
||||
#
|
||||
# @stdout The JSON representation of the updated issue.
|
||||
# [/CONTRACT]
|
||||
function update_task_status() {
|
||||
local issue_id=""
|
||||
local old_status=""
|
||||
local new_status=""
|
||||
|
||||
# Parsing arguments like --issue-id 123
|
||||
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 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$old_status" || -z "$new_status" ]]; then
|
||||
echo "Usage: update-task-status --issue-id <id> --old <old_status> --new <new_status>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# In Gitea, we manage status with labels.
|
||||
# This function will remove the old status label and add the new one.
|
||||
# First, get existing labels for the issue.
|
||||
local issue_data=$(api_request "GET" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id")
|
||||
if [[ -z "$issue_data" ]]; then
|
||||
echo "Error: Could not retrieve issue data for issue ID $issue_id. The issue may not exist or there might be a problem with the Gitea API or your token." >&2
|
||||
return 1
|
||||
fi
|
||||
local existing_labels=$(echo "$issue_data" | jq -r '.labels | .[].name')
|
||||
|
||||
local -a new_labels
|
||||
for label in ${=existing_labels};
|
||||
do
|
||||
if [[ "$label" != "$old_status" ]]; then
|
||||
new_labels+=($label)
|
||||
fi
|
||||
done
|
||||
new_labels+=($new_status)
|
||||
|
||||
local new_labels_json=$(printf '%s\n' "${new_labels[@]}" | jq -R . | jq -s .)
|
||||
|
||||
local data=$(jq -n --argjson labels "$new_labels_json" '{labels: $labels}')
|
||||
|
||||
api_request "PATCH" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('update_task_status')]
|
||||
|
||||
# [ENTITY: 'Function'('create_pr')]
|
||||
# [CONTRACT]
|
||||
# Creates a new Pull Request in the repository.
|
||||
#
|
||||
# @param --title: The title of the pull request.
|
||||
# @param --head: The source branch for the pull request.
|
||||
# @param --body: (Optional) The body/description of the pull request.
|
||||
# @param --base: (Optional) The target branch. Defaults to 'main'.
|
||||
#
|
||||
# @stdout The JSON representation of the newly created pull request.
|
||||
# [/CONTRACT]
|
||||
function create_pr() {
|
||||
local title=""
|
||||
local body=""
|
||||
local head_branch=""
|
||||
local base_branch="main" # Assuming 'main' is the default base
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--title) title="$2"; shift 2 ;;
|
||||
--body) body="$2"; shift 2 ;;
|
||||
--head) head_branch="$2"; shift 2 ;;
|
||||
--base) base_branch="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$title" || -z "$head_branch" ]]; then
|
||||
echo "Usage: create-pr --title <title> --head <head_branch> [--body <body>] [--base <base_branch>]" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg body "$body" \
|
||||
--arg head "$head_branch" \
|
||||
--arg base "$base_branch" \
|
||||
'{title: $title, body: $body, head: $head, base: $base}')
|
||||
|
||||
api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/pulls" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('create_pr')]
|
||||
|
||||
# [ENTITY: 'Function'('create_task')]
|
||||
# [CONTRACT]
|
||||
# Creates a new issue (task) in the repository.
|
||||
#
|
||||
# @param --title: The title of the issue.
|
||||
# @param --body: (Optional) The body/description of the issue.
|
||||
# @param --assignee: (Optional) Comma-separated list of usernames to assign.
|
||||
# @param --labels: (Optional) Comma-separated list of labels to add.
|
||||
#
|
||||
# @stdout The JSON representation of the newly created issue.
|
||||
# [/CONTRACT]
|
||||
function create_task() {
|
||||
local title=""
|
||||
local body=""
|
||||
local assignee=""
|
||||
local 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 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$title" ]]; then
|
||||
echo "Usage: create-task --title <title> [--body <body>] [--assignee <assignee>] [--labels <labels>]" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local labels_json="[]"
|
||||
if [[ -n "$labels" ]]; then
|
||||
# Split by comma
|
||||
local -a labels_arr
|
||||
IFS=',' read -rA labels_arr <<< "$labels"
|
||||
labels_json=$(printf '%s\n' "${labels_arr[@]}" | jq -R . | jq -s .)
|
||||
|
||||
fi
|
||||
|
||||
local assignees_json="[]"
|
||||
if [[ -n "$assignee" ]]; then
|
||||
# Split by comma
|
||||
local -a assignees_arr
|
||||
IFS=',' read -rA assignees_arr <<< "$assignee"
|
||||
assignees_json=$(printf '%s\n' "${assignees_arr[@]}" | jq -R . | jq -s .)
|
||||
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg body "$body" \
|
||||
--argjson assignees "$assignees_json" \
|
||||
--argjson labels "$labels_json" \
|
||||
'{title: $title, body: $body, assignees: $assignees, labels: $labels}')
|
||||
|
||||
api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/issues" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('create_task')]
|
||||
|
||||
# [ENTITY: 'Function'('add_comment')]
|
||||
# [CONTRACT]
|
||||
# Adds a comment to an existing issue or pull request.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue/PR to comment on.
|
||||
# @param --body: The content of the comment.
|
||||
#
|
||||
# @stdout The JSON representation of the newly created comment.
|
||||
# [/CONTRACT]
|
||||
function add_comment() {
|
||||
local issue_id=""
|
||||
local comment_body=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--issue-id) issue_id="$2"; shift 2 ;;
|
||||
--body) comment_body="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$comment_body" ]]; then
|
||||
echo "Usage: add-comment --issue-id <id> --body <comment_body>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n --arg body "$comment_body" '{body: $body}')
|
||||
api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id/comments" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('add_comment')]
|
||||
|
||||
# [ENTITY: 'Function'('merge_and_complete')]
|
||||
# [CONTRACT]
|
||||
# Atomic operation to merge a PR, delete its source branch, and close the associated issue.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue to close.
|
||||
# @param --pr-id: The ID of the pull request to merge.
|
||||
# @param --branch: The name of the source branch to delete after merging.
|
||||
#
|
||||
# @stderr Log messages indicating the progress of each step.
|
||||
# @returns 1 on failure to merge or close the issue.
|
||||
# [/CONTRACT]
|
||||
function merge_and_complete() {
|
||||
local issue_id=""
|
||||
local pr_id=""
|
||||
local branch_to_delete=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--issue-id) issue_id="$2"; shift 2 ;;
|
||||
--pr-id) pr_id="$2"; shift 2 ;;
|
||||
--branch) branch_to_delete="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$pr_id" || -z "$branch_to_delete" ]]; then
|
||||
echo "Usage: merge-and-complete --issue-id <issue_id> --pr-id <pr_id> --branch <branch_to_delete>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 1. Merge the PR
|
||||
echo "Attempting to merge PR #$pr_id..."
|
||||
local merge_data=$(jq -n '{Do: "merge"} ) # Gitea API expects a MergePullRequestOption object
|
||||
local merge_response=$(api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/pulls/$pr_id/merge" "$merge_data")
|
||||
if echo "$merge_response" | jq -e '.merged' > /dev/null; then
|
||||
echo "PR #$pr_id merged successfully."
|
||||
else
|
||||
echo "Error merging PR #$pr_id: $merge_response" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# 2. Delete the branch
|
||||
echo "Attempting to delete branch $branch_to_delete..."
|
||||
local delete_branch_response=$(api_request "DELETE" "repos/$GITEA_OWNER/$GITEA_REPO/branches/$branch_to_delete")
|
||||
if [[ -z "$delete_branch_response" ]]; then # Gitea API returns empty on successful delete
|
||||
echo "Branch $branch_to_delete deleted successfully."
|
||||
else
|
||||
echo "Error deleting branch $branch_to_delete: $delete_branch_response" >&2
|
||||
# Do not return 1 here, as PR might be merged even if branch deletion fails
|
||||
}
|
||||
|
||||
# 3. Close the associated issue
|
||||
echo "Attempting to close issue #$issue_id..."
|
||||
local close_issue_data=$(jq -n '{state: "closed"}')
|
||||
api_request "PATCH" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id" "$close_issue_data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('merge_and_complete')]
|
||||
|
||||
# [ENTITY: 'Function'('return_to_dev')]
|
||||
# [CONTRACT]
|
||||
# Atomically changes the status of a task by removing an old status label and adding a new one.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue to update.
|
||||
# @param --pr-id: The ID of the pull request to update.
|
||||
# @param --report: The defect report text.
|
||||
#
|
||||
# @stdout The JSON representation of the updated issue.
|
||||
# [/CONTRACT]
|
||||
function return_to_dev() {
|
||||
local issue_id=""
|
||||
local pr_id=""
|
||||
local report_text=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--issue-id) issue_id="$2"; shift 2 ;;
|
||||
--pr-id) pr_id="$2"; shift 2 ;;
|
||||
--report) report_text="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$pr_id" || -z "$report_text" ]]; then
|
||||
echo "Usage: return-to-dev --issue-id <issue_id> --pr-id <pr_id> --report <report_text>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Attempting to return PR #$pr_id and issue #$issue_id to developer with report: $report_text"
|
||||
|
||||
# 1. Add comment to PR/Issue
|
||||
add_comment --issue-id "$pr_id" --body "Defect Report: $report_text"
|
||||
add_comment --issue-id "$issue_id" --body "Defect Report: $report_text"
|
||||
|
||||
# 2. Reopen issue and change status to 'in-progress' for developer
|
||||
# First, get existing labels for the issue.
|
||||
local issue_data=$(api_request "GET" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id")
|
||||
if [[ -z "$issue_data" ]]; then
|
||||
echo "Error: Could not retrieve issue data for issue ID $issue_id. The issue may not exist or there might be a problem with the Gitea API or your token." >&2
|
||||
return 1
|
||||
fi
|
||||
local existing_labels=$(echo "$issue_data" | jq -r '.labels | .[].name')
|
||||
|
||||
local -a new_labels
|
||||
for label in ${=existing_labels};
|
||||
do
|
||||
if [[ "$label" == "status::completed" || "$label" == "status::in-review" ]]; then
|
||||
continue # Remove completed/in-review status
|
||||
}
|
||||
new_labels+=($label)
|
||||
done
|
||||
new_labels+=("status::in-progress") # Add in-progress status
|
||||
|
||||
local new_labels_json=$(printf '%s\n' "${new_labels[@]}" | jq -R . | jq -s .)
|
||||
|
||||
local data=$(jq -n --argjson labels "$new_labels_json" '{state: "open", labels: $labels}')
|
||||
api_request "PATCH" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id" "$data"
|
||||
|
||||
# 3. Close PR (or leave open for developer to fix and re-push) - for now, just comment
|
||||
# Gitea API doesn't have a direct "reject PR" or "return to dev" state.
|
||||
# We'll just comment and update the issue.
|
||||
echo "PR #$pr_id commented. Issue #$issue_id status updated to in-progress."
|
||||
}
|
||||
# [END_ENTITY: 'Function'('return_to_dev')]
|
||||
|
||||
# Test calls for each function
|
||||
echo "--- Testing find_tasks ---"
|
||||
find_tasks --type "type::development"
|
||||
find_tasks
|
||||
|
||||
echo "--- Testing update_task_status ---"
|
||||
update_task_status --issue-id 123 --old "status::pending" --new "status::in-progress"
|
||||
|
||||
echo "--- Testing create_pr ---"
|
||||
create_pr --title "Test PR" --head "feature/test-branch" --body "This is a test pull request."
|
||||
|
||||
echo "--- Testing create_task ---"
|
||||
create_task --title "Test Task" --body "This is a test task body." --assignee "busya" --labels "type::test,status::pending"
|
||||
create_task --title "Another Test Task"
|
||||
|
||||
echo "--- Testing add_comment ---"
|
||||
add_comment --issue-id 456 --body "This is a test comment."
|
||||
|
||||
echo "--- Testing merge_and_complete ---"
|
||||
merge_and_complete --issue-id 123 --pr-id 789 --branch "feature/test-branch"
|
||||
|
||||
echo "--- Testing return_to_dev ---"
|
||||
return_to_dev --issue-id 123 --pr-id 789 --report "Found a bug in feature X."
|
||||
|
||||
echo "--- All tests completed ---"
|
||||
485
gitea-client.zsh
Executable file
485
gitea-client.zsh
Executable file
@@ -0,0 +1,485 @@
|
||||
#!/usr/bin/env zsh
|
||||
# [PACKAGE: 'homebox_lens']
|
||||
# [FILE: 'gitea-client.zsh']
|
||||
# [SEMANTICS]
|
||||
# [ENTITY: 'File'('gitea-client.zsh')]
|
||||
# [ENTITY: 'Function'('api_request')]
|
||||
# [ENTITY: 'Function'('find_tasks')]
|
||||
# [ENTITY: 'Function'('update_task_status')]
|
||||
# [ENTITY: 'Function'('create_pr')]
|
||||
# [ENTITY: 'Function'('create_task')]
|
||||
# [ENTITY: 'Function'('add_comment')]
|
||||
# [ENTITY: 'Function'('merge_and_complete')]
|
||||
# [ENTITY: 'Function'('return_to_dev')]
|
||||
# [ENTITY: 'EntryPoint'('main_dispatch')]
|
||||
# [ENTITY: 'Configuration'('GITEA_URL')]
|
||||
# [ENTITY: 'Configuration'('GITEA_TOKEN')]
|
||||
# [ENTITY: 'Configuration'('GITEA_OWNER')]
|
||||
# [ENTITY: 'Configuration'('GITEA_REPO')]
|
||||
# [ENTITY: 'ExternalCommand'('jq')]
|
||||
# [ENTITY: 'ExternalCommand'('curl')]
|
||||
# [RELATION: 'File'('gitea-client.zsh')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'File'('gitea-client.zsh')] -> [DEPENDS_ON] -> ['ExternalCommand'('curl')]
|
||||
# [RELATION: 'Function'('api_request')] -> [DEPENDS_ON] -> ['ExternalCommand'('curl')]
|
||||
# [RELATION: 'Function'('api_request')] -> [READS_FROM] -> ['Configuration'('GITEA_URL')]
|
||||
# [RELATION: 'Function'('api_request')] -> [READS_FROM] -> ['Configuration'('GITEA_TOKEN')]
|
||||
# [RELATION: 'Function'('find_tasks')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('update_task_status')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('update_task_status')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('create_pr')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('create_pr')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('create_task')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('create_task')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('add_comment')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('add_comment')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('merge_and_complete')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('merge_and_complete')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'Function'('return_to_dev')] -> [CALLS] -> ['Function'('api_request')]
|
||||
# [RELATION: 'Function'('return_to_dev')] -> [DEPENDS_ON] -> ['ExternalCommand'('jq')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('find_tasks')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('update_task_status')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('create_pr')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('create_task')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('add_comment')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('merge_and_complete')]
|
||||
# [RELATION: 'EntryPoint'('main_dispatch')] -> [CALLS] -> ['Function'('return_to_dev')]
|
||||
# [END_SEMANTICS]
|
||||
|
||||
set -x
|
||||
|
||||
# [DEPENDENCIES]
|
||||
# Gitea Client Script
|
||||
# Version: 1.0
|
||||
if ! command -v jq &> /dev/null;
|
||||
then
|
||||
echo "jq could not be found. Please install jq to use this script."
|
||||
exit 1
|
||||
fi
|
||||
# [END_DEPENDENCIES]
|
||||
|
||||
# [CONFIGURATION]
|
||||
# IMPORTANT: Replace with your Gitea URL, API Token, repository owner and repository name.
|
||||
# You can also set these as environment variables: GITEA_URL, GITEA_TOKEN, GITEA_OWNER, GITEA_REPO
|
||||
: ${GITEA_URL:="https://gitea.bebesh.ru"}
|
||||
: ${GITEA_TOKEN:="c6fb6d73a18b2b4ddf94b67f2da6b6bb832164ce"}
|
||||
: ${GITEA_OWNER:="busya"}
|
||||
: ${GITEA_REPO:="gitea-client-tests"} # <-- Убедитесь, что здесь тестовый репозиторий
|
||||
# [END_CONFIGURATION]
|
||||
|
||||
|
||||
# [HELPERS]
|
||||
|
||||
# [ENTITY: 'Function'('api_request')]
|
||||
# [CONTRACT]
|
||||
# Generic function to make requests to the Gitea API.
|
||||
# This is the central communication point with the Gitea instance.
|
||||
#
|
||||
# @param $1: method - The HTTP method (GET, POST, PATCH, DELETE).
|
||||
# @param $2: endpoint - The API endpoint (e.g., "repos/owner/repo/issues").
|
||||
# @param $3: json_data - The JSON payload for POST/PATCH requests.
|
||||
#
|
||||
# @stdout The body of the API response on success.
|
||||
# @stderr Error messages on failure.
|
||||
#
|
||||
# @returns 0 on success, 1 on unsupported method. Curl exit code on curl failure.
|
||||
# [/CONTRACT]
|
||||
# ЗАМЕНИТЕ ВСЮ ФУНКЦИЮ api_request НА ЭТУ ВЕРСИЮ
|
||||
|
||||
function api_request() {
|
||||
local method="$1"
|
||||
local endpoint="$2"
|
||||
local data="$3"
|
||||
local url="$GITEA_URL/api/v1/$endpoint"
|
||||
|
||||
local http_code
|
||||
local response_body
|
||||
|
||||
# Создаем временный файл для хранения тела ответа
|
||||
local body_file=$(mktemp)
|
||||
|
||||
local -a curl_opts
|
||||
# -s: silent
|
||||
# -w '%{http_code}': записать http-код в stdout ПОСЛЕ ответа
|
||||
# -o "$body_file": записать тело ответа в файл
|
||||
curl_opts=("-s" "-w" "%{http_code}" "-o" "$body_file" \
|
||||
"-H" "Authorization: token $GITEA_TOKEN" \
|
||||
"-H" "Content-Type: application/json")
|
||||
|
||||
case "$method" in
|
||||
GET|DELETE)
|
||||
http_code=$(curl "${curl_opts[@]}" -X "$method" "$url")
|
||||
;;
|
||||
POST|PATCH)
|
||||
http_code=$(curl "${curl_opts[@]}" -X "$method" -d @- "$url" <<< "$data")
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported HTTP method: $method" >&2
|
||||
rm -f "$body_file" # Очистка перед выходом
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
response_body=$(<"$body_file")
|
||||
rm -f "$body_file" # Очистка после использования
|
||||
|
||||
if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then
|
||||
if [[ -z "$response_body" ]]; then
|
||||
echo "{\"http_status\": $http_code, \"body\": \"empty\"}"
|
||||
else
|
||||
echo "$response_body"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
echo "API Error: Received HTTP status $http_code. Body: $response_body" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
# [END_ENTITY: 'Function'('api_request')]
|
||||
|
||||
# [END_HELPERS]
|
||||
|
||||
|
||||
# [COMMANDS]
|
||||
|
||||
# [ENTITY: 'Function'('find_tasks')]
|
||||
# [CONTRACT]
|
||||
# Finds open issues with a specific type and 'status::pending' label.
|
||||
#
|
||||
# @param --type: The label to filter issues by (e.g., "type::development").
|
||||
#
|
||||
# @stdout A JSON array of Gitea issues matching the criteria.
|
||||
# [/CONTRACT]
|
||||
function find_tasks() {
|
||||
local type=""
|
||||
# Parsing arguments like --type "type::development"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--type) type="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
local labels="type::development,status::pending"
|
||||
if [[ -n "$type" ]]; then
|
||||
labels="status::pending,${type}"
|
||||
fi
|
||||
|
||||
api_request "GET" "repos/$GITEA_OWNER/$GITEA_REPO/issues?labels=$labels&state=open"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('find_tasks')]
|
||||
|
||||
# [ENTITY: 'Function'('update_task_status')]
|
||||
# [CONTRACT]
|
||||
# Atomically changes the status of a task by removing an old status label and adding a new one.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue to update.
|
||||
# @param --old: The old status label to remove (e.g., "status::pending").
|
||||
# @param --new: The new status label to add (e.g., "status::in-progress").
|
||||
#
|
||||
# @stdout The JSON representation of the updated issue.
|
||||
# [/CONTRACT]
|
||||
function update_task_status() {
|
||||
local issue_id=""
|
||||
local old_status=""
|
||||
local 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 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$old_status" || -z "$new_status" ]]; then
|
||||
echo "Usage: update-task-status --issue-id <id> --old <old_status> --new <new_status>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local issue_data=$(api_request "GET" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id")
|
||||
if [[ -z "$issue_data" ]]; then
|
||||
echo "Error: Could not retrieve issue data for issue ID $issue_id." >&2
|
||||
return 1
|
||||
fi
|
||||
local existing_labels=$(echo "$issue_data" | jq -r '.labels | .[].name')
|
||||
|
||||
local -a new_labels
|
||||
for label in ${=existing_labels};
|
||||
do
|
||||
if [[ "$label" != "$old_status" ]]; then
|
||||
new_labels+=($label)
|
||||
fi
|
||||
done
|
||||
new_labels+=($new_status)
|
||||
|
||||
local new_labels_json=$(printf '%s\n' "${new_labels[@]}" | jq -R . | jq -s .)
|
||||
local data=$(jq -n --argjson labels "$new_labels_json" '{labels: $labels}')
|
||||
|
||||
api_request "PATCH" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('update_task_status')]
|
||||
|
||||
# [ENTITY: 'Function'('create_pr')]
|
||||
# [CONTRACT]
|
||||
# Creates a new Pull Request in the repository.
|
||||
#
|
||||
# @param --title: The title of the pull request.
|
||||
# @param --head: The source branch for the pull request.
|
||||
# @param --body: (Optional) The body/description of the pull request.
|
||||
# @param --base: (Optional) The target branch. Defaults to 'main'.
|
||||
#
|
||||
# @stdout The JSON representation of the newly created pull request.
|
||||
# [/CONTRACT]
|
||||
function create_pr() {
|
||||
local title=""
|
||||
local body=""
|
||||
local head_branch=""
|
||||
local base_branch="main"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--title) title="$2"; shift 2 ;;
|
||||
--body) body="$2"; shift 2 ;;
|
||||
--head) head_branch="$2"; shift 2 ;;
|
||||
--base) base_branch="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$title" || -z "$head_branch" ]]; then
|
||||
echo "Usage: create-pr --title <title> --head <head_branch> [--body <body>] [--base <base_branch>]" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg body "$body" \
|
||||
--arg head "$head_branch" \
|
||||
--arg base "$base_branch" \
|
||||
'{title: $title, body: $body, head: $head, base: $base}')
|
||||
|
||||
api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/pulls" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('create_pr')]
|
||||
|
||||
# [ENTITY: 'Function'('create_task')]
|
||||
# [CONTRACT]
|
||||
# Creates a new issue (task) in the repository.
|
||||
#
|
||||
# @param --title: The title of the issue.
|
||||
# @param --body: (Optional) The body/description of the issue.
|
||||
# @param --assignee: (Optional) Comma-separated list of usernames to assign.
|
||||
# @param --labels: (Optional) Comma-separated list of labels to add.
|
||||
#
|
||||
# @stdout The JSON representation of the newly created issue.
|
||||
# [/CONTRACT]
|
||||
function create_task() {
|
||||
local title=""
|
||||
local body=""
|
||||
local assignee=""
|
||||
local 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 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$title" ]]; then
|
||||
echo "Usage: create-task --title <title> [--body <body>] [--assignee <assignee>] [--labels <labels>]" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local labels_json="[]"
|
||||
if [[ -n "$labels" ]]; then
|
||||
local -a labels_arr
|
||||
IFS=',' read -rA labels_arr <<< "$labels"
|
||||
labels_json=$(printf '%s\n' "${labels_arr[@]}" | jq -R . | jq -s .)
|
||||
fi
|
||||
|
||||
local assignees_json="[]"
|
||||
if [[ -n "$assignee" ]]; then
|
||||
local -a assignees_arr
|
||||
IFS=',' read -rA assignees_arr <<< "$assignee"
|
||||
assignees_json=$(printf '%s\n' "${assignees_arr[@]}" | jq -R . | jq -s .)
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg body "$body" \
|
||||
--argjson assignees "$assignees_json" \
|
||||
--argjson labels "$labels_json" \
|
||||
'{title: $title, body: $body, assignees: $assignees, labels: $labels}')
|
||||
|
||||
api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/issues" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('create_task')]
|
||||
|
||||
# [ENTITY: 'Function'('add_comment')]
|
||||
# [CONTRACT]
|
||||
# Adds a comment to an existing issue or pull request.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue/PR to comment on.
|
||||
# @param --body: The content of the comment.
|
||||
#
|
||||
# @stdout The JSON representation of the newly created comment.
|
||||
# [/CONTRACT]
|
||||
function add_comment() {
|
||||
local issue_id=""
|
||||
local comment_body=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--issue-id) issue_id="$2"; shift 2 ;;
|
||||
--body) comment_body="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$comment_body" ]]; then
|
||||
echo "Usage: add-comment --issue-id <id> --body <comment_body>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n --arg body "$comment_body" '{body: $body}')
|
||||
api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id/comments" "$data"
|
||||
}
|
||||
# [END_ENTITY: 'Function'('add_comment')]
|
||||
|
||||
# [ENTITY: 'Function'('merge_and_complete')]
|
||||
# [CONTRACT]
|
||||
# Atomic operation to merge a PR, delete its source branch, and close the associated issue.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue to close.
|
||||
# @param --pr-id: The ID of the pull request to merge.
|
||||
# @param --branch: The name of the source branch to delete after merging.
|
||||
#
|
||||
# @stderr Log messages indicating the progress of each step.
|
||||
# @returns 1 on failure to merge or close the issue.
|
||||
# [/CONTRACT]
|
||||
function merge_and_complete() {
|
||||
local issue_id=""
|
||||
local pr_id=""
|
||||
local branch_to_delete=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--issue-id) issue_id="$2"; shift 2 ;;
|
||||
--pr-id) pr_id="$2"; shift 2 ;;
|
||||
--branch) branch_to_delete="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$pr_id" || -z "$branch_to_delete" ]]; then
|
||||
echo "Usage: merge-and-complete --issue-id <issue_id> --pr-id <pr_id> --branch <branch_to_delete>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 1. Merge the PR
|
||||
echo "Attempting to merge PR #$pr_id..."
|
||||
local merge_data=$(jq -n '{Do: "merge"}' )
|
||||
# Запускаем в подоболочке, чтобы обработать возможную ошибку, если api_request вернет 1
|
||||
local merge_response
|
||||
if ! merge_response=$(api_request "POST" "repos/$GITEA_OWNER/$GITEA_REPO/pulls/$pr_id/merge" "$merge_data"); then
|
||||
echo "Error merging PR #$pr_id: API request failed." >&2
|
||||
echo "Response: $merge_response" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# API на успешный мерж возвращает ПУСТОЕ тело и код 200/204.
|
||||
# Наша новая api_request вернет JSON-маркер. Проверяем это.
|
||||
if echo "$merge_response" | jq -e '.body == "empty"' > /dev/null; then
|
||||
echo "PR #$pr_id merged successfully."
|
||||
else
|
||||
# Если тело не пустое, это может быть тоже успех (старые версии Gitea) или ошибка
|
||||
if echo "$merge_response" | jq -e '.merged' > /dev/null; then
|
||||
echo "PR #$pr_id merged successfully (with response body)."
|
||||
else
|
||||
echo "Error merging PR #$pr_id: Unexpected API response: $merge_response" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2. Delete the branch
|
||||
echo "Attempting to delete branch $branch_to_delete..."
|
||||
if api_request "DELETE" "repos/$GITEA_OWNER/$GITEA_REPO/branches/$branch_to_delete" > /dev/null; then
|
||||
echo "Branch $branch_to_delete deleted successfully."
|
||||
else
|
||||
echo "Warning: Failed to delete branch $branch_to_delete. It might have already been deleted or protected." >&2
|
||||
fi
|
||||
|
||||
# 3. Close the associated issue
|
||||
echo "Attempting to close issue #$issue_id..."
|
||||
local close_issue_data=$(jq -n '{state: "closed"}')
|
||||
local close_response
|
||||
if ! close_response=$(api_request "PATCH" "repos/$GITEA_OWNER/$GITEA_REPO/issues/$issue_id" "$close_issue_data"); then
|
||||
echo "Error closing issue #$issue_id: API request failed." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if echo "$close_response" | jq -e '.state == "closed"' > /dev/null; then
|
||||
echo "Issue #$issue_id closed successfully."
|
||||
else
|
||||
echo "Error closing issue #$issue_id: Unexpected API response: $close_response" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
# [END_ENTITY: 'Function'('merge_and_complete')]
|
||||
|
||||
# [ENTITY: 'Function'('return_to_dev')]
|
||||
# [CONTRACT]
|
||||
# Returns an issue to development by adding a comment and changing its status.
|
||||
# It specifically changes the status from 'status::in-review' to 'status::in-progress'.
|
||||
#
|
||||
# @param --issue-id: The ID of the issue to update.
|
||||
# @param --comment: The comment explaining why the issue is being returned.
|
||||
#
|
||||
# @stderr Log messages indicating the progress of each step.
|
||||
# @returns 1 on failure to add comment or update status.
|
||||
# [/CONTRACT]
|
||||
function return_to_dev() {
|
||||
local issue_id=""
|
||||
local comment_body=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--issue-id) issue_id="$2"; shift 2 ;;
|
||||
--comment) comment_body="$2"; shift 2 ;;
|
||||
*) echo "Unknown parameter: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$issue_id" || -z "$comment_body" ]]; then
|
||||
echo "Usage: return-to-dev --issue-id <id> --comment <comment_body>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 1. Add the comment
|
||||
echo "Adding comment to issue #$issue_id..."
|
||||
local add_comment_response
|
||||
add_comment_response=$(add_comment --issue-id "$issue_id" --body "$comment_body")
|
||||
if ! echo "$add_comment_response" | jq -e '.id' > /dev/null; then
|
||||
echo "Error: Failed to add comment to issue #$issue_id. Response: $add_comment_response" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 2. Update the status
|
||||
echo "Updating status for issue #$issue_id..."
|
||||
local update_status_response
|
||||
update_status_response=$(update_task_status --issue-id "$issue_id" --old "status::in-review" --new "status::in-progress")
|
||||
if ! echo "$update_status_response" | jq -e '.id' > /dev/null; then
|
||||
echo "Error: Failed to update status for issue #$issue_id. Response: $update_status_response" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Issue #$issue_id returned to development."
|
||||
}
|
||||
# [END_ENTITY: 'Function'('return_to_dev')]
|
||||
|
||||
# Здесь может быть функция main_dispatch, если она вам нужна
|
||||
35
tasks/current_work_order.xml
Normal file
35
tasks/current_work_order.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<WORK_ORDERS>
|
||||
<WORK_ORDER id="1" title="Implement Inventory List Screen">
|
||||
<INTENT_SPECIFICATION>
|
||||
Implement the UI for the inventory list screen in `InventoryListScreen.kt` to display a list of items using Jetpack Compose.
|
||||
Implement the `InventoryListViewModel.kt` to fetch a paginated list of items from the `ItemRepository` and expose it to the UI.
|
||||
The screen should show a loading indicator while data is being fetched and handle empty or error states.
|
||||
</INTENT_SPECIFICATION>
|
||||
<TARGET_FILES>
|
||||
<FILE>app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt</FILE>
|
||||
<FILE>app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt</FILE>
|
||||
</TARGET_FILES>
|
||||
</WORK_ORDER>
|
||||
<WORK_ORDER id="2" title="Implement Item Details Screen">
|
||||
<INTENT_SPECIFICATION>
|
||||
Implement the UI for the item details screen in `ItemDetailsScreen.kt`. It should display all the information about a specific item.
|
||||
Implement the `ItemDetailsViewModel.kt` to fetch the details of a single item from the `ItemRepository` using its ID.
|
||||
The screen should handle cases where the item is not found.
|
||||
</INTENT_SPECIFICATION>
|
||||
<TARGET_FILES>
|
||||
<FILE>app/src/main/java/com/homebox/lens/ui/screen/itemdetails/ItemDetailsScreen.kt</FILE>
|
||||
<FILE>app/src/main/java/com/homebox/lens/ui/screen/itemdetails/ItemDetailsViewModel.kt</FILE>
|
||||
</TARGET_FILES>
|
||||
</WORK_ORDER>
|
||||
<WORK_ORDER id="3" title="Implement Search Screen">
|
||||
<INTENT_SPECIFICATION>
|
||||
Implement the UI for the search screen in `SearchScreen.kt`. It should contain a search bar and a list to display search results.
|
||||
Implement the `SearchViewModel.kt` to take a search query, call the `SearchItemsUseCase`, and expose the results to the UI.
|
||||
The search should be triggered as the user types, with debouncing to avoid excessive API calls.
|
||||
</INTENT_SPECIFICATION>
|
||||
<TARGET_FILES>
|
||||
<FILE>app/src/main/java/com/homebox/lens/ui/screen/search/SearchScreen.kt</FILE>
|
||||
<FILE>app/src/main/java/com/homebox/lens/ui/screen/search/SearchViewModel.kt</FILE>
|
||||
</TARGET_FILES>
|
||||
</WORK_ORDER>
|
||||
</WORK_ORDERS>
|
||||
Reference in New Issue
Block a user