Skip to content

Manual Release

Manual Release #115

name: Manual Release
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
- custom
custom_version:
description: 'Custom version (only used if release_type is custom, e.g., 1.16.1)'
required: false
type: string
release_notes:
description: 'Additional release notes (optional)'
required: false
type: string
env:
CARGO_TERM_COLOR: always
permissions:
contents: write
jobs:
prepare-release:
name: Prepare Release
runs-on: ubuntu-latest
outputs:
new_version: ${{ steps.version.outputs.new_version }}
release_notes: ${{ steps.notes.outputs.notes }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Determine version
id: version
run: |
# Get current version from Cargo.toml
CURRENT_VERSION=$(grep "^version" sql-cli/Cargo.toml | sed 's/version = "\(.*\)"/\1/')
echo "Current version: $CURRENT_VERSION"
# Parse version components
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
# Determine new version based on input
if [ "${{ github.event.inputs.release_type }}" = "custom" ]; then
if [ -z "${{ github.event.inputs.custom_version }}" ]; then
echo "Error: Custom version not provided"
exit 1
fi
NEW_VERSION="${{ github.event.inputs.custom_version }}"
elif [ "${{ github.event.inputs.release_type }}" = "major" ]; then
NEW_VERSION="$((MAJOR + 1)).0.0"
elif [ "${{ github.event.inputs.release_type }}" = "minor" ]; then
NEW_VERSION="$MAJOR.$((MINOR + 1)).0"
else
NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
fi
echo "New version: $NEW_VERSION"
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
- name: Update version in Cargo.toml
run: |
sed -i "s/^version = .*/version = \"${{ steps.version.outputs.new_version }}\"/" sql-cli/Cargo.toml
- name: Generate comprehensive release notes
id: notes
run: |
VERSION="${{ steps.version.outputs.new_version }}"
LAST_TAG=$(git tag --sort=-version:refname | head -n 1 || echo "")
# Get commit statistics
if [ -n "$LAST_TAG" ]; then
# Check if there are any commits since last tag
if git rev-list ${LAST_TAG}..HEAD --count > /dev/null 2>&1 && [ "$(git rev-list --count ${LAST_TAG}..HEAD 2>/dev/null)" -gt 0 ]; then
COMMIT_COUNT=$(git rev-list --count ${LAST_TAG}..HEAD)
FILES_CHANGED=$(git diff --name-only ${LAST_TAG}..HEAD | wc -l)
COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"%H|%s|%b")
else
# No commits since last tag
COMMIT_COUNT="0"
FILES_CHANGED="0"
COMMITS=""
fi
else
COMMIT_COUNT=$(git rev-list --count HEAD 2>/dev/null || echo "0")
FILES_CHANGED=$(git ls-files | wc -l || echo "0")
COMMITS=$(git log --pretty=format:"%H|%s|%b" 2>/dev/null || echo "")
fi
{
echo "# SQL CLI v${VERSION}"
echo ""
echo "**Release Date:** $(date +'%B %d, %Y')"
echo ""
# Add custom notes if provided
if [ -n "${{ github.event.inputs.release_notes }}" ]; then
echo "## πŸ“’ Release Notes"
echo ""
echo "${{ github.event.inputs.release_notes }}"
echo ""
fi
# Add statistics
echo "## πŸ“Š Release Overview"
echo "- **Commits in this release:** $COMMIT_COUNT"
echo "- **Files updated:** $FILES_CHANGED"
echo ""
# Detect and highlight features
echo "## ✨ Highlights"
echo ""
# Check for visual enhancements
if echo "$COMMITS" | grep -qi "cell.*render\|visual\|key.*indicator\|fade\|theme"; then
echo "### 🎨 Visual Improvements"
if echo "$COMMITS" | grep -qi "key.*indicator"; then
echo "- **Key Press Indicator**: Visual feedback for key presses with fade effects (F12 to toggle)"
fi
if echo "$COMMITS" | grep -qi "cell.*highlight"; then
echo "- **Enhanced Cell Selection**: Multiple rendering modes for better visual feedback"
fi
echo ""
fi
# Check for debugging improvements
if echo "$COMMITS" | grep -qi "debug\|log\|diagnostic"; then
echo "### πŸ” Enhanced Debugging"
if echo "$COMMITS" | grep -qi "dual.*log"; then
echo "- **Dual Logging**: Simultaneous file and in-memory logging"
fi
echo "- **Better Diagnostics**: Improved error messages and state dumps"
echo ""
fi
# Check for state management
if echo "$COMMITS" | grep -qi "state.*container\|refactor.*v[0-9]"; then
echo "### πŸ—οΈ Architecture Improvements"
echo "- **State Management**: Continued migration to centralized AppStateContainer"
echo "- **Code Quality**: Transaction-like state updates for better consistency"
echo ""
fi
# Check for data integrity
if echo "$COMMITS" | grep -qi "history.*protect\|corrupt\|atomic"; then
echo "### πŸ’Ύ Data Protection"
echo "- **History Recovery**: Automatic recovery from corrupted files"
echo "- **Atomic Writes**: Safer file operations to prevent data loss"
echo ""
fi
# Traditional categorized changes
echo "## πŸ“ Changes by Category"
echo ""
# Features
if [ -n "$LAST_TAG" ] && [ "$COMMIT_COUNT" -gt 0 ]; then
FEATURES=$(git log ${LAST_TAG}..HEAD --pretty=format:"%s" 2>/dev/null | grep -E "^feat(\(.*\))?:" | sed 's/^feat[^:]*: //' | grep -v "bump version" || true)
if [ -n "$FEATURES" ]; then
echo "### πŸš€ New Features"
echo "$FEATURES" | while IFS= read -r line; do
[ -n "$line" ] && echo "- $line"
done
echo ""
fi
# Bug Fixes
FIXES=$(git log ${LAST_TAG}..HEAD --pretty=format:"%s" 2>/dev/null | grep -E "^fix(\(.*\))?:" | sed 's/^fix[^:]*: //' | grep -v "bump version" || true)
if [ -n "$FIXES" ]; then
echo "### πŸ› Bug Fixes"
echo "$FIXES" | while IFS= read -r line; do
[ -n "$line" ] && echo "- $line"
done
echo ""
fi
# Refactoring
REFACTORS=$(git log ${LAST_TAG}..HEAD --pretty=format:"%s" 2>/dev/null | grep -E "^refactor(\(.*\))?:" | sed 's/^refactor[^:]*: //' | grep -v "bump version" || true)
if [ -n "$REFACTORS" ]; then
echo "### πŸ”§ Refactoring"
echo "$REFACTORS" | while IFS= read -r line; do
[ -n "$line" ] && echo "- $line"
done
echo ""
fi
# Documentation
DOCS=$(git log ${LAST_TAG}..HEAD --pretty=format:"%s" 2>/dev/null | grep -E "^docs(\(.*\))?:" | sed 's/^docs[^:]*: //' | grep -v "bump version" || true)
if [ -n "$DOCS" ]; then
echo "### πŸ“š Documentation"
echo "$DOCS" | while IFS= read -r line; do
[ -n "$line" ] && echo "- $line"
done
echo ""
fi
fi
# Collapsible full commit list
if [ "$COMMIT_COUNT" -gt 0 ]; then
echo "<details>"
echo "<summary>πŸ“‹ View all commits</summary>"
echo ""
if [ -n "$LAST_TAG" ]; then
git log ${LAST_TAG}..HEAD --pretty=format:"- %s (%an)" 2>/dev/null | grep -v "bump version" || true
else
git log --pretty=format:"- %s (%an)" 2>/dev/null | head -20 || true
fi
echo ""
echo "</details>"
fi
echo ""
# Key features section
echo "## 🎯 Key Features"
echo ""
echo "- **Instant Data Preview**: CSV/JSON files load immediately"
echo "- **Visual Feedback**: Key press indicator, cell highlighting"
echo "- **Advanced Navigation**: Vim-style keys, viewport/cursor lock"
echo "- **Powerful Search**: Regular search (Ctrl+F), fuzzy filter (Ctrl+/)"
echo "- **Data Export**: Save as CSV or JSON"
echo "- **Debug Mode**: Press F5 for comprehensive state information"
echo ""
# Installation
echo "## πŸ“¦ Installation"
echo ""
echo "Download the binary for your platform from the assets below."
echo ""
echo "---"
echo "**Thank you for using SQL CLI!** πŸŽ‰"
echo ""
echo "Report issues: [GitHub Issues](https://github.com/TimelordUK/sql-cli/issues)"
} > RELEASE_NOTES.md
# Save to output
echo "notes<<EOF" >> $GITHUB_OUTPUT
cat RELEASE_NOTES.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Commit version bump
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add sql-cli/Cargo.toml
git commit -m "chore: bump version to v${{ steps.version.outputs.new_version }}"
git push
- name: Create and push tag
run: |
git tag -a "v${{ steps.version.outputs.new_version }}" -m "Release v${{ steps.version.outputs.new_version }}"
git push origin "v${{ steps.version.outputs.new_version }}"
build:
name: Build Release Binaries
needs: prepare-release
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact: sql-cli-linux-x64
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact: sql-cli-windows-x64
- os: macos-latest
target: x86_64-apple-darwin
artifact: sql-cli-macos-x64
- os: macos-latest
target: aarch64-apple-darwin
artifact: sql-cli-macos-arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
ref: v${{ needs.prepare-release.outputs.new_version }}
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: ${{ matrix.target }}
override: true
- name: Build Release
working-directory: ./sql-cli
run: cargo build --release --target ${{ matrix.target }}
- name: Create artifact directory
run: mkdir -p artifacts
- name: Copy binary (Unix)
if: matrix.os != 'windows-latest'
run: cp sql-cli/target/${{ matrix.target }}/release/sql-cli artifacts/${{ matrix.artifact }}
- name: Copy binary (Windows)
if: matrix.os == 'windows-latest'
run: cp sql-cli/target/${{ matrix.target }}/release/sql-cli.exe artifacts/${{ matrix.artifact }}.exe
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: artifacts/*
release:
name: Create GitHub Release
needs: [prepare-release, build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: v${{ needs.prepare-release.outputs.new_version }}
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ needs.prepare-release.outputs.new_version }}
name: v${{ needs.prepare-release.outputs.new_version }}
body: ${{ needs.prepare-release.outputs.release_notes }}
files: artifacts/**/*
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}