Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 167 additions & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,99 +1,170 @@
# ============================================================================
# KEEGEES AUTOMATED RELEASE WORKFLOW
# ============================================================================
# This workflow provides comprehensive automated versioning and release
# management for the keegees GNOME keybinding management CLI tool.
#
# FEATURES:
# - Automated semantic version increments (patch-level)
# - Multi-file version synchronization (README.md, keegees.sh)
# - Comprehensive quality assurance via ShellCheck validation
# - Professional release asset generation (tar.gz, zip archives)
# - Dynamic release notes with installation instructions
# - GitHub release creation with automated asset attachment
#
# TRIGGER CONDITIONS:
# - Automatic: Push to master branch (production releases)
# - Manual: workflow_dispatch for ad-hoc releases and testing
#
# PERMISSIONS REQUIRED:
# - contents:write - Repository file modifications and tag creation
# - packages:write - Release asset publishing and management
# ============================================================================

name: 🏷️ Auto Tag and Release

# Triggers on push to master branch (fully automated)
on:
push:
branches: [ master ]
workflow_dispatch: # Manual trigger option
workflow_dispatch:

# Required permissions for tagging and releasing
permissions:
contents: write
packages: write

jobs:
# Job 1: Validate and Calculate Version
# ==========================================================================
# JOB 1: VALIDATION AND VERSION CALCULATION
# ==========================================================================
# Performs comprehensive quality assurance and determines the next semantic
# version number for the keegees release. This job validates shell scripts
# using ShellCheck and calculates version increments based on existing git
# tags, ensuring consistent and reliable version management.
#
# OUTPUTS:
# - version: Semantic version number (e.g., "0.0.2")
# - tag: Git tag format (e.g., "v0.0.2")
#
# DEPENDENCIES: None (entry point job)
# ==========================================================================
validate-and-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_next_version.outputs.version }}
tag: ${{ steps.get_next_version.outputs.tag }}
steps:
# ----------------------------------------------------------------------
# STEP: Repository Checkout with Full History
# Retrieves complete git history for accurate version calculation and
# tag analysis. Full history is required for git describe operations.
# ----------------------------------------------------------------------
- name: 🔄 Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

# ----------------------------------------------------------------------
# STEP: Shell Script Quality Assurance
# Validates keegees.sh and install.sh using ShellCheck to ensure
# adherence to best practices and prevent shell scripting errors.
# ----------------------------------------------------------------------
- name: 🔍 Run ShellCheck
run: |
shellcheck keegees.sh
shellcheck install.sh

# ----------------------------------------------------------------------
# STEP: Semantic Version Calculation
# Analyzes existing git tags to determine the next patch version.
# Implements automated semantic versioning with consistent increment logic.
# ----------------------------------------------------------------------
- name: 📊 Calculate Next Version
id: get_next_version
run: |
# Get latest tag or default to 0.0.0
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")

# Extract version number (remove v prefix)
CURRENT_VERSION=${LATEST_TAG#v}

# Split version into components
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"

# Increment patch version (as per requirement 1.1)
NEXT_PATCH=$((PATCH + 1))
NEXT_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}"

echo "version=$NEXT_VERSION" >> $GITHUB_OUTPUT
echo "tag=v$NEXT_VERSION" >> $GITHUB_OUTPUT
echo "📊 Next version will be: v$NEXT_VERSION"

# Job 2: Update Version References and Create Tag
# ==========================================================================
# JOB 2: VERSION SYNCHRONIZATION AND GIT TAGGING
# ==========================================================================
# Synchronizes version references across multiple project files and creates
# annotated git tags for release tracking. Updates README.md version badges,
# CLI display versions, and keegees.sh VERSION constants to maintain
# consistency throughout the codebase.
#
# FILE UPDATES:
# - README.md: Version badges and warning text
# - keegees.sh: Internal VERSION constant
#
# GIT OPERATIONS:
# - Atomic commits with [skip ci] to prevent recursion
# - Annotated tag creation with automated messages
# - Remote repository synchronization
#
# DEPENDENCIES: validate-and-version (requires version outputs)
# ==========================================================================
version-sync-and-tag:
runs-on: ubuntu-latest
needs: validate-and-version
steps:
# ----------------------------------------------------------------------
# STEP: Repository Checkout for File Modifications
# Retrieves repository contents for version synchronization operations.
# Full history enables proper git operations for tagging and pushing.
# ----------------------------------------------------------------------
- name: 🔄 Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.ADMIN_TOKEN || secrets.GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
Copy link

Copilot AI Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The token configuration was changed from ${{ secrets.ADMIN_TOKEN || secrets.GITHUB_TOKEN }} to only ${{ secrets.GITHUB_TOKEN }}. This removes the fallback to ADMIN_TOKEN which may be intentional, but could impact functionality if ADMIN_TOKEN was required for specific permissions that GITHUB_TOKEN lacks.

