gitlink-cli/workflows/01-community-ops.sh

296 lines
13 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────
# Scenario 1: Community Operations Automation
# Flow: Issue auto-classify → Assign responsible → Weekly report → Release notes
#
# Commands/Skills chained:
# 1. issue +list -- fetch open issues
# 2. issue +view -- read issue details
# 3. issue +batch-label -- add classification labels
# 4. issue +batch-assign -- assign responsible person
# 5. pr +list -- collect merged PRs for weekly report
# 6. wiki +create -- publish community weekly report
# 7. release +create -- publish release notes
# ─────────────────────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/common.sh"
usage() {
echo "Usage: $0 --owner OWNER --repo REPO [--week WEEKS_AGO] [--dry-run]"
echo ""
echo " --owner OWNER Repository owner (org or user)"
echo " --repo REPO Repository name"
echo " --week N Generate report for N weeks ago (default: 0 = this week)"
echo " --dry-run Preview actions without executing"
exit 1
}
WEEKS_AGO=0
DRY_RUN=false
OWNER=""
REPO=""
while [[ $# -gt 0 ]]; do
case "$1" in
--owner) OWNER="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
--week) WEEKS_AGO="$2"; shift 2 ;;
--dry-run) DRY_RUN="true"; shift ;;
--help|-h) usage ;;
*) log_err "Unknown arg: $1"; usage ;;
esac
done
check_auth
require_owner_repo
# ─────────────────────────────────────────────────────────────────────
log_title "Phase 1: Issue Auto-Classification"
# ─────────────────────────────────────────────────────────────────────
log_step "Fetching open issues..."
ISSUES_JSON=$(gl_check issue +list --owner "$OWNER" --repo "$REPO" --state open --limit 100)
ISSUE_COUNT=$(echo "$ISSUES_JSON" | jq '.data.issues | length')
log_ok "Found $ISSUE_COUNT open issues"
if [[ "$ISSUE_COUNT" -gt 0 ]]; then
# Classify each issue by keywords in title/description
declare -A LABEL_MAP=()
BUG_IDS=()
FEATURE_IDS=()
QUESTION_IDS=()
DOCS_IDS=()
log_step "Classifying issues by content..."
for i in $(seq 0 $((ISSUE_COUNT - 1))); do
ISSUE_ID=$(echo "$ISSUES_JSON" | jq -r ".data.issues[$i].id")
ISSUE_TITLE=$(echo "$ISSUES_JSON" | jq -r ".data.issues[$i].subject // .data.issues[$i].title // \"\"")
ISSUE_DESC=$(echo "$ISSUES_JSON" | jq -r ".data.issues[$i].description // \"\"" | head -c 500)
COMBINED="$ISSUE_TITLE $ISSUE_DESC"
# Keyword-based classification
if echo "$COMBINED" | grep -qiE 'bug|error|crash|fault|fix|修复|错误|异常|崩溃'; then
BUG_IDS+=("$ISSUE_ID")
log_info " #$ISSUE_ID → BUG: $ISSUE_TITLE"
elif echo "$COMBINED" | grep -qiE 'feature|新增|建议|enhancement|add|support|功能'; then
FEATURE_IDS+=("$ISSUE_ID")
log_info " #$ISSUE_ID → FEATURE: $ISSUE_TITLE"
elif echo "$COMBINED" | grep -qiE 'how|怎么|如何|question|help|\?|'; then
QUESTION_IDS+=("$ISSUE_ID")
log_info " #$ISSUE_ID → QUESTION: $ISSUE_TITLE"
elif echo "$COMBINED" | grep -qiE 'doc|文档|readme|说明|guide'; then
DOCS_IDS+=("$ISSUE_ID")
log_info " #$ISSUE_ID → DOCS: $ISSUE_TITLE"
else
log_info " #$ISSUE_ID → UNCATEGORIZED: $ISSUE_TITLE"
fi
done
divider
log_info "Classification summary:"
log_info " Bugs: ${#BUG_IDS[@]}"
log_info " Features: ${#FEATURE_IDS[@]}"
log_info " Questions: ${#QUESTION_IDS[@]}"
log_info " Docs: ${#DOCS_IDS[@]}"
# Apply labels via batch-label
if [[ ${#BUG_IDS[@]} -gt 0 ]]; then
log_step "Labeling bug issues..."
for bid in "${BUG_IDS[@]}"; do
gl_run issue +label-add --owner "$OWNER" --repo "$REPO" --number "$bid" --labels "bug" > /dev/null 2>&1 || true
done
log_ok "Labeled ${#BUG_IDS[@]} bug issues"
fi
if [[ ${#FEATURE_IDS[@]} -gt 0 ]]; then
log_step "Labeling feature issues..."
for fid in "${FEATURE_IDS[@]}"; do
gl_run issue +label-add --owner "$OWNER" --repo "$REPO" --number "$fid" --labels "feature" > /dev/null 2>&1 || true
done
log_ok "Labeled ${#FEATURE_IDS[@]} feature issues"
fi
if [[ ${#QUESTION_IDS[@]} -gt 0 ]]; then
log_step "Labeling question issues..."
for qid in "${QUESTION_IDS[@]}"; do
gl_run issue +label-add --owner "$OWNER" --repo "$REPO" --number "$qid" --labels "question" > /dev/null 2>&1 || true
done
log_ok "Labeled ${#QUESTION_IDS[@]} question issues"
fi
if [[ ${#DOCS_IDS[@]} -gt 0 ]]; then
log_step "Labeling docs issues..."
for did in "${DOCS_IDS[@]}"; do
gl_run issue +label-add --owner "$OWNER" --repo "$REPO" --number "$did" --labels "documentation" > /dev/null 2>&1 || true
done
log_ok "Labeled ${#DOCS_IDS[@]} docs issues"
fi
fi
# ─────────────────────────────────────────────────────────────────────
log_title "Phase 2: Assign Responsible Persons"
# ─────────────────────────────────────────────────────────────────────
log_step "Fetching repo members for assignment..."
MEMBERS_JSON=$(gl_run repo +members --owner "$OWNER" --repo "$REPO" --limit 50)
MEMBER_COUNT=$(echo "$MEMBERS_JSON" | jq '.data.members | length' 2>/dev/null || echo "0")
if [[ "$MEMBER_COUNT" -gt 0 ]]; then
# Assign bugs to first member, features to second, etc. (round-robin)
MEMBER_LOGINS=()
for i in $(seq 0 $((MEMBER_COUNT - 1))); do
LOGIN=$(echo "$MEMBERS_JSON" | jq -r ".data.members[$i].login // .data.members[$i].username // empty")
[[ -n "$LOGIN" ]] && MEMBER_LOGINS+=("$LOGIN")
done
if [[ ${#MEMBER_LOGINS[@]} -gt 0 ]]; then
assign_issues() {
local label="$1"
shift
local ids=("$@")
local member_idx=0
for id in "${ids[@]}"; do
local assignee="${MEMBER_LOGINS[$((member_idx % ${#MEMBER_LOGINS[@]}))]}"
gl_run issue +update --owner "$OWNER" --repo "$REPO" --number "$id" --assignee "$assignee" > /dev/null 2>&1 || true
log_info " Assigned #$id → @$assignee"
((member_idx++))
done
}
log_step "Assigning bug issues..."
assign_issues "bug" "${BUG_IDS[@]}" 2>/dev/null || true
log_step "Assigning feature issues..."
assign_issues "feature" "${FEATURE_IDS[@]}" 2>/dev/null || true
log_ok "Assignment complete"
fi
else
log_warn "No repo members found, skipping assignment"
fi
# ─────────────────────────────────────────────────────────────────────
log_title "Phase 3: Generate Community Weekly Report"
# ─────────────────────────────────────────────────────────────────────
WEEK_START=$(date -d "$((WEEKS_AGO * 7)) days ago" +%Y-%m-%d 2>/dev/null || date_today)
WEEK_END=$(date_today)
log_step "Collecting weekly data (week of $WEEK_START)..."
# Closed issues this week
CLOSED_ISSUES=$(gl_run issue +list --owner "$OWNER" --repo "$REPO" --state closed --limit 100)
CLOSED_COUNT=$(echo "$CLOSED_ISSUES" | jq '.data.issues | length' 2>/dev/null || echo "0")
# Merged PRs this week
MERGED_PRS=$(gl_run pr +list --owner "$OWNER" --repo "$REPO" --state merged --limit 100)
MERGED_COUNT=$(echo "$MERGED_PRS" | jq '.data.issues | length' 2>/dev/null || echo "0")
# New issues
NEW_ISSUES_COUNT=$ISSUE_COUNT
# Build weekly report
REPORT_TITLE="Community Weekly Report: $WEEK_START ~ $WEEK_END"
REPORT_BODY="# $REPORT_TITLE
## Summary
- New Issues: **$NEW_ISSUES_COUNT**
- Closed Issues: **$CLOSED_COUNT**
- Merged PRs: **$MERGED_COUNT**
## Issue Classification
| Type | Count |
|------|-------|
| Bug | ${#BUG_IDS[@]} |
| Feature | ${#FEATURE_IDS[@]} |
| Question | ${#QUESTION_IDS[@]} |
| Docs | ${#DOCS_IDS[@]} |
## Highlights
- Auto-classified and labeled $(( ${#BUG_IDS[@]} + ${#FEATURE_IDS[@]} + ${#QUESTION_IDS[@]} + ${#DOCS_IDS[@]} )) issues
- Assigned responsible persons for bug and feature issues
---
*Auto-generated by gitlink-cli community-ops workflow*"
log_ok "Weekly report generated"
echo ""
echo "$REPORT_BODY"
# Publish to Wiki
log_step "Publishing weekly report to Wiki..."
WIKI_RESULT=$(gl_run wiki +create --owner "$OWNER" --repo "$REPO" \
--title "$REPORT_TITLE" \
--content "$REPORT_BODY" 2>&1) || true
if [[ "$(json_ok "$WIKI_RESULT")" == "true" ]]; then
log_ok "Weekly report published to Wiki"
else
log_warn "Wiki publish may have failed (wiki module might not be enabled)"
fi
# ─────────────────────────────────────────────────────────────────────
log_title "Phase 4: Auto-Publish Release Notes"
# ─────────────────────────────────────────────────────────────────────
log_step "Collecting recent changes for release notes..."
# Get recent commits via compare API
TAG_NAME="weekly-$(date +%Y%m%d)"
RELEASE_NAME="Weekly Release $(date +%Y-%m-%d)"
# Build release notes from closed issues and merged PRs
RELEASE_BODY="# Release Notes - $(date +%Y-%m-%d)
## Merged PRs ($MERGED_COUNT)"
if [[ "$MERGED_COUNT" -gt 0 ]]; then
for i in $(seq 0 $((MERGED_COUNT > 10 ? 9 : MERGED_COUNT - 1))); do
PR_TITLE=$(echo "$MERGED_PRS" | jq -r ".data.issues[$i].subject // .data.issues[$i].title // \"\"")
PR_NUM=$(echo "$MERGED_PRS" | jq -r ".data.issues[$i].id // .data.issues[$i].number // \"\"")
RELEASE_BODY+=$'\n'"- #$PR_NUM $PR_TITLE"
done
fi
RELEASE_BODY+="
## Closed Issues ($CLOSED_COUNT)"
if [[ "$CLOSED_COUNT" -gt 0 ]]; then
for i in $(seq 0 $((CLOSED_COUNT > 10 ? 9 : CLOSED_COUNT - 1))); do
ISSUE_TITLE=$(echo "$CLOSED_ISSUES" | jq -r ".data.issues[$i].subject // .data.issues[$i].title // \"\"")
ISSUE_NUM=$(echo "$CLOSED_ISSUES" | jq -r ".data.issues[$i].id // .data.issues[$i].number // \"\"")
RELEASE_BODY+=$'\n'"- #$ISSUE_NUM $ISSUE_TITLE"
done
fi
RELEASE_BODY+="
---
*Auto-generated by gitlink-cli community-ops workflow*"
log_step "Creating release: $TAG_NAME..."
RELEASE_RESULT=$(gl_run release +create --owner "$OWNER" --repo "$REPO" \
--tag "$TAG_NAME" \
--name "$RELEASE_NAME" \
--body "$RELEASE_BODY" 2>&1) || true
if [[ "$(json_ok "$RELEASE_RESULT")" == "true" ]]; then
log_ok "Release $TAG_NAME created successfully"
else
log_warn "Release creation may have failed (tag might already exist)"
log_info "You can manually create with: gitlink-cli release +create --owner $OWNER --repo $REPO --tag $TAG_NAME --name '$RELEASE_NAME'"
fi
# ─────────────────────────────────────────────────────────────────────
log_title "Community Operations Complete"
# ─────────────────────────────────────────────────────────────────────
echo -e "${GREEN}Summary:${NC}"
echo " Issues classified: $(( ${#BUG_IDS[@]} + ${#FEATURE_IDS[@]} + ${#QUESTION_IDS[@]} + ${#DOCS_IDS[@]} ))"
echo " Closed this week: $CLOSED_COUNT"
echo " Merged PRs: $MERGED_COUNT"
echo " Weekly report: Published to Wiki"
echo " Release notes: $TAG_NAME"
echo ""