Add a GitHub workflow to monitor PR events and send notifications to WeChat Work bot. #2
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: notifybot | |
# Listen to PR event trigger types, including opened, synchronize, and reopened PRs | |
on: | |
pull_request: | |
types: [opened, synchronize, reopened] | |
jobs: | |
poll_workflows: | |
runs-on: ubuntu-latest | |
# Define required environment variables | |
env: | |
PR_NUMBER: ${{ github.event.pull_request.number }} | |
REPO_OWNER: ${{ github.repository_owner }} | |
REPO_NAME: ${{ github.event.repository.name }} # Ensure it only contains the repository name | |
EVENT_TITLE: ${{ github.event.pull_request.title }} | |
WECHAT_WEBHOOK_KEY: ${{ secrets.WECHAT_WEBHOOK_KEY }} | |
MAX_ATTEMPTS: 60 # Maximum number of attempts (e.g., 30 attempts ~ 30 minutes) | |
SLEEP_DURATION: 30 # Sleep duration between each polling (seconds) | |
REQUIRED_WORKFLOWS: "build,autotest,Tencent DevOps(OpenSource)" # Required workflows to monitor, separated by commas | |
HEAD_REF: ${{ github.event.pull_request.head.ref }} | |
steps: | |
# Step 1: Set up GitHub CLI and authenticate | |
- name: Set up GitHub CLI | |
run: | | |
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg | |
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg | |
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null | |
sudo apt update | |
sudo apt install gh -y | |
echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token | |
# Step 2: Install necessary dependencies | |
- name: Install Dependencies | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y jq curl | |
# Step 3: Fetch and print all workflows associated with the PR | |
- name: Fetch and Print Associated Workflows | |
id: fetch_workflows | |
run: | | |
echo "Fetching all workflows associated with PR #$PR_NUMBER on branch $HEAD_REF..." | |
# Use GitHub CLI to get all workflow runs on the specified branch | |
workflow_runs=$(gh api "repos/$REPO_OWNER/$REPO_NAME/actions/runs?branch=$HEAD_REF&per_page=100" || echo "{}") | |
# Check if the API request was successful | |
if [ "$workflow_runs" = "{}" ]; then | |
echo "Failed to fetch workflow runs. Please check repository name and permissions." | |
exit 1 | |
fi | |
# Extract workflow names and remove duplicates | |
associated_workflows=$(echo "$workflow_runs" | jq -r '.workflow_runs[].name' | sort | uniq) | |
if [ -z "$associated_workflows" ]; then | |
echo "No associated workflows found." | |
else | |
echo "Associated workflows:" | |
echo "$associated_workflows" | |
fi | |
# Remove items from REQUIRED_WORKFLOWS that are not in associated_workflows | |
IFS=',' read -ra REQUIRED_WORKFLOWS_ARRAY <<< "$REQUIRED_WORKFLOWS" | |
filtered_workflows=() | |
for workflow in "${REQUIRED_WORKFLOWS_ARRAY[@]}"; do | |
if echo "$associated_workflows" | grep -q "$workflow"; then | |
filtered_workflows+=("$workflow") | |
fi | |
done | |
REQUIRED_WORKFLOWS=$(IFS=','; echo "${filtered_workflows[*]}") | |
echo "Filtered REQUIRED_WORKFLOWS: $REQUIRED_WORKFLOWS" | |
# Set output variable | |
echo "filtered_workflows=$REQUIRED_WORKFLOWS" >> $GITHUB_OUTPUT | |
# Step 4: Poll workflow statuses and send notifications | |
- name: Poll Workflow Status and Send Notifications | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
PR_NUMBER: ${{ env.PR_NUMBER }} | |
REPO_OWNER: ${{ env.REPO_OWNER }} | |
REPO_NAME: ${{ env.REPO_NAME }} | |
WECHAT_WEBHOOK_KEY: ${{ env.WECHAT_WEBHOOK_KEY }} | |
MAX_ATTEMPTS: ${{ env.MAX_ATTEMPTS }} | |
SLEEP_DURATION: ${{ env.SLEEP_DURATION }} | |
REQUIRED_WORKFLOWS: ${{ steps.fetch_workflows.outputs.filtered_workflows }} | |
EVENT_TITLE: ${{ env.EVENT_TITLE }} | |
HEAD_REF: ${{ env.HEAD_REF }} | |
run: | | |
# Split the required workflow names into an array | |
IFS=',' read -ra WORKFLOWS <<< "$REQUIRED_WORKFLOWS" | |
attempt=0 | |
success=true | |
failure=false | |
echo "Starting to poll workflow statuses for PR #$PR_NUMBER..." | |
while [ $attempt -lt $MAX_ATTEMPTS ]; do | |
echo "Checking workflow statuses, attempt: $((attempt+1))/${MAX_ATTEMPTS}" | |
all_success=true | |
any_failure=false | |
for workflow in "${WORKFLOWS[@]}"; do | |
echo "Checking the latest run status of workflow \"$workflow\"..." | |
# Use GitHub CLI to get the latest run of a specific workflow | |
workflow_run=$(gh api "repos/$REPO_OWNER/$REPO_NAME/actions/workflows/$workflow.yml/runs?branch=$HEAD_REF&per_page=1" --jq '.workflow_runs[0]' || echo "{}") | |
if [ "$workflow_run" = "{}" ]; then | |
echo "Workflow \"$workflow\" has not started running yet." | |
all_success=false | |
continue | |
fi | |
# Extract conclusion and current status | |
conclusion=$(echo "$workflow_run" | jq -r '.conclusion // "no_run"') | |
status=$(echo "$workflow_run" | jq -r '.status') | |
echo "Workflow \"$workflow\" status: $conclusion, progress: $status" | |
if [[ "$status" == "completed" && "$conclusion" == "success" ]]; then | |
echo "Workflow \"$workflow\" has successfully completed." | |
elif [[ "$conclusion" == "failure" || "$conclusion" == "cancelled" || "$conclusion" == "timed_out" || "$conclusion" == "action_required" ]]; then | |
echo "Workflow \"$workflow\" failed or requires manual intervention." | |
any_failure=true | |
all_success=false | |
elif [[ "$status" == "queued" || "$status" == "in_progress" ]]; then | |
echo "Workflow \"$workflow\" is still in progress." | |
all_success=false | |
else | |
echo "Workflow \"$workflow\" has an unknown status." | |
all_success=false | |
fi | |
done | |
# Decide next steps based on current workflow statuses | |
if [ "$all_success" = true ]; then | |
echo "All monitored workflows have successfully completed." | |
# Send success notification | |
curl -X POST -H "Content-Type: application/json" \ | |
-d "{ | |
\"msgtype\": \"text\", | |
\"text\": { | |
\"content\": \"The build and tests for repository ${REPO_NAME} have successfully completed.\nTitle: ${EVENT_TITLE}\nPlease merge promptly: https://github.com/${REPO_OWNER}/${REPO_NAME}/pull/${PR_NUMBER}\" | |
} | |
}" \ | |
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WECHAT_WEBHOOK_KEY}" | |
break | |
elif [ "$any_failure" = true ]; then | |
echo "At least one workflow has failed or requires manual intervention." | |
# Send failure notification | |
curl -X POST -H "Content-Type: application/json" \ | |
-d "{ | |
\"msgtype\": \"text\", | |
\"text\": { | |
\"content\": \"The build and tests for repository ${REPO_NAME} have failed.\nTitle: ${EVENT_TITLE}\nPlease check the detailed logs: https://github.com/${REPO_OWNER}/${REPO_NAME}/pull/${PR_NUMBER}\" | |
} | |
}" \ | |
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WECHAT_WEBHOOK_KEY}" | |
failure=true | |
break | |
else | |
echo "Some workflows are not yet completed. Waiting $SLEEP_DURATION seconds before retrying." | |
sleep $SLEEP_DURATION | |
attempt=$((attempt+1)) | |
fi | |
done | |
PR_URL="https://github.com/$REPO_OWNER/$REPO_NAME/pull/$PR_NUMBER" | |
if [ "$all_success" = true ]; then | |
# Success notification already sent above | |
exit 0 | |
elif [ "$failure" = true ]; then | |
# Failure notification already sent above | |
exit 1 | |
else | |
echo "Workflow statuses were not detected within the maximum number of attempts." | |
# Send timeout notification | |
curl -X POST -H "Content-Type: application/json" \ | |
-d "{ | |
\"msgtype\": \"text\", | |
\"text\": { | |
\"content\": \"The build and test checks for repository ${REPO_NAME} have timed out.\nTitle: ${EVENT_TITLE}\nPlease manually check the related workflows.\" | |
} | |
}" \ | |
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WECHAT_WEBHOOK_KEY}" | |
exit 1 | |
fi | |
shell: bash |