Suggested change
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.ADMIN_TOKEN || secrets.GITHUB_TOKEN }}

Copilot uses AI. Check for mistakes.

# ----------------------------------------------------------------------
# STEP: Multi-File Version Synchronization
# Updates version references across README.md and keegees.sh to maintain
# consistency. Uses sed for reliable pattern matching and replacement.
# ----------------------------------------------------------------------
- name: 🔄 Synchronize Version Across Files
run: |
NEW_VERSION="${{ needs.validate-and-version.outputs.version }}"
echo "🔄 Updating version to $NEW_VERSION across all files..."

# Update README.md version badge
sed -i "s/Version-[0-9.]*/Version-$NEW_VERSION/g" README.md

# Update README.md version warning text
sed -i "s/version [0-9.]*/version $NEW_VERSION/g" README.md

# Update CLI example in README.md (the "Version 1.0.0" display)
sed -i "s/Version [0-9.]\+/Version $NEW_VERSION/g" README.md

# Update keegees.sh VERSION constant
sed -i "s/readonly VERSION=\"[0-9.]*\"/readonly VERSION=\"$NEW_VERSION\"/g" keegees.sh

# Verify changes
echo "📊 Version references updated:"
echo " README.md badge: $(grep -o 'Version-[0-9.]*' README.md)"
echo " README.md warning: $(grep -o 'version [0-9.]*' README.md)"
echo " keegees.sh VERSION: $(grep -o 'readonly VERSION=\"[0-9.]*\"' keegees.sh)"

# ----------------------------------------------------------------------
# STEP: Atomic Version Update Commit
# Creates atomic commit with version changes and [skip ci] tag to
# prevent recursive workflow triggers. Ensures clean git history.
# ----------------------------------------------------------------------
- name: 💾 Commit Version Updates
run: |
NEW_VERSION="${{ needs.validate-and-version.outputs.version }}"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

# Add updated files
git add README.md keegees.sh

# Check if there are changes to commit
if git diff --cached --quiet; then
echo "No version updates needed"
else
Expand All @@ -106,46 +177,80 @@ jobs:
[skip ci]"
fi

# ----------------------------------------------------------------------
# STEP: Git Tag Creation and Remote Push
# Creates annotated git tag and pushes commits and tags to remote.
# Implements proper sequencing to avoid race conditions.
# ----------------------------------------------------------------------
- name: 🏷️ Create and Push Tag
run: |
TAG="${{ needs.validate-and-version.outputs.tag }}"
git tag -a "$TAG" -m "🤖 Automated version tag: $TAG"
# Push commits first, then tag (commits have [skip ci] to prevent recursion)
git push
git push origin "$TAG"

# Job 3: Create Release Assets
# ==========================================================================
# JOB 3: RELEASE ASSET CREATION
# ==========================================================================
# Generates professional release archives and comprehensive release notes
# for distribution. Creates both tar.gz and zip formats with proper
# directory structures, excluding development files and maintaining
# professional packaging standards.
#
# ARCHIVE FORMATS:
# - tar.gz: Unix/Linux preferred format with directory transformation
# - zip: Windows/cross-platform compatibility format
#
# RELEASE NOTES:
# - Dynamic version warnings based on stability (pre-1.0 vs stable)
# - Installation instructions with correct download URLs
# - Filtered commit history excluding automated version updates
# - Professional formatting with requirements and feature descriptions
#
# DEPENDENCIES: validate-and-version, version-sync-and-tag
# ==========================================================================
create-release-assets:
runs-on: ubuntu-latest
needs: [validate-and-version, version-sync-and-tag]
steps:
# ----------------------------------------------------------------------
# STEP: Repository Checkout for Asset Generation
# Retrieves repository contents for creating distribution archives.
# Full git history supports release notes generation.
# ----------------------------------------------------------------------
- name: 🔄 Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.ADMIN_TOKEN || secrets.GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
Copy link

Copilot AI Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to line 130, the token configuration was changed from ${{ secrets.ADMIN_TOKEN || secrets.GITHUB_TOKEN }} to only ${{ secrets.GITHUB_TOKEN }}. This removes the ADMIN_TOKEN fallback which may have been necessary for certain repository operations.

Suggested change
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.ADMIN_TOKEN || secrets.GITHUB_TOKEN }}

Copilot uses AI. Check for mistakes.

# ----------------------------------------------------------------------
# STEP: Professional Release Archive Creation
# Generates tar.gz and zip archives with proper directory structure.
# Excludes development files while maintaining distribution integrity.
# ----------------------------------------------------------------------
- name: 📦 Create Release Archives
run: |
# Create release directory
mkdir -p release

