Skip to content

fix: preserve trailing newlines in text-based 3-way merges #19190

fix: preserve trailing newlines in text-based 3-way merges

fix: preserve trailing newlines in text-based 3-way merges #19190

Workflow file for this run

name: Release Documentation Check
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled, ready_for_review]
jobs:
check-release-docs:
name: Check for changelog and roadmap updates
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0
- name: Check if PR has minor or major label and targets main
id: check-labels
run: |
if [ ! -f "$GITHUB_EVENT_PATH" ]; then
echo "GitHub event payload not found: $GITHUB_EVENT_PATH"
exit 1
fi
# Skip checks for draft PRs entirely
IS_DRAFT=$(jq -r '.pull_request.draft // false' "$GITHUB_EVENT_PATH")
if [ "$IS_DRAFT" = "true" ]; then
echo "requires_docs=false" >> "$GITHUB_OUTPUT"
echo "✅ PR is a draft - release documentation check skipped"
exit 0
fi
BASE_REF=$(jq -r '.pull_request.base.ref // ""' "$GITHUB_EVENT_PATH")
LABELS=$(jq -r '.pull_request.labels[]?.name' "$GITHUB_EVENT_PATH")
# Only require changelog for PRs targeting main branch
if [ "$BASE_REF" != "main" ]; then
echo "requires_docs=false" >> "$GITHUB_OUTPUT"
echo "✅ PR does not target main branch - release documentation not required"
exit 0
fi
if echo "$LABELS" | grep -qE '^(minor|major)$'; then
echo "requires_docs=true" >> "$GITHUB_OUTPUT"
echo "PR targets main and has minor or major label - release documentation required"
else
echo "requires_docs=false" >> "$GITHUB_OUTPUT"
echo "PR does not have minor or major label - release documentation not required"
fi
- name: Check for new blog post
if: steps.check-labels.outputs.requires_docs == 'true'
id: check-blog
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
# Use git diff directly instead of gh pr diff to avoid API limitations
# GitHub's diff API has a limit of ~300 files or ~3000 lines, which fails on large PRs
# git diff works locally without these limitations
echo "Checking for blog post files between $BASE_SHA and $HEAD_SHA"
NEW_BLOG_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -E '^website/blog/.*\.(md|mdx)$' | grep -v 'tags.yml' || true)
if [ -z "$NEW_BLOG_FILES" ]; then
echo "has_changelog=false" >> "$GITHUB_OUTPUT"
echo "❌ No changelog entry found"
else
{
echo "has_changelog=true"
echo "blog_files<<EOF"
echo "$NEW_BLOG_FILES"
echo "EOF"
} >> "$GITHUB_OUTPUT"
echo "✅ Changelog entry found:"
echo "$NEW_BLOG_FILES"
fi
- name: Check for roadmap update
if: steps.check-labels.outputs.requires_docs == 'true'
id: check-roadmap
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
# Check if website/src/data/roadmap.js was modified
echo "Checking for roadmap updates between $BASE_SHA and $HEAD_SHA"
ROADMAP_CHANGED=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -E '^website/src/data/roadmap\.js$' || true)
if [ -z "$ROADMAP_CHANGED" ]; then
echo "has_roadmap=false" >> "$GITHUB_OUTPUT"
echo "❌ No roadmap update found"
else
echo "has_roadmap=true" >> "$GITHUB_OUTPUT"
echo "✅ Roadmap update found"
fi
- name: Comment on PR if documentation missing
if: |
steps.check-labels.outputs.requires_docs == 'true' &&
(steps.check-blog.outputs.has_changelog == 'false' || steps.check-roadmap.outputs.has_roadmap == 'false')
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HAS_CHANGELOG: ${{ steps.check-blog.outputs.has_changelog }}
HAS_ROADMAP: ${{ steps.check-roadmap.outputs.has_roadmap }}
GH_REPO: ${{ github.repository }}
run: |
# Build checklist based on what's missing
MISSING_ITEMS=""
if [ "$HAS_CHANGELOG" = "false" ]; then
MISSING_ITEMS="${MISSING_ITEMS}
> - [ ] **Changelog entry** - Add a blog post in \`website/blog/YYYY-MM-DD-feature-name.mdx\`"
else
MISSING_ITEMS="${MISSING_ITEMS}
> - [x] **Changelog entry** ✅"
fi
if [ "$HAS_ROADMAP" = "false" ]; then
MISSING_ITEMS="${MISSING_ITEMS}
> - [ ] **Roadmap update** - Update \`website/src/data/roadmap.js\` with the new milestone"
else
MISSING_ITEMS="${MISSING_ITEMS}
> - [x] **Roadmap update** ✅"
fi
# Check if comment already exists
EXISTING_COMMENT=$(gh api --paginate "/repos/${GH_REPO}/issues/${PR_NUMBER}/comments" --jq '.[] | select(.body | contains("<!-- release-docs-check -->")) | .id' | head -1)
COMMENT_BODY="<!-- release-docs-check -->
> [!WARNING]
> #### Release Documentation Required
>
> This PR is labeled \`minor\` or \`major\` and requires documentation updates:
${MISSING_ITEMS}
>
> **Alternatively:** If this change doesn't require release documentation, remove the \`minor\` or \`major\` label."
if [ -n "$EXISTING_COMMENT" ]; then
echo "Updating existing comment..."
gh api -X PATCH "/repos/${GH_REPO}/issues/comments/$EXISTING_COMMENT" \
-f body="$COMMENT_BODY" || {
echo "⚠️ Failed to update comment, creating new one..."
gh pr comment "$PR_NUMBER" --body "$COMMENT_BODY"
}
else
echo "Creating new comment..."
gh pr comment "$PR_NUMBER" --body "$COMMENT_BODY"
fi
- name: Update comment with success message
if: |
steps.check-labels.outputs.requires_docs == 'true' &&
steps.check-blog.outputs.has_changelog == 'true' &&
steps.check-roadmap.outputs.has_roadmap == 'true'
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
BLOG_FILES: ${{ steps.check-blog.outputs.blog_files }}
GH_REPO: ${{ github.repository }}
run: |
# Find existing comment (warning or success)
EXISTING_COMMENT=$(gh api --paginate "/repos/${GH_REPO}/issues/${PR_NUMBER}/comments" --jq '.[] | select(.body | contains("<!-- release-docs-check -->")) | .id' | head -1)
EXISTING_COMMENT_BODY=""
if [ -n "$EXISTING_COMMENT" ]; then
EXISTING_COMMENT_BODY=$(gh api "/repos/${GH_REPO}/issues/comments/$EXISTING_COMMENT" --jq '.body')
fi
SUCCESS_COMMENT_BODY="<!-- release-docs-check -->
> [!NOTE]
> #### Release Documentation Complete ✅
>
> - [x] **Changelog:** $(echo "$BLOG_FILES" | head -1 | sed 's/^/`/' | sed 's/$/`/')
> - [x] **Roadmap:** \`website/src/data/roadmap.js\`
>
> Thank you!"
if [ -n "$EXISTING_COMMENT" ]; then
# Check if comment already shows success
if echo "$EXISTING_COMMENT_BODY" | grep -q "Release Documentation Complete ✅"; then
echo "ℹ️ Comment already shows success - no update needed"
else
echo "Updating existing comment with success message..."
gh api -X PATCH "/repos/${GH_REPO}/issues/comments/$EXISTING_COMMENT" \
-f body="$SUCCESS_COMMENT_BODY" || {
echo "⚠️ Failed to update comment (it may have been deleted)"
}
echo "✅ Comment updated from warning to success"
fi
else
echo "ℹ️ No existing comment to update (comment only created when documentation is missing)"
fi
- name: Fail if documentation missing
if: |
steps.check-labels.outputs.requires_docs == 'true' &&
(steps.check-blog.outputs.has_changelog == 'false' || steps.check-roadmap.outputs.has_roadmap == 'false')
env:
HAS_CHANGELOG: ${{ steps.check-blog.outputs.has_changelog }}
HAS_ROADMAP: ${{ steps.check-roadmap.outputs.has_roadmap }}
run: |
echo "❌ ERROR: PR is labeled 'minor' or 'major' but release documentation is incomplete."
echo ""
if [ "$HAS_CHANGELOG" = "false" ]; then
echo "Missing: Changelog entry"
echo " → Add a blog post in website/blog/YYYY-MM-DD-feature-name.mdx"
echo ""
fi
if [ "$HAS_ROADMAP" = "false" ]; then
echo "Missing: Roadmap update"
echo " → Update website/src/data/roadmap.js with the new milestone"
echo ""
fi
echo "If this change should not require release documentation, remove the 'minor' or 'major' label."
exit 1
- name: Success
if: |
steps.check-labels.outputs.requires_docs == 'false' ||
(steps.check-blog.outputs.has_changelog == 'true' && steps.check-roadmap.outputs.has_roadmap == 'true')
env:
REQUIRES_DOCS: ${{ steps.check-labels.outputs.requires_docs }}
run: |
if [ "$REQUIRES_DOCS" = "false" ]; then
echo "✅ No release documentation required for this PR"
else
echo "✅ Release documentation complete - check passed"
fi