feat: Add @mosaic/cli-tools package for git operations
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
New package providing CLI tools that work with both Gitea and GitHub:
Commands:
- mosaic-issue-{create,list,view,assign,edit,close,reopen,comment}
- mosaic-pr-{create,list,view,merge,review,close}
- mosaic-milestone-{create,list,close}
Features:
- Auto-detects platform (Gitea vs GitHub) from git remote
- Unified interface regardless of platform
- Available via `pnpm exec mosaic-*` in monorepo context
Updated docs/claude/orchestrator.md:
- Added CLI Tools section with usage examples
- Updated issue creation to use package commands
This makes Mosaic Stack fully self-contained for orchestration tooling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,25 @@ envsubst < docs/templates/orchestrator/orchestrator-learnings.json.template > do
|
|||||||
|
|
||||||
See `docs/templates/README.md` for full documentation.
|
See `docs/templates/README.md` for full documentation.
|
||||||
|
|
||||||
|
### CLI Tools
|
||||||
|
|
||||||
|
Git operations use `@mosaic/cli-tools` package (auto-detects Gitea vs GitHub):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Issue operations
|
||||||
|
pnpm exec mosaic-issue-create -t "Title" -b "Body" -m "Milestone"
|
||||||
|
pnpm exec mosaic-issue-list -s open -m "Milestone"
|
||||||
|
|
||||||
|
# PR operations
|
||||||
|
pnpm exec mosaic-pr-create -t "Title" -b "Body" -B develop
|
||||||
|
pnpm exec mosaic-pr-merge -n 42 -m squash -d
|
||||||
|
|
||||||
|
# Milestone operations
|
||||||
|
pnpm exec mosaic-milestone-create -t "M7-Feature" -d "Description"
|
||||||
|
```
|
||||||
|
|
||||||
|
See `packages/cli-tools/README.md` for full command reference.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 1: Bootstrap
|
## Phase 1: Bootstrap
|
||||||
@@ -121,23 +140,25 @@ docs/reports/{report-name}/
|
|||||||
|
|
||||||
### Step 5: Create Gitea Issues (Phase-Level)
|
### Step 5: Create Gitea Issues (Phase-Level)
|
||||||
|
|
||||||
Create ONE issue per phase:
|
Create ONE issue per phase using `@mosaic/cli-tools`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Use tea directly for Mosaic Stack (Gitea)
|
# Use mosaic CLI tools (auto-detects Gitea vs GitHub)
|
||||||
tea issue create \
|
pnpm exec mosaic-issue-create \
|
||||||
--title "Phase 1: Critical Security Fixes" \
|
-t "Phase 1: Critical Security Fixes" \
|
||||||
--description "## Findings
|
-b "## Findings
|
||||||
- SEC-API-1: Description
|
- SEC-API-1: Description
|
||||||
- SEC-WEB-2: Description
|
- SEC-WEB-2: Description
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
- [ ] All critical findings remediated
|
- [ ] All critical findings remediated
|
||||||
- [ ] Quality gates passing" \
|
- [ ] Quality gates passing" \
|
||||||
--labels "security" \
|
-l "security" \
|
||||||
--milestone "{milestone-name}"
|
-m "{milestone-name}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**CLI tools location:** `packages/cli-tools/bin/` - see `packages/cli-tools/README.md` for full documentation.
|
||||||
|
|
||||||
### Step 6: Create docs/tasks.md
|
### Step 6: Create docs/tasks.md
|
||||||
|
|
||||||
Create the file with this exact schema:
|
Create the file with this exact schema:
|
||||||
|
|||||||
126
packages/cli-tools/README.md
Normal file
126
packages/cli-tools/README.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# @mosaic/cli-tools
|
||||||
|
|
||||||
|
CLI tools for Mosaic Stack orchestration - git operations that work with both Gitea and GitHub.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
These scripts abstract the differences between `tea` (Gitea CLI) and `gh` (GitHub CLI), providing a unified interface for:
|
||||||
|
|
||||||
|
- Issue management (create, list, assign, close, comment)
|
||||||
|
- Pull request management (create, list, merge, review)
|
||||||
|
- Milestone management (create, list, close)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
The package is part of the Mosaic Stack monorepo. After `pnpm install`, the commands are available in the monorepo context.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From monorepo root
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# Commands available via pnpm exec or npx
|
||||||
|
pnpm exec mosaic-issue-create -t "Title" -b "Body"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### Issues
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| ---------------------- | ------------------------------------------- |
|
||||||
|
| `mosaic-issue-create` | Create a new issue |
|
||||||
|
| `mosaic-issue-list` | List issues (with filters) |
|
||||||
|
| `mosaic-issue-view` | View issue details |
|
||||||
|
| `mosaic-issue-assign` | Assign issue to user |
|
||||||
|
| `mosaic-issue-edit` | Edit issue (title, body, labels, milestone) |
|
||||||
|
| `mosaic-issue-close` | Close an issue |
|
||||||
|
| `mosaic-issue-reopen` | Reopen a closed issue |
|
||||||
|
| `mosaic-issue-comment` | Add comment to issue |
|
||||||
|
|
||||||
|
### Pull Requests
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| ------------------ | --------------------- |
|
||||||
|
| `mosaic-pr-create` | Create a pull request |
|
||||||
|
| `mosaic-pr-list` | List pull requests |
|
||||||
|
| `mosaic-pr-view` | View PR details |
|
||||||
|
| `mosaic-pr-merge` | Merge a pull request |
|
||||||
|
| `mosaic-pr-review` | Review a pull request |
|
||||||
|
| `mosaic-pr-close` | Close a pull request |
|
||||||
|
|
||||||
|
### Milestones
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| ------------------------- | ------------------ |
|
||||||
|
| `mosaic-milestone-create` | Create a milestone |
|
||||||
|
| `mosaic-milestone-list` | List milestones |
|
||||||
|
| `mosaic-milestone-close` | Close a milestone |
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Create an issue with milestone
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic-issue-create \
|
||||||
|
-t "Fix authentication bug" \
|
||||||
|
-b "Users cannot log in when..." \
|
||||||
|
-l "bug,security" \
|
||||||
|
-m "M6-AgentOrchestration"
|
||||||
|
```
|
||||||
|
|
||||||
|
### List open issues in milestone
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic-issue-list -s open -m "M6-AgentOrchestration"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a pull request
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic-pr-create \
|
||||||
|
-t "Fix authentication bug" \
|
||||||
|
-b "Resolves #123" \
|
||||||
|
-B develop \
|
||||||
|
-H fix/auth-bug
|
||||||
|
```
|
||||||
|
|
||||||
|
### Merge with squash
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic-pr-merge -n 42 -m squash -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Platform Detection
|
||||||
|
|
||||||
|
The scripts automatically detect whether you're working with Gitea or GitHub by examining the git remote URL. No configuration needed.
|
||||||
|
|
||||||
|
- `git.mosaicstack.dev` → Gitea (uses `tea`)
|
||||||
|
- `github.com` → GitHub (uses `gh`)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- **Gitea**: `tea` CLI installed and authenticated
|
||||||
|
- **GitHub**: `gh` CLI installed and authenticated
|
||||||
|
- **Both**: `git` available in PATH
|
||||||
|
|
||||||
|
## For Orchestrators
|
||||||
|
|
||||||
|
When using these tools in orchestrator/worker contexts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In worker prompt, reference via pnpm exec
|
||||||
|
pnpm exec mosaic-issue-create -t "Title" -m "Milestone"
|
||||||
|
|
||||||
|
# Or add to PATH in orchestrator setup
|
||||||
|
export PATH="$PATH:./node_modules/.bin"
|
||||||
|
mosaic-issue-create -t "Title" -m "Milestone"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Scripts are plain bash - edit directly in `bin/`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lint with shellcheck (if installed)
|
||||||
|
pnpm lint
|
||||||
|
```
|
||||||
80
packages/cli-tools/bin/detect-platform.sh
Executable file
80
packages/cli-tools/bin/detect-platform.sh
Executable file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# detect-platform.sh - Detect git platform (Gitea or GitHub) for current repo
|
||||||
|
# Usage: source detect-platform.sh && detect_platform
|
||||||
|
# or: ./detect-platform.sh (prints platform name)
|
||||||
|
|
||||||
|
detect_platform() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -z "$remote_url" ]]; then
|
||||||
|
echo "error: not a git repository or no origin remote" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for GitHub
|
||||||
|
if [[ "$remote_url" == *"github.com"* ]]; then
|
||||||
|
PLATFORM="github"
|
||||||
|
export PLATFORM
|
||||||
|
echo "github"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for common Gitea indicators
|
||||||
|
# Gitea URLs typically don't contain github.com, gitlab.com, bitbucket.org
|
||||||
|
if [[ "$remote_url" != *"gitlab.com"* ]] && \
|
||||||
|
[[ "$remote_url" != *"bitbucket.org"* ]]; then
|
||||||
|
# Assume Gitea for self-hosted repos
|
||||||
|
PLATFORM="gitea"
|
||||||
|
export PLATFORM
|
||||||
|
echo "gitea"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORM="unknown"
|
||||||
|
export PLATFORM
|
||||||
|
echo "unknown"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_repo_info() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -z "$remote_url" ]]; then
|
||||||
|
echo "error: not a git repository or no origin remote" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract owner/repo from URL
|
||||||
|
# Handles: git@host:owner/repo.git, https://host/owner/repo.git, https://host/owner/repo
|
||||||
|
local repo_path
|
||||||
|
if [[ "$remote_url" == git@* ]]; then
|
||||||
|
repo_path="${remote_url#*:}"
|
||||||
|
else
|
||||||
|
repo_path="${remote_url#*://}"
|
||||||
|
repo_path="${repo_path#*/}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove .git suffix if present
|
||||||
|
repo_path="${repo_path%.git}"
|
||||||
|
|
||||||
|
echo "$repo_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_repo_owner() {
|
||||||
|
local repo_info
|
||||||
|
repo_info=$(get_repo_info)
|
||||||
|
echo "${repo_info%%/*}"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_repo_name() {
|
||||||
|
local repo_info
|
||||||
|
repo_info=$(get_repo_info)
|
||||||
|
echo "${repo_info##*/}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# If script is run directly (not sourced), output the platform
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
detect_platform
|
||||||
|
fi
|
||||||
135
packages/cli-tools/bin/issue-assign.sh
Executable file
135
packages/cli-tools/bin/issue-assign.sh
Executable file
@@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-assign.sh - Assign issues on Gitea or GitHub
|
||||||
|
# Usage: issue-assign.sh -i ISSUE_NUMBER [-a assignee] [-l labels] [-m milestone]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
ISSUE=""
|
||||||
|
ASSIGNEE=""
|
||||||
|
LABELS=""
|
||||||
|
MILESTONE=""
|
||||||
|
REMOVE_ASSIGNEE=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
Assign or update an issue on the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-i, --issue NUMBER Issue number (required)
|
||||||
|
-a, --assignee USER Assign to user (use @me for self)
|
||||||
|
-l, --labels LABELS Add comma-separated labels
|
||||||
|
-m, --milestone NAME Set milestone
|
||||||
|
-r, --remove-assignee Remove current assignee
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") -i 42 -a "username"
|
||||||
|
$(basename "$0") -i 42 -l "in-progress" -m "0.2.0"
|
||||||
|
$(basename "$0") -i 42 -a @me
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-a|--assignee)
|
||||||
|
ASSIGNEE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--labels)
|
||||||
|
LABELS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-m|--milestone)
|
||||||
|
MILESTONE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-r|--remove-assignee)
|
||||||
|
REMOVE_ASSIGNEE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISSUE" ]]; then
|
||||||
|
echo "Error: Issue number is required (-i)" >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
if [[ -n "$ASSIGNEE" ]]; then
|
||||||
|
gh issue edit "$ISSUE" --add-assignee "$ASSIGNEE"
|
||||||
|
fi
|
||||||
|
if [[ "$REMOVE_ASSIGNEE" == true ]]; then
|
||||||
|
# Get current assignees and remove them
|
||||||
|
CURRENT=$(gh issue view "$ISSUE" --json assignees -q '.assignees[].login' 2>/dev/null | tr '\n' ',')
|
||||||
|
if [[ -n "$CURRENT" ]]; then
|
||||||
|
gh issue edit "$ISSUE" --remove-assignee "${CURRENT%,}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -n "$LABELS" ]]; then
|
||||||
|
gh issue edit "$ISSUE" --add-label "$LABELS"
|
||||||
|
fi
|
||||||
|
if [[ -n "$MILESTONE" ]]; then
|
||||||
|
gh issue edit "$ISSUE" --milestone "$MILESTONE"
|
||||||
|
fi
|
||||||
|
echo "Issue #$ISSUE updated successfully"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
# tea issue edit syntax
|
||||||
|
CMD="tea issue edit $ISSUE"
|
||||||
|
NEEDS_EDIT=false
|
||||||
|
|
||||||
|
if [[ -n "$ASSIGNEE" ]]; then
|
||||||
|
# tea uses --assignees flag
|
||||||
|
CMD="$CMD --assignees \"$ASSIGNEE\""
|
||||||
|
NEEDS_EDIT=true
|
||||||
|
fi
|
||||||
|
if [[ -n "$LABELS" ]]; then
|
||||||
|
# tea uses --labels flag (replaces existing)
|
||||||
|
CMD="$CMD --labels \"$LABELS\""
|
||||||
|
NEEDS_EDIT=true
|
||||||
|
fi
|
||||||
|
if [[ -n "$MILESTONE" ]]; then
|
||||||
|
MILESTONE_ID=$(tea milestones list 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1)
|
||||||
|
if [[ -n "$MILESTONE_ID" ]]; then
|
||||||
|
CMD="$CMD --milestone $MILESTONE_ID"
|
||||||
|
NEEDS_EDIT=true
|
||||||
|
else
|
||||||
|
echo "Warning: Could not find milestone '$MILESTONE'" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$NEEDS_EDIT" == true ]]; then
|
||||||
|
eval "$CMD"
|
||||||
|
echo "Issue #$ISSUE updated successfully"
|
||||||
|
else
|
||||||
|
echo "No changes specified"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
64
packages/cli-tools/bin/issue-close.sh
Executable file
64
packages/cli-tools/bin/issue-close.sh
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-close.sh - Close an issue on GitHub or Gitea
|
||||||
|
# Usage: issue-close.sh -i <issue_number> [-c <comment>]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Source platform detection
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
ISSUE_NUMBER=""
|
||||||
|
COMMENT=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-c|--comment)
|
||||||
|
COMMENT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: issue-close.sh -i <issue_number> [-c <comment>]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -i, --issue Issue number (required)"
|
||||||
|
echo " -c, --comment Comment to add before closing (optional)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISSUE_NUMBER" ]]; then
|
||||||
|
echo "Error: Issue number is required (-i)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect platform and close issue
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
if [[ -n "$COMMENT" ]]; then
|
||||||
|
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
|
||||||
|
fi
|
||||||
|
gh issue close "$ISSUE_NUMBER"
|
||||||
|
echo "Closed GitHub issue #$ISSUE_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
if [[ -n "$COMMENT" ]]; then
|
||||||
|
tea issue comment "$ISSUE_NUMBER" "$COMMENT"
|
||||||
|
fi
|
||||||
|
tea issue close "$ISSUE_NUMBER"
|
||||||
|
echo "Closed Gitea issue #$ISSUE_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
61
packages/cli-tools/bin/issue-comment.sh
Executable file
61
packages/cli-tools/bin/issue-comment.sh
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-comment.sh - Add a comment to an issue on GitHub or Gitea
|
||||||
|
# Usage: issue-comment.sh -i <issue_number> -c <comment>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
ISSUE_NUMBER=""
|
||||||
|
COMMENT=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-c|--comment)
|
||||||
|
COMMENT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: issue-comment.sh -i <issue_number> -c <comment>"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -i, --issue Issue number (required)"
|
||||||
|
echo " -c, --comment Comment text (required)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISSUE_NUMBER" ]]; then
|
||||||
|
echo "Error: Issue number is required (-i)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$COMMENT" ]]; then
|
||||||
|
echo "Error: Comment is required (-c)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
|
||||||
|
echo "Added comment to GitHub issue #$ISSUE_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
tea issue comment "$ISSUE_NUMBER" "$COMMENT"
|
||||||
|
echo "Added comment to Gitea issue #$ISSUE_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
92
packages/cli-tools/bin/issue-create.sh
Executable file
92
packages/cli-tools/bin/issue-create.sh
Executable file
@@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-create.sh - Create issues on Gitea or GitHub
|
||||||
|
# Usage: issue-create.sh -t "Title" [-b "Body"] [-l "label1,label2"] [-m "milestone"]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
TITLE=""
|
||||||
|
BODY=""
|
||||||
|
LABELS=""
|
||||||
|
MILESTONE=""
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
Create an issue on the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-t, --title TITLE Issue title (required)
|
||||||
|
-b, --body BODY Issue body/description
|
||||||
|
-l, --labels LABELS Comma-separated labels (e.g., "bug,feature")
|
||||||
|
-m, --milestone NAME Milestone name to assign
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") -t "Fix login bug" -l "bug,priority-high"
|
||||||
|
$(basename "$0") -t "Add dark mode" -b "Implement theme switching" -m "0.2.0"
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-t|--title)
|
||||||
|
TITLE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-b|--body)
|
||||||
|
BODY="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--labels)
|
||||||
|
LABELS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-m|--milestone)
|
||||||
|
MILESTONE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$TITLE" ]]; then
|
||||||
|
echo "Error: Title is required (-t)" >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
CMD="gh issue create --title \"$TITLE\""
|
||||||
|
[[ -n "$BODY" ]] && CMD="$CMD --body \"$BODY\""
|
||||||
|
[[ -n "$LABELS" ]] && CMD="$CMD --label \"$LABELS\""
|
||||||
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
CMD="tea issue create --title \"$TITLE\""
|
||||||
|
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
|
||||||
|
[[ -n "$LABELS" ]] && CMD="$CMD --labels \"$LABELS\""
|
||||||
|
# tea accepts milestone by name directly (verified 2026-02-05)
|
||||||
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
84
packages/cli-tools/bin/issue-edit.sh
Executable file
84
packages/cli-tools/bin/issue-edit.sh
Executable file
@@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-edit.sh - Edit an issue on GitHub or Gitea
|
||||||
|
# Usage: issue-edit.sh -i <issue_number> [-t <title>] [-b <body>] [-l <labels>] [-m <milestone>]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
ISSUE_NUMBER=""
|
||||||
|
TITLE=""
|
||||||
|
BODY=""
|
||||||
|
LABELS=""
|
||||||
|
MILESTONE=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-t|--title)
|
||||||
|
TITLE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-b|--body)
|
||||||
|
BODY="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--labels)
|
||||||
|
LABELS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-m|--milestone)
|
||||||
|
MILESTONE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: issue-edit.sh -i <issue_number> [-t <title>] [-b <body>] [-l <labels>] [-m <milestone>]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -i, --issue Issue number (required)"
|
||||||
|
echo " -t, --title New title"
|
||||||
|
echo " -b, --body New body/description"
|
||||||
|
echo " -l, --labels Labels (comma-separated, replaces existing)"
|
||||||
|
echo " -m, --milestone Milestone name"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISSUE_NUMBER" ]]; then
|
||||||
|
echo "Error: Issue number is required (-i)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
CMD="gh issue edit $ISSUE_NUMBER"
|
||||||
|
[[ -n "$TITLE" ]] && CMD="$CMD --title \"$TITLE\""
|
||||||
|
[[ -n "$BODY" ]] && CMD="$CMD --body \"$BODY\""
|
||||||
|
[[ -n "$LABELS" ]] && CMD="$CMD --add-label \"$LABELS\""
|
||||||
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
|
eval $CMD
|
||||||
|
echo "Updated GitHub issue #$ISSUE_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
CMD="tea issue edit $ISSUE_NUMBER"
|
||||||
|
[[ -n "$TITLE" ]] && CMD="$CMD --title \"$TITLE\""
|
||||||
|
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
|
||||||
|
[[ -n "$LABELS" ]] && CMD="$CMD --add-labels \"$LABELS\""
|
||||||
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
|
eval $CMD
|
||||||
|
echo "Updated Gitea issue #$ISSUE_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
104
packages/cli-tools/bin/issue-list.sh
Executable file
104
packages/cli-tools/bin/issue-list.sh
Executable file
@@ -0,0 +1,104 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-list.sh - List issues on Gitea or GitHub
|
||||||
|
# Usage: issue-list.sh [-s state] [-l label] [-m milestone] [-a assignee]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
STATE="open"
|
||||||
|
LABEL=""
|
||||||
|
MILESTONE=""
|
||||||
|
ASSIGNEE=""
|
||||||
|
LIMIT=30
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
List issues from the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-s, --state STATE Filter by state: open, closed, all (default: open)
|
||||||
|
-l, --label LABEL Filter by label
|
||||||
|
-m, --milestone NAME Filter by milestone name
|
||||||
|
-a, --assignee USER Filter by assignee
|
||||||
|
-n, --limit N Maximum issues to show (default: 30)
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") # List open issues
|
||||||
|
$(basename "$0") -s all -l bug # All issues with 'bug' label
|
||||||
|
$(basename "$0") -m "0.2.0" # Issues in milestone 0.2.0
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-s|--state)
|
||||||
|
STATE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--label)
|
||||||
|
LABEL="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-m|--milestone)
|
||||||
|
MILESTONE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-a|--assignee)
|
||||||
|
ASSIGNEE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-n|--limit)
|
||||||
|
LIMIT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
CMD="gh issue list --state $STATE --limit $LIMIT"
|
||||||
|
[[ -n "$LABEL" ]] && CMD="$CMD --label \"$LABEL\""
|
||||||
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
|
[[ -n "$ASSIGNEE" ]] && CMD="$CMD --assignee \"$ASSIGNEE\""
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
CMD="tea issues list --state $STATE --limit $LIMIT"
|
||||||
|
[[ -n "$LABEL" ]] && CMD="$CMD --labels \"$LABEL\""
|
||||||
|
# tea uses different syntax for milestone filtering
|
||||||
|
if [[ -n "$MILESTONE" ]]; then
|
||||||
|
MILESTONE_ID=$(tea milestones list 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1)
|
||||||
|
if [[ -n "$MILESTONE_ID" ]]; then
|
||||||
|
CMD="$CMD --milestones $MILESTONE_ID"
|
||||||
|
else
|
||||||
|
echo "Warning: Could not find milestone '$MILESTONE'" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Note: tea may not support assignee filter directly
|
||||||
|
eval "$CMD"
|
||||||
|
if [[ -n "$ASSIGNEE" ]]; then
|
||||||
|
echo "Note: Assignee filtering may require manual review for Gitea" >&2
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
62
packages/cli-tools/bin/issue-reopen.sh
Executable file
62
packages/cli-tools/bin/issue-reopen.sh
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-reopen.sh - Reopen a closed issue on GitHub or Gitea
|
||||||
|
# Usage: issue-reopen.sh -i <issue_number> [-c <comment>]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
ISSUE_NUMBER=""
|
||||||
|
COMMENT=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-c|--comment)
|
||||||
|
COMMENT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: issue-reopen.sh -i <issue_number> [-c <comment>]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -i, --issue Issue number (required)"
|
||||||
|
echo " -c, --comment Comment to add when reopening (optional)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISSUE_NUMBER" ]]; then
|
||||||
|
echo "Error: Issue number is required (-i)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
if [[ -n "$COMMENT" ]]; then
|
||||||
|
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
|
||||||
|
fi
|
||||||
|
gh issue reopen "$ISSUE_NUMBER"
|
||||||
|
echo "Reopened GitHub issue #$ISSUE_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
if [[ -n "$COMMENT" ]]; then
|
||||||
|
tea issue comment "$ISSUE_NUMBER" "$COMMENT"
|
||||||
|
fi
|
||||||
|
tea issue reopen "$ISSUE_NUMBER"
|
||||||
|
echo "Reopened Gitea issue #$ISSUE_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
48
packages/cli-tools/bin/issue-view.sh
Executable file
48
packages/cli-tools/bin/issue-view.sh
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# issue-view.sh - View issue details on GitHub or Gitea
|
||||||
|
# Usage: issue-view.sh -i <issue_number>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
ISSUE_NUMBER=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: issue-view.sh -i <issue_number>"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -i, --issue Issue number (required)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISSUE_NUMBER" ]]; then
|
||||||
|
echo "Error: Issue number is required (-i)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
gh issue view "$ISSUE_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
tea issue "$ISSUE_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
50
packages/cli-tools/bin/milestone-close.sh
Executable file
50
packages/cli-tools/bin/milestone-close.sh
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# milestone-close.sh - Close a milestone on GitHub or Gitea
|
||||||
|
# Usage: milestone-close.sh -t <title>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
TITLE=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-t|--title)
|
||||||
|
TITLE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: milestone-close.sh -t <title>"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -t, --title Milestone title (required)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$TITLE" ]]; then
|
||||||
|
echo "Error: Milestone title is required (-t)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
gh api -X PATCH "/repos/{owner}/{repo}/milestones/$(gh api "/repos/{owner}/{repo}/milestones" --jq ".[] | select(.title==\"$TITLE\") | .number")" -f state=closed
|
||||||
|
echo "Closed GitHub milestone: $TITLE"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
tea milestone close "$TITLE"
|
||||||
|
echo "Closed Gitea milestone: $TITLE"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
117
packages/cli-tools/bin/milestone-create.sh
Executable file
117
packages/cli-tools/bin/milestone-create.sh
Executable file
@@ -0,0 +1,117 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# milestone-create.sh - Create milestones on Gitea or GitHub
|
||||||
|
# Usage: milestone-create.sh -t "Title" [-d "Description"] [--due "YYYY-MM-DD"]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
TITLE=""
|
||||||
|
DESCRIPTION=""
|
||||||
|
DUE_DATE=""
|
||||||
|
LIST_ONLY=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
Create or list milestones on the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Versioning Convention:
|
||||||
|
- Features get dedicated milestones
|
||||||
|
- Pre-release: 0.X.0 for breaking changes, 0.X.Y for patches
|
||||||
|
- Post-release: X.0.0 for breaking changes
|
||||||
|
- MVP starts at 0.1.0
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-t, --title TITLE Milestone title/version (e.g., "0.2.0")
|
||||||
|
-d, --desc DESCRIPTION Milestone description
|
||||||
|
--due DATE Due date (YYYY-MM-DD format)
|
||||||
|
--list List existing milestones
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") --list
|
||||||
|
$(basename "$0") -t "0.1.0" -d "MVP Release"
|
||||||
|
$(basename "$0") -t "0.2.0" -d "User Authentication Feature" --due "2025-03-01"
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-t|--title)
|
||||||
|
TITLE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-d|--desc)
|
||||||
|
DESCRIPTION="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--due)
|
||||||
|
DUE_DATE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--list)
|
||||||
|
LIST_ONLY=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
if [[ "$LIST_ONLY" == true ]]; then
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
gh api repos/:owner/:repo/milestones --jq '.[] | "\(.number)\t\(.title)\t\(.state)\t\(.open_issues)/\(.closed_issues) issues"'
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
tea milestones list
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$TITLE" ]]; then
|
||||||
|
echo "Error: Title is required (-t) for creating milestones" >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
# GitHub uses the API for milestone creation
|
||||||
|
JSON_PAYLOAD="{\"title\":\"$TITLE\""
|
||||||
|
[[ -n "$DESCRIPTION" ]] && JSON_PAYLOAD="$JSON_PAYLOAD,\"description\":\"$DESCRIPTION\""
|
||||||
|
[[ -n "$DUE_DATE" ]] && JSON_PAYLOAD="$JSON_PAYLOAD,\"due_on\":\"${DUE_DATE}T00:00:00Z\""
|
||||||
|
JSON_PAYLOAD="$JSON_PAYLOAD}"
|
||||||
|
|
||||||
|
gh api repos/:owner/:repo/milestones --method POST --input - <<< "$JSON_PAYLOAD"
|
||||||
|
echo "Milestone '$TITLE' created successfully"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
CMD="tea milestones create --title \"$TITLE\""
|
||||||
|
[[ -n "$DESCRIPTION" ]] && CMD="$CMD --description \"$DESCRIPTION\""
|
||||||
|
[[ -n "$DUE_DATE" ]] && CMD="$CMD --deadline \"$DUE_DATE\""
|
||||||
|
eval "$CMD"
|
||||||
|
echo "Milestone '$TITLE' created successfully"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
43
packages/cli-tools/bin/milestone-list.sh
Executable file
43
packages/cli-tools/bin/milestone-list.sh
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# milestone-list.sh - List milestones on GitHub or Gitea
|
||||||
|
# Usage: milestone-list.sh [-s <state>]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
STATE="open"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-s|--state)
|
||||||
|
STATE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: milestone-list.sh [-s <state>]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -s, --state Filter by state: open, closed, all (default: open)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
gh api "/repos/{owner}/{repo}/milestones?state=$STATE" --jq '.[] | "\(.title) (\(.state)) - \(.open_issues) open, \(.closed_issues) closed"'
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
tea milestone list
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
62
packages/cli-tools/bin/pr-close.sh
Executable file
62
packages/cli-tools/bin/pr-close.sh
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-close.sh - Close a pull request without merging on GitHub or Gitea
|
||||||
|
# Usage: pr-close.sh -n <pr_number> [-c <comment>]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
PR_NUMBER=""
|
||||||
|
COMMENT=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-n|--number)
|
||||||
|
PR_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-c|--comment)
|
||||||
|
COMMENT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: pr-close.sh -n <pr_number> [-c <comment>]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -n, --number PR number (required)"
|
||||||
|
echo " -c, --comment Comment before closing (optional)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PR_NUMBER" ]]; then
|
||||||
|
echo "Error: PR number is required (-n)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
if [[ -n "$COMMENT" ]]; then
|
||||||
|
gh pr comment "$PR_NUMBER" --body "$COMMENT"
|
||||||
|
fi
|
||||||
|
gh pr close "$PR_NUMBER"
|
||||||
|
echo "Closed GitHub PR #$PR_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
if [[ -n "$COMMENT" ]]; then
|
||||||
|
tea pr comment "$PR_NUMBER" "$COMMENT"
|
||||||
|
fi
|
||||||
|
tea pr close "$PR_NUMBER"
|
||||||
|
echo "Closed Gitea PR #$PR_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
164
packages/cli-tools/bin/pr-create.sh
Executable file
164
packages/cli-tools/bin/pr-create.sh
Executable file
@@ -0,0 +1,164 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-create.sh - Create pull requests on Gitea or GitHub
|
||||||
|
# Usage: pr-create.sh -t "Title" [-b "Body"] [-B base] [-H head] [-l "labels"] [-m "milestone"]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
TITLE=""
|
||||||
|
BODY=""
|
||||||
|
BASE_BRANCH=""
|
||||||
|
HEAD_BRANCH=""
|
||||||
|
LABELS=""
|
||||||
|
MILESTONE=""
|
||||||
|
DRAFT=false
|
||||||
|
ISSUE=""
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
Create a pull request on the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-t, --title TITLE PR title (required, or use --issue)
|
||||||
|
-b, --body BODY PR description/body
|
||||||
|
-B, --base BRANCH Base branch to merge into (default: main/master)
|
||||||
|
-H, --head BRANCH Head branch with changes (default: current branch)
|
||||||
|
-l, --labels LABELS Comma-separated labels
|
||||||
|
-m, --milestone NAME Milestone name
|
||||||
|
-i, --issue NUMBER Link to issue (auto-generates title if not provided)
|
||||||
|
-d, --draft Create as draft PR
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") -t "Add login feature" -b "Implements user authentication"
|
||||||
|
$(basename "$0") -t "Fix bug" -B main -H feature/fix-123
|
||||||
|
$(basename "$0") -i 42 -b "Implements the feature described in #42"
|
||||||
|
$(basename "$0") -t "WIP: New feature" --draft
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-t|--title)
|
||||||
|
TITLE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-b|--body)
|
||||||
|
BODY="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-B|--base)
|
||||||
|
BASE_BRANCH="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-H|--head)
|
||||||
|
HEAD_BRANCH="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--labels)
|
||||||
|
LABELS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-m|--milestone)
|
||||||
|
MILESTONE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-i|--issue)
|
||||||
|
ISSUE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-d|--draft)
|
||||||
|
DRAFT=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# If no title but issue provided, generate title
|
||||||
|
if [[ -z "$TITLE" ]] && [[ -n "$ISSUE" ]]; then
|
||||||
|
TITLE="Fixes #$ISSUE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$TITLE" ]]; then
|
||||||
|
echo "Error: Title is required (-t) or provide an issue (-i)" >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default head branch to current branch
|
||||||
|
if [[ -z "$HEAD_BRANCH" ]]; then
|
||||||
|
HEAD_BRANCH=$(git branch --show-current)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add issue reference to body if provided
|
||||||
|
if [[ -n "$ISSUE" ]]; then
|
||||||
|
if [[ -n "$BODY" ]]; then
|
||||||
|
BODY="$BODY
|
||||||
|
|
||||||
|
Fixes #$ISSUE"
|
||||||
|
else
|
||||||
|
BODY="Fixes #$ISSUE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
CMD="gh pr create --title \"$TITLE\""
|
||||||
|
[[ -n "$BODY" ]] && CMD="$CMD --body \"$BODY\""
|
||||||
|
[[ -n "$BASE_BRANCH" ]] && CMD="$CMD --base \"$BASE_BRANCH\""
|
||||||
|
[[ -n "$HEAD_BRANCH" ]] && CMD="$CMD --head \"$HEAD_BRANCH\""
|
||||||
|
[[ -n "$LABELS" ]] && CMD="$CMD --label \"$LABELS\""
|
||||||
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
|
[[ "$DRAFT" == true ]] && CMD="$CMD --draft"
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
# tea pull create syntax
|
||||||
|
CMD="tea pr create --title \"$TITLE\""
|
||||||
|
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
|
||||||
|
[[ -n "$BASE_BRANCH" ]] && CMD="$CMD --base \"$BASE_BRANCH\""
|
||||||
|
[[ -n "$HEAD_BRANCH" ]] && CMD="$CMD --head \"$HEAD_BRANCH\""
|
||||||
|
|
||||||
|
# Handle labels for tea
|
||||||
|
if [[ -n "$LABELS" ]]; then
|
||||||
|
# tea may use --labels flag
|
||||||
|
CMD="$CMD --labels \"$LABELS\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle milestone for tea
|
||||||
|
if [[ -n "$MILESTONE" ]]; then
|
||||||
|
MILESTONE_ID=$(tea milestones list 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1)
|
||||||
|
if [[ -n "$MILESTONE_ID" ]]; then
|
||||||
|
CMD="$CMD --milestone $MILESTONE_ID"
|
||||||
|
else
|
||||||
|
echo "Warning: Could not find milestone '$MILESTONE', creating without milestone" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Note: tea may not support --draft flag in all versions
|
||||||
|
if [[ "$DRAFT" == true ]]; then
|
||||||
|
echo "Note: Draft PR may not be supported by your tea version" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
93
packages/cli-tools/bin/pr-list.sh
Executable file
93
packages/cli-tools/bin/pr-list.sh
Executable file
@@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-list.sh - List pull requests on Gitea or GitHub
|
||||||
|
# Usage: pr-list.sh [-s state] [-l label] [-a author]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
STATE="open"
|
||||||
|
LABEL=""
|
||||||
|
AUTHOR=""
|
||||||
|
LIMIT=30
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
List pull requests from the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-s, --state STATE Filter by state: open, closed, merged, all (default: open)
|
||||||
|
-l, --label LABEL Filter by label
|
||||||
|
-a, --author USER Filter by author
|
||||||
|
-n, --limit N Maximum PRs to show (default: 30)
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") # List open PRs
|
||||||
|
$(basename "$0") -s all # All PRs
|
||||||
|
$(basename "$0") -s merged -a username # Merged PRs by user
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-s|--state)
|
||||||
|
STATE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--label)
|
||||||
|
LABEL="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-a|--author)
|
||||||
|
AUTHOR="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-n|--limit)
|
||||||
|
LIMIT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
CMD="gh pr list --state $STATE --limit $LIMIT"
|
||||||
|
[[ -n "$LABEL" ]] && CMD="$CMD --label \"$LABEL\""
|
||||||
|
[[ -n "$AUTHOR" ]] && CMD="$CMD --author \"$AUTHOR\""
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
# tea pr list - note: tea uses 'pulls' subcommand in some versions
|
||||||
|
CMD="tea pr list --state $STATE --limit $LIMIT"
|
||||||
|
|
||||||
|
# tea filtering may be limited
|
||||||
|
if [[ -n "$LABEL" ]]; then
|
||||||
|
echo "Note: Label filtering may require manual review for Gitea" >&2
|
||||||
|
fi
|
||||||
|
if [[ -n "$AUTHOR" ]]; then
|
||||||
|
echo "Note: Author filtering may require manual review for Gitea" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
110
packages/cli-tools/bin/pr-merge.sh
Executable file
110
packages/cli-tools/bin/pr-merge.sh
Executable file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-merge.sh - Merge pull requests on Gitea or GitHub
|
||||||
|
# Usage: pr-merge.sh -n PR_NUMBER [-m method] [-d]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
PR_NUMBER=""
|
||||||
|
MERGE_METHOD="merge" # merge, squash, rebase
|
||||||
|
DELETE_BRANCH=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
Merge a pull request on the current repository (Gitea or GitHub).
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-n, --number NUMBER PR number to merge (required)
|
||||||
|
-m, --method METHOD Merge method: merge, squash, rebase (default: merge)
|
||||||
|
-d, --delete-branch Delete the head branch after merge
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") -n 42 # Merge PR #42
|
||||||
|
$(basename "$0") -n 42 -m squash # Squash merge
|
||||||
|
$(basename "$0") -n 42 -m rebase -d # Rebase and delete branch
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-n|--number)
|
||||||
|
PR_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-m|--method)
|
||||||
|
MERGE_METHOD="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-d|--delete-branch)
|
||||||
|
DELETE_BRANCH=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PR_NUMBER" ]]; then
|
||||||
|
echo "Error: PR number is required (-n)" >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
|
case "$PLATFORM" in
|
||||||
|
github)
|
||||||
|
CMD="gh pr merge $PR_NUMBER"
|
||||||
|
case "$MERGE_METHOD" in
|
||||||
|
merge) CMD="$CMD --merge" ;;
|
||||||
|
squash) CMD="$CMD --squash" ;;
|
||||||
|
rebase) CMD="$CMD --rebase" ;;
|
||||||
|
*)
|
||||||
|
echo "Error: Invalid merge method '$MERGE_METHOD'" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
[[ "$DELETE_BRANCH" == true ]] && CMD="$CMD --delete-branch"
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
gitea)
|
||||||
|
# tea pr merge syntax
|
||||||
|
CMD="tea pr merge $PR_NUMBER"
|
||||||
|
|
||||||
|
# tea merge style flags
|
||||||
|
case "$MERGE_METHOD" in
|
||||||
|
merge) CMD="$CMD --style merge" ;;
|
||||||
|
squash) CMD="$CMD --style squash" ;;
|
||||||
|
rebase) CMD="$CMD --style rebase" ;;
|
||||||
|
*)
|
||||||
|
echo "Error: Invalid merge method '$MERGE_METHOD'" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Delete branch after merge if requested
|
||||||
|
if [[ "$DELETE_BRANCH" == true ]]; then
|
||||||
|
echo "Note: Branch deletion after merge may need to be done separately with tea" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$CMD"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "PR #$PR_NUMBER merged successfully"
|
||||||
115
packages/cli-tools/bin/pr-review.sh
Executable file
115
packages/cli-tools/bin/pr-review.sh
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-review.sh - Review a pull request on GitHub or Gitea
|
||||||
|
# Usage: pr-review.sh -n <pr_number> -a <action> [-c <comment>]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
PR_NUMBER=""
|
||||||
|
ACTION=""
|
||||||
|
COMMENT=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-n|--number)
|
||||||
|
PR_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-a|--action)
|
||||||
|
ACTION="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-c|--comment)
|
||||||
|
COMMENT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: pr-review.sh -n <pr_number> -a <action> [-c <comment>]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -n, --number PR number (required)"
|
||||||
|
echo " -a, --action Review action: approve, request-changes, comment (required)"
|
||||||
|
echo " -c, --comment Review comment (required for request-changes)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PR_NUMBER" ]]; then
|
||||||
|
echo "Error: PR number is required (-n)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ACTION" ]]; then
|
||||||
|
echo "Error: Action is required (-a): approve, request-changes, comment"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
case $ACTION in
|
||||||
|
approve)
|
||||||
|
gh pr review "$PR_NUMBER" --approve ${COMMENT:+--body "$COMMENT"}
|
||||||
|
echo "Approved GitHub PR #$PR_NUMBER"
|
||||||
|
;;
|
||||||
|
request-changes)
|
||||||
|
if [[ -z "$COMMENT" ]]; then
|
||||||
|
echo "Error: Comment required for request-changes"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
gh pr review "$PR_NUMBER" --request-changes --body "$COMMENT"
|
||||||
|
echo "Requested changes on GitHub PR #$PR_NUMBER"
|
||||||
|
;;
|
||||||
|
comment)
|
||||||
|
if [[ -z "$COMMENT" ]]; then
|
||||||
|
echo "Error: Comment required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
gh pr review "$PR_NUMBER" --comment --body "$COMMENT"
|
||||||
|
echo "Added review comment to GitHub PR #$PR_NUMBER"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Unknown action: $ACTION"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
case $ACTION in
|
||||||
|
approve)
|
||||||
|
tea pr approve "$PR_NUMBER" ${COMMENT:+--comment "$COMMENT"}
|
||||||
|
echo "Approved Gitea PR #$PR_NUMBER"
|
||||||
|
;;
|
||||||
|
request-changes)
|
||||||
|
if [[ -z "$COMMENT" ]]; then
|
||||||
|
echo "Error: Comment required for request-changes"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
tea pr reject "$PR_NUMBER" --comment "$COMMENT"
|
||||||
|
echo "Requested changes on Gitea PR #$PR_NUMBER"
|
||||||
|
;;
|
||||||
|
comment)
|
||||||
|
if [[ -z "$COMMENT" ]]; then
|
||||||
|
echo "Error: Comment required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
tea pr comment "$PR_NUMBER" "$COMMENT"
|
||||||
|
echo "Added comment to Gitea PR #$PR_NUMBER"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Unknown action: $ACTION"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
48
packages/cli-tools/bin/pr-view.sh
Executable file
48
packages/cli-tools/bin/pr-view.sh
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-view.sh - View pull request details on GitHub or Gitea
|
||||||
|
# Usage: pr-view.sh -n <pr_number>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
PR_NUMBER=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-n|--number)
|
||||||
|
PR_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: pr-view.sh -n <pr_number>"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -n, --number PR number (required)"
|
||||||
|
echo " -h, --help Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PR_NUMBER" ]]; then
|
||||||
|
echo "Error: PR number is required (-n)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
gh pr view "$PR_NUMBER"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
tea pr "$PR_NUMBER"
|
||||||
|
else
|
||||||
|
echo "Error: Unknown platform"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
44
packages/cli-tools/package.json
Normal file
44
packages/cli-tools/package.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "@mosaic/cli-tools",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "CLI tools for Mosaic Stack orchestration - git operations for Gitea/GitHub",
|
||||||
|
"private": true,
|
||||||
|
"bin": {
|
||||||
|
"mosaic-detect-platform": "./bin/detect-platform.sh",
|
||||||
|
"mosaic-issue-assign": "./bin/issue-assign.sh",
|
||||||
|
"mosaic-issue-close": "./bin/issue-close.sh",
|
||||||
|
"mosaic-issue-comment": "./bin/issue-comment.sh",
|
||||||
|
"mosaic-issue-create": "./bin/issue-create.sh",
|
||||||
|
"mosaic-issue-edit": "./bin/issue-edit.sh",
|
||||||
|
"mosaic-issue-list": "./bin/issue-list.sh",
|
||||||
|
"mosaic-issue-reopen": "./bin/issue-reopen.sh",
|
||||||
|
"mosaic-issue-view": "./bin/issue-view.sh",
|
||||||
|
"mosaic-milestone-close": "./bin/milestone-close.sh",
|
||||||
|
"mosaic-milestone-create": "./bin/milestone-create.sh",
|
||||||
|
"mosaic-milestone-list": "./bin/milestone-list.sh",
|
||||||
|
"mosaic-pr-close": "./bin/pr-close.sh",
|
||||||
|
"mosaic-pr-create": "./bin/pr-create.sh",
|
||||||
|
"mosaic-pr-list": "./bin/pr-list.sh",
|
||||||
|
"mosaic-pr-merge": "./bin/pr-merge.sh",
|
||||||
|
"mosaic-pr-review": "./bin/pr-review.sh",
|
||||||
|
"mosaic-pr-view": "./bin/pr-view.sh"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "shellcheck bin/*.sh || true",
|
||||||
|
"test": "echo 'No tests yet'"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"cli",
|
||||||
|
"git",
|
||||||
|
"gitea",
|
||||||
|
"github",
|
||||||
|
"orchestration"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"linux",
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user