diff --git a/.github/workflows/auto-blog-post.yaml b/.github/workflows/auto-blog-post.yaml new file mode 100644 index 00000000..f7aacb41 --- /dev/null +++ b/.github/workflows/auto-blog-post.yaml @@ -0,0 +1,61 @@ +name: Auto-generate Blog Post for New Radius Release + +on: + repository_dispatch: + types: [radius-release-published] + workflow_dispatch: + inputs: + tag_name: + description: 'Release tag name (optional - will use latest if not provided)' + required: false + type: string + push: + branches: + - 'autogen' + +jobs: + generate-blog-post: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Determine release tag + run: | + # Get release tag from event or use latest + INPUT_TAG="${{ github.event.client_payload.tag_name || github.event.inputs.tag_name || '' }}" + + if [ -z "$INPUT_TAG" ]; then + echo "No tag provided, getting latest release..." + RELEASE_TAG=$(curl -s "https://api.github.com/repos/radius-project/radius/releases/latest" | jq -r '.tag_name') + else + RELEASE_TAG="$INPUT_TAG" + fi + + echo "Using release tag: $RELEASE_TAG" + echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV + + - name: Generate blog post + run: | + # Generate complete blog post using determined tag + ./scripts/generate-blog-post.sh "${{ env.RELEASE_TAG }}" "${{ secrets.GITHUB_TOKEN }}" + + - name: Create Pull Request + uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0 + with: + token: ${{ secrets.GH_RAD_CI_BOT_PAT }} + commit-message: "Add blog post for Radius ${{ env.RELEASE_TAG }}" + signoff: true + title: "Add blog post for Radius ${{ env.RELEASE_TAG }}" + body: | + Auto-generated blog post for **Radius ${{ env.RELEASE_TAG }}** + + - **Tag:** ${{ env.RELEASE_TAG }} + - **Release:** https://github.com/radius-project/radius/releases/tag/${{ env.RELEASE_TAG }} + + 🤖 Generated automatically by GitHub Actions + branch: "blog-post-${{ env.RELEASE_TAG }}" + base: main + delete-branch: true \ No newline at end of file diff --git a/radblog/content/posts/2025/radius-v0.50.0-release/index.md b/radblog/content/posts/2025/radius-v0.50.0-release/index.md index 05c06729..500fc1b4 100644 --- a/radblog/content/posts/2025/radius-v0.50.0-release/index.md +++ b/radblog/content/posts/2025/radius-v0.50.0-release/index.md @@ -33,4 +33,4 @@ We would love for you to join us to help build Radius: - Checkout the Radius roadmap and influence future features at [https://aka.ms/radius-roadmap](https://aka.ms/radius-roadmap) - Join our monthly community meeting to see demos and hear the latest updates (join the [Radius Google Group](https://groups.google.com/g/radapp_io) to get email announcements) - Join the discussion or ask for help on the [Radius Discord server](https://aka.ms/radius/discord) -- Subscribe to the [Radius YouTube channel](https://www.youtube.com/@radapp_io) for more demos +- Subscribe to the [Radius YouTube channel](https://www.youtube.com/@radapp_io) for more demos \ No newline at end of file diff --git a/scripts/blog-prompt.md b/scripts/blog-prompt.md new file mode 100644 index 00000000..def80c56 --- /dev/null +++ b/scripts/blog-prompt.md @@ -0,0 +1,40 @@ +Write a technical blog post announcing Radius {RELEASE_NAME} for developers and platform engineers. + +Release notes (YOUR ONLY SOURCE OF TRUTH): +{RELEASE_NOTES} + +CRITICAL CONTENT CONSTRAINTS - FOLLOW EXACTLY: +- ONLY use information explicitly stated in the release notes above +- Do NOT add any information not found in the release notes +- Do NOT make up features, examples, or documentation links not present in the release notes +- ABSOLUTELY NO CODE SNIPPETS unless they are copy-pasted directly from the release notes +- DO NOT create example code, sample configurations, or illustrative commands +- DO NOT include breaking changes as a separate section +- DO NOT speculate about future features or capabilities +- ONLY include links that are explicitly mentioned in the release notes +- If no code examples exist in release notes, describe features in text only +- Verify the content thoroughly and ensure all details are accurate + +CRITICAL STYLE CONSTRAINTS - FOLLOW EXACTLY: +{STYLE_GUIDE} + +STRUCTURE REQUIREMENTS: +- Start immediately with introductory content, NO heading. +- Summarize the release, include a link to the release notes at {RELEASE_URL} and for new users, provide guidance on how to get started with Radius. +- Use ## headings for main features (not # headings) and summarize each feature in a concise paragraph. Include details from the linked documentation if relevant. +- Feature summary should have breaking changes as a highlight within, not a separate section +- End with the exact "Learn more and Get Involved" section below + +REQUIRED CLOSING SECTION (copy exactly): + +## Learn More and Get Involved + +We would love for you to join us to help build Radius: + +- Try the [Radius Tutorial](https://docs.radapp.io/tutorials/) +- Checkout the Radius roadmap and influence future features at [https://aka.ms/radius-roadmap](https://aka.ms/radius-roadmap) +- Join our monthly community meeting to see demos and hear the latest updates (join the [Radius Google Group](https://groups.google.com/g/radapp_io) to get email announcements) +- Join the discussion or ask for help on the [Radius Discord server](https://aka.ms/radius/discord) +- Subscribe to the [Radius YouTube channel](https://www.youtube.com/@radapp_io) for more demos + +Generate only the blog content (no frontmatter). Be technical, be specific, avoid fluff, check for grammatical and spelling mistakes \ No newline at end of file diff --git a/scripts/generate-blog-post.sh b/scripts/generate-blog-post.sh new file mode 100755 index 00000000..c2cd3d89 --- /dev/null +++ b/scripts/generate-blog-post.sh @@ -0,0 +1,132 @@ +#!/bin/bash +set -e + +# Script to generate complete blog post from release tag +# Usage: ./generate-blog-post.sh +# Outputs: Complete blog post in radblog/content/posts/ + +RELEASE_TAG="$1" +GITHUB_TOKEN="$2" + +if [ -z "$RELEASE_TAG" ] || [ -z "$GITHUB_TOKEN" ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +echo "Generating blog post for Radius $RELEASE_TAG..." + +# Cleanup temporary files on exit +trap 'rm -f prompt_template.md final_prompt.md temp_style_guide.txt temp_release_notes.txt release_body.md' EXIT + +# ============================================================================= +# PREPROCESSING: Gather data +# ============================================================================= +echo "=== PREPROCESSING: Gathering data ===" + +# Get release data +RELEASE_DATA=$(curl -s "https://api.github.com/repos/radius-project/radius/releases/tags/$RELEASE_TAG") +RELEASE_BODY=$(echo "$RELEASE_DATA" | jq -r '.body') +PUBLISHED_AT=$(echo "$RELEASE_DATA" | jq -r '.published_at') + +# Load style guide +if [ -f "radblog/guide/contribution-guide.md" ]; then + FORMATTING_RULES=$(awk '/## Writing Guidelines/,/## Formatting Standards/ { if (!/## Formatting Standards/) print } /## Formatting Standards/,/## Submission Process/ { if (!/## Submission Process/) print }' "radblog/guide/contribution-guide.md") + STYLE_GUIDE=$(printf "CRITICAL FORMATTING REQUIREMENTS - THESE RULES ARE MANDATORY:\n%s\n\nCOMPLETE STYLE GUIDE:\n%s" "$FORMATTING_RULES" "$(cat "radblog/guide/contribution-guide.md")") +else + STYLE_GUIDE="WRITING GUIDELINES: Conversational, user-focused, technical depth, no marketing language, evidence-based content only from release notes." +fi + +# Build AI prompt +cp scripts/blog-prompt.md prompt_template.md +sed -i.bak "s/{RELEASE_NAME}/Radius $RELEASE_TAG/g" prompt_template.md && rm -f prompt_template.md.bak +sed -i.bak "s|{RELEASE_URL}|https://github.com/radius-project/radius/releases/tag/$RELEASE_TAG|g" prompt_template.md && rm -f prompt_template.md.bak + +echo "$STYLE_GUIDE" > temp_style_guide.txt +echo "$RELEASE_BODY" > temp_release_notes.txt + +awk '/{RELEASE_NOTES}/ { while ((getline line < "temp_release_notes.txt") > 0) { print line } close("temp_release_notes.txt"); next } /{STYLE_GUIDE}/ { while ((getline line < "temp_style_guide.txt") > 0) { print line } close("temp_style_guide.txt"); next } /{BLOG_CONTEXT}/ { print "Previous Radius blog posts focus on technical features and developer workflows."; next } { print }' prompt_template.md > final_prompt.md + +# ============================================================================= +# AI GENERATION: Generate content +# ============================================================================= +echo "=== AI GENERATION: Calling GitHub Models API ===" + +RESPONSE=$(curl -s -X POST "https://models.inference.ai.azure.com/chat/completions" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -d "{\"model\": \"gpt-4o\", \"messages\": [{\"role\": \"system\", \"content\": \"You are a technical content writer for cloud-native application platforms. You MUST follow all formatting rules and style guidelines exactly as specified. Failure to follow formatting rules is not acceptable.\"}, {\"role\": \"user\", \"content\": \"$(cat final_prompt.md | sed 's/"/\\"/g' | tr '\n' ' ')\"}], \"max_tokens\": 3500, \"temperature\": 0.2}") + +# ============================================================================= +# POST-PROCESSING: Create blog post +# ============================================================================= +echo "=== POST-PROCESSING: Creating blog post ===" + +if echo "$RESPONSE" | jq -e '.choices[0].message.content' > /dev/null 2>&1; then + echo "$RESPONSE" | jq -r '.choices[0].message.content' > ai_content.md + + # Apply style guide fixes + sed -i.bak 's/\bapplications\b/Applications/g' ai_content.md && rm -f ai_content.md.bak + sed -i.bak 's/\benvironments\b/Environments/g' ai_content.md && rm -f ai_content.md.bak + sed -i.bak 's/\brecipes\b/Recipes/g' ai_content.md && rm -f ai_content.md.bak + sed -i.bak 's/\bresource types\b/Resource Types/g' ai_content.md && rm -f ai_content.md.bak + sed -i.bak 's/ */ /g' ai_content.md && rm -f ai_content.md.bak + + # Create blog directory + YEAR=$(date -d "$PUBLISHED_AT" "+%Y" 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%SZ" "$PUBLISHED_AT" "+%Y") + BLOG_DIR="radblog/content/posts/$YEAR/radius-$RELEASE_TAG-release" + mkdir -p "$BLOG_DIR" + + # Create blog post with frontmatter + BLOG_DATE=$(date -d "$PUBLISHED_AT" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%SZ" "$PUBLISHED_AT" "+%Y-%m-%dT%H:%M:%S%z") + + cat > "$BLOG_DIR/index.md" << EOF +--- +date: "$BLOG_DATE" +title: "Announcing Radius $RELEASE_TAG" +linkTitle: "Radius $RELEASE_TAG" +author: "Radius Team" +type: blog +--- + +EOF + + cat ai_content.md >> "$BLOG_DIR/index.md" + rm ai_content.md + + echo "Blog post created successfully at: $BLOG_DIR/index.md" + echo "RELEASE_TAG=$RELEASE_TAG" +else + echo "AI generation failed, using fallback content" + + # Create blog directory + YEAR=$(date +%Y) + BLOG_DIR="radblog/content/posts/$YEAR/radius-$RELEASE_TAG-release" + mkdir -p "$BLOG_DIR" + + cat > "$BLOG_DIR/index.md" << EOF +--- +date: "$(date -u +%Y-%m-%dT%H:%M:%S%z)" +title: "Announcing Radius $RELEASE_TAG" +linkTitle: "Radius $RELEASE_TAG" +author: "Radius Team" +type: blog +--- + +We're excited to announce the release of Radius $RELEASE_TAG! + +For detailed information about this release, see the [release notes](https://github.com/radius-project/radius/releases/tag/$RELEASE_TAG). + +## Learn More and Get Involved + +We would love for you to join us to help build Radius: + +- Try the [Radius Tutorial](https://docs.radapp.io/tutorials/new-app/) +- Checkout the Radius roadmap and influence future features at [https://aka.ms/radius-roadmap](https://aka.ms/radius-roadmap) +- Join our monthly community meeting to see demos and hear the latest updates (join the [Radius Google Group](https://groups.google.com/g/radapp_io) to get email announcements) +- Join the discussion or ask for help on the [Radius Discord server](https://aka.ms/radius/discord) +- Subscribe to the [Radius YouTube channel](https://www.youtube.com/@radapp_io) for more demos +EOF + + echo "Blog post created with fallback content at: $BLOG_DIR/index.md" +fi +