mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 06:19:58 +00:00
## Summary - Improves Storybook deployment and PR comment workflow similar to the Playwright improvements in #5425 - Creates unified deployment and commenting system for better maintainability - Adds Cloudflare Pages deployment for Storybook previews ## Deployment Cases Matrix | Case | PR Type | Branch | Deployment | Features | |------|---------|--------|------------|----------| | **1** | Non-forked PR | `version-bump-*` | ✅ Chromatic | • Visual diff testing<br>• Chromatic build URL<br>• Chromatic Storybook URL<br>• Shows visual changes | | **2** | Non-forked PR | All branches | ✅ Cloudflare Pages | • Live Storybook preview<br>• pages.dev URL<br>• No visual diff | | **3** | Forked PR | Any branch | ✅ Cloudflare Pages | • Live Storybook preview<br>• pages.dev URL<br>• No visual diff<br>• Runs via separate workflow to avoid permission problems | ### Key Points: - **Chromatic** (paid service): Only for `version-bump-*` branches to track visual changes between releases - **Cloudflare Pages** (free): For all other PRs to provide Storybook preview without visual diff - **Security**: Forked PRs use a separate workflow with limited permissions ## Changes ### New Features - 🚀 **Cloudflare Pages Deployment**: Storybook builds are now deployed to Cloudflare Pages for easy preview - 🔄 **Unified Script**: Single reusable shell script handles both deployment and PR comments - 🔒 **Better Security**: Separate workflows for fork vs non-fork PRs ### Improvements - ♻️ **Retry Logic**: Automatic retry (3 attempts) for failed deployments - 📝 **Better Comments**: Clearer PR comments with deployment links and status - 🎯 **Simplified Logic**: Workflow logic moved to reusable script for easier maintenance - ⚡ **Better Error Handling**: Proper handling of different workflow conclusions - 🐛 **Fixed Comment Output**: Deployment logs now properly redirected to stderr ### Files Changed - `scripts/cicd/pr-storybook-deploy-and-comment.sh` - New unified deployment script - `.github/workflows/chromatic.yaml` - Updated to use new script and add deployment - `.github/workflows/pr-storybook-deploy.yaml` - New workflow for forked PRs - `.github/workflows/pr-storybook-comment.yaml` - Removed (replaced by new system) ## ⚠️ Required Setup The Cloudflare Pages project `comfyui-storybook` needs to be created under the organization's Cloudflare account: ```bash # Using the account ID from GitHub secrets export CLOUDFLARE_ACCOUNT_ID=5ae914d9b87bcf6bbe1ada5798f92a5f export CLOUDFLARE_API_TOKEN=<org-token> wrangler pages project create comfyui-storybook --production-branch main ``` **Note**: The project must be created under the same Cloudflare account that's configured in the GitHub secrets. ## Test Plan - [x] Create Cloudflare Pages project `comfyui-storybook` - [x] Workflow runs successfully on all PRs - [x] PR comments are posted correctly at start and completion - [x] Storybook deploys to Cloudflare Pages with correct URL - [ ] Fork PRs are handled by separate workflow - [ ] Non-fork PRs get inline deployment - [ ] version-bump-* branches show Chromatic info ## References - Similar improvements for Playwright: #5459 - Based on pattern from sno-fix-playwright-comment-2 branch 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude <noreply@anthropic.com>
247 lines
7.5 KiB
Bash
Executable File
247 lines
7.5 KiB
Bash
Executable File
#!/bin/bash
|
||
set -e
|
||
|
||
# Deploy Storybook to Cloudflare Pages and comment on PR
|
||
# Usage: ./pr-storybook-deploy-and-comment.sh <pr_number> <branch_name> <status> [start_time]
|
||
|
||
# Input validation
|
||
# Validate PR number is numeric
|
||
case "$1" in
|
||
''|*[!0-9]*)
|
||
echo "Error: PR_NUMBER must be numeric" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
PR_NUMBER="$1"
|
||
|
||
# Sanitize and validate branch name (allow alphanumeric, dots, dashes, underscores, slashes)
|
||
BRANCH_NAME=$(echo "$2" | sed 's/[^a-zA-Z0-9._/-]//g')
|
||
if [ -z "$BRANCH_NAME" ]; then
|
||
echo "Error: Invalid or empty branch name" >&2
|
||
exit 1
|
||
fi
|
||
|
||
# Validate status parameter
|
||
STATUS="${3:-completed}"
|
||
case "$STATUS" in
|
||
starting|completed) ;;
|
||
*)
|
||
echo "Error: STATUS must be 'starting' or 'completed'" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
START_TIME="${4:-$(date -u '+%m/%d/%Y, %I:%M:%S %p')}"
|
||
|
||
# Required environment variables
|
||
: "${GITHUB_TOKEN:?GITHUB_TOKEN is required}"
|
||
: "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is required}"
|
||
|
||
# Cloudflare variables only required for deployment
|
||
if [ "$STATUS" = "completed" ]; then
|
||
: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN is required for deployment}"
|
||
: "${CLOUDFLARE_ACCOUNT_ID:?CLOUDFLARE_ACCOUNT_ID is required for deployment}"
|
||
fi
|
||
|
||
# Configuration
|
||
COMMENT_MARKER="<!-- STORYBOOK_BUILD_STATUS -->"
|
||
|
||
# Install wrangler if not available (output to stderr for debugging)
|
||
if ! command -v wrangler > /dev/null 2>&1; then
|
||
echo "Installing wrangler v4..." >&2
|
||
npm install -g wrangler@^4.0.0 >&2 || {
|
||
echo "Failed to install wrangler" >&2
|
||
echo "failed"
|
||
return
|
||
}
|
||
fi
|
||
|
||
# Deploy Storybook report, WARN: ensure inputs are sanitized before calling this function
|
||
deploy_storybook() {
|
||
dir="$1"
|
||
branch="$2"
|
||
|
||
[ ! -d "$dir" ] && echo "failed" && return
|
||
|
||
project="comfy-storybook"
|
||
|
||
echo "Deploying Storybook to project $project on branch $branch..." >&2
|
||
|
||
# Try deployment up to 3 times
|
||
i=1
|
||
while [ $i -le 3 ]; do
|
||
echo "Deployment attempt $i of 3..." >&2
|
||
# Branch is already sanitized, use it directly
|
||
if output=$(wrangler pages deploy "$dir" \
|
||
--project-name="$project" \
|
||
--branch="$branch" 2>&1); then
|
||
|
||
# Extract URL from output (improved regex for valid URL characters)
|
||
url=$(echo "$output" | grep -oE 'https://[a-zA-Z0-9.-]+\.pages\.dev\S*' | head -1)
|
||
result="${url:-https://${branch}.${project}.pages.dev}"
|
||
echo "Success! URL: $result" >&2
|
||
echo "$result" # Only this goes to stdout for capture
|
||
return
|
||
else
|
||
echo "Deployment failed on attempt $i: $output" >&2
|
||
fi
|
||
[ $i -lt 3 ] && sleep 10
|
||
i=$((i + 1))
|
||
done
|
||
|
||
echo "failed"
|
||
}
|
||
|
||
# Post or update GitHub comment
|
||
post_comment() {
|
||
body="$1"
|
||
temp_file=$(mktemp)
|
||
echo "$body" > "$temp_file"
|
||
|
||
if command -v gh > /dev/null 2>&1; then
|
||
# Find existing comment ID
|
||
existing=$(gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \
|
||
--jq ".[] | select(.body | contains(\"$COMMENT_MARKER\")) | .id" | head -1)
|
||
|
||
if [ -n "$existing" ]; then
|
||
# Update specific comment by ID
|
||
gh api --method PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$existing" \
|
||
--field body="$(cat "$temp_file")"
|
||
else
|
||
gh pr comment "$PR_NUMBER" --body-file "$temp_file"
|
||
fi
|
||
else
|
||
echo "GitHub CLI not available, outputting comment:"
|
||
cat "$temp_file"
|
||
fi
|
||
|
||
rm -f "$temp_file"
|
||
}
|
||
|
||
# Main execution
|
||
if [ "$STATUS" = "starting" ]; then
|
||
# Check if this is a version-bump branch
|
||
IS_VERSION_BUMP="false"
|
||
if echo "$BRANCH_NAME" | grep -q "^version-bump-"; then
|
||
IS_VERSION_BUMP="true"
|
||
fi
|
||
|
||
# Post starting comment with appropriate message
|
||
if [ "$IS_VERSION_BUMP" = "true" ]; then
|
||
comment=$(cat <<EOF
|
||
$COMMENT_MARKER
|
||
## 🎨 Storybook Build Status
|
||
|
||
<img alt='loading' src='https://github.com/user-attachments/assets/755c86ee-e445-4ea8-bc2c-cca85df48686' width='14px' height='14px'/> **Build is starting...**
|
||
|
||
⏰ Started at: $START_TIME UTC
|
||
|
||
### 🚀 Building Storybook
|
||
- 📦 Installing dependencies...
|
||
- 🔧 Building Storybook components...
|
||
- 🎨 Running Chromatic visual tests...
|
||
|
||
---
|
||
⏱️ Please wait while the Storybook build is in progress...
|
||
EOF
|
||
)
|
||
else
|
||
comment=$(cat <<EOF
|
||
$COMMENT_MARKER
|
||
## 🎨 Storybook Build Status
|
||
|
||
<img alt='loading' src='https://github.com/user-attachments/assets/755c86ee-e445-4ea8-bc2c-cca85df48686' width='14px' height='14px'/> **Build is starting...**
|
||
|
||
⏰ Started at: $START_TIME UTC
|
||
|
||
### 🚀 Building Storybook
|
||
- 📦 Installing dependencies...
|
||
- 🔧 Building Storybook components...
|
||
- 🌐 Preparing deployment to Cloudflare Pages...
|
||
|
||
---
|
||
⏱️ Please wait while the Storybook build is in progress...
|
||
EOF
|
||
)
|
||
fi
|
||
post_comment "$comment"
|
||
|
||
elif [ "$STATUS" = "completed" ]; then
|
||
# Deploy and post completion comment
|
||
# Convert branch name to Cloudflare-compatible format (lowercase, only alphanumeric and dashes)
|
||
cloudflare_branch=$(echo "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | \
|
||
sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
|
||
|
||
echo "Looking for Storybook build in: $(pwd)/storybook-static"
|
||
|
||
# Deploy Storybook if build exists
|
||
deployment_url="Not deployed"
|
||
if [ -d "storybook-static" ]; then
|
||
echo "Found Storybook build, deploying..."
|
||
url=$(deploy_storybook "storybook-static" "$cloudflare_branch")
|
||
if [ "$url" != "failed" ] && [ -n "$url" ]; then
|
||
deployment_url="[View Storybook]($url)"
|
||
else
|
||
deployment_url="Deployment failed"
|
||
fi
|
||
else
|
||
echo "Storybook build not found at storybook-static"
|
||
fi
|
||
|
||
# Get workflow conclusion from environment or default to success
|
||
WORKFLOW_CONCLUSION="${WORKFLOW_CONCLUSION:-success}"
|
||
WORKFLOW_URL="${WORKFLOW_URL:-}"
|
||
|
||
# Generate completion comment based on conclusion
|
||
if [ "$WORKFLOW_CONCLUSION" = "success" ]; then
|
||
status_icon="✅"
|
||
status_text="Build completed successfully!"
|
||
footer_text="🎉 Your Storybook is ready for review!"
|
||
elif [ "$WORKFLOW_CONCLUSION" = "skipped" ]; then
|
||
status_icon="⏭️"
|
||
status_text="Build skipped."
|
||
footer_text="ℹ️ Chromatic was skipped for this PR."
|
||
elif [ "$WORKFLOW_CONCLUSION" = "cancelled" ]; then
|
||
status_icon="🚫"
|
||
status_text="Build cancelled."
|
||
footer_text="ℹ️ The Chromatic run was cancelled."
|
||
else
|
||
status_icon="❌"
|
||
status_text="Build failed!"
|
||
footer_text="⚠️ Please check the workflow logs for error details."
|
||
fi
|
||
|
||
comment="$COMMENT_MARKER
|
||
## 🎨 Storybook Build Status
|
||
|
||
$status_icon **$status_text**
|
||
|
||
⏰ Completed at: $(date -u '+%m/%d/%Y, %I:%M:%S %p') UTC
|
||
|
||
### 🔗 Links
|
||
- [📊 View Workflow Run]($WORKFLOW_URL)"
|
||
|
||
# Add deployment status
|
||
if [ "$deployment_url" != "Not deployed" ]; then
|
||
if [ "$deployment_url" = "Deployment failed" ]; then
|
||
comment="$comment
|
||
- ❌ Storybook deployment failed"
|
||
elif [ "$WORKFLOW_CONCLUSION" = "success" ]; then
|
||
comment="$comment
|
||
- 🎨 $deployment_url"
|
||
else
|
||
comment="$comment
|
||
- ⚠️ Build failed - $deployment_url"
|
||
fi
|
||
elif [ "$WORKFLOW_CONCLUSION" != "success" ]; then
|
||
comment="$comment
|
||
- ⏭️ Storybook deployment skipped (build did not succeed)"
|
||
fi
|
||
|
||
comment="$comment
|
||
|
||
---
|
||
$footer_text"
|
||
|
||
post_comment "$comment"
|
||
fi |