feat: add create-pr command #3
@@ -43,6 +43,21 @@ Create a new git repository on git.hangman-lab.top.
|
|||||||
|
|
||||||
> **Note**: The repository will be created at `${AGENT_WORKSPACE}/${repo-name}` (default: `/root/.openclaw/workspace/workspace-mentor`)
|
> **Note**: The repository will be created at `${AGENT_WORKSPACE}/${repo-name}` (default: `/root/.openclaw/workspace/workspace-mentor`)
|
||||||
|
|
||||||
|
### Pull Request Operations
|
||||||
|
|
||||||
|
Manage pull requests on git.hangman-lab.top.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
{baseDir}/scripts/git-ctrl pr create <repo-local-path> <head-branch> <base-branch> [pr-title] [pr-body]
|
||||||
|
{baseDir}/scripts/git-ctrl pr list <repo-local-path>
|
||||||
|
{baseDir}/scripts/git-ctrl pr commits <repo-local-path> <pr-index>
|
||||||
|
{baseDir}/scripts/git-ctrl pr merge <repo-local-path> <pr-index> <do> [commit-id] [title] [message]
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**: The access token will be automatically generated if not found.
|
||||||
|
|
||||||
|
> **`<do>`** can be: `merge`, `squash`, `rebase`, `manually-merged`
|
||||||
|
|
||||||
### Link Keycloak Account
|
### Link Keycloak Account
|
||||||
|
|
||||||
Link Keycloak account with Gitea (for OAuth binding).
|
Link Keycloak account with Gitea (for OAuth binding).
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|||||||
"$SCRIPT_DIR/check-git-cred"
|
"$SCRIPT_DIR/check-git-cred"
|
||||||
|
|
||||||
username=$(secret-mgr get-username --key git)
|
username=$(secret-mgr get-username --key git)
|
||||||
token=$("$SCRIPT_DIR/gitea" admin user generate-access-token --username "$username" --token-name "$username")
|
token_output=$("$SCRIPT_DIR/gitea" admin user generate-access-token --username "$username" --token-name "$username")
|
||||||
|
|
||||||
|
# Extract token from output (format: "Access token was successfully created: <token>")
|
||||||
|
token=$(echo "$token_output" | awk '{print $NF}')
|
||||||
|
|
||||||
secret-mgr set --key git-access-token --username "$username" --secret "$token"
|
secret-mgr set --key git-access-token --username "$username" --secret "$token"
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ if [[ $# -eq 0 ]]; then
|
|||||||
echo " check-git-cred Verify git credentials"
|
echo " check-git-cred Verify git credentials"
|
||||||
echo " create-git-account Create a new git account"
|
echo " create-git-account Create a new git account"
|
||||||
echo " create-repo Create a new repository"
|
echo " create-repo Create a new repository"
|
||||||
|
echo " pr Pull request operations (create/list/commits/merge)"
|
||||||
echo " generate-access-token Generate access token for current user"
|
echo " generate-access-token Generate access token for current user"
|
||||||
echo " link-keycloak Link Keycloak account with Gitea"
|
echo " link-keycloak Link Keycloak account with Gitea"
|
||||||
echo " repo-add-collaborators Add collaborator to repository"
|
echo " repo-add-collaborators Add collaborator to repository"
|
||||||
@@ -35,6 +36,9 @@ case "$subcommand" in
|
|||||||
create-repo)
|
create-repo)
|
||||||
"$SCRIPT_DIR/create-repo" "$@"
|
"$SCRIPT_DIR/create-repo" "$@"
|
||||||
;;
|
;;
|
||||||
|
pr)
|
||||||
|
"$SCRIPT_DIR/pr" "$@"
|
||||||
|
;;
|
||||||
generate-access-token)
|
generate-access-token)
|
||||||
"$SCRIPT_DIR/generate-access-token" "$@"
|
"$SCRIPT_DIR/generate-access-token" "$@"
|
||||||
;;
|
;;
|
||||||
|
|||||||
263
git-hangman-lab/scripts/pr
Executable file
263
git-hangman-lab/scripts/pr
Executable file
@@ -0,0 +1,263 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Get the directory where this script is located
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
|
# Ensure access token exists
|
||||||
|
ensure_token() {
|
||||||
|
# Check if git-access-token exists, if not generate it
|
||||||
|
if ! secret-mgr list 2>/dev/null | grep -q "git-access-token"; then
|
||||||
|
echo "Access token not found, generating..."
|
||||||
|
"$SCRIPT_DIR/generate-access-token"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the access token (extract actual token from "Access token was successfully created: <token>")
|
||||||
|
GIT_TOKEN="$(secret-mgr get-secret --key git-access-token | awk '{print $NF}')"
|
||||||
|
|
||||||
|
if [[ -z "$GIT_TOKEN" ]]; then
|
||||||
|
echo "Error: Failed to get git-access-token"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$GIT_TOKEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get owner and repo from local git repo
|
||||||
|
get_repo_info() {
|
||||||
|
local repo_path="$1"
|
||||||
|
|
||||||
|
if [[ ! -d "$repo_path/.git" ]]; then
|
||||||
|
echo "Error: Not a git repository: $repo_path"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REMOTE_URL="$(git -C "$repo_path" remote get-url origin)"
|
||||||
|
|
||||||
|
if [[ "$REMOTE_URL" =~ https://git\.hangman-lab\.top/([^/]+)/([^/]+)\.git ]]; then
|
||||||
|
OWNER="${BASH_REMATCH[1]}"
|
||||||
|
REPO_NAME="${BASH_REMATCH[2]}"
|
||||||
|
else
|
||||||
|
echo "Error: Invalid remote URL format: $REMOTE_URL"
|
||||||
|
echo "Expected: https://git.hangman-lab.top/\${owner}/\${repo-name}.git"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subcommand: create
|
||||||
|
cmd_create() {
|
||||||
|
local repo_path="$1"
|
||||||
|
local head_branch="$2"
|
||||||
|
local base_branch="$3"
|
||||||
|
local pr_title="${4:-untitled pull request}"
|
||||||
|
local pr_body="${5:-}"
|
||||||
|
|
||||||
|
get_repo_info "$repo_path"
|
||||||
|
local token
|
||||||
|
token="$(ensure_token)"
|
||||||
|
|
||||||
|
echo "Creating PR: $OWNER/$REPO_NAME ($head_branch -> $base_branch)"
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X POST "https://git.hangman-lab.top/api/v1/repos/${OWNER}/${REPO_NAME}/pulls" \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-H "Authorization: token ${token}" \
|
||||||
|
-d "$(jq -n \
|
||||||
|
--arg head "$head_branch" \
|
||||||
|
--arg base "$base_branch" \
|
||||||
|
--arg title "$pr_title" \
|
||||||
|
--arg body "$pr_body" \
|
||||||
|
'{head: $head, base: $base, title: $title, body: $body}')")
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | jq -e '.message' >/dev/null 2>&1; then
|
||||||
|
ERROR_MSG=$(echo "$RESPONSE" | jq -r '.message')
|
||||||
|
echo "Error: $ERROR_MSG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PR_URL=$(echo "$RESPONSE" | jq -r '.html_url // empty')
|
||||||
|
|
||||||
|
if [[ -n "$PR_URL" ]]; then
|
||||||
|
echo "Pull request created successfully!"
|
||||||
|
echo "URL: $PR_URL"
|
||||||
|
else
|
||||||
|
echo "Error: Failed to create pull request"
|
||||||
|
echo "Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subcommand: list
|
||||||
|
cmd_list() {
|
||||||
|
local repo_path="$1"
|
||||||
|
|
||||||
|
get_repo_info "$repo_path"
|
||||||
|
local token
|
||||||
|
token="$(ensure_token)"
|
||||||
|
|
||||||
|
echo "Listing PRs for: $OWNER/$REPO_NAME"
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X GET "https://git.hangman-lab.top/api/v1/repos/${OWNER}/${REPO_NAME}/pulls/pinned" \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H "Authorization: token ${token}")
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | jq -e '.message' >/dev/null 2>&1; then
|
||||||
|
ERROR_MSG=$(echo "$RESPONSE" | jq -r '.message')
|
||||||
|
echo "Error: $ERROR_MSG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$RESPONSE" | jq -r '.[] | "\(.number)\t\(.title)\t\(.state)\t\(.html_url)"' 2>/dev/null || echo "$RESPONSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subcommand: commits
|
||||||
|
cmd_commits() {
|
||||||
|
local repo_path="$1"
|
||||||
|
local pr_index="$2"
|
||||||
|
|
||||||
|
get_repo_info "$repo_path"
|
||||||
|
local token
|
||||||
|
token="$(ensure_token)"
|
||||||
|
|
||||||
|
echo "Fetching commits for PR #$pr_index in: $OWNER/$REPO_NAME"
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X GET "https://git.hangman-lab.top/api/v1/repos/${OWNER}/${REPO_NAME}/pulls/${pr_index}/commits" \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H "Authorization: token ${token}")
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | jq -e '.message' >/dev/null 2>&1; then
|
||||||
|
ERROR_MSG=$(echo "$RESPONSE" | jq -r '.message')
|
||||||
|
echo "Error: $ERROR_MSG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$RESPONSE" | jq -r '.[] | "\(.sha[0:7])\t\(.commit.message | split("\n")[0])"' 2>/dev/null || echo "$RESPONSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subcommand: merge
|
||||||
|
cmd_merge() {
|
||||||
|
local repo_path="$1"
|
||||||
|
local pr_index="$2"
|
||||||
|
local do="$3"
|
||||||
|
local commit_id="${4:-}"
|
||||||
|
local title="${5:-}"
|
||||||
|
local message="${6:-}"
|
||||||
|
|
||||||
|
get_repo_info "$repo_path"
|
||||||
|
local token
|
||||||
|
token="$(ensure_token)"
|
||||||
|
|
||||||
|
echo "Merging PR #$pr_index in: $OWNER/$REPO_NAME (Do: $do)"
|
||||||
|
|
||||||
|
# Get PR head sha first
|
||||||
|
PR_INFO=$(curl -s -X GET "https://git.hangman-lab.top/api/v1/repos/${OWNER}/${REPO_NAME}/pulls/${pr_index}" \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H "Authorization: token ${token}")
|
||||||
|
|
||||||
|
HEAD_SHA=$(echo "$PR_INFO" | jq -r '.head.sha')
|
||||||
|
|
||||||
|
if [[ -z "$HEAD_SHA" || "$HEAD_SHA" == "null" ]]; then
|
||||||
|
echo "Error: Failed to get PR head sha"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build JSON body
|
||||||
|
local json
|
||||||
|
json=$(jq -n \
|
||||||
|
--arg do "$do" \
|
||||||
|
--arg commit_id "$commit_id" \
|
||||||
|
--arg title "$title" \
|
||||||
|
--arg message "$message" \
|
||||||
|
--arg head_sha "$HEAD_SHA" \
|
||||||
|
'{
|
||||||
|
Do: $do,
|
||||||
|
MergeCommitID: (if $commit_id != "" then $commit_id else null end),
|
||||||
|
MergeMessageField: (if $message != "" then $message else null end),
|
||||||
|
MergeTitleField: (if $title != "" then $title else null end),
|
||||||
|
delete_branch_after_merge: true,
|
||||||
|
force_merge: false,
|
||||||
|
head_commit_id: $head_sha,
|
||||||
|
merge_when_checks_succeed: true
|
||||||
|
}')
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X POST "https://git.hangman-lab.top/api/v1/repos/${OWNER}/${REPO_NAME}/pulls/${pr_index}/merge" \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-H "Authorization: token ${token}" \
|
||||||
|
-d "$json")
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | jq -e '.message' >/dev/null 2>&1; then
|
||||||
|
ERROR_MSG=$(echo "$RESPONSE" | jq -r '.message')
|
||||||
|
echo "Error: $ERROR_MSG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MERGED=$(echo "$RESPONSE" | jq -r '.merged')
|
||||||
|
|
||||||
|
if [[ "$MERGED" == "true" ]]; then
|
||||||
|
echo "Pull request merged successfully!"
|
||||||
|
else
|
||||||
|
echo "Error: Failed to merge pull request"
|
||||||
|
echo "$RESPONSE" | jq '.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <command> [options]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " create <repo-local-path> <head-branch> <base-branch> [pr-title] [pr-body]"
|
||||||
|
echo " Create a pull request"
|
||||||
|
echo " list <repo-local-path> List pull requests"
|
||||||
|
echo " commits <repo-local-path> <pr-index> List commits in a PR"
|
||||||
|
echo " merge <repo-local-path> <pr-index> <do> [commit-id] [title] [message]"
|
||||||
|
echo " Merge a pull request"
|
||||||
|
echo ""
|
||||||
|
echo " <do> can be: merge, squash, rebase, manually-merged"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMAND="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$COMMAND" in
|
||||||
|
create)
|
||||||
|
if [[ $# -lt 3 ]]; then
|
||||||
|
echo "Error: create requires <repo-local-path> <head-branch> <base-branch>"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
cmd_create "$@"
|
||||||
|
;;
|
||||||
|
list)
|
||||||
|
if [[ $# -lt 1 ]]; then
|
||||||
|
echo "Error: list requires <repo-local-path>"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
cmd_list "$@"
|
||||||
|
;;
|
||||||
|
commits)
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
echo "Error: commits requires <repo-local-path> <pr-index>"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
cmd_commits "$@"
|
||||||
|
;;
|
||||||
|
merge)
|
||||||
|
if [[ $# -lt 3 ]]; then
|
||||||
|
echo "Error: merge requires <repo-local-path> <pr-index> <do>"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
cmd_merge "$@"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Unknown command: $COMMAND"
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user