Skip to content

fix: preserve content when converting note types #103

fix: preserve content when converting note types

fix: preserve content when converting note types #103

Workflow file for this run

name: Create Release
on:
push:
branches: ['main']
tags:
- 'v*.*.*'
workflow_dispatch:
permissions:
contents: write
jobs:
# ──────────────────────────────────────────────────────────────
# Job 1: "latest" release — updated on every push to main
# Always overwrites the same "latest" tag and release
# ──────────────────────────────────────────────────────────────
latest:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: github-pages
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
- name: Create ZIP archive
run: |
cd dist
zip -r ../quicknotes-latest.zip .
- name: Generate latest release notes
id: notes
run: |
RELEASE_DATE=$(date -u +"%d-%m-%Y at %I:%M %p UTC")
COMMIT_SHA=$(git rev-parse --short HEAD)
COMMIT_MSG=$(git log -1 --format="%s")
# Get the last versioned tag for commit range
LATEST_TAG=$(git tag -l 'v*.*.*' --sort=-v:refname | head -n 1)
if [ -n "$LATEST_TAG" ]; then
RANGE="${LATEST_TAG}..HEAD"
COMMIT_COUNT=$(git rev-list --count "$RANGE" 2>/dev/null || echo "0")
SINCE_TEXT="**${COMMIT_COUNT} commit(s)** since last versioned release \`${LATEST_TAG}\`"
else
COMMIT_COUNT=$(git rev-list --count HEAD 2>/dev/null || echo "0")
SINCE_TEXT="**${COMMIT_COUNT} commit(s)** total"
fi
# Collect recent changes (last 15 commits or since last tag)
ITEMS_FILE=$(mktemp)
if [ -n "$RANGE" ]; then
HASHES=$(git log "$RANGE" --no-merges --format="%H" 2>/dev/null)
else
HASHES=$(git log --no-merges -15 --format="%H" 2>/dev/null)
fi
while read -r HASH; do
[ -z "$HASH" ] && continue
SUBJECT=$(git log -1 "$HASH" --format="%s")
BODY=$(git log -1 "$HASH" --format="%b")
case "$SUBJECT" in
feat:*|feat\(*|add:*|add\(*|new:*|new\(*)
CAT="FEAT" ;;
fix:*|fix\(*|bug:*|bug\(*|patch:*|patch\(*|hotfix:*|hotfix\(*)
CAT="FIX" ;;
ci:*|ci\(*|build:*|build\(*|chore:*|chore\(*|refactor:*|refactor\(*|style:*|style\(*|docs:*|docs\(*)
CAT="MAINT" ;;
*)
CAT="OTHER" ;;
esac
BULLETS=$(echo "$BODY" | grep -E '^\s*[-*•]\s+' | sed 's/^[[:space:]]*[-*•][[:space:]]*//' || true)
if [ -n "$BULLETS" ]; then
while IFS= read -r item; do
[ -n "$item" ] && echo "${CAT}|${item}" >> "$ITEMS_FILE"
done <<< "$BULLETS"
else
CLEAN=$(echo "$SUBJECT" | sed -E 's/^(feat|add|new|fix|bug|patch|hotfix|ci|build|chore|refactor|style|docs)(\([^)]*\))?[: ]*//')
[ -n "$CLEAN" ] && echo "${CAT}|${CLEAN}" >> "$ITEMS_FILE"
fi
done <<< "$HASHES"
FEATURES=""
FIXES=""
MAINTENANCE=""
OTHER=""
if [ -f "$ITEMS_FILE" ]; then
while IFS='|' read -r category text; do
[ -z "$text" ] && continue
text="$(echo "${text:0:1}" | tr '[:lower:]' '[:upper:]')${text:1}"
case "$category" in
FEAT) FEATURES="${FEATURES}\n• \u2800${text}" ;;
FIX) FIXES="${FIXES}\n• \u2800${text}" ;;
MAINT) MAINTENANCE="${MAINTENANCE}\n• \u2800${text}" ;;
OTHER) OTHER="${OTHER}\n• \u2800${text}" ;;
esac
done < "$ITEMS_FILE"
fi
rm -f "$ITEMS_FILE"
{
echo "body<<EOFMARKER"
echo "> **⚠️ This is a rolling release that always contains the latest build from \`main\`.**"
echo "> It is automatically updated on every push. For stable versions, use a [versioned release](https://github.com/BerndHagen/QuickNotes-Simple-Note-Manager/releases)."
echo ""
echo "**Last updated:** ${RELEASE_DATE}"
echo "**Commit:** \`${COMMIT_SHA}\` — ${COMMIT_MSG}"
echo "**Changes:** ${SINCE_TEXT}"
echo ""
if [ -n "$FEATURES" ]; then
echo "**New Features & Improvements**"
echo -e "$FEATURES"
echo ""
fi
if [ -n "$FIXES" ]; then
echo "**Bug Fixes**"
echo -e "$FIXES"
echo ""
fi
if [ -n "$MAINTENANCE" ]; then
echo "**Maintenance**"
echo -e "$MAINTENANCE"
echo ""
fi
if [ -n "$OTHER" ]; then
echo "**Other Changes**"
echo -e "$OTHER"
echo ""
fi
echo "**Note:** If you encounter any bugs or issues, please don't hesitate to open an [issue](https://github.com/BerndHagen/QuickNotes-Simple-Note-Manager/issues). For any questions or to start a discussion, feel free to initiate a [discussion](https://github.com/BerndHagen/QuickNotes-Simple-Note-Manager/discussions) on the GitHub repository."
echo "EOFMARKER"
} >> $GITHUB_OUTPUT
- name: Delete existing latest release
run: gh release delete latest --yes --cleanup-tag 2>/dev/null || true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create latest release
uses: softprops/action-gh-release@v2
with:
tag_name: latest
name: "Latest Build"
body: ${{ steps.notes.outputs.body }}
prerelease: true
files: quicknotes-latest.zip
# ──────────────────────────────────────────────────────────────
# Job 2: Versioned release — only when a tag like v1.0.0 is pushed
# These releases are permanent and represent stable milestones
# ──────────────────────────────────────────────────────────────
versioned:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
- name: Extract version
id: version
run: |
TAG="${GITHUB_REF#refs/tags/}"
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "Version tag: $TAG"
- name: Create ZIP archive
run: |
cd dist
zip -r ../quicknotes-${{ steps.version.outputs.tag }}.zip .
- name: Generate versioned release notes
id: notes
run: |
RELEASE_DATE=$(date -u +"%d-%m-%Y at %I:%M %p UTC")
CURRENT_TAG="${GITHUB_REF#refs/tags/}"
# Find previous versioned tag (exclude "latest" and current tag)
PREV_TAG=$(git tag -l 'v*.*.*' --sort=-v:refname | grep -v "^${CURRENT_TAG}$" | head -n 1)
if [ -n "$PREV_TAG" ]; then
RANGE="${PREV_TAG}..${CURRENT_TAG}"
else
RANGE=""
fi
ITEMS_FILE=$(mktemp)
if [ -n "$RANGE" ]; then
HASHES=$(git log "$RANGE" --no-merges --format="%H" 2>/dev/null)
else
HASHES=$(git log --no-merges -20 --format="%H" 2>/dev/null)
fi
while read -r HASH; do
[ -z "$HASH" ] && continue
SUBJECT=$(git log -1 "$HASH" --format="%s")
BODY=$(git log -1 "$HASH" --format="%b")
case "$SUBJECT" in
feat:*|feat\(*|add:*|add\(*|new:*|new\(*)
CAT="FEAT" ;;
fix:*|fix\(*|bug:*|bug\(*|patch:*|patch\(*|hotfix:*|hotfix\(*)
CAT="FIX" ;;
ci:*|ci\(*|build:*|build\(*|chore:*|chore\(*|refactor:*|refactor\(*|style:*|style\(*|docs:*|docs\(*)
CAT="MAINT" ;;
*)
CAT="OTHER" ;;
esac
BULLETS=$(echo "$BODY" | grep -E '^\s*[-*•]\s+' | sed 's/^[[:space:]]*[-*•][[:space:]]*//' || true)
if [ -n "$BULLETS" ]; then
while IFS= read -r item; do
[ -n "$item" ] && echo "${CAT}|${item}" >> "$ITEMS_FILE"
done <<< "$BULLETS"
else
CLEAN=$(echo "$SUBJECT" | sed -E 's/^(feat|add|new|fix|bug|patch|hotfix|ci|build|chore|refactor|style|docs)(\([^)]*\))?[: ]*//')
[ -n "$CLEAN" ] && echo "${CAT}|${CLEAN}" >> "$ITEMS_FILE"
fi
done <<< "$HASHES"
FEATURES=""
FIXES=""
MAINTENANCE=""
OTHER=""
if [ -f "$ITEMS_FILE" ]; then
while IFS='|' read -r category text; do
[ -z "$text" ] && continue
text="$(echo "${text:0:1}" | tr '[:lower:]' '[:upper:]')${text:1}"
case "$category" in
FEAT) FEATURES="${FEATURES}\n• \u2800${text}" ;;
FIX) FIXES="${FIXES}\n• \u2800${text}" ;;
MAINT) MAINTENANCE="${MAINTENANCE}\n• \u2800${text}" ;;
OTHER) OTHER="${OTHER}\n• \u2800${text}" ;;
esac
done < "$ITEMS_FILE"
fi
rm -f "$ITEMS_FILE"
FEAT_COUNT=$(echo -e "$FEATURES" | grep -c "•" || true)
FIX_COUNT=$(echo -e "$FIXES" | grep -c "•" || true)
SUMMARY="Release of QuickNotes with"
PARTS=""
if [ "$FEAT_COUNT" -gt 0 ]; then
PARTS="${PARTS} ${FEAT_COUNT} new feature(s),"
fi
if [ "$FIX_COUNT" -gt 0 ]; then
PARTS="${PARTS} ${FIX_COUNT} bug fix(es),"
fi
if [ -n "$PARTS" ]; then
PARTS=$(echo "$PARTS" | sed 's/,$//')
SUMMARY="${SUMMARY}${PARTS}."
else
SUMMARY="Maintenance release of QuickNotes with internal improvements and updates."
fi
{
echo "body<<EOFMARKER"
echo "**Release: ${RELEASE_DATE}**"
echo "${SUMMARY}"
echo ""
if [ -n "$FEATURES" ]; then
echo "**New Features & Improvements**"
echo -e "$FEATURES"
echo ""
fi
if [ -n "$FIXES" ]; then
echo "**Bug Fixes**"
echo -e "$FIXES"
echo ""
fi
if [ -n "$MAINTENANCE" ]; then
echo "**Maintenance**"
echo -e "$MAINTENANCE"
echo ""
fi
if [ -n "$OTHER" ]; then
echo "**Other Changes**"
echo -e "$OTHER"
echo ""
fi
echo "**Note:** If you encounter any bugs or issues, please don't hesitate to open an [issue](https://github.com/BerndHagen/QuickNotes-Simple-Note-Manager/issues). For any questions or to start a discussion, feel free to initiate a [discussion](https://github.com/BerndHagen/QuickNotes-Simple-Note-Manager/discussions) on the GitHub repository."
echo "EOFMARKER"
} >> $GITHUB_OUTPUT
- name: Create versioned release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: ${{ steps.version.outputs.tag }}
body: ${{ steps.notes.outputs.body }}
files: quicknotes-${{ steps.version.outputs.tag }}.zip