# Webhook 完整工作流示例

本文档提供了 GitLink Webhook 的完整使用场景和最佳实践示例。

## 目录

- [场景1: CI/CD 自动化](#场景1-cicd-自动化)
- [场景2: Issue 和 PR 通知](#场景2-issue-和-pr-通知)
- [场景3: 多环境部署](#场景3-多环境部署)
- [场景4: Webhook 迁移](#场景4-webhook-迁移)
- [场景5: 故障排查](#场景5-故障排查)
- [场景6: 安全最佳实践](#场景6-安全最佳实践)

---

## 场景1: CI/CD 自动化

### 目标
为 Jenkins CI/CD 系统配置 Webhook，实现代码推送时自动触发构建。

### 完整流程

```bash
#!/bin/bash
# cicd-webhook-setup.sh

PROJECT_OWNER="mycompany"
PROJECT_REPO="main-app"
JENKINS_URL="https://jenkins.example.com/gitlink-webhook"
WEBHOOK_SECRET="jenkins-secret-key-2024"

echo "=== Setting up CI/CD Webhook for $PROJECT_OWNER/$PROJECT_REPO ==="

# 1. 检查是否已存在 CI/CD Webhook
echo "1. Checking existing webhooks..."
existing=$(gitlink-cli webhook +list \
  --owner $PROJECT_OWNER \
  --repo $PROJECT_REPO \
  --format json | \
  jq -r ".data.webhooks[] | select(.hook_url | contains(\"jenkins\")) | .id")

if [ -n "$existing" ]; then
    echo "Found existing CI/CD webhook: $existing"
    read -p "Delete existing webhook? (y/n) " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        gitlink-cli webhook +delete --owner $PROJECT_OWNER --repo $PROJECT_REPO --id $existing
        echo "Existing webhook deleted"
    else
        echo "Aborting setup"
        exit 1
    fi
fi

# 2. 创建新的 Webhook
echo "2. Creating new CI/CD webhook..."
WEBHOOK_INFO=$(gitlink-cli webhook +create \
  --owner $PROJECT_OWNER \
  --repo $PROJECT_REPO \
  --url "$JENKINS_URL" \
  --events push,pull_request \
  --secret "$WEBHOOK_SECRET" \
  --description "Jenkins CI/CD automation" \
  --format json)

if [ $? -eq 0 ]; then
    WEBHOOK_ID=$(echo $WEBHOOK_INFO | jq -r '.data.id')
    echo "✓ Webhook created successfully: $WEBHOOK_ID"
else
    echo "✗ Failed to create webhook"
    exit 1
fi

# 3. 测试 Webhook
echo "3. Testing webhook..."
if gitlink-cli webhook +test --owner $PROJECT_OWNER --repo $PROJECT_REPO --id $WEBHOOK_ID; then
    echo "✓ Webhook test successful"
else
    echo "⚠ Webhook test failed, please check Jenkins server"
    read -p "Continue anyway? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        gitlink-cli webhook +delete --id $WEBHOOK_ID
        echo "Webhook deleted due to test failure"
        exit 1
    fi
fi

# 4. 验证配置
echo "4. Verifying configuration..."
gitlink-cli webhook +info --owner $PROJECT_OWNER --repo $PROJECT_REPO --id $WEBHOOK_ID

echo "=== CI/CD Webhook Setup Complete ==="
echo "Webhook ID: $WEBHOOK_ID"
echo "Jenkins URL: $JENKINS_URL"
echo "Events: push, pull_request"
```

### 使用说明

```bash
# 1. 设置脚本权限
chmod +x cicd-webhook-setup.sh

# 2. 运行脚本
./cicd-webhook-setup.sh

# 3. 验证 Webhook 是否正常工作
# 在 Jenkins 中检查是否收到 Webhook 事件
```

---

## 场景2: Issue 和 PR 通知

### 目标
配置 Slack 通知，在 Issue 和 PR 活动时发送消息到团队频道。

### 完整流程

```bash
#!/bin/bash
# notification-webhook-setup.sh

PROJECT_OWNER="myteam"
PROJECT_REPO="project-x"
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

echo "=== Setting up Notification Webhooks ==="

# Issue 通知 Webhook
echo "1. Creating Issue notification webhook..."
ISSUE_WEBHOOK_ID=$(gitlink-cli webhook +create \
  --owner $PROJECT_OWNER \
  --repo $PROJECT_REPO \
  --url "$SLACK_WEBHOOK_URL" \
  --events issue,issue_comment,issue_assign \
  --description "Issue notifications to #dev-team" \
  --format json | jq -r '.data.id')

echo "✓ Issue webhook created: $ISSUE_WEBHOOK_ID"

# PR 通知 Webhook
echo "2. Creating PR notification webhook..."
PR_WEBHOOK_ID=$(gitlink-cli webhook +create \
  --owner $PROJECT_OWNER \
  --repo $PROJECT_REPO \
  --url "$SLACK_WEBHOOK_URL" \
  --events pull_request,pull_request_comment,pull_request_assign \
  --description "PR notifications to #dev-team" \
  --format json | jq -r '.data.id')

echo "✓ PR webhook created: $PR_WEBHOOK_ID"

# 测试两个 Webhook
echo "3. Testing webhooks..."
gitlink-cli webhook +test --id $ISSUE_WEBHOOK_ID --event issue
gitlink-cli webhook +test --id $PR_WEBHOOK_ID --event pull_request

# 查看配置
echo "4. Webhook summary:"
echo "Issue Webhook: $ISSUE_WEBHOOK_ID"
gitlink-cli webhook +info --id $ISSUE_WEBHOOK_ID
echo
echo "PR Webhook: $PR_WEBHOOK_ID"
gitlink-cli webhook +info --id $PR_WEBHOOK_ID

echo "=== Notification Setup Complete ==="
```

### 多团队通知

```bash
#!/bin/bash
# multi-team-notifications.sh

# 为不同团队配置不同的通知
declare -A TEAM_WEBHOOKS=(
    ["dev-team"]="https://hooks.slack.com/services/DEV/TEAM/WEBHOOK"
    ["ops-team"]="https://hooks.slack.com/services/OPS/TEAM/WEBHOOK"
    ["security-team"]="https://hooks.slack.com/services/SECURITY/TEAM/WEBHOOK"
)

for team in "${!TEAM_WEBHOOKS[@]}"; do
    webhook_url="${TEAM_WEBHOOKS[$team]}"
    
    echo "Setting up webhook for $team..."
    
    gitlink-cli webhook +create \
      --owner $PROJECT_OWNER \
      --repo $PROJECT_REPO \
      --url "$webhook_url" \
      --events push,pull_request,issue \
      --description "Notifications for #$team"
done
```

---

## 场景3: 多环境部署

### 目标
为不同环境（开发、测试、生产）配置独立的 Webhook。

### 完整流程

```bash
#!/bin/bash
# multi-env-webhook-setup.sh

PROJECT_OWNER="mycompany"
PROJECT_REPO="main-app"

# 环境配置
declare -A ENVIRONMENTS=(
    ["development"]="https://ci-dev.example.com/webhook"
    ["testing"]="https://ci-test.example.com/webhook"
    ["production"]="https:ci-prod.example.com/webhook"
)

# 为每个环境创建 Webhook
for env in "${!ENVIRONMENTS[@]}"; do
    webhook_url="${ENVIRONMENTS[$env]}"
    secret="${env}-secret-$(date +%Y%m%d)"
    
    echo "=== Setting up $env environment webhook ==="
    
    # 创建 Webhook
    webhook_id=$(gitlink-cli webhook +create \
      --owner $PROJECT_OWNER \
      --repo $PROJECT_REPO \
      --url "$webhook_url" \
      --events push,pull_request \
      --secret "$secret" \
      --description "$env environment CI/CD" \
      --format json | jq -r '.data.id')
    
    echo "✓ $env webhook created: $webhook_id"
    
    # 根据环境设置不同的激活状态
    if [ "$env" = "production" ]; then
        # 生产环境默认激活
        echo "Production webhook is active"
    else
        # 其他环境暂时停用，需要时手动激活
        gitlink-cli webhook +update --id $webhook_id --active false
        echo "$env webhook created but inactive (activate manually when needed)"
    fi
    
    echo
done

echo "=== Multi-environment setup complete ==="
echo "Review created webhooks:"
gitlink-cli webhook +list
```

### 环境切换

```bash
#!/bin/bash
# switch-active-environment.sh

# 切换激活的环境
TARGET_ENV=$1

if [ -z "$TARGET_ENV" ]; then
    echo "Usage: $0 <environment>"
    echo "Available environments: development, testing, production"
    exit 1
fi

echo "=== Switching to $TARGET_ENV environment ==="

# 停用所有环境 Webhook
for id in $(gitlink-cli webhook +list --format json | jq -r '.data.webhooks[].id'); do
    webhook_url=$(gitlink-cli webhook +info --id $id --format json | jq -r '.data.hook_url')
    
    if [[ "$webhook_url" == *"ci-"* ]]; then
        echo "Deactivating webhook $id..."
        gitlink-cli webhook +update --id $id --active false
    fi
done

# 激活目标环境 Webhook
target_webhook_id=$(gitlink-cli webhook +list --format json | \
    jq -r ".data.webhooks[] | select(.hook_url | contains(\"$TARGET_ENV\")) | .id")

if [ -n "$target_webhook_id" ]; then
    echo "Activating $TARGET_ENV webhook: $target_webhook_id"
    gitlink-cli webhook +update --id $target_webhook_id --active true
    
    # 测试激活的 Webhook
    gitlink-cli webhook +test --id $target_webhook_id
    
    echo "✓ Switched to $TARGET_ENV environment"
else
    echo "✗ No webhook found for $TARGET_ENV environment"
    exit 1
fi
```

---

## 场景4: Webhook 迁移

### 目标
将 Webhook 从旧服务器迁移到新服务器。

### 完整流程

```bash
#!/bin/bash
# webhook-migration.sh

OLD_SERVER="old-ci.example.com"
NEW_SERVER="new-ci.example.com"
PROJECT_OWNER="mycompany"
PROJECT_REPO="main-app"

echo "=== Webhook Migration: $OLD_SERVER → $NEW_SERVER ==="

# 1. 查找需要迁移的 Webhook
echo "1. Finding webhooks to migrate..."
webhooks_to_migrate=$(gitlink-cli webhook +list \
  --owner $PROJECT_OWNER \
  --repo $PROJECT_REPO \
  --format json | \
  jq -r ".data.webhooks[] | select(.hook_url | contains(\"$OLD_SERVER\"))")

webhook_count=$(echo "$webhooks_to_migrate" | jq -r '. | length')

if [ "$webhook_count" -eq 0 ]; then
    echo "No webhooks found for $OLD_SERVER"
    exit 0
fi

echo "Found $webhook_count webhook(s) to migrate"

# 2. 为每个 Webhook 创建迁移记录
echo "$webhooks_to_migrate" | jq -c '.[]' | while read -r webhook; do
    old_id=$(echo $webhook | jq -r '.id')
    old_url=$(echo $webhook | jq -r '.hook_url')
    events=$(echo $webhook | jq -r '.events | join(",")')
    description=$(echo $webhook | jq -r '.description')
    
    # 生成新 URL
    new_url=$(echo $old_url | sed "s/$OLD_SERVER/$NEW_SERVER/g")
    
    echo "=== Migrating webhook $old_id ==="
    echo "Old URL: $old_url"
    echo "New URL: $new_url"
    echo "Events: $events"
    
    # 创建新 Webhook
    echo "Creating new webhook..."
    new_id=$(gitlink-cli webhook +create \
      --owner $PROJECT_OWNER \
      --repo $PROJECT_REPO \
      --url "$new_url" \
      --events "$events" \
      --description "$description (migrated)" \
      --format json | jq -r '.data.id')
    
    if [ $? -eq 0 ]; then
        echo "✓ New webhook created: $new_id"
        
        # 测试新 Webhook
        echo "Testing new webhook..."
        if gitlink-cli webhook +test --id $new_id; then
            echo "✓ New webhook test successful"
            
            # 备份旧 Webhook 配置
            echo "$webhook" > "webhook_backup_${old_id}.json"
            
            # 删除旧 Webhook
            echo "Deleting old webhook: $old_id"
            gitlink-cli webhook +delete --id $old_id
            
            echo "✓ Migration complete for webhook $old_id"
        else
            echo "⚠ New webhook test failed, keeping old webhook"
            gitlink-cli webhook +delete --id $new_id
        fi
    else
        echo "✗ Failed to create new webhook"
    fi
    
    echo
done

echo "=== Migration Complete ==="
echo "Current webhooks:"
gitlink-cli webhook +list --owner $PROJECT_OWNER --repo $PROJECT_REPO
```

### 回滚迁移

```bash
#!/bin/bash
# rollback-migration.sh

echo "=== Webhook Migration Rollback ==="

# 从备份文件恢复 Webhook
for backup_file in webhook_backup_*.json; do
    old_id=$(echo $backup_file | sed 's/webhook_backup_\([0-9]*\)\.json/\1/')
    
    echo "Restoring webhook: $old_id"
    
    # 读取备份配置
    webhook_config=$(cat "$backup_file")
    old_url=$(echo $webhook_config | jq -r '.hook_url')
    events=$(echo $webhook_config | jq -r '.events | join(",")')
    description=$(echo $webhook_config | jq -r '.description')
    
    # 重新创建 Webhook
    restored_id=$(gitlink-cli webhook +create \
      --url "$old_url" \
      --events "$events" \
      --description "$description (restored)" \
      --format json | jq -r '.data.id')
    
    echo "✓ Webhook restored: $restored_id"
done

echo "=== Rollback Complete ==="
```

---

## 场景5: 故障排查

### 目标
诊断和修复 Webhook 问题。

### 故障排查脚本

```bash
#!/bin/bash
# webhook-troubleshooting.sh

WEBHOOK_ID=$1

if [ -z "$WEBHOOK_ID" ]; then
    echo "Usage: $0 <webhook_id>"
    exit 1
fi

echo "=== Webhook Troubleshooting for ID: $WEBHOOK_ID ==="
echo

# 1. 检查 Webhook 是否存在
echo "1. Checking webhook existence..."
if ! gitlink-cli webhook +info --id $WEBHOOK_ID >/dev/null 2>&1; then
    echo "✗ Webhook not found"
    echo "Available webhooks:"
    gitlink-cli webhook +list
    exit 1
fi
echo "✓ Webhook exists"

# 2. 获取 Webhook 详细信息
echo "2. Webhook configuration:"
webhook_info=$(gitlink-cli webhook +info --id $WEBHOOK_ID --format json)
echo "$webhook_info" | jq -r '.data | {
    URL: .hook_url,
    Active: .is_active,
    Events: .events | join(", "),
    "Last Delivery": .last_delivery.timestamp,
    "Success Rate": (.delivery_statistics.success_rate // "N/A")
}'

# 3. 检查 Webhook 是否激活
is_active=$(echo $webhook_info | jq -r '.data.is_active')
if [ "$is_active" != "true" ]; then
    echo "⚠ Webhook is not active"
    read -p "Activate webhook now? (y/n) " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        gitlink-cli webhook +update --id $WEBHOOK_ID --active true
        echo "✓ Webhook activated"
    fi
fi

# 4. 测试网络连通性
echo "3. Testing network connectivity..."
webhook_url=$(echo $webhook_info | jq -r '.data.hook_url')
if curl -s -o /dev/null -w "%{http_code}" "$webhook_url" | grep -q "200\|301\|302"; then
    echo "✓ URL is accessible (HTTP $(curl -s -o /dev/null -w "%{http_code}" "$webhook_url"))"
else
    echo "✗ URL is not accessible"
    echo "Testing with curl:"
    curl -v "$webhook_url" 2>&1 | head -20
fi

# 5. 测试 Webhook
echo "4. Testing webhook delivery..."
if gitlink-cli webhook +test --id $WEBHOOK_ID; then
    echo "✓ Webhook test successful"
else
    echo "✗ Webhook test failed"
    echo "Common issues:"
    echo "  - URL is not reachable"
    echo "  - Server is not responding"
    echo "  - Firewall blocking requests"
    echo "  - SSL certificate issues"
fi

# 6. 检查成功率
echo "5. Checking delivery statistics..."
success_rate=$(echo $webhook_info | jq -r '.data.delivery_statistics.success_rate // "N/A"')
if [ "$success_rate" != "N/A" ]; then
    if (( $(echo "$success_rate < 90" | bc -l) )); then
        echo "⚠ Low success rate: $success_rate%"
        echo "Recommendation: Check webhook server logs for errors"
    else
        echo "✓ Good success rate: $success_rate%"
    fi
else
    echo "No delivery statistics available (webhook may be new)"
fi

# 7. 诊断建议
echo "6. Troubleshooting recommendations:"
echo "  - Check webhook server logs: tail -f /var/log/webhook-server.log"
echo "  - Test webhook URL manually: curl -X POST $webhook_url"
echo "  - Verify SSL certificate: openssl s_client -connect $(echo $webhook_url | sed 's/https:\/\///' | sed 's/:443//')"

echo "=== Troubleshooting Complete ==="
```

### 常见问题解决

```bash
#!/bin/bash
# common-webhook-fixes.sh

# 问题1: Webhook 未触发
fix_inactive_webhook() {
    WEBHOOK_ID=$1
    echo "Fixing inactive webhook: $WEBHOOK_ID"
    gitlink-cli webhook +update --id $WEBHOOK_ID --active true
    gitlink-cli webhook +test --id $WEBHOOK_ID
}

# 问题2: URL 配置错误
fix_webhook_url() {
    WEBHOOK_ID=$1
    CORRECT_URL=$2
    echo "Fixing webhook URL for: $WEBHOOK_ID"
    gitlink-cli webhook +update --id $WEBHOOK_ID --url "$CORRECT_URL"
    gitlink-cli webhook +test --id $WEBHOOK_ID
}

# 问题3: 事件配置不完整
fix_webhook_events() {
    WEBHOOK_ID=$1
    DESIRED_EVENTS=$2
    echo "Updating webhook events for: $WEBHOOK_ID"
    gitlink-cli webhook +update --id $WEBHOOK_ID --events "$DESIRED_EVENTS"
}

# 问题4: 密钥过期
rotate_webhook_secret() {
    WEBHOOK_ID=$1
    NEW_SECRET=$(openssl rand -hex 32)
    echo "Rotating secret for webhook: $WEBHOOK_ID"
    gitlink-cli webhook +update --id $WEBHOOK_ID --secret "$NEW_SECRET"
    echo "New secret: $NEW_SECRET"
    echo "Please update the receiving server with the new secret"
}
```

---

## 场景6: 安全最佳实践

### 目标
确保 Webhook 配置符合安全最佳实践。

### 安全配置检查

```bash
#!/bin/bash
# webhook-security-audit.sh

echo "=== Webhook Security Audit ==="

# 1. 检查所有 Webhook 是否使用 HTTPS
echo "1. Checking HTTPS usage..."
insecure_count=0
for id in $(gitlink-cli webhook +list --format json | jq -r '.data.webhooks[].id'); do
    url=$(gitlink-cli webhook +info --id $id --format json | jq -r '.data.hook_url')
    if [[ ! $url =~ ^https:// ]]; then
        echo "⚠ Insecure URL found: $url (webhook $id)"
        insecure_count=$((insecure_count + 1))
    fi
done
if [ $insecure_count -eq 0 ]; then
    echo "✓ All webhooks use HTTPS"
else
    echo "✗ Found $insecure_count webhook(s) using non-HTTPS URLs"
fi

# 2. 检查是否设置了密钥
echo "2. Checking secret usage..."
no_secret_count=0
for id in $(gitlink-cli webhook +list --format json | jq -r '.data.webhooks[].id'); do
    has_secret=$(gitlink-cli webhook +info --id $id --format json | jq -r '.data.has_secret // false')
    if [ "$has_secret" = "false" ]; then
        echo "⚠ Webhook without secret: $id"
        no_secret_count=$((no_secret_count + 1))
    fi
done
if [ $no_secret_count -eq 0 ]; then
    echo "✓ All webhooks have secrets configured"
else
    echo "⚠ $no_secret_count webhook(s) without secrets"
fi

# 3. 检查 Webhook 数量
echo "3. Checking webhook count..."
webhook_count=$(gitlink-cli webhook +list --format json | jq -r '.data.total_count')
if [ $webhook_count -gt 15 ]; then
    echo "⚠ High webhook count: $webhook_count (consider cleanup)"
else
    echo "✓ Reasonable webhook count: $webhook_count"
fi

# 4. 检查不活跃的 Webhook
echo "4. Checking inactive webhooks..."
inactive_count=$(gitlink-cli webhook +list --format json | jq -r '[.data.webhooks[] | select(.is_active == false)] | length')
if [ $inactive_count -gt 0 ]; then
    echo "⚠ Found $inactive_count inactive webhook(s)"
    echo "Consider removing inactive webhooks:"
    gitlink-cli webhook +list --format json | jq -r '.data.webhooks[] | select(.is_active == false) | "\(.id): \(.hook_url)"'
else
    echo "✓ All webhooks are active"
fi

echo "=== Security Audit Complete ==="
```

### 安全加固脚本

```bash
#!/bin/bash
# webhook-security-hardening.sh

echo "=== Webhook Security Hardening ==="

# 1. 为所有 Webhook 添加密钥
echo "1. Adding secrets to webhooks without them..."
for id in $(gitlink-cli webhook +list --format json | jq -r '.data.webhooks[].id'); do
    has_secret=$(gitlink-cli webhook +info --id $id --format json | jq -r '.data.has_secret // false')
    if [ "$has_secret" = "false" ]; then
        echo "Adding secret to webhook $id..."
        new_secret=$(openssl rand -hex 32)
        gitlink-cli webhook +update --id $id --secret "$new_secret"
        echo "✓ Secret added. Save this secret: $new_secret"
    fi
done

# 2. 停用不必要的 Webhook
echo "2. Reviewing webhooks for necessity..."
gitlink-cli webhook +list --format json | jq -r '.data.webhooks[] | "\(.id): \(.description"' | while read -r webhook; do
    echo "Webhook: $webhook"
    read -p "Is this webhook still needed? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        webhook_id=$(echo $webhook | cut -d':' -f1)
        gitlink-cli webhook +delete --id $webhook_id
        echo "✓ Webhook deleted"
    fi
done

echo "=== Security Hardening Complete ==="
```

---

## 总结

这些工作流示例涵盖了 Webhook 管理的主要场景：

1. **CI/CD 自动化** - 配置持续集成/部署
2. **通知系统** - Issue 和 PR 消息通知
3. **多环境部署** - 为不同环境配置独立 Webhook
4. **Webhook 迁移** - 安全地迁移 Webhook 配置
5. **故障排查** - 诊断和修复 Webhook 问题
6. **安全最佳实践** - 确保 Webhook 配置安全

使用这些示例作为起点，根据您的具体需求进行调整和扩展。