# Create tarball
tar -czf "release/keegees-${{ needs.validate-and-version.outputs.version }}.tar.gz" \
--exclude='.git' \
--exclude='.github' \
--exclude='release' \
--transform "s|^|keegees-${{ needs.validate-and-version.outputs.version }}/|" \
.

# Create zip archive
zip -r "release/keegees-${{ needs.validate-and-version.outputs.version }}.zip" \
. \
-x '.git/*' '.github/*' 'release/*'

# ----------------------------------------------------------------------
# STEP: Dynamic Release Notes Generation
# Creates comprehensive release documentation with installation
# instructions, change logs, and version-appropriate warnings.
# ----------------------------------------------------------------------
- name: 📝 Generate Release Notes
run: |
# Get commits since last tag (exclude current version being created)
LAST_TAG=$(git describe --tags --abbrev=0 --exclude="${{ needs.validate-and-version.outputs.tag }}" 2>/dev/null || echo "")

if [ -n "$LAST_TAG" ]; then
Expand All @@ -154,7 +259,6 @@ jobs:
COMMITS=$(git log --oneline --no-merges | grep -v "🔄 Sync version" || true)
fi

# Set dynamic version warning based on version
NEW_VERSION="${{ needs.validate-and-version.outputs.version }}"
MAJOR=$(echo "$NEW_VERSION" | cut -d. -f1)
if [ "$MAJOR" = "0" ]; then
Expand All @@ -163,7 +267,6 @@ jobs:
EARLY_WARNING="**✅ Stable Release**: Ready for production use."
fi

# Create release notes
cat << EOF > release_notes.md
## 🚀 keegees ${{ needs.validate-and-version.outputs.tag }}

Expand All @@ -176,7 +279,6 @@ jobs:

### ⚡ Quick Install
\`\`\`bash
# Download and extract
wget https://github.com/nutthead/keegees/releases/download/${{ needs.validate-and-version.outputs.tag }}/keegees-${{ needs.validate-and-version.outputs.version }}.tar.gz
tar -xzf keegees-${{ needs.validate-and-version.outputs.version }}.tar.gz
cd keegees-${{ needs.validate-and-version.outputs.version }}
Expand All @@ -195,6 +297,11 @@ jobs:
${EARLY_WARNING}
EOF

# ----------------------------------------------------------------------
# STEP: Artifact Upload for Inter-Job Transfer
# Uploads generated assets and documentation for consumption by
# the GitHub release creation job using Actions artifact system.
# ----------------------------------------------------------------------
- name: 📤 Upload Release Assets
uses: actions/upload-artifact@v4
with:
Expand All @@ -203,16 +310,43 @@ jobs:
release/
release_notes.md

# Job 4: Create GitHub Release
# ==========================================================================
# JOB 4: GITHUB RELEASE PUBLICATION
# ==========================================================================
# Publishes the final GitHub release with all generated assets and
# documentation. Downloads artifacts from previous jobs and creates a
# comprehensive release entry with professional presentation and
# accessibility.
#
# RELEASE FEATURES:
# - Automatic latest release designation
# - Professional release naming and descriptions
# - Multi-format asset attachment (tar.gz, zip)
# - Generated and custom release notes integration
# - Public accessibility for end-users
#
# DEPENDENCIES: All previous jobs (validate-and-version,
# version-sync-and-tag, create-release-assets)
# ==========================================================================
create-github-release:
runs-on: ubuntu-latest
needs: [validate-and-version, version-sync-and-tag, create-release-assets]
steps:
# ----------------------------------------------------------------------
# STEP: Release Asset Retrieval
# Downloads artifacts generated by previous jobs including archives
# and release notes for GitHub release publication.
# ----------------------------------------------------------------------
- name: 📥 Download Release Assets
uses: actions/download-artifact@v4
with:
name: release-assets

# ----------------------------------------------------------------------
# STEP: GitHub Release Publication
# Creates public GitHub release with professional presentation,
# asset attachments, and comprehensive documentation.
# ----------------------------------------------------------------------
- name: 🎉 Create GitHub Release
uses: softprops/action-gh-release@v2
with:
Expand All @@ -228,6 +362,11 @@ jobs:
release/keegees-${{ needs.validate-and-version.outputs.version }}.zip
token: ${{ secrets.GITHUB_TOKEN }}

# ----------------------------------------------------------------------
# STEP: Release Completion Summary
# Outputs final release information including URLs and asset details
# for verification and user communication.
# ----------------------------------------------------------------------
- name: ✅ Release Summary
run: |
echo "🎉 Successfully created release: ${{ needs.validate-and-version.outputs.tag }}"
Expand Down