Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/a7t-ai_slipway.json
T

1 line
70 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "a7t-ai/slipway", "files": {"scripts/workflows/generate_release_notes.sh": {"5897e50b1e47148e4a173108a030291af2f48ab4": {"t": 1785745945.7637355, "n": 10741, "h": "13b2296176f53727", "c": "#!/bin/bash\n\n# ==========================================\n# GENERATE RELEASE NOTES SCRIPT (BASH VERSION)\n# ==========================================\n# This script generates AI-powered release notes using DeepSeek API\n# and translates them to multiple languages using bash and curl\n#\n# Usage:\n# ./scripts/workflows/generate_release_notes.sh --type custom --changes \"change1;change2\"\n# ./scripts/workflows/generate_release_notes.sh --type default --note \"default note\"\n# ./scripts/workflows/generate_release_notes.sh --changes-file CHANGES_IN_VERSION.md\n#\n# Prefer --changes-file in CI: it reads the changelog straight from disk so the\n# text never has to be threaded back through the workflow (see SHELL-SAFETY note).\n#\n# Environment Variables:\n# DEEPSEEK_API_KEY - Required for AI generation\n\nset -e\n\n# Default values\nTYPE=\"\"\nCHANGES=\"\"\nNOTE=\"\"\nCHANGES_FILE=\"\"\n\n# Parse command line arguments\nwhile [[ $# -gt 0 ]]; do\n case $1 in\n --type)\n TYPE=\"$2\"\n shift 2\n ;;\n --changes)\n CHANGES=\"$2\"\n shift 2\n ;;\n --note)\n NOTE=\"$2\"\n shift 2\n ;;\n --changes-file)\n CHANGES_FILE=\"$2\"\n shift 2\n ;;\n *)\n echo \"Unknown parameter: $1\"\n exit 1\n ;;\n esac\ndone\n\n# ---------------------------------------------------------------------------\n# SHELL-SAFETY: read release-notes text straight from CHANGES_IN_VERSION.md.\n#\n# The workflow used to extract these strings and pass them back as\n# --changes/--note. Threading free-form text (apostrophes, \"quotes\") through a\n# workflow run: block breaks shell parsing (\"unexpected EOF while looking for\n# matching '\"). Parsing the file here keeps that text out of the workflow.\n# Do NOT reintroduce inline ${{ }} interpolation of changelog text into a\n# run: block — read the file (this mode) or pass via env: and read \"$VAR\".\n# ---------------------------------------------------------------------------\nparse_changes_file() {\n local file=\"$1\"\n if [ ! -f \"$file\" ]; then\n echo \"❌ Error: changes file not found: $file\"\n exit 1\n fi\n\n # Custom changes = bullet lines that appear before the \"Default\" header.\n # Match \"- \" (dash + space) so real bullets qualify but markdown comment\n # delimiters like \"-->\" or \"---\" rules never get mistaken for a bullet.\n local custom_changes\n custom_changes=$(awk '/### Default Release Notes/{exit} 1' \"$file\" | grep '^- ' || true)\n\n if [ -n \"$custom_changes\" ]; then\n TYPE=\"custom\"\n # Strip \"- \" and join bullets with ';' (generate splits back on ';').\n CHANGES=$(printf '%s\\n' \"$custom_changes\" | sed 's/^- //' | tr '\\n' ';' | sed 's/;$//')\n echo \"✅ Using custom changes from $file\"\n else\n # No custom changes -> pick a random default note.\n local default_notes count line\n default_notes=$(awk '/### Default Release Notes/{flag=1; next} /^###/{flag=0} flag' \"$file\" | grep '^- ' || true)\n if [ -z \"$default_notes\" ]; then\n echo \"❌ Error: no release notes found in $file\"\n exit 1\n fi\n count=$(printf '%s\\n' \"$default_notes\" | grep -c '^- ')\n line=$(( RANDOM % count + 1 ))\n TYPE=\"default\"\n NOTE=$(printf '%s\\n' \"$default_notes\" | sed -n \"${line}p\" | sed 's/^- //')\n echo \"🎲 Using random default note from $file\"\n fi\n}\n\nif [ -n \"$CHANGES_FILE\" ]; then\n parse_changes_file \"$CHANGES_FILE\"\nfi\n\n# Validate required arguments\nif [ -z \"$TYPE\" ]; then\n echo \"❌ Error: --type is required (custom or default)\"\n exit 1\nfi\n\nif [ -z \"$DEEPSEEK_API_KEY\" ]; then\n echo \"❌ Error: DEEPSEEK_API_KEY environment variable is required\"\n exit 1\nfi\n\n# Load copywriting persona (voice, tone, anti-slop rules) to steer the model\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPERSONA_FILE=\"$SCRIPT_DIR/copywriting_persona.md\"\nif [ -f \"$PERSONA_FILE\" ]; then\n PERSONA_CONTENT=$(cat \"$PERSONA_FILE\")\nelse\n echo \"⚠️ Warning: copywriting_persona.md not found at $PERSONA_FILE; falling back to default system prompt\"\n PERSONA_CONTENT=\"\"\nfi\n\n# JSON-escape stdin for safe embedding in a JSON payload\njson_escape() {\n python3 -c 'import json,sys; sys.stdout.write(json.dumps(sys.stdin.read()))'\n}\n\n# Function to call DeepSeek API\ncall_deepseek_api() {\n local prompt=\"$1\"\n local max_tokens=\"${2:-150}\"\n\n local system_message=\"You are a helpful assistant that creates App Store release notes for an iOS app. Be concise, engaging, and user-friendly. Focus on benefits to users.\"\n if [ -n \"$PERSONA_CONTENT\" ]; then\n system_message=\"${system_message}\n\nFollow the voice, tone, and writing rules defined in the persona below. Pay special attention to the Anti-Slop Rules (banned phrases and patterns) and the rule against em dashes and en dashes.\n\n--- PERSONA ---\n${PERSONA_CONTENT}\n--- END PERSONA ---\"\n fi\n\n local escaped_system\n escaped_system=$(printf '%s' \"$system_message\" | json_escape)\n local escaped_user\n escaped_user=$(printf '%s' \"$prompt\" | json_escape)\n\n local json_payload=$(cat <<EOF\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": $escaped_system\n },\n {\n \"role\": \"user\",\n \"content\": $escaped_user\n }\n ],\n \"max_tokens\": $max_tokens,\n \"temperature\": 0.7\n}\nEOF\n)\n \n # Make API call\n local response=$(curl -s -X POST \"https://api.deepseek.com/chat/completions\" \\\n -H \"Authorization: Bearer $DEEPSEEK_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"$json_payload\")\n \n # Extract content from response\n local content=$(echo \"$response\" | grep -o '\"content\":\"[^\"]*\"' | head -1 | sed 's/\"content\":\"//' | sed 's/\"$//' | sed 's/\\\\n/\\n/g' | sed 's/\\\\\"/\"/g')\n \n if [ -z \"$content\" ]; then\n echo \"❌ Error: Failed to get response from DeepSeek API\"\n echo \"Response: $response\"\n exit 1\n fi\n \n echo \"$content\"\n}\n\n# Function to generate release notes based on type\ngenerate_release_notes() {\n local prompt=\"\"\n \n if [ \"$TYPE\" = \"custom\" ]; then\n if [ -z \"$CHANGES\" ]; then\n echo \"❌ Error: --changes is required for custom type\"\n exit 1\n fi\n \n # Convert semicolon-separated changes to bullet points\n local formatted_changes=$(echo \"$CHANGES\" | tr ';' '\\n' | sed 's/^/- /')\n\n prompt=\"Create engaging App Store release notes as a cohesive paragraph for these app changes:\n\n$formatted_changes\n\nImportant formatting rules:\n- Write a cohesive paragraph with multiple sentences for better readability\n- Use periods to create natural breaks between distinct features or ideas\n- Do NOT use bullet points, dashes (—), em-dashes, en-dashes, hyphens, or emojis\n- Connect related ideas with commas and conjunctions, but separate major features with periods\n- Make it user-friendly, highlighting benefits and improvements\n- Keep it concise, exciting, and engaging as a unified message\n\nCritical content rule:\n- Do NOT invent or add any features not listed above\n- Only describe the changes explicitly provided in the list\n- Stay strictly accurate to what was actually changed\"\n \n elif [ \"$TYPE\" = \"default\" ]; then\n if [ -z \"$NOTE\" ]; then\n echo \"❌ Error: --note is required for default type\"\n exit 1\n fi\n\n prompt=\"Transform this default release note into an engaging App Store description paragraph:\n\n\\\"$NOTE\\\"\n\nImportant formatting rules:\n- Write a cohesive paragraph with multiple sentences for better readability\n- Use periods to separate distinct ideas and create natural breaks\n- Do NOT use bullet points, dashes (—), em-dashes, en-dashes, or hyphens for separation\n- Connect related ideas with commas and conjunctions, but use periods between major points\n- Keep the playful tone while being professional and user-focused\n- Highlight the value to users in a flowing, conversational style\n\nCritical content rule:\n- Do NOT invent or add any specific features or changes\n- Only expand and refine the general message provided above\n- Keep the description general and avoid mentioning specific features not stated\"\n \n else\n echo \"❌ Error: Invalid type '$TYPE'. Must be 'custom' or 'default'\"\n exit 1\n fi\n \n echo \"🤖 Generating English release notes...\" >&2\n call_deepseek_api \"$prompt\" 200\n}\n\n# Function to translate text\ntranslate_text() {\n local text=\"$1\"\n local target_language=\"$2\"\n local language_name=\"$3\"\n\n echo \"🌍 Translating to $language_name...\" >&2\n\n local prompt=\"Translate this App Store release note to $target_language:\n\n\\\"$text\\\"\n\nTranslation guidelines:\n- Convert idioms and expressions to their natural equivalents in the target language\n- Do NOT use literal word-for-word translations\n- Adapt cultural references to be appropriate for the target audience\n- Ensure it sounds completely natural to native speakers\n- Keep the same tone, style, and message intent\n- Maintain the same formatting (single paragraph, no dashes)\n\nProvide only the translation, no explanations.\"\n\n call_deepseek_api \"$prompt\" 250\n}\n\n# Generate English release notes\necho \"📝 Generating AI-powered release notes...\"\nENGLISH_NOTES=$(generate_release_notes)\n\nif [ -z \"$ENGLISH_NOTES\" ]; then\n echo \"❌ Failed to generate English release notes\"\n exit 1\nfi\n\necho \"✅ Generated English release notes\"\n\n# Generate translations\nGERMAN_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"German\" \"German\")\nPORTUGUESE_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"Portuguese (Brazil)\" \"Portuguese (Brazil)\")\nSPANISH_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"Spanish (Spain)\" \"Spanish (Spain)\")\n\n# Validate all translations were generated\nif [ -z \"$GERMAN_NOTES\" ] || [ -z \"$PORTUGUESE_NOTES\" ] || [ -z \"$SPANISH_NOTES\" ]; then\n echo \"❌ Failed to generate all translations\"\n exit 1\nfi\n\necho \"✅ Generated all translations\"\n\n# Output to GitHub Actions using heredoc for multiline strings\n{\n echo \"english_notes<<EOF\"\n echo \"$ENGLISH_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"german_notes<<EOF\"\n echo \"$GERMAN_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"portuguese_notes<<EOF\"\n echo \"$PORTUGUESE_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"spanish_notes<<EOF\"\n echo \"$SPANISH_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n# Debug output\necho \"\"\necho \"📋 Generated Release Notes:\"\necho \"🇺🇸 English: $ENGLISH_NOTES\"\necho \"🇩🇪 German: $GERMAN_NOTES\"\necho \"🇧🇷 Portuguese: $PORTUGUESE_NOTES\"\necho \"🇪🇸 Spanish: $SPANISH_NOTES\"\n\necho \"\"\necho \"✅ Release notes generation completed successfully\""}, "036318d98053c2484384bff0415ca3fa5e631812": {"t": 1785758175.0168273, "n": 10741, "h": "13b2296176f53727", "c": "#!/bin/bash\n\n# ==========================================\n# GENERATE RELEASE NOTES SCRIPT (BASH VERSION)\n# ==========================================\n# This script generates AI-powered release notes using DeepSeek API\n# and translates them to multiple languages using bash and curl\n#\n# Usage:\n# ./scripts/workflows/generate_release_notes.sh --type custom --changes \"change1;change2\"\n# ./scripts/workflows/generate_release_notes.sh --type default --note \"default note\"\n# ./scripts/workflows/generate_release_notes.sh --changes-file CHANGES_IN_VERSION.md\n#\n# Prefer --changes-file in CI: it reads the changelog straight from disk so the\n# text never has to be threaded back through the workflow (see SHELL-SAFETY note).\n#\n# Environment Variables:\n# DEEPSEEK_API_KEY - Required for AI generation\n\nset -e\n\n# Default values\nTYPE=\"\"\nCHANGES=\"\"\nNOTE=\"\"\nCHANGES_FILE=\"\"\n\n# Parse command line arguments\nwhile [[ $# -gt 0 ]]; do\n case $1 in\n --type)\n TYPE=\"$2\"\n shift 2\n ;;\n --changes)\n CHANGES=\"$2\"\n shift 2\n ;;\n --note)\n NOTE=\"$2\"\n shift 2\n ;;\n --changes-file)\n CHANGES_FILE=\"$2\"\n shift 2\n ;;\n *)\n echo \"Unknown parameter: $1\"\n exit 1\n ;;\n esac\ndone\n\n# ---------------------------------------------------------------------------\n# SHELL-SAFETY: read release-notes text straight from CHANGES_IN_VERSION.md.\n#\n# The workflow used to extract these strings and pass them back as\n# --changes/--note. Threading free-form text (apostrophes, \"quotes\") through a\n# workflow run: block breaks shell parsing (\"unexpected EOF while looking for\n# matching '\"). Parsing the file here keeps that text out of the workflow.\n# Do NOT reintroduce inline ${{ }} interpolation of changelog text into a\n# run: block — read the file (this mode) or pass via env: and read \"$VAR\".\n# ---------------------------------------------------------------------------\nparse_changes_file() {\n local file=\"$1\"\n if [ ! -f \"$file\" ]; then\n echo \"❌ Error: changes file not found: $file\"\n exit 1\n fi\n\n # Custom changes = bullet lines that appear before the \"Default\" header.\n # Match \"- \" (dash + space) so real bullets qualify but markdown comment\n # delimiters like \"-->\" or \"---\" rules never get mistaken for a bullet.\n local custom_changes\n custom_changes=$(awk '/### Default Release Notes/{exit} 1' \"$file\" | grep '^- ' || true)\n\n if [ -n \"$custom_changes\" ]; then\n TYPE=\"custom\"\n # Strip \"- \" and join bullets with ';' (generate splits back on ';').\n CHANGES=$(printf '%s\\n' \"$custom_changes\" | sed 's/^- //' | tr '\\n' ';' | sed 's/;$//')\n echo \"✅ Using custom changes from $file\"\n else\n # No custom changes -> pick a random default note.\n local default_notes count line\n default_notes=$(awk '/### Default Release Notes/{flag=1; next} /^###/{flag=0} flag' \"$file\" | grep '^- ' || true)\n if [ -z \"$default_notes\" ]; then\n echo \"❌ Error: no release notes found in $file\"\n exit 1\n fi\n count=$(printf '%s\\n' \"$default_notes\" | grep -c '^- ')\n line=$(( RANDOM % count + 1 ))\n TYPE=\"default\"\n NOTE=$(printf '%s\\n' \"$default_notes\" | sed -n \"${line}p\" | sed 's/^- //')\n echo \"🎲 Using random default note from $file\"\n fi\n}\n\nif [ -n \"$CHANGES_FILE\" ]; then\n parse_changes_file \"$CHANGES_FILE\"\nfi\n\n# Validate required arguments\nif [ -z \"$TYPE\" ]; then\n echo \"❌ Error: --type is required (custom or default)\"\n exit 1\nfi\n\nif [ -z \"$DEEPSEEK_API_KEY\" ]; then\n echo \"❌ Error: DEEPSEEK_API_KEY environment variable is required\"\n exit 1\nfi\n\n# Load copywriting persona (voice, tone, anti-slop rules) to steer the model\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPERSONA_FILE=\"$SCRIPT_DIR/copywriting_persona.md\"\nif [ -f \"$PERSONA_FILE\" ]; then\n PERSONA_CONTENT=$(cat \"$PERSONA_FILE\")\nelse\n echo \"⚠️ Warning: copywriting_persona.md not found at $PERSONA_FILE; falling back to default system prompt\"\n PERSONA_CONTENT=\"\"\nfi\n\n# JSON-escape stdin for safe embedding in a JSON payload\njson_escape() {\n python3 -c 'import json,sys; sys.stdout.write(json.dumps(sys.stdin.read()))'\n}\n\n# Function to call DeepSeek API\ncall_deepseek_api() {\n local prompt=\"$1\"\n local max_tokens=\"${2:-150}\"\n\n local system_message=\"You are a helpful assistant that creates App Store release notes for an iOS app. Be concise, engaging, and user-friendly. Focus on benefits to users.\"\n if [ -n \"$PERSONA_CONTENT\" ]; then\n system_message=\"${system_message}\n\nFollow the voice, tone, and writing rules defined in the persona below. Pay special attention to the Anti-Slop Rules (banned phrases and patterns) and the rule against em dashes and en dashes.\n\n--- PERSONA ---\n${PERSONA_CONTENT}\n--- END PERSONA ---\"\n fi\n\n local escaped_system\n escaped_system=$(printf '%s' \"$system_message\" | json_escape)\n local escaped_user\n escaped_user=$(printf '%s' \"$prompt\" | json_escape)\n\n local json_payload=$(cat <<EOF\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": $escaped_system\n },\n {\n \"role\": \"user\",\n \"content\": $escaped_user\n }\n ],\n \"max_tokens\": $max_tokens,\n \"temperature\": 0.7\n}\nEOF\n)\n \n # Make API call\n local response=$(curl -s -X POST \"https://api.deepseek.com/chat/completions\" \\\n -H \"Authorization: Bearer $DEEPSEEK_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"$json_payload\")\n \n # Extract content from response\n local content=$(echo \"$response\" | grep -o '\"content\":\"[^\"]*\"' | head -1 | sed 's/\"content\":\"//' | sed 's/\"$//' | sed 's/\\\\n/\\n/g' | sed 's/\\\\\"/\"/g')\n \n if [ -z \"$content\" ]; then\n echo \"❌ Error: Failed to get response from DeepSeek API\"\n echo \"Response: $response\"\n exit 1\n fi\n \n echo \"$content\"\n}\n\n# Function to generate release notes based on type\ngenerate_release_notes() {\n local prompt=\"\"\n \n if [ \"$TYPE\" = \"custom\" ]; then\n if [ -z \"$CHANGES\" ]; then\n echo \"❌ Error: --changes is required for custom type\"\n exit 1\n fi\n \n # Convert semicolon-separated changes to bullet points\n local formatted_changes=$(echo \"$CHANGES\" | tr ';' '\\n' | sed 's/^/- /')\n\n prompt=\"Create engaging App Store release notes as a cohesive paragraph for these app changes:\n\n$formatted_changes\n\nImportant formatting rules:\n- Write a cohesive paragraph with multiple sentences for better readability\n- Use periods to create natural breaks between distinct features or ideas\n- Do NOT use bullet points, dashes (—), em-dashes, en-dashes, hyphens, or emojis\n- Connect related ideas with commas and conjunctions, but separate major features with periods\n- Make it user-friendly, highlighting benefits and improvements\n- Keep it concise, exciting, and engaging as a unified message\n\nCritical content rule:\n- Do NOT invent or add any features not listed above\n- Only describe the changes explicitly provided in the list\n- Stay strictly accurate to what was actually changed\"\n \n elif [ \"$TYPE\" = \"default\" ]; then\n if [ -z \"$NOTE\" ]; then\n echo \"❌ Error: --note is required for default type\"\n exit 1\n fi\n\n prompt=\"Transform this default release note into an engaging App Store description paragraph:\n\n\\\"$NOTE\\\"\n\nImportant formatting rules:\n- Write a cohesive paragraph with multiple sentences for better readability\n- Use periods to separate distinct ideas and create natural breaks\n- Do NOT use bullet points, dashes (—), em-dashes, en-dashes, or hyphens for separation\n- Connect related ideas with commas and conjunctions, but use periods between major points\n- Keep the playful tone while being professional and user-focused\n- Highlight the value to users in a flowing, conversational style\n\nCritical content rule:\n- Do NOT invent or add any specific features or changes\n- Only expand and refine the general message provided above\n- Keep the description general and avoid mentioning specific features not stated\"\n \n else\n echo \"❌ Error: Invalid type '$TYPE'. Must be 'custom' or 'default'\"\n exit 1\n fi\n \n echo \"🤖 Generating English release notes...\" >&2\n call_deepseek_api \"$prompt\" 200\n}\n\n# Function to translate text\ntranslate_text() {\n local text=\"$1\"\n local target_language=\"$2\"\n local language_name=\"$3\"\n\n echo \"🌍 Translating to $language_name...\" >&2\n\n local prompt=\"Translate this App Store release note to $target_language:\n\n\\\"$text\\\"\n\nTranslation guidelines:\n- Convert idioms and expressions to their natural equivalents in the target language\n- Do NOT use literal word-for-word translations\n- Adapt cultural references to be appropriate for the target audience\n- Ensure it sounds completely natural to native speakers\n- Keep the same tone, style, and message intent\n- Maintain the same formatting (single paragraph, no dashes)\n\nProvide only the translation, no explanations.\"\n\n call_deepseek_api \"$prompt\" 250\n}\n\n# Generate English release notes\necho \"📝 Generating AI-powered release notes...\"\nENGLISH_NOTES=$(generate_release_notes)\n\nif [ -z \"$ENGLISH_NOTES\" ]; then\n echo \"❌ Failed to generate English release notes\"\n exit 1\nfi\n\necho \"✅ Generated English release notes\"\n\n# Generate translations\nGERMAN_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"German\" \"German\")\nPORTUGUESE_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"Portuguese (Brazil)\" \"Portuguese (Brazil)\")\nSPANISH_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"Spanish (Spain)\" \"Spanish (Spain)\")\n\n# Validate all translations were generated\nif [ -z \"$GERMAN_NOTES\" ] || [ -z \"$PORTUGUESE_NOTES\" ] || [ -z \"$SPANISH_NOTES\" ]; then\n echo \"❌ Failed to generate all translations\"\n exit 1\nfi\n\necho \"✅ Generated all translations\"\n\n# Output to GitHub Actions using heredoc for multiline strings\n{\n echo \"english_notes<<EOF\"\n echo \"$ENGLISH_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"german_notes<<EOF\"\n echo \"$GERMAN_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"portuguese_notes<<EOF\"\n echo \"$PORTUGUESE_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"spanish_notes<<EOF\"\n echo \"$SPANISH_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n# Debug output\necho \"\"\necho \"📋 Generated Release Notes:\"\necho \"🇺🇸 English: $ENGLISH_NOTES\"\necho \"🇩🇪 German: $GERMAN_NOTES\"\necho \"🇧🇷 Portuguese: $PORTUGUESE_NOTES\"\necho \"🇪🇸 Spanish: $SPANISH_NOTES\"\n\necho \"\"\necho \"✅ Release notes generation completed successfully\""}, "44983588ca5c8c08e9e39351c2102cbe71037c0f": {"t": 1785758176.6032727, "n": 8211, "h": "0d9f792518308b4e", "c": "#!/bin/bash\n\n# ==========================================\n# GENERATE RELEASE NOTES SCRIPT (BASH VERSION)\n# ==========================================\n# This script generates AI-powered release notes using DeepSeek API\n# and translates them to multiple languages using bash and curl\n#\n# Usage:\n# ./scripts/workflows/generate_release_notes.sh --type custom --changes \"change1;change2\"\n# ./scripts/workflows/generate_release_notes.sh --type default --note \"default note\"\n#\n# Environment Variables:\n# DEEPSEEK_API_KEY - Required for AI generation\n\nset -e\n\n# Default values\nTYPE=\"\"\nCHANGES=\"\"\nNOTE=\"\"\n\n# Parse command line arguments\nwhile [[ $# -gt 0 ]]; do\n case $1 in\n --type)\n TYPE=\"$2\"\n shift 2\n ;;\n --changes)\n CHANGES=\"$2\"\n shift 2\n ;;\n --note)\n NOTE=\"$2\"\n shift 2\n ;;\n *)\n echo \"Unknown parameter: $1\"\n exit 1\n ;;\n esac\ndone\n\n# Validate required arguments\nif [ -z \"$TYPE\" ]; then\n echo \"❌ Error: --type is required (custom or default)\"\n exit 1\nfi\n\nif [ -z \"$DEEPSEEK_API_KEY\" ]; then\n echo \"❌ Error: DEEPSEEK_API_KEY environment variable is required\"\n exit 1\nfi\n\n# Load copywriting persona (voice, tone, anti-slop rules) to steer the model\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPERSONA_FILE=\"$SCRIPT_DIR/copywriting_persona.md\"\nif [ -f \"$PERSONA_FILE\" ]; then\n PERSONA_CONTENT=$(cat \"$PERSONA_FILE\")\nelse\n echo \"⚠️ Warning: copywriting_persona.md not found at $PERSONA_FILE; falling back to default system prompt\"\n PERSONA_CONTENT=\"\"\nfi\n\n# JSON-escape stdin for safe embedding in a JSON payload\njson_escape() {\n python3 -c 'import json,sys; sys.stdout.write(json.dumps(sys.stdin.read()))'\n}\n\n# Function to call DeepSeek API\ncall_deepseek_api() {\n local prompt=\"$1\"\n local max_tokens=\"${2:-150}\"\n\n local system_message=\"You are a helpful assistant that creates App Store release notes for an iOS app. Be concise, engaging, and user-friendly. Focus on benefits to users.\"\n if [ -n \"$PERSONA_CONTENT\" ]; then\n system_message=\"${system_message}\n\nFollow the voice, tone, and writing rules defined in the persona below. Pay special attention to the Anti-Slop Rules (banned phrases and patterns) and the rule against em dashes and en dashes.\n\n--- PERSONA ---\n${PERSONA_CONTENT}\n--- END PERSONA ---\"\n fi\n\n local escaped_system\n escaped_system=$(printf '%s' \"$system_message\" | json_escape)\n local escaped_user\n escaped_user=$(printf '%s' \"$prompt\" | json_escape)\n\n local json_payload=$(cat <<EOF\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": $escaped_system\n },\n {\n \"role\": \"user\",\n \"content\": $escaped_user\n }\n ],\n \"max_tokens\": $max_tokens,\n \"temperature\": 0.7\n}\nEOF\n)\n \n # Make API call\n local response=$(curl -s -X POST \"https://api.deepseek.com/chat/completions\" \\\n -H \"Authorization: Bearer $DEEPSEEK_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"$json_payload\")\n \n # Extract content from response\n local content=$(echo \"$response\" | grep -o '\"content\":\"[^\"]*\"' | head -1 | sed 's/\"content\":\"//' | sed 's/\"$//' | sed 's/\\\\n/\\n/g' | sed 's/\\\\\"/\"/g')\n \n if [ -z \"$content\" ]; then\n echo \"❌ Error: Failed to get response from DeepSeek API\"\n echo \"Response: $response\"\n exit 1\n fi\n \n echo \"$content\"\n}\n\n# Function to generate release notes based on type\ngenerate_release_notes() {\n local prompt=\"\"\n \n if [ \"$TYPE\" = \"custom\" ]; then\n if [ -z \"$CHANGES\" ]; then\n echo \"❌ Error: --changes is required for custom type\"\n exit 1\n fi\n \n # Convert semicolon-separated changes to bullet points\n local formatted_changes=$(echo \"$CHANGES\" | tr ';' '\\n' | sed 's/^/- /')\n\n prompt=\"Create engaging App Store release notes as a cohesive paragraph for these app changes:\n\n$formatted_changes\n\nImportant formatting rules:\n- Write a cohesive paragraph with multiple sentences for better readability\n- Use periods to create natural breaks between distinct features or ideas\n- Do NOT use bullet points, dashes (—), em-dashes, en-dashes, hyphens, or emojis\n- Connect related ideas with commas and conjunctions, but separate major features with periods\n- Make it user-friendly, highlighting benefits and improvements\n- Keep it concise, exciting, and engaging as a unified message\n\nCritical content rule:\n- Do NOT invent or add any features not listed above\n- Only describe the changes explicitly provided in the list\n- Stay strictly accurate to what was actually changed\"\n \n elif [ \"$TYPE\" = \"default\" ]; then\n if [ -z \"$NOTE\" ]; then\n echo \"❌ Error: --note is required for default type\"\n exit 1\n fi\n\n prompt=\"Transform this default release note into an engaging App Store description paragraph:\n\n\\\"$NOTE\\\"\n\nImportant formatting rules:\n- Write a cohesive paragraph with multiple sentences for better readability\n- Use periods to separate distinct ideas and create natural breaks\n- Do NOT use bullet points, dashes (—), em-dashes, en-dashes, or hyphens for separation\n- Connect related ideas with commas and conjunctions, but use periods between major points\n- Keep the playful tone while being professional and user-focused\n- Highlight the value to users in a flowing, conversational style\n\nCritical content rule:\n- Do NOT invent or add any specific features or changes\n- Only expand and refine the general message provided above\n- Keep the description general and avoid mentioning specific features not stated\"\n \n else\n echo \"❌ Error: Invalid type '$TYPE'. Must be 'custom' or 'default'\"\n exit 1\n fi\n \n echo \"🤖 Generating English release notes...\" >&2\n call_deepseek_api \"$prompt\" 200\n}\n\n# Function to translate text\ntranslate_text() {\n local text=\"$1\"\n local target_language=\"$2\"\n local language_name=\"$3\"\n\n echo \"🌍 Translating to $language_name...\" >&2\n\n local prompt=\"Translate this App Store release note to $target_language:\n\n\\\"$text\\\"\n\nTranslation guidelines:\n- Convert idioms and expressions to their natural equivalents in the target language\n- Do NOT use literal word-for-word translations\n- Adapt cultural references to be appropriate for the target audience\n- Ensure it sounds completely natural to native speakers\n- Keep the same tone, style, and message intent\n- Maintain the same formatting (single paragraph, no dashes)\n\nProvide only the translation, no explanations.\"\n\n call_deepseek_api \"$prompt\" 250\n}\n\n# Generate English release notes\necho \"📝 Generating AI-powered release notes...\"\nENGLISH_NOTES=$(generate_release_notes)\n\nif [ -z \"$ENGLISH_NOTES\" ]; then\n echo \"❌ Failed to generate English release notes\"\n exit 1\nfi\n\necho \"✅ Generated English release notes\"\n\n# Generate translations\nGERMAN_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"German\" \"German\")\nPORTUGUESE_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"Portuguese (Brazil)\" \"Portuguese (Brazil)\")\nSPANISH_NOTES=$(translate_text \"$ENGLISH_NOTES\" \"Spanish (Spain)\" \"Spanish (Spain)\")\n\n# Validate all translations were generated\nif [ -z \"$GERMAN_NOTES\" ] || [ -z \"$PORTUGUESE_NOTES\" ] || [ -z \"$SPANISH_NOTES\" ]; then\n echo \"❌ Failed to generate all translations\"\n exit 1\nfi\n\necho \"✅ Generated all translations\"\n\n# Output to GitHub Actions using heredoc for multiline strings\n{\n echo \"english_notes<<EOF\"\n echo \"$ENGLISH_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"german_notes<<EOF\"\n echo \"$GERMAN_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"portuguese_notes<<EOF\"\n echo \"$PORTUGUESE_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n{\n echo \"spanish_notes<<EOF\"\n echo \"$SPANISH_NOTES\"\n echo \"EOF\"\n} >> $GITHUB_OUTPUT\n\n# Debug output\necho \"\"\necho \"📋 Generated Release Notes:\"\necho \"🇺🇸 English: $ENGLISH_NOTES\"\necho \"🇩🇪 German: $GERMAN_NOTES\"\necho \"🇧🇷 Portuguese: $PORTUGUESE_NOTES\"\necho \"🇪🇸 Spanish: $SPANISH_NOTES\"\n\necho \"\"\necho \"✅ Release notes generation completed successfully\""}}, ".github/workflows/trigger-new-version-process.yml": {"5897e50b1e47148e4a173108a030291af2f48ab4": {"t": 1785747054.3094199, "n": 19085, "h": "aee49c2d67170d6b", "c": "# ==========================================\n# TRIGGER NEW VERSION PROCESS WORKFLOW\n# ==========================================\n# This workflow orchestrates a complete new version release process including:\n# - Creating App Store version entry with current MARKETING_VERSION\n# - Writing AI-powered release notes (optional - can be skipped with keep_release_notes)\n# - Clearing release notes for next version (optional - skipped when keep_release_notes is true)\n# - Building and delivering to TestFlight\n# - Adding build to release and submitting for App Store review\n\nname: Trigger New Version Process\n\n# Set permissions for the workflow\npermissions:\n contents: write\n pull-requests: write\n actions: read\non:\n # ==========================================\n # MANUAL TRIGGER\n # ==========================================\n workflow_dispatch:\n inputs:\n platform:\n description: 'Platform'\n required: true\n default: 'iOS'\n type: choice\n options:\n - 'iOS'\n\n xcode_version:\n description: 'Xcode Version'\n required: false\n default: 'Xcode-26.4.1.app'\n type: choice\n options:\n - 'Xcode-26.4.1.app'\n\n test_group:\n description: 'TestFlight beta group name'\n required: false\n default: 'Reviewers'\n type: choice\n options:\n - 'Reviewers'\n\n skip_slack_posting:\n description: 'Skip Slack notifications'\n required: false\n type: boolean\n default: false\n\n keep_release_notes:\n description: 'Keep current release notes (skip writing and clearing)'\n required: false\n type: boolean\n default: false\n\n # ==========================================\n # SCHEDULED TRIGGER (DISABLED)\n # ==========================================\n schedule:\n - cron: '0 3 * * 2' # 03:00 UTC = 04:00 CET (during standard time), every Tuesday\n\n # ==========================================\n # REUSABLE WORKFLOW TRIGGER\n # ==========================================\n workflow_call:\n inputs:\n platform:\n description: 'Platform'\n required: false\n default: 'iOS'\n type: string\n\n xcode_version:\n description: 'Xcode Version'\n required: false\n default: 'Xcode-26.4.1.app'\n type: string\n\n test_group:\n description: 'TestFlight beta group name'\n required: false\n default: 'Reviewers'\n type: string\n\n skip_slack_posting:\n description: 'Skip Slack notifications'\n required: false\n default: true\n type: boolean\n\n keep_release_notes:\n description: 'Keep current release notes (skip writing and clearing)'\n required: false\n default: false\n type: boolean\n secrets:\n APP_STORE_CONNECT_KEY_ID:\n required: true\n APP_STORE_CONNECT_ISSUER_ID:\n required: true\n APP_STORE_CONNECT_KEY_CONTENT:\n required: true\n MATCH_PASSWORD:\n description: 'Match password for code signing'\n required: true\n DEEPSEEK_API_KEY:\n description: 'DeepSeek API key for AI-powered release notes generation'\n required: true\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL:\n description: 'Slack webhook for notifications (optional)'\n required: false\n\n# Environment variables\nenv:\n LANG: en_US.UTF-8\n LANGUAGE: en_US.UTF-8\n LC_ALL: en_US.UTF-8\n APP_NAME: ${{ vars.APP_NAME }}\n APP_SLUG: ${{ vars.APP_SLUG }}\n BUNDLE_ID: ${{ vars.BUNDLE_ID }}\n XCCONFIG_PATH: ${{ vars.XCCONFIG_PATH }}\n MARKETING_URL: ${{ vars.MARKETING_URL }}\n APPLE_ID: ${{ secrets.APPLE_ID }}\n APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}\n APPLE_ITC_TEAM_ID: ${{ secrets.APPLE_ITC_TEAM_ID }}\n MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}\n\njobs:\n # ==========================================\n # JOB 1: BUMP VERSION\n # ==========================================\n bump-version:\n name: Bump Version for New Release\n uses: ./.github/workflows/bump-version.yml\n with:\n version_type: current # 'current' keeps current marketing version, only increments build number\n skip_slack_posting: true\n secrets: inherit\n\n # ==========================================\n # JOB 2: CREATE APP STORE VERSION ENTRY\n # ==========================================\n create-appstore-version:\n name: Create App Store Version Entry\n needs: [bump-version]\n if: needs.bump-version.result == 'success'\n uses: ./.github/workflows/create-appstore-version.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n skip_slack_posting: true\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n\n # ==========================================\n # JOB 3: WRITE RELEASE NOTES\n # ==========================================\n write-release-notes:\n name: Write Release Notes\n needs: [create-appstore-version]\n if: needs.create-appstore-version.result == 'success' && !inputs.keep_release_notes\n uses: ./.github/workflows/write-release-notes.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n skip_slack_posting: true\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}\n GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}\n\n # ==========================================\n # JOB 3b: UPLOAD APP STORE METADATA\n # ==========================================\n upload-metadata:\n name: Upload App Store Metadata\n needs: [create-appstore-version]\n if: needs.create-appstore-version.result == 'success'\n uses: ./.github/workflows/upload-metadata.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n BETA_CONTACT_EMAIL: ${{ secrets.BETA_CONTACT_EMAIL }}\n BETA_CONTACT_PHONE: ${{ secrets.BETA_CONTACT_PHONE }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n\n # ==========================================\n # JOB 4: DELIVER TO TESTFLIGHT\n # ==========================================\n deliver-to-testflight:\n name: Deliver to TestFlight\n needs: [write-release-notes, create-appstore-version, upload-metadata]\n if: |\n always() &&\n needs.create-appstore-version.result == 'success' &&\n (needs.write-release-notes.result == 'success' || needs.write-release-notes.result == 'skipped') &&\n (needs.upload-metadata.result == 'success' || needs.upload-metadata.result == 'skipped')\n uses: ./.github/workflows/deliver-to-testflight.yml\n with:\n scheme: '${{ vars.APP_NAME }}'\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n test_group: ${{ inputs.test_group || 'Reviewers' }}\n release_notes: ''\n secrets:\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n SLACK_USER_ID: ${{ secrets.SLACK_USER_ID }}\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}\n BETA_CONTACT_EMAIL: ${{ secrets.BETA_CONTACT_EMAIL }}\n BETA_CONTACT_PHONE: ${{ secrets.BETA_CONTACT_PHONE }}\n BETA_DEMO_ACCOUNT_NAME: ${{ secrets.BETA_DEMO_ACCOUNT_NAME }}\n BETA_DEMO_ACCOUNT_PASSWORD: ${{ secrets.BETA_DEMO_ACCOUNT_PASSWORD }}\n GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}\n GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}\n\n # ==========================================\n # JOB 5: ADD BUILD TO RELEASE\n # ==========================================\n add-build-to-release:\n name: Add Build to Release\n needs: [deliver-to-testflight, create-appstore-version]\n if: needs.deliver-to-testflight.result == 'success'\n uses: ./.github/workflows/add-build-to-release.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n version: ${{ needs.create-appstore-version.outputs.version }}\n build_number: ${{ needs.deliver-to-testflight.outputs.build_number }}\n submit_for_review: true\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n skip_slack_posting: true\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n\n # ==========================================\n # JOB 6: CLEAR RELEASE NOTES\n # ==========================================\n clear-release-notes:\n name: Clear Release Notes\n needs: [add-build-to-release, write-release-notes]\n if: |\n always() &&\n (needs.add-build-to-release.result == 'success' || needs.write-release-notes.result == 'success') &&\n !inputs.keep_release_notes\n uses: ./.github/workflows/clear-release-notes.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n skip_slack_posting: true\n secrets:\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}\n GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}\n\n # ==========================================\n # JOB 7: SEND FINAL STATUS NOTIFICATION\n # ==========================================\n notify-final-status:\n name: Send Final Status Notification\n runs-on: macos-latest\n needs: [bump-version, create-appstore-version, write-release-notes, deliver-to-testflight, add-build-to-release, clear-release-notes]\n if: always() && !inputs.skip_slack_posting\n timeout-minutes: 5\n\n steps:\n - name: Send Slack notification\n uses: slackapi/slack-github-action@v2.1.0\n with:\n webhook: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n webhook-type: incoming-webhook\n payload: |\n {\n \"text\": \"${{ vars.APP_NAME }} iOS - New Version Process: ${{ needs.add-build-to-release.result == 'success' && '✅ Completed Successfully' || '❌ Failed or Incomplete' }}\",\n \"blocks\": [\n {\n \"type\": \"header\",\n \"text\": {\n \"type\": \"plain_text\",\n \"text\": \"🚀 ${{ vars.APP_NAME }} iOS - New Version Process Summary\",\n \"emoji\": true\n }\n },\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Overall Status:*\\n${{ needs.add-build-to-release.result == 'success' && '✅ Completed Successfully' || '❌ Failed or Incomplete' }}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Platform:*\\n${{ inputs.platform || 'iOS' }}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Version:*\\n`${{ needs.create-appstore-version.outputs.version || 'Unknown' }}`\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Build:*\\n`${{ needs.deliver-to-testflight.outputs.build_number || 'Unknown' }}`\"\n }\n ]\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Process Steps:*\\n• Bump Version: ${{ needs.bump-version.result == 'success' && '✅' || needs.bump-version.result == 'failure' && '❌' || '⏳' }}\\n• App Store Version: ${{ needs.create-appstore-version.result == 'success' && '✅' || needs.create-appstore-version.result == 'failure' && '❌' || '⏳' }}\\n• Release Notes: ${{ inputs.keep_release_notes && '⏭️ (kept)' || needs.write-release-notes.result == 'success' && '✅' || needs.write-release-notes.result == 'failure' && '❌' || needs.write-release-notes.result == 'skipped' && '⏭️' || '⏳' }}\\n• Clear Notes: ${{ inputs.keep_release_notes && '⏭️ (kept)' || needs.clear-release-notes.result == 'success' && '✅' || needs.clear-release-notes.result == 'failure' && '❌' || needs.clear-release-notes.result == 'skipped' && '⏭️' || '⏳' }}\\n• TestFlight: ${{ needs.deliver-to-testflight.result == 'success' && '✅' || needs.deliver-to-testflight.result == 'failure' && '❌' || needs.deliver-to-testflight.result == 'skipped' && '⏭️' || '⏳' }}\\n• Submit for Review: ${{ needs.add-build-to-release.result == 'success' && '✅' || needs.add-build-to-release.result == 'failure' && '❌' || needs.add-build-to-release.result == 'skipped' && '⏭️' || '⏳' }}\"\n }\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Workflow:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run #${{ github.run_number }}>\\n\\n${{ needs.add-build-to-release.result == 'success' && 'New version process completed successfully! The app has been submitted for App Store review. 🎉' || 'New version process encountered issues. Please check the workflow logs for details. 🚨' }}\"\n }\n }\n ]\n }\n\n # ==========================================\n # WORKFLOW SUMMARY\n # ==========================================\n - name: Post workflow summary\n if: always()\n run: |\n echo \"## 🚀 New Version Process Summary\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"### Process Status\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Overall Status:** ${{ needs.add-build-to-release.result == 'success' && '✅ Completed Successfully' || '❌ Failed or Incomplete' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Platform:** ${{ inputs.platform || 'iOS' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Version:** ${{ needs.create-appstore-version.outputs.version || 'Unknown' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Build Number:** ${{ needs.deliver-to-testflight.outputs.build_number || 'Unknown' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **TestFlight Group:** ${{ inputs.test_group || 'Reviewers' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"### Step Results\" >> $GITHUB_STEP_SUMMARY\n echo \"| Step | Status | Result |\" >> $GITHUB_STEP_SUMMARY\n echo \"|------|--------|--------|\" >> $GITHUB_STEP_SUMMARY\n echo \"| Bump Version | ${{ needs.bump-version.result == 'success' && '✅ Success' || needs.bump-version.result == 'failure' && '❌ Failed' || '⏳ Pending' }} | Version: ${{ needs.bump-version.outputs.new_version || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Create App Store Version | ${{ needs.create-appstore-version.result == 'success' && '✅ Success' || needs.create-appstore-version.result == 'failure' && '❌ Failed' || '⏳ Pending' }} | Version: ${{ needs.create-appstore-version.outputs.version || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Write Release Notes | ${{ inputs.keep_release_notes && '⏭️ Skipped (kept)' || needs.write-release-notes.result == 'success' && '✅ Success' || needs.write-release-notes.result == 'failure' && '❌ Failed' || needs.write-release-notes.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | ${{ inputs.keep_release_notes && 'Release notes kept from previous version' || needs.write-release-notes.outputs.status || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Clear Release Notes | ${{ inputs.keep_release_notes && '⏭️ Skipped (kept)' || needs.clear-release-notes.result == 'success' && '✅ Success' || needs.clear-release-notes.result == 'failure' && '❌ Failed' || needs.clear-release-notes.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | ${{ inputs.keep_release_notes && 'Kept for next version' || 'Cleared for next version' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Deliver to TestFlight | ${{ needs.deliver-to-testflight.result == 'success' && '✅ Success' || needs.deliver-to-testflight.result == 'failure' && '❌ Failed' || needs.deliver-to-testflight.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | Build: ${{ needs.deliver-to-testflight.outputs.build_number || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Add Build to Release | ${{ needs.add-build-to-release.result == 'success' && '✅ Success' || needs.add-build-to-release.result == 'failure' && '❌ Failed' || needs.add-build-to-release.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | Submitted for review |\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"### Next Steps\" >> $GITHUB_STEP_SUMMARY\n if [ \"${{ needs.add-build-to-release.result }}\" = \"success\" ]; then\n echo \"🎉 **Process completed successfully!** Your app has been:\" >> $GITHUB_STEP_SUMMARY\n echo \"- ✅ Version bumped to ${{ needs.bump-version.outputs.new_version || 'N/A' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- ✅ Version entry created in App Store Connect\" >> $GITHUB_STEP_SUMMARY\n if [ \"${{ inputs.keep_release_notes }}\" = \"true\" ]; then\n echo \"- ℹ️ Release notes kept from previous version (not regenerated)\" >> $GITHUB_STEP_SUMMARY\n else\n echo \"- ✅ Release notes written\" >> $GITHUB_STEP_SUMMARY\n fi\n echo \"- ✅ Built and delivered to TestFlight\" >> $GITHUB_STEP_SUMMARY\n echo \"- ✅ Submitted for App Store review\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"The app is now in the App Store review queue. You can monitor the review status in App Store Connect.\" >> $GITHUB_STEP_SUMMARY\n else\n echo \"❌ **Process incomplete.** Please check the individual step logs for error details and retry as needed.\" >> $GITHUB_STEP_SUMMARY\n fi\n"}, "44983588ca5c8c08e9e39351c2102cbe71037c0f": {"t": 1785758174.840638, "n": 19085, "h": "aee49c2d67170d6b", "c": "# ==========================================\n# TRIGGER NEW VERSION PROCESS WORKFLOW\n# ==========================================\n# This workflow orchestrates a complete new version release process including:\n# - Creating App Store version entry with current MARKETING_VERSION\n# - Writing AI-powered release notes (optional - can be skipped with keep_release_notes)\n# - Clearing release notes for next version (optional - skipped when keep_release_notes is true)\n# - Building and delivering to TestFlight\n# - Adding build to release and submitting for App Store review\n\nname: Trigger New Version Process\n\n# Set permissions for the workflow\npermissions:\n contents: write\n pull-requests: write\n actions: read\non:\n # ==========================================\n # MANUAL TRIGGER\n # ==========================================\n workflow_dispatch:\n inputs:\n platform:\n description: 'Platform'\n required: true\n default: 'iOS'\n type: choice\n options:\n - 'iOS'\n\n xcode_version:\n description: 'Xcode Version'\n required: false\n default: 'Xcode-26.4.1.app'\n type: choice\n options:\n - 'Xcode-26.4.1.app'\n\n test_group:\n description: 'TestFlight beta group name'\n required: false\n default: 'Reviewers'\n type: choice\n options:\n - 'Reviewers'\n\n skip_slack_posting:\n description: 'Skip Slack notifications'\n required: false\n type: boolean\n default: false\n\n keep_release_notes:\n description: 'Keep current release notes (skip writing and clearing)'\n required: false\n type: boolean\n default: false\n\n # ==========================================\n # SCHEDULED TRIGGER (DISABLED)\n # ==========================================\n schedule:\n - cron: '0 3 * * 2' # 03:00 UTC = 04:00 CET (during standard time), every Tuesday\n\n # ==========================================\n # REUSABLE WORKFLOW TRIGGER\n # ==========================================\n workflow_call:\n inputs:\n platform:\n description: 'Platform'\n required: false\n default: 'iOS'\n type: string\n\n xcode_version:\n description: 'Xcode Version'\n required: false\n default: 'Xcode-26.4.1.app'\n type: string\n\n test_group:\n description: 'TestFlight beta group name'\n required: false\n default: 'Reviewers'\n type: string\n\n skip_slack_posting:\n description: 'Skip Slack notifications'\n required: false\n default: true\n type: boolean\n\n keep_release_notes:\n description: 'Keep current release notes (skip writing and clearing)'\n required: false\n default: false\n type: boolean\n secrets:\n APP_STORE_CONNECT_KEY_ID:\n required: true\n APP_STORE_CONNECT_ISSUER_ID:\n required: true\n APP_STORE_CONNECT_KEY_CONTENT:\n required: true\n MATCH_PASSWORD:\n description: 'Match password for code signing'\n required: true\n DEEPSEEK_API_KEY:\n description: 'DeepSeek API key for AI-powered release notes generation'\n required: true\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL:\n description: 'Slack webhook for notifications (optional)'\n required: false\n\n# Environment variables\nenv:\n LANG: en_US.UTF-8\n LANGUAGE: en_US.UTF-8\n LC_ALL: en_US.UTF-8\n APP_NAME: ${{ vars.APP_NAME }}\n APP_SLUG: ${{ vars.APP_SLUG }}\n BUNDLE_ID: ${{ vars.BUNDLE_ID }}\n XCCONFIG_PATH: ${{ vars.XCCONFIG_PATH }}\n MARKETING_URL: ${{ vars.MARKETING_URL }}\n APPLE_ID: ${{ secrets.APPLE_ID }}\n APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}\n APPLE_ITC_TEAM_ID: ${{ secrets.APPLE_ITC_TEAM_ID }}\n MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}\n\njobs:\n # ==========================================\n # JOB 1: BUMP VERSION\n # ==========================================\n bump-version:\n name: Bump Version for New Release\n uses: ./.github/workflows/bump-version.yml\n with:\n version_type: current # 'current' keeps current marketing version, only increments build number\n skip_slack_posting: true\n secrets: inherit\n\n # ==========================================\n # JOB 2: CREATE APP STORE VERSION ENTRY\n # ==========================================\n create-appstore-version:\n name: Create App Store Version Entry\n needs: [bump-version]\n if: needs.bump-version.result == 'success'\n uses: ./.github/workflows/create-appstore-version.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n skip_slack_posting: true\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n\n # ==========================================\n # JOB 3: WRITE RELEASE NOTES\n # ==========================================\n write-release-notes:\n name: Write Release Notes\n needs: [create-appstore-version]\n if: needs.create-appstore-version.result == 'success' && !inputs.keep_release_notes\n uses: ./.github/workflows/write-release-notes.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n skip_slack_posting: true\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}\n GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}\n\n # ==========================================\n # JOB 3b: UPLOAD APP STORE METADATA\n # ==========================================\n upload-metadata:\n name: Upload App Store Metadata\n needs: [create-appstore-version]\n if: needs.create-appstore-version.result == 'success'\n uses: ./.github/workflows/upload-metadata.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n BETA_CONTACT_EMAIL: ${{ secrets.BETA_CONTACT_EMAIL }}\n BETA_CONTACT_PHONE: ${{ secrets.BETA_CONTACT_PHONE }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n\n # ==========================================\n # JOB 4: DELIVER TO TESTFLIGHT\n # ==========================================\n deliver-to-testflight:\n name: Deliver to TestFlight\n needs: [write-release-notes, create-appstore-version, upload-metadata]\n if: |\n always() &&\n needs.create-appstore-version.result == 'success' &&\n (needs.write-release-notes.result == 'success' || needs.write-release-notes.result == 'skipped') &&\n (needs.upload-metadata.result == 'success' || needs.upload-metadata.result == 'skipped')\n uses: ./.github/workflows/deliver-to-testflight.yml\n with:\n scheme: '${{ vars.APP_NAME }}'\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n test_group: ${{ inputs.test_group || 'Reviewers' }}\n release_notes: ''\n secrets:\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n SLACK_USER_ID: ${{ secrets.SLACK_USER_ID }}\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}\n BETA_CONTACT_EMAIL: ${{ secrets.BETA_CONTACT_EMAIL }}\n BETA_CONTACT_PHONE: ${{ secrets.BETA_CONTACT_PHONE }}\n BETA_DEMO_ACCOUNT_NAME: ${{ secrets.BETA_DEMO_ACCOUNT_NAME }}\n BETA_DEMO_ACCOUNT_PASSWORD: ${{ secrets.BETA_DEMO_ACCOUNT_PASSWORD }}\n GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}\n GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}\n\n # ==========================================\n # JOB 5: ADD BUILD TO RELEASE\n # ==========================================\n add-build-to-release:\n name: Add Build to Release\n needs: [deliver-to-testflight, create-appstore-version]\n if: needs.deliver-to-testflight.result == 'success'\n uses: ./.github/workflows/add-build-to-release.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n version: ${{ needs.create-appstore-version.outputs.version }}\n build_number: ${{ needs.deliver-to-testflight.outputs.build_number }}\n submit_for_review: true\n xcode_version: ${{ inputs.xcode_version || 'Xcode-26.4.1.app' }}\n skip_slack_posting: true\n secrets:\n APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}\n APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}\n APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n\n # ==========================================\n # JOB 6: CLEAR RELEASE NOTES\n # ==========================================\n clear-release-notes:\n name: Clear Release Notes\n needs: [add-build-to-release, write-release-notes]\n if: |\n always() &&\n (needs.add-build-to-release.result == 'success' || needs.write-release-notes.result == 'success') &&\n !inputs.keep_release_notes\n uses: ./.github/workflows/clear-release-notes.yml\n with:\n platform: ${{ inputs.platform || 'iOS' }}\n skip_slack_posting: true\n secrets:\n SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}\n GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}\n\n # ==========================================\n # JOB 7: SEND FINAL STATUS NOTIFICATION\n # ==========================================\n notify-final-status:\n name: Send Final Status Notification\n runs-on: macos-latest\n needs: [bump-version, create-appstore-version, write-release-notes, deliver-to-testflight, add-build-to-release, clear-release-notes]\n if: always() && !inputs.skip_slack_posting\n timeout-minutes: 5\n\n steps:\n - name: Send Slack notification\n uses: slackapi/slack-github-action@v2.1.0\n with:\n webhook: ${{ secrets.SLACK_WEBHOOK_GITHUB_EVENTS_CHANNEL }}\n webhook-type: incoming-webhook\n payload: |\n {\n \"text\": \"${{ vars.APP_NAME }} iOS - New Version Process: ${{ needs.add-build-to-release.result == 'success' && '✅ Completed Successfully' || '❌ Failed or Incomplete' }}\",\n \"blocks\": [\n {\n \"type\": \"header\",\n \"text\": {\n \"type\": \"plain_text\",\n \"text\": \"🚀 ${{ vars.APP_NAME }} iOS - New Version Process Summary\",\n \"emoji\": true\n }\n },\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Overall Status:*\\n${{ needs.add-build-to-release.result == 'success' && '✅ Completed Successfully' || '❌ Failed or Incomplete' }}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Platform:*\\n${{ inputs.platform || 'iOS' }}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Version:*\\n`${{ needs.create-appstore-version.outputs.version || 'Unknown' }}`\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Build:*\\n`${{ needs.deliver-to-testflight.outputs.build_number || 'Unknown' }}`\"\n }\n ]\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Process Steps:*\\n• Bump Version: ${{ needs.bump-version.result == 'success' && '✅' || needs.bump-version.result == 'failure' && '❌' || '⏳' }}\\n• App Store Version: ${{ needs.create-appstore-version.result == 'success' && '✅' || needs.create-appstore-version.result == 'failure' && '❌' || '⏳' }}\\n• Release Notes: ${{ inputs.keep_release_notes && '⏭️ (kept)' || needs.write-release-notes.result == 'success' && '✅' || needs.write-release-notes.result == 'failure' && '❌' || needs.write-release-notes.result == 'skipped' && '⏭️' || '⏳' }}\\n• Clear Notes: ${{ inputs.keep_release_notes && '⏭️ (kept)' || needs.clear-release-notes.result == 'success' && '✅' || needs.clear-release-notes.result == 'failure' && '❌' || needs.clear-release-notes.result == 'skipped' && '⏭️' || '⏳' }}\\n• TestFlight: ${{ needs.deliver-to-testflight.result == 'success' && '✅' || needs.deliver-to-testflight.result == 'failure' && '❌' || needs.deliver-to-testflight.result == 'skipped' && '⏭️' || '⏳' }}\\n• Submit for Review: ${{ needs.add-build-to-release.result == 'success' && '✅' || needs.add-build-to-release.result == 'failure' && '❌' || needs.add-build-to-release.result == 'skipped' && '⏭️' || '⏳' }}\"\n }\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Workflow:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run #${{ github.run_number }}>\\n\\n${{ needs.add-build-to-release.result == 'success' && 'New version process completed successfully! The app has been submitted for App Store review. 🎉' || 'New version process encountered issues. Please check the workflow logs for details. 🚨' }}\"\n }\n }\n ]\n }\n\n # ==========================================\n # WORKFLOW SUMMARY\n # ==========================================\n - name: Post workflow summary\n if: always()\n run: |\n echo \"## 🚀 New Version Process Summary\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"### Process Status\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Overall Status:** ${{ needs.add-build-to-release.result == 'success' && '✅ Completed Successfully' || '❌ Failed or Incomplete' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Platform:** ${{ inputs.platform || 'iOS' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Version:** ${{ needs.create-appstore-version.outputs.version || 'Unknown' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **Build Number:** ${{ needs.deliver-to-testflight.outputs.build_number || 'Unknown' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- **TestFlight Group:** ${{ inputs.test_group || 'Reviewers' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"### Step Results\" >> $GITHUB_STEP_SUMMARY\n echo \"| Step | Status | Result |\" >> $GITHUB_STEP_SUMMARY\n echo \"|------|--------|--------|\" >> $GITHUB_STEP_SUMMARY\n echo \"| Bump Version | ${{ needs.bump-version.result == 'success' && '✅ Success' || needs.bump-version.result == 'failure' && '❌ Failed' || '⏳ Pending' }} | Version: ${{ needs.bump-version.outputs.new_version || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Create App Store Version | ${{ needs.create-appstore-version.result == 'success' && '✅ Success' || needs.create-appstore-version.result == 'failure' && '❌ Failed' || '⏳ Pending' }} | Version: ${{ needs.create-appstore-version.outputs.version || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Write Release Notes | ${{ inputs.keep_release_notes && '⏭️ Skipped (kept)' || needs.write-release-notes.result == 'success' && '✅ Success' || needs.write-release-notes.result == 'failure' && '❌ Failed' || needs.write-release-notes.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | ${{ inputs.keep_release_notes && 'Release notes kept from previous version' || needs.write-release-notes.outputs.status || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Clear Release Notes | ${{ inputs.keep_release_notes && '⏭️ Skipped (kept)' || needs.clear-release-notes.result == 'success' && '✅ Success' || needs.clear-release-notes.result == 'failure' && '❌ Failed' || needs.clear-release-notes.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | ${{ inputs.keep_release_notes && 'Kept for next version' || 'Cleared for next version' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Deliver to TestFlight | ${{ needs.deliver-to-testflight.result == 'success' && '✅ Success' || needs.deliver-to-testflight.result == 'failure' && '❌ Failed' || needs.deliver-to-testflight.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | Build: ${{ needs.deliver-to-testflight.outputs.build_number || 'N/A' }} |\" >> $GITHUB_STEP_SUMMARY\n echo \"| Add Build to Release | ${{ needs.add-build-to-release.result == 'success' && '✅ Success' || needs.add-build-to-release.result == 'failure' && '❌ Failed' || needs.add-build-to-release.result == 'skipped' && '⏭️ Skipped' || '⏳ Pending' }} | Submitted for review |\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"### Next Steps\" >> $GITHUB_STEP_SUMMARY\n if [ \"${{ needs.add-build-to-release.result }}\" = \"success\" ]; then\n echo \"🎉 **Process completed successfully!** Your app has been:\" >> $GITHUB_STEP_SUMMARY\n echo \"- ✅ Version bumped to ${{ needs.bump-version.outputs.new_version || 'N/A' }}\" >> $GITHUB_STEP_SUMMARY\n echo \"- ✅ Version entry created in App Store Connect\" >> $GITHUB_STEP_SUMMARY\n if [ \"${{ inputs.keep_release_notes }}\" = \"true\" ]; then\n echo \"- ℹ️ Release notes kept from previous version (not regenerated)\" >> $GITHUB_STEP_SUMMARY\n else\n echo \"- ✅ Release notes written\" >> $GITHUB_STEP_SUMMARY\n fi\n echo \"- ✅ Built and delivered to TestFlight\" >> $GITHUB_STEP_SUMMARY\n echo \"- ✅ Submitted for App Store review\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"The app is now in the App Store review queue. You can monitor the review status in App Store Connect.\" >> $GITHUB_STEP_SUMMARY\n else\n echo \"❌ **Process incomplete.** Please check the individual step logs for error details and retry as needed.\" >> $GITHUB_STEP_SUMMARY\n fi\n"}}}}