forked from stackblitz-labs/bolt.diy
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/main'
- Loading branch information
Showing
85 changed files
with
4,018 additions
and
925 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--- | ||
name: Epic | ||
about: Epics define long-term vision and capabilities of the software. They will never be finished but serve as umbrella for features. | ||
title: '' | ||
labels: | ||
- epic | ||
assignees: '' | ||
--- | ||
|
||
# Strategic Impact | ||
|
||
<!-- Why does this area matter? How is it integrated into the product or the development process? What would happen if we ignore it? --> | ||
|
||
# Target Audience | ||
|
||
<!-- Who benefits most from improvements in this area? | ||
Usual values: Software Developers using the IDE | Contributors --> | ||
|
||
# Capabilities | ||
|
||
<!-- which existing capabilities or future features can be imagined that belong to this epic? This list serves as illustration to sketch the boundaries of this epic. | ||
Once features are actually being planned / described in detail, they can be linked here. --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
name: Feature | ||
about: A pretty vague description of how a capability of our software can be added or improved. | ||
title: '' | ||
labels: | ||
- feature | ||
assignees: '' | ||
--- | ||
|
||
# Motivation | ||
|
||
<!-- What capability should be either established or improved? How is life of the target audience better after it's been done? --> | ||
|
||
# Scope | ||
|
||
<!-- This is kind-of the definition-of-done for a feature. | ||
Try to keep the scope as small as possible and prefer creating multiple, small features which each solve a single problem / make something better | ||
--> | ||
|
||
# Options | ||
|
||
<!-- If you already have an idea how this can be implemented, please describe it here. | ||
This allows potential other contributors to join forces and provide meaningful feedback prio to even starting work on it. | ||
--> | ||
|
||
# Related | ||
|
||
<!-- Link to the epic or other issues or PRs which are related to this feature. --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Ensure we're running in bash | ||
if [ -z "$BASH_VERSION" ]; then | ||
echo "This script requires bash. Please run with: bash $0" >&2 | ||
exit 1 | ||
fi | ||
|
||
# Ensure we're using bash 4.0 or later for associative arrays | ||
if ((BASH_VERSINFO[0] < 4)); then | ||
echo "This script requires bash version 4 or later" >&2 | ||
echo "Current bash version: $BASH_VERSION" >&2 | ||
exit 1 | ||
fi | ||
|
||
# Set default values for required environment variables if not in GitHub Actions | ||
if [ -z "$GITHUB_ACTIONS" ]; then | ||
: "${GITHUB_SERVER_URL:=https://github.com}" | ||
: "${GITHUB_REPOSITORY:=stackblitz-labs/bolt.diy}" | ||
: "${GITHUB_OUTPUT:=/tmp/github_output}" | ||
touch "$GITHUB_OUTPUT" | ||
|
||
# Running locally | ||
echo "Running locally - checking for upstream remote..." | ||
MAIN_REMOTE="origin" | ||
if git remote -v | grep -q "upstream"; then | ||
MAIN_REMOTE="upstream" | ||
fi | ||
MAIN_BRANCH="main" # or "master" depending on your repository | ||
|
||
# Ensure we have latest tags | ||
git fetch ${MAIN_REMOTE} --tags | ||
|
||
# Use the remote reference for git log | ||
GITLOG_REF="${MAIN_REMOTE}/${MAIN_BRANCH}" | ||
else | ||
# Running in GitHub Actions | ||
GITLOG_REF="HEAD" | ||
fi | ||
|
||
# Get the latest tag | ||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | ||
|
||
# Start changelog file | ||
echo "# 🚀 Release v${NEW_VERSION}" > changelog.md | ||
echo "" >> changelog.md | ||
echo "## What's Changed 🌟" >> changelog.md | ||
echo "" >> changelog.md | ||
|
||
if [ -z "$LATEST_TAG" ]; then | ||
echo "### 🎉 First Release" >> changelog.md | ||
echo "" >> changelog.md | ||
echo "Exciting times! This marks our first release. Thanks to everyone who contributed! 🙌" >> changelog.md | ||
echo "" >> changelog.md | ||
COMPARE_BASE="$(git rev-list --max-parents=0 HEAD)" | ||
else | ||
echo "### 🔄 Changes since $LATEST_TAG" >> changelog.md | ||
echo "" >> changelog.md | ||
COMPARE_BASE="$LATEST_TAG" | ||
fi | ||
|
||
# Function to extract conventional commit type and associated emoji | ||
get_commit_type() { | ||
local msg="$1" | ||
if [[ $msg =~ ^feat(\(.+\))?:|^feature(\(.+\))?: ]]; then echo "✨ Features" | ||
elif [[ $msg =~ ^fix(\(.+\))?: ]]; then echo "🐛 Bug Fixes" | ||
elif [[ $msg =~ ^docs(\(.+\))?: ]]; then echo "📚 Documentation" | ||
elif [[ $msg =~ ^style(\(.+\))?: ]]; then echo "💎 Styles" | ||
elif [[ $msg =~ ^refactor(\(.+\))?: ]]; then echo "♻️ Code Refactoring" | ||
elif [[ $msg =~ ^perf(\(.+\))?: ]]; then echo "⚡ Performance Improvements" | ||
elif [[ $msg =~ ^test(\(.+\))?: ]]; then echo "🧪 Tests" | ||
elif [[ $msg =~ ^build(\(.+\))?: ]]; then echo "🛠️ Build System" | ||
elif [[ $msg =~ ^ci(\(.+\))?: ]]; then echo "⚙️ CI" | ||
elif [[ $msg =~ ^chore(\(.+\))?: ]]; then echo "" # Skip chore commits | ||
else echo "🔍 Other Changes" # Default category with emoji | ||
fi | ||
} | ||
|
||
# Initialize associative arrays | ||
declare -A CATEGORIES | ||
declare -A COMMITS_BY_CATEGORY | ||
declare -A ALL_AUTHORS | ||
declare -A NEW_CONTRIBUTORS | ||
|
||
# Get all historical authors before the compare base | ||
while IFS= read -r author; do | ||
ALL_AUTHORS["$author"]=1 | ||
done < <(git log "${COMPARE_BASE}" --pretty=format:"%ae" | sort -u) | ||
|
||
# Process all commits since last tag | ||
while IFS= read -r commit_line; do | ||
if [[ ! $commit_line =~ ^[a-f0-9]+\| ]]; then | ||
echo "WARNING: Skipping invalid commit line format: $commit_line" >&2 | ||
continue | ||
fi | ||
|
||
HASH=$(echo "$commit_line" | cut -d'|' -f1) | ||
COMMIT_MSG=$(echo "$commit_line" | cut -d'|' -f2) | ||
BODY=$(echo "$commit_line" | cut -d'|' -f3) | ||
# Skip if hash doesn't match the expected format | ||
if [[ ! $HASH =~ ^[a-f0-9]{40}$ ]]; then | ||
continue | ||
fi | ||
|
||
HASH=$(echo "$commit_line" | cut -d'|' -f1) | ||
COMMIT_MSG=$(echo "$commit_line" | cut -d'|' -f2) | ||
BODY=$(echo "$commit_line" | cut -d'|' -f3) | ||
|
||
|
||
# Validate hash format | ||
if [[ ! $HASH =~ ^[a-f0-9]{40}$ ]]; then | ||
echo "WARNING: Invalid commit hash format: $HASH" >&2 | ||
continue | ||
fi | ||
|
||
# Check if it's a merge commit | ||
if [[ $COMMIT_MSG =~ Merge\ pull\ request\ #([0-9]+) ]]; then | ||
# echo "Processing as merge commit" >&2 | ||
PR_NUM="${BASH_REMATCH[1]}" | ||
|
||
# Extract the PR title from the merge commit body | ||
PR_TITLE=$(echo "$BODY" | grep -v "^Merge pull request" | head -n 1) | ||
|
||
# Only process if it follows conventional commit format | ||
CATEGORY=$(get_commit_type "$PR_TITLE") | ||
|
||
if [ -n "$CATEGORY" ]; then # Only process if it's a conventional commit | ||
# Get PR author's GitHub username | ||
GITHUB_USERNAME=$(gh pr view "$PR_NUM" --json author --jq '.author.login') | ||
|
||
if [ -n "$GITHUB_USERNAME" ]; then | ||
# Check if this is a first-time contributor | ||
AUTHOR_EMAIL=$(git show -s --format='%ae' "$HASH") | ||
if [ -z "${ALL_AUTHORS[$AUTHOR_EMAIL]}" ]; then | ||
NEW_CONTRIBUTORS["$GITHUB_USERNAME"]=1 | ||
ALL_AUTHORS["$AUTHOR_EMAIL"]=1 | ||
fi | ||
|
||
CATEGORIES["$CATEGORY"]=1 | ||
COMMITS_BY_CATEGORY["$CATEGORY"]+="* ${PR_TITLE#*: } ([#$PR_NUM](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/$PR_NUM)) by @$GITHUB_USERNAME"$'\n' | ||
else | ||
COMMITS_BY_CATEGORY["$CATEGORY"]+="* ${PR_TITLE#*: } ([#$PR_NUM](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/$PR_NUM))"$'\n' | ||
fi | ||
fi | ||
# Check if it's a squash merge by looking for (#NUMBER) pattern | ||
elif [[ $COMMIT_MSG =~ \(#([0-9]+)\) ]]; then | ||
# echo "Processing as squash commit" >&2 | ||
PR_NUM="${BASH_REMATCH[1]}" | ||
|
||
# Only process if it follows conventional commit format | ||
CATEGORY=$(get_commit_type "$COMMIT_MSG") | ||
|
||
if [ -n "$CATEGORY" ]; then # Only process if it's a conventional commit | ||
# Get PR author's GitHub username | ||
GITHUB_USERNAME=$(gh pr view "$PR_NUM" --json author --jq '.author.login') | ||
|
||
if [ -n "$GITHUB_USERNAME" ]; then | ||
# Check if this is a first-time contributor | ||
AUTHOR_EMAIL=$(git show -s --format='%ae' "$HASH") | ||
if [ -z "${ALL_AUTHORS[$AUTHOR_EMAIL]}" ]; then | ||
NEW_CONTRIBUTORS["$GITHUB_USERNAME"]=1 | ||
ALL_AUTHORS["$AUTHOR_EMAIL"]=1 | ||
fi | ||
|
||
CATEGORIES["$CATEGORY"]=1 | ||
COMMIT_TITLE=${COMMIT_MSG%% (#*} # Remove the PR number suffix | ||
COMMIT_TITLE=${COMMIT_TITLE#*: } # Remove the type prefix | ||
COMMITS_BY_CATEGORY["$CATEGORY"]+="* $COMMIT_TITLE ([#$PR_NUM](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/$PR_NUM)) by @$GITHUB_USERNAME"$'\n' | ||
else | ||
COMMIT_TITLE=${COMMIT_MSG%% (#*} # Remove the PR number suffix | ||
COMMIT_TITLE=${COMMIT_TITLE#*: } # Remove the type prefix | ||
COMMITS_BY_CATEGORY["$CATEGORY"]+="* $COMMIT_TITLE ([#$PR_NUM](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/$PR_NUM))"$'\n' | ||
fi | ||
fi | ||
|
||
else | ||
# echo "Processing as regular commit" >&2 | ||
# Process conventional commits without PR numbers | ||
CATEGORY=$(get_commit_type "$COMMIT_MSG") | ||
|
||
if [ -n "$CATEGORY" ]; then # Only process if it's a conventional commit | ||
# Get commit author info | ||
AUTHOR_EMAIL=$(git show -s --format='%ae' "$HASH") | ||
|
||
# Try to get GitHub username using gh api | ||
if [ -n "$GITHUB_ACTIONS" ] || command -v gh >/dev/null 2>&1; then | ||
GITHUB_USERNAME=$(gh api "/repos/${GITHUB_REPOSITORY}/commits/${HASH}" --jq '.author.login' 2>/dev/null) | ||
fi | ||
|
||
if [ -n "$GITHUB_USERNAME" ]; then | ||
# If we got GitHub username, use it | ||
if [ -z "${ALL_AUTHORS[$AUTHOR_EMAIL]}" ]; then | ||
NEW_CONTRIBUTORS["$GITHUB_USERNAME"]=1 | ||
ALL_AUTHORS["$AUTHOR_EMAIL"]=1 | ||
fi | ||
|
||
CATEGORIES["$CATEGORY"]=1 | ||
COMMIT_TITLE=${COMMIT_MSG#*: } # Remove the type prefix | ||
COMMITS_BY_CATEGORY["$CATEGORY"]+="* $COMMIT_TITLE (${HASH:0:7}) by @$GITHUB_USERNAME"$'\n' | ||
else | ||
# Fallback to git author name if no GitHub username found | ||
AUTHOR_NAME=$(git show -s --format='%an' "$HASH") | ||
|
||
if [ -z "${ALL_AUTHORS[$AUTHOR_EMAIL]}" ]; then | ||
NEW_CONTRIBUTORS["$AUTHOR_NAME"]=1 | ||
ALL_AUTHORS["$AUTHOR_EMAIL"]=1 | ||
fi | ||
|
||
CATEGORIES["$CATEGORY"]=1 | ||
COMMIT_TITLE=${COMMIT_MSG#*: } # Remove the type prefix | ||
COMMITS_BY_CATEGORY["$CATEGORY"]+="* $COMMIT_TITLE (${HASH:0:7}) by $AUTHOR_NAME"$'\n' | ||
fi | ||
fi | ||
fi | ||
|
||
done < <(git log "${COMPARE_BASE}..${GITLOG_REF}" --pretty=format:"%H|%s|%b" --reverse --first-parent) | ||
|
||
# Write categorized commits to changelog with their emojis | ||
for category in "✨ Features" "🐛 Bug Fixes" "📚 Documentation" "💎 Styles" "♻️ Code Refactoring" "⚡ Performance Improvements" "🧪 Tests" "🛠️ Build System" "⚙️ CI" "🔍 Other Changes"; do | ||
if [ -n "${COMMITS_BY_CATEGORY[$category]}" ]; then | ||
echo "### $category" >> changelog.md | ||
echo "" >> changelog.md | ||
echo "${COMMITS_BY_CATEGORY[$category]}" >> changelog.md | ||
echo "" >> changelog.md | ||
fi | ||
done | ||
|
||
# Add first-time contributors section if there are any | ||
if [ ${#NEW_CONTRIBUTORS[@]} -gt 0 ]; then | ||
echo "## ✨ First-time Contributors" >> changelog.md | ||
echo "" >> changelog.md | ||
echo "A huge thank you to our amazing new contributors! Your first contribution marks the start of an exciting journey! 🌟" >> changelog.md | ||
echo "" >> changelog.md | ||
# Use readarray to sort the keys | ||
readarray -t sorted_contributors < <(printf '%s\n' "${!NEW_CONTRIBUTORS[@]}" | sort) | ||
for github_username in "${sorted_contributors[@]}"; do | ||
echo "* 🌟 [@$github_username](https://github.com/$github_username)" >> changelog.md | ||
done | ||
echo "" >> changelog.md | ||
fi | ||
|
||
# Add compare link if not first release | ||
if [ -n "$LATEST_TAG" ]; then | ||
echo "## 📈 Stats" >> changelog.md | ||
echo "" >> changelog.md | ||
echo "**Full Changelog**: [\`$LATEST_TAG..v${NEW_VERSION}\`](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/compare/$LATEST_TAG...v${NEW_VERSION})" >> changelog.md | ||
fi | ||
|
||
# Output the changelog content | ||
CHANGELOG_CONTENT=$(cat changelog.md) | ||
{ | ||
echo "content<<EOF" | ||
echo "$CHANGELOG_CONTENT" | ||
echo "EOF" | ||
} >> "$GITHUB_OUTPUT" | ||
|
||
# Also print to stdout for local testing | ||
echo "Generated changelog:" | ||
echo "===================" | ||
cat changelog.md | ||
echo "===================" |
Oops, something went wrong.