This document describes how the PR deployment status comment system works across multiple GitHub Actions workflows.
When a PR is created or updated in the sgex repository, potentially two workflows run to build and deploy the branch preview:
- deploy-branch workflow (
branch-deployment.yml): Builds the React application and deploys it to the gh-pages branch - pages-build-deployment workflow (GitHub native): GitHub's built-in workflow that builds the static site from the gh-pages branch content
Each workflow maintains its own status comment on the PR to provide real-time feedback throughout the deployment process.
The scripts/manage-pr-comment.py Python script ensures exactly one comment per workflow run by using an action ID as a unique identifier:
- Each workflow run passes its own
action_idwhen calling the script - The script embeds this ID in an HTML comment marker:
<!-- sgex-deployment-status-comment:ACTION_ID --> - When updating, the script finds the comment with the matching marker
- This prevents duplicate comments and ensures clean, organized PR feedback
Different workflows use different action IDs:
| Workflow | Action ID Source | Example Value |
|---|---|---|
| deploy-branch | ${{ github.run_id }} |
12345678 |
| pages-build-deployment | ${{ github.event.deployment.id }} |
dep_abc123 |
| workflow_dispatch (manual) | ${{ github.run_id }} |
87654321 |
The branch-deployment.yml workflow updates its comment at these stages:
- started - Build initiated (immediately after checkout) - Status: 🟠 (in-progress)
- setup - Dependencies installed and environment ready - Status: 🟠 (in-progress)
- building - React application being compiled - Status: 🟠 (in-progress)
- deploying - Pushing built files to gh-pages branch - Status: 🟠 (in-progress)
- verifying - Checking if deployment is accessible - Status: 🟠 (in-progress)
- success - Deployment complete and verified - Status: 🟢 (completed)
- failure - Build or deployment failed - Status: 🔴 (failed)
Note: When a new stage begins, all previous in-progress (🟠) steps are automatically changed to completed (🟢) while preserving their original timestamps.
GitHub's native Pages workflow can update the comment at:
- pages-built - Static site built from gh-pages content - Status: 🟢 (completed)
- name: Update PR comment - Build Started
if: steps.find_pr.outputs.result != ''
continue-on-error: true
run: |
python3 scripts/manage-pr-comment.py \
--token "${{ secrets.GITHUB_TOKEN }}" \
--repo "${{ github.repository }}" \
--pr "${{ steps.find_pr.outputs.result }}" \
--action-id "${{ github.run_id }}" \
--stage "started" \
--data '{"commit_sha":"...","branch_name":"...","commit_url":"...","workflow_url":"..."}'- name: Update PR comment - Pages Built
run: |
python3 scripts/manage-pr-comment.py \
--token "${{ secrets.GITHUB_TOKEN }}" \
--repo "${{ github.repository }}" \
--pr "${{ steps.find_pr.outputs.result }}" \
--action-id "${{ github.event.deployment.id }}" \
--stage "pages-built" \
--data '{"commit_sha":"...","branch_name":"...","commit_url":"...","workflow_url":"...","branch_url":"..."}'The system works seamlessly with manual workflow triggers:
-
From PR "Approve workflows to run":
- GitHub automatically sets
github.run_id - PR number detected from branch name
- Comment updates normally
- GitHub automatically sets
-
From GitHub Actions UI (workflow_dispatch):
- User provides branch name as input
- Script finds associated PR from branch
- Uses
github.run_idas action ID - Creates/updates comment for that specific run
- Developer pushes to
feature/new-widgetbranch with open PR #123 - deploy-branch workflow starts (run_id: 11111)
- Comment created:
<!-- sgex-deployment-status-comment:11111 --> - Status: "Build Started" 🟠
- Preamble shows: Action ID, Commit SHA, and Workflow Step link
- Comment created:
- Workflow progresses through stages, updating the SAME comment:
- "Setting Up Environment" 🟠 (previous step "Build Started" changes from 🟠 to 🟢)
- "Building Application" 🟠 (previous steps change to 🟢)
- "Deploying to GitHub Pages" 🟠 (previous steps change to 🟢)
- "Verifying Deployment" 🟠 (previous steps change to 🟢)
- Workflow completes
- Final status: "Successfully Deployed 🟢" (all previous steps show 🟢)
- GitHub pages-build-deployment runs (deployment_id: dep_22222)
- NEW comment created:
<!-- sgex-deployment-status-comment:dep_22222 --> - Status: "GitHub Pages Built" 🟢
- NEW comment created:
Result: PR #123 has TWO comments:
- One from deploy-branch (tracking build/deploy with timeline showing progress)
- One from pages-build-deployment (tracking Pages build)
- Real-time visibility: See deployment progress without checking Actions tab
- Clear status: Each stage clearly labeled with consistent circle icons (🟠 in-progress, 🟢 completed, 🔴 failed)
- Timeline tracking: Previous steps automatically marked as completed when advancing to next step
- Quick actions: Direct links to logs, preview URLs, and retry options
- Organized feedback: One comment per workflow, no clutter
- Workflow transparency: Each timeline entry links to the specific workflow step in the GitHub workflow file
- Deployment details: Preamble shows Action ID, Commit SHA, and direct links to workflow run and commit changes
- Content injection protection: All inputs sanitized to prevent attacks
- Reliable tracking: Action IDs ensure no duplicate or lost comments
- Flexible: Works with both automatic and manual workflow triggers
- Extensible: Easy to add new stages or workflows
- Consistent iconography: Circle icons (🟠/🟢/🔴) match across all stages and status indicators
The Python script includes multiple security measures:
- Stage validation: Only allowed stage names accepted
- Input sanitization: All user content (commit SHA, branch names) sanitized
- URL validation: Only HTTPS GitHub URLs allowed
- Length limits: All inputs have maximum length constraints
- Control character removal: Prevents injection attacks
- Action ID sanitization: Only alphanumeric characters and hyphens/underscores allowed
Cause: Script can't find existing comment
Solution: Check that --action-id is consistent across all update calls in the same workflow run
Cause: Action ID changed between updates
Solution: Ensure --action-id uses same source (e.g., always github.run_id) throughout the workflow
Causes:
- No PR found for branch
- Script failed (check logs)
- Permission issues
Solutions:
- Ensure branch has an open PR
- Check workflow logs for Python script output
- Verify workflow has
pull-requests: writepermission
Potential improvements to the system:
- Add more granular stages (e.g., "Running Tests", "Linting Code")
- Include build artifacts information (size, changes)
- Add estimated completion time based on historical data
- Support multiple deployment targets (staging, production)
- Add rollback capabilities with one-click buttons