mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 20:55:44 +00:00
- Add CRUD handlers for managing what's-new entries stored in S3 - Add whats_new.html template with add/edit/delete forms - Add navigation link to layout.html - Add player-friendly summary generation to generate_changelog.sh - Add seed JSON file for initial data The admin console at /whats-new allows managing changelog entries that will be displayed to players in the Unity client. The script integration generates summaries and opens the admin console with pre-populated content after sending weekly changelogs. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
603 lines
19 KiB
Bash
Executable File
603 lines
19 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# generate_changelog.sh
|
|
#
|
|
# Generates a weekly changelog from merged PRs, uses Claude to create a synopsis,
|
|
# and sends an HTML email via Fastmail JMAP API.
|
|
#
|
|
# Usage: ./scripts/generate_changelog.sh [--dry-run]
|
|
#
|
|
# Configuration files (in ~/.config/eagle0/):
|
|
# fastmail_token - API token (required)
|
|
# changelog_recipient - Email addresses, one per line (optional, defaults to sender)
|
|
#
|
|
# To set up:
|
|
# mkdir -p ~/.config/eagle0
|
|
# echo 'your-token' > ~/.config/eagle0/fastmail_token
|
|
# chmod 600 ~/.config/eagle0/fastmail_token
|
|
#
|
|
# # Optional: configure recipients (one per line, # for comments)
|
|
# cat > ~/.config/eagle0/changelog_recipient << EOF
|
|
# alice@example.com
|
|
# bob@example.com
|
|
# EOF
|
|
#
|
|
# The script tracks its last run using a git tag 'changelog-last-run'.
|
|
# On first run (no tag), it defaults to the previous Friday at 4pm.
|
|
|
|
set -euo pipefail
|
|
|
|
# Ensure homebrew binaries are in PATH
|
|
export PATH="/opt/homebrew/bin:$PATH"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
TAG_NAME="changelog-last-run"
|
|
DRY_RUN=false
|
|
FASTMAIL_API="https://api.fastmail.com/jmap/api/"
|
|
CONFIG_DIR="$HOME/.config/eagle0"
|
|
TOKEN_FILE="$CONFIG_DIR/fastmail_token"
|
|
RECIPIENT_FILE="$CONFIG_DIR/changelog_recipient"
|
|
|
|
# Load API token from file or environment
|
|
load_api_token() {
|
|
# Environment variable takes precedence
|
|
if [[ -n "${FASTMAIL_API_TOKEN:-}" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
# Try loading from config file
|
|
if [[ -f "$TOKEN_FILE" ]]; then
|
|
FASTMAIL_API_TOKEN=$(cat "$TOKEN_FILE" | tr -d '[:space:]')
|
|
if [[ -n "$FASTMAIL_API_TOKEN" ]]; then
|
|
echo "Loaded API token from $TOKEN_FILE"
|
|
export FASTMAIL_API_TOKEN
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
# Load recipient emails from config file (one per line)
|
|
# Returns JSON array fragment like: {"email": "a@b.com"}, {"email": "c@d.com"}
|
|
load_recipients_json() {
|
|
local recipients=""
|
|
if [[ -f "$RECIPIENT_FILE" ]]; then
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
# Skip empty lines and comments
|
|
line=$(echo "$line" | tr -d '[:space:]')
|
|
[[ -z "$line" || "$line" == \#* ]] && continue
|
|
|
|
if [[ -n "$recipients" ]]; then
|
|
recipients="$recipients, "
|
|
fi
|
|
recipients="$recipients{\"email\": \"$line\"}"
|
|
done < "$RECIPIENT_FILE"
|
|
fi
|
|
echo "$recipients"
|
|
}
|
|
|
|
# Get human-readable list of recipients
|
|
load_recipients_display() {
|
|
if [[ -f "$RECIPIENT_FILE" ]]; then
|
|
grep -v '^#' "$RECIPIENT_FILE" | grep -v '^[[:space:]]*$' | tr '\n' ', ' | sed 's/, $//'
|
|
fi
|
|
}
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
echo "Usage: $0 [--dry-run]"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
cd "$REPO_ROOT"
|
|
|
|
# Get the cutoff date - either from tag or previous Friday 4pm
|
|
get_cutoff_date() {
|
|
# Try to get the date from the tag
|
|
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
|
|
# Get the commit date of the tagged commit
|
|
git log -1 --format="%aI" "$TAG_NAME"
|
|
else
|
|
# Calculate previous Friday at 4pm
|
|
# Get current day of week (1=Monday, 7=Sunday)
|
|
local dow=$(date +%u)
|
|
local days_since_friday
|
|
|
|
if [[ $dow -ge 5 ]]; then
|
|
# Friday (5), Saturday (6), or Sunday (7)
|
|
days_since_friday=$((dow - 5))
|
|
else
|
|
# Monday (1) through Thursday (4)
|
|
days_since_friday=$((dow + 2))
|
|
fi
|
|
|
|
# Get previous Friday at 4pm in ISO format
|
|
if [[ "$(uname)" == "Darwin" ]]; then
|
|
date -v-"${days_since_friday}d" -v16H -v0M -v0S +"%Y-%m-%dT%H:%M:%S%z"
|
|
else
|
|
date -d "$days_since_friday days ago 16:00:00" --iso-8601=seconds
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Fetch merged PRs since the cutoff date
|
|
fetch_merged_prs() {
|
|
local since_date="$1"
|
|
local output_file="$2"
|
|
|
|
echo "Fetching PRs merged since: $since_date"
|
|
|
|
# Use gh to search for merged PRs
|
|
gh pr list \
|
|
--state merged \
|
|
--base main \
|
|
--json number,title,body,mergedAt,author \
|
|
--jq ".[] | select(.mergedAt >= \"$since_date\")" \
|
|
> "$output_file.json"
|
|
|
|
# Format the output nicely
|
|
echo "# Merged PRs since $since_date" > "$output_file"
|
|
echo "" >> "$output_file"
|
|
|
|
# Process each PR
|
|
jq -r '
|
|
"## PR #\(.number): \(.title)\n" +
|
|
"Author: \(.author.login)\n" +
|
|
"Merged: \(.mergedAt)\n\n" +
|
|
"### Description\n" +
|
|
(.body // "(No description)") +
|
|
"\n\n---\n"
|
|
' "$output_file.json" >> "$output_file"
|
|
|
|
# Count PRs
|
|
local pr_count=$(jq -s 'length' "$output_file.json")
|
|
echo "Found $pr_count merged PRs"
|
|
|
|
rm -f "$output_file.json"
|
|
|
|
if [[ $pr_count -eq 0 ]]; then
|
|
echo "No PRs found since $since_date"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Generate synopsis using Claude
|
|
generate_synopsis() {
|
|
local input_file="$1"
|
|
local output_file="$2"
|
|
|
|
echo "Generating synopsis with Claude..."
|
|
|
|
# Create a prompt file to avoid shell escaping issues
|
|
local prompt_file="/tmp/eagle0_prompt_$$.txt"
|
|
# Get repo URL for PR links
|
|
local repo_url=$(gh repo view --json url -q '.url')
|
|
|
|
cat > "$prompt_file" <<PROMPT_HEADER
|
|
You are summarizing changes for a weekly engineering update email.
|
|
|
|
Read the following list of merged PRs and create a concise synopsis grouped by theme/feature/area of the codebase.
|
|
|
|
Structure:
|
|
1. <h1> title (e.g., "Eagle0 Weekly Update")
|
|
2. <h2>BLUF</h2> (Bottom Line Up Front) - A short prose paragraph (2-4 sentences) highlighting the 1-3 most important changes this week and what to look for when testing. This should be conversational and help readers quickly understand what matters most.
|
|
3. Synopsis sections (<h2> headings with bullet point summaries)
|
|
4. <hr> divider
|
|
5. <h2>PR Details</h2> with the same groupings, but smaller (<h3> headings) and listing PR links
|
|
- Format each PR as: <a href="${repo_url}/pull/NUMBER">#NUMBER</a>: Title
|
|
|
|
Guidelines for the SYNOPSIS sections:
|
|
- Group related changes together under clear headings (use <h2> tags)
|
|
- Use bullet points (<ul><li>) for individual changes
|
|
- Highlight any significant new features, breaking changes, or important fixes
|
|
- Keep the tone professional but accessible
|
|
- Don't include PR numbers in the synopsis - focus on what changed and why it matters
|
|
|
|
IMPORTANT: Output valid HTML that can be used directly in an email body. Do NOT wrap in \`\`\`html code blocks - just output the raw HTML.
|
|
|
|
Here are the merged PRs:
|
|
|
|
PROMPT_HEADER
|
|
|
|
cat "$input_file" >> "$prompt_file"
|
|
echo "" >> "$prompt_file"
|
|
echo "Generate the synopsis now:" >> "$prompt_file"
|
|
|
|
# Use Claude CLI to generate the synopsis, wrapped in proper HTML with charset
|
|
local raw_output="/tmp/eagle0_raw_$$.html"
|
|
cat "$prompt_file" | claude --print > "$raw_output"
|
|
|
|
# Wrap in HTML document with UTF-8 charset
|
|
cat > "$output_file" <<'HTML_HEAD'
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
</head>
|
|
<body>
|
|
HTML_HEAD
|
|
cat "$raw_output" >> "$output_file"
|
|
echo "</body></html>" >> "$output_file"
|
|
|
|
rm -f "$prompt_file" "$raw_output"
|
|
echo "Synopsis generated at: $output_file"
|
|
}
|
|
|
|
# Get Fastmail session info (account ID, identity ID, drafts mailbox ID)
|
|
get_fastmail_session() {
|
|
echo "Fetching Fastmail session info..." >&2
|
|
|
|
# Get session
|
|
local session=$(curl -s \
|
|
-H "Authorization: Bearer $FASTMAIL_API_TOKEN" \
|
|
"https://api.fastmail.com/jmap/session")
|
|
|
|
# Extract account ID (first account)
|
|
FASTMAIL_ACCOUNT_ID=$(echo "$session" | jq -r '.primaryAccounts["urn:ietf:params:jmap:mail"]')
|
|
|
|
if [[ -z "$FASTMAIL_ACCOUNT_ID" || "$FASTMAIL_ACCOUNT_ID" == "null" ]]; then
|
|
echo "Error: Could not get Fastmail account ID. Check your API token." >&2
|
|
return 1
|
|
fi
|
|
echo "Account ID: $FASTMAIL_ACCOUNT_ID" >&2
|
|
|
|
# Get identity ID
|
|
local identity_response=$(curl -s \
|
|
-H "Authorization: Bearer $FASTMAIL_API_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-X POST \
|
|
-d "{
|
|
\"using\": [\"urn:ietf:params:jmap:core\", \"urn:ietf:params:jmap:mail\", \"urn:ietf:params:jmap:submission\"],
|
|
\"methodCalls\": [
|
|
[\"Identity/get\", {\"accountId\": \"$FASTMAIL_ACCOUNT_ID\"}, \"0\"]
|
|
]
|
|
}" \
|
|
"$FASTMAIL_API")
|
|
|
|
FASTMAIL_IDENTITY_ID=$(echo "$identity_response" | jq -r '.methodResponses[0][1].list[0].id')
|
|
FASTMAIL_FROM_EMAIL=$(echo "$identity_response" | jq -r '.methodResponses[0][1].list[0].email')
|
|
|
|
if [[ -z "$FASTMAIL_IDENTITY_ID" || "$FASTMAIL_IDENTITY_ID" == "null" ]]; then
|
|
echo "Error: Could not get Fastmail identity ID." >&2
|
|
return 1
|
|
fi
|
|
echo "Identity ID: $FASTMAIL_IDENTITY_ID (${FASTMAIL_FROM_EMAIL})" >&2
|
|
|
|
# Get drafts mailbox ID
|
|
local mailbox_response=$(curl -s \
|
|
-H "Authorization: Bearer $FASTMAIL_API_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-X POST \
|
|
-d "{
|
|
\"using\": [\"urn:ietf:params:jmap:core\", \"urn:ietf:params:jmap:mail\"],
|
|
\"methodCalls\": [
|
|
[\"Mailbox/query\", {\"accountId\": \"$FASTMAIL_ACCOUNT_ID\", \"filter\": {\"role\": \"drafts\"}}, \"0\"]
|
|
]
|
|
}" \
|
|
"$FASTMAIL_API")
|
|
|
|
FASTMAIL_DRAFTS_ID=$(echo "$mailbox_response" | jq -r '.methodResponses[0][1].ids[0]')
|
|
|
|
if [[ -z "$FASTMAIL_DRAFTS_ID" || "$FASTMAIL_DRAFTS_ID" == "null" ]]; then
|
|
echo "Error: Could not get Fastmail drafts mailbox ID." >&2
|
|
return 1
|
|
fi
|
|
echo "Drafts mailbox ID: $FASTMAIL_DRAFTS_ID" >&2
|
|
|
|
return 0
|
|
}
|
|
|
|
# Send email via Fastmail JMAP API
|
|
send_email_fastmail() {
|
|
local synopsis_file="$1"
|
|
local recipients_json="$2" # JSON array fragment: {"email": "a@b.com"}, {"email": "c@d.com"}
|
|
|
|
local subject="Eagle0 Weekly Changelog - $(date +%Y-%m-%d)"
|
|
local html_body=$(cat "$synopsis_file" | jq -Rs .)
|
|
|
|
echo "Sending email via Fastmail JMAP API..."
|
|
|
|
# Create the email and send it in one request
|
|
local response=$(curl -s \
|
|
-H "Authorization: Bearer $FASTMAIL_API_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-X POST \
|
|
-d "{
|
|
\"using\": [
|
|
\"urn:ietf:params:jmap:core\",
|
|
\"urn:ietf:params:jmap:mail\",
|
|
\"urn:ietf:params:jmap:submission\"
|
|
],
|
|
\"methodCalls\": [
|
|
[\"Email/set\", {
|
|
\"accountId\": \"$FASTMAIL_ACCOUNT_ID\",
|
|
\"create\": {
|
|
\"draft\": {
|
|
\"from\": [{\"email\": \"$FASTMAIL_FROM_EMAIL\"}],
|
|
\"to\": [$recipients_json],
|
|
\"subject\": \"$subject\",
|
|
\"mailboxIds\": {\"$FASTMAIL_DRAFTS_ID\": true},
|
|
\"keywords\": {\"\$draft\": true},
|
|
\"htmlBody\": [{\"partId\": \"body\", \"type\": \"text/html\"}],
|
|
\"bodyValues\": {
|
|
\"body\": {
|
|
\"charset\": \"utf-8\",
|
|
\"value\": $html_body
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}, \"0\"],
|
|
[\"EmailSubmission/set\", {
|
|
\"accountId\": \"$FASTMAIL_ACCOUNT_ID\",
|
|
\"onSuccessDestroyEmail\": [\"#sendIt\"],
|
|
\"create\": {
|
|
\"sendIt\": {
|
|
\"emailId\": \"#draft\",
|
|
\"identityId\": \"$FASTMAIL_IDENTITY_ID\"
|
|
}
|
|
}
|
|
}, \"1\"]
|
|
]
|
|
}" \
|
|
"$FASTMAIL_API")
|
|
|
|
# Check for errors
|
|
local error=$(echo "$response" | jq -r '.methodResponses[0][1].notCreated.draft.description // empty')
|
|
if [[ -n "$error" ]]; then
|
|
echo "Error creating email: $error" >&2
|
|
echo "Full response: $response" >&2
|
|
return 1
|
|
fi
|
|
|
|
local send_error=$(echo "$response" | jq -r '.methodResponses[1][1].notCreated.sendIt.description // empty')
|
|
if [[ -n "$send_error" ]]; then
|
|
echo "Error sending email: $send_error" >&2
|
|
echo "Full response: $response" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Email sent successfully"
|
|
}
|
|
|
|
# Generate player-friendly "What's New" summary
|
|
# This creates a short summary suitable for in-game display
|
|
generate_whats_new_summary() {
|
|
local pr_file="$1"
|
|
local output_file="/tmp/eagle0_whats_new_$$.txt"
|
|
|
|
echo "Generating player-friendly What's New summary..." >&2
|
|
|
|
# Create a prompt for player-facing summary
|
|
local prompt_file="/tmp/eagle0_whats_new_prompt_$$.txt"
|
|
|
|
cat > "$prompt_file" <<'WHATS_NEW_PROMPT'
|
|
Based on these merged PRs, write a SHORT player-friendly summary.
|
|
Focus only on changes players will notice. Ignore internal/technical changes.
|
|
|
|
Output format (exactly this format, no markdown, no extra text):
|
|
TITLE: (5-10 words describing the main change)
|
|
DESCRIPTION: (1-2 sentences, what players can now do differently)
|
|
CATEGORY: (one of: feature, improvement, fix, content)
|
|
|
|
If there are multiple notable player-visible changes, pick the single most important one.
|
|
If there are no player-visible changes at all, output exactly: NONE
|
|
|
|
Examples of good output:
|
|
TITLE: Bug Reporting
|
|
DESCRIPTION: You can now report bugs directly from the Settings menu.
|
|
CATEGORY: feature
|
|
|
|
TITLE: Faster Reconnection
|
|
DESCRIPTION: The game now reconnects more smoothly after network interruptions.
|
|
CATEGORY: improvement
|
|
|
|
Here are the merged PRs:
|
|
|
|
WHATS_NEW_PROMPT
|
|
|
|
cat "$pr_file" >> "$prompt_file"
|
|
|
|
# Use Claude CLI to generate the summary
|
|
if ! command -v claude &> /dev/null; then
|
|
echo "NONE"
|
|
rm -f "$prompt_file"
|
|
return
|
|
fi
|
|
|
|
cat "$prompt_file" | claude --print > "$output_file" 2>/dev/null
|
|
|
|
rm -f "$prompt_file"
|
|
|
|
# Check if the output is NONE
|
|
if grep -q "^NONE$" "$output_file"; then
|
|
echo "NONE"
|
|
rm -f "$output_file"
|
|
return
|
|
fi
|
|
|
|
# Return the output
|
|
cat "$output_file"
|
|
rm -f "$output_file"
|
|
}
|
|
|
|
# URL encode a string for use in query parameters
|
|
urlencode() {
|
|
local string="$1"
|
|
local strlen=${#string}
|
|
local encoded=""
|
|
local pos c o
|
|
|
|
for (( pos=0 ; pos<strlen ; pos++ )); do
|
|
c=${string:$pos:1}
|
|
case "$c" in
|
|
[-_.~a-zA-Z0-9] ) o="${c}" ;;
|
|
* ) printf -v o '%%%02x' "'$c"
|
|
esac
|
|
encoded+="${o}"
|
|
done
|
|
echo "${encoded}"
|
|
}
|
|
|
|
# Open the admin console with pre-populated what's new content
|
|
open_whats_new_preview() {
|
|
local title="$1"
|
|
local description="$2"
|
|
local category="$3"
|
|
|
|
local encoded_title=$(urlencode "$title")
|
|
local encoded_desc=$(urlencode "$description")
|
|
local encoded_cat=$(urlencode "$category")
|
|
|
|
local preview_url="https://admin.eagle0.net/whats-new?preview=true&title=${encoded_title}&description=${encoded_desc}&category=${encoded_cat}"
|
|
|
|
echo ""
|
|
echo "=== What's New Preview ==="
|
|
echo "Title: $title"
|
|
echo "Description: $description"
|
|
echo "Category: $category"
|
|
echo ""
|
|
echo "Opening admin console preview..."
|
|
|
|
# Open the URL in the default browser
|
|
if [[ "$(uname)" == "Darwin" ]]; then
|
|
open "$preview_url"
|
|
elif command -v xdg-open &> /dev/null; then
|
|
xdg-open "$preview_url"
|
|
else
|
|
echo "Preview URL: $preview_url"
|
|
fi
|
|
}
|
|
|
|
# Update the tag to mark this run
|
|
update_tag() {
|
|
echo "Updating $TAG_NAME tag..."
|
|
|
|
# Delete existing tag if present
|
|
git tag -d "$TAG_NAME" 2>/dev/null || true
|
|
git push origin --delete "$TAG_NAME" 2>/dev/null || true
|
|
|
|
# Create new tag at HEAD
|
|
git tag "$TAG_NAME"
|
|
git push origin "$TAG_NAME"
|
|
|
|
echo "Tag updated to current HEAD"
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
echo "=== Eagle0 Weekly Changelog Generator ==="
|
|
echo ""
|
|
|
|
# Load API token (only required for actual send)
|
|
if [[ "$DRY_RUN" != "true" ]]; then
|
|
if ! load_api_token; then
|
|
echo "Error: No Fastmail API token found."
|
|
echo ""
|
|
echo "To create a token:"
|
|
echo "1. Go to Fastmail Settings -> Password & Security -> API tokens"
|
|
echo "2. Create a new token with 'Email submission' scope"
|
|
echo "3. Save it using one of these methods:"
|
|
echo ""
|
|
echo " Option A (recommended): Store in config file"
|
|
echo " mkdir -p ~/.config/eagle0"
|
|
echo " echo 'your-token' > ~/.config/eagle0/fastmail_token"
|
|
echo " chmod 600 ~/.config/eagle0/fastmail_token"
|
|
echo ""
|
|
echo " Option B: Set environment variable"
|
|
echo " export FASTMAIL_API_TOKEN='your-token'"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Get cutoff date
|
|
local cutoff_date=$(get_cutoff_date)
|
|
echo "Cutoff date: $cutoff_date"
|
|
|
|
# Create temp files
|
|
local pr_file="/tmp/eagle0_prs_$(date +%s).md"
|
|
local synopsis_file="/tmp/eagle0_synopsis_$(date +%s).html"
|
|
|
|
# Fetch PRs
|
|
if ! fetch_merged_prs "$cutoff_date" "$pr_file"; then
|
|
echo "No changes to report. Exiting."
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
echo "PR details saved to: $pr_file"
|
|
|
|
# Generate synopsis
|
|
generate_synopsis "$pr_file" "$synopsis_file"
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo ""
|
|
echo "=== DRY RUN - Synopsis content ==="
|
|
cat "$synopsis_file"
|
|
echo ""
|
|
echo "=== DRY RUN - Skipping email send and tag update ==="
|
|
else
|
|
# Get Fastmail session info
|
|
if ! get_fastmail_session; then
|
|
echo "Failed to get Fastmail session info. Exiting."
|
|
exit 1
|
|
fi
|
|
|
|
# Determine recipients (from config file, or default to sender)
|
|
local recipients_json=$(load_recipients_json)
|
|
if [[ -z "$recipients_json" ]]; then
|
|
recipients_json="{\"email\": \"$FASTMAIL_FROM_EMAIL\"}"
|
|
echo "No recipients configured, sending to self ($FASTMAIL_FROM_EMAIL)"
|
|
else
|
|
local recipients_display=$(load_recipients_display)
|
|
echo "Sending to: $recipients_display"
|
|
fi
|
|
|
|
# Send email
|
|
send_email_fastmail "$synopsis_file" "$recipients_json"
|
|
|
|
# Update tag for next run
|
|
update_tag
|
|
|
|
# Generate player-friendly What's New summary and open admin preview
|
|
echo ""
|
|
echo "Generating What's New summary for in-game display..."
|
|
whats_new_output=$(generate_whats_new_summary "$pr_file")
|
|
|
|
if [[ "$whats_new_output" != "NONE" ]]; then
|
|
# Parse the output
|
|
title=$(echo "$whats_new_output" | grep "^TITLE:" | sed 's/^TITLE:[[:space:]]*//')
|
|
description=$(echo "$whats_new_output" | grep "^DESCRIPTION:" | sed 's/^DESCRIPTION:[[:space:]]*//')
|
|
category=$(echo "$whats_new_output" | grep "^CATEGORY:" | sed 's/^CATEGORY:[[:space:]]*//')
|
|
|
|
if [[ -n "$title" && -n "$description" ]]; then
|
|
open_whats_new_preview "$title" "$description" "$category"
|
|
else
|
|
echo "Could not parse What's New output, skipping preview"
|
|
fi
|
|
else
|
|
echo "No player-visible changes detected, skipping What's New preview"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "Done!"
|
|
echo "PR details: $pr_file"
|
|
echo "Synopsis: $synopsis_file"
|
|
}
|
|
|
|
main
|