Skip to content

Merge pull request #9 from streed/lets-convert-to-wails #30

Merge pull request #9 from streed/lets-convert-to-wails

Merge pull request #9 from streed/lets-convert-to-wails #30

Workflow file for this run

name: Release
on:
push:
branches: [main]
workflow_dispatch:
inputs:
version_bump:
description: 'Version bump type (patch, minor, major)'
required: false
default: 'patch'
type: choice
options:
- patch
- minor
- major
prerelease:
description: 'Create as pre-release'
required: false
default: false
type: boolean
draft:
description: 'Create as draft'
required: false
default: false
type: boolean
permissions:
contents: write
pull-requests: write
jobs:
release:
name: Create Release
runs-on: ubuntu-latest
outputs:
has_changes: ${{ steps.check_changes.outputs.has_changes }}
version: ${{ steps.next_version.outputs.version }}
version_without_v: ${{ steps.next_version.outputs.version_without_v }}
changelog: ${{ steps.changelog.outputs.changelog }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for tags
- name: Get previous tag
id: prev_tag
run: |
# Get the latest tag, default to v0.0.0 if no tags exist
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "tag=${LATEST_TAG}" >> $GITHUB_OUTPUT
echo "Latest tag: ${LATEST_TAG}"
- name: Calculate next version
id: next_version
run: |
LATEST_TAG="${{ steps.prev_tag.outputs.tag }}"
BUMP_TYPE="${{ github.event.inputs.version_bump || 'patch' }}"
# Remove 'v' prefix if present
VERSION=${LATEST_TAG#v}
# Split version into components
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
# Default values if parsing fails
MAJOR=${MAJOR:-0}
MINOR=${MINOR:-0}
PATCH=${PATCH:-0}
# Increment based on bump type
case "$BUMP_TYPE" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac
# Create new version
NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
echo "version_without_v=${MAJOR}.${MINOR}.${PATCH}" >> $GITHUB_OUTPUT
echo "bump_type=${BUMP_TYPE}" >> $GITHUB_OUTPUT
echo "Next version: ${NEW_VERSION} (${BUMP_TYPE} bump)"
- name: Check for changes
id: check_changes
run: |
# Check if there are any changes since the last tag
LATEST_TAG="${{ steps.prev_tag.outputs.tag }}"
if [ "$LATEST_TAG" = "v0.0.0" ]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
CHANGES=$(git diff --name-only ${LATEST_TAG}..HEAD | grep -v '^\.github/' || true)
if [ -n "$CHANGES" ]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "Changes detected since ${LATEST_TAG}"
else
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "No changes detected since ${LATEST_TAG}"
fi
fi
- name: Generate changelog
id: changelog
if: steps.check_changes.outputs.has_changes == 'true'
run: |
LATEST_TAG="${{ steps.prev_tag.outputs.tag }}"
NEW_VERSION="${{ steps.next_version.outputs.version }}"
# Generate changelog from commit messages
echo "## What's Changed" > CHANGELOG.md
echo "" >> CHANGELOG.md
if [ "$LATEST_TAG" = "v0.0.0" ]; then
# First release - include all commits
git log --pretty=format:"* %s (%h)" >> CHANGELOG.md
else
# Include commits since last tag
git log ${LATEST_TAG}..HEAD --pretty=format:"* %s (%h)" >> CHANGELOG.md
fi
echo "" >> CHANGELOG.md
echo "" >> CHANGELOG.md
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${LATEST_TAG}...${NEW_VERSION}" >> CHANGELOG.md
# Output changelog for release body
echo "changelog<<EOF" >> $GITHUB_OUTPUT
cat CHANGELOG.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Setup Go
if: steps.check_changes.outputs.has_changes == 'true'
uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Run tests
if: steps.check_changes.outputs.has_changes == 'true'
run: |
go test -v -race ./...
build:
name: Build Release Binaries
if: needs.release.outputs.has_changes == 'true'
needs: release
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
name: linux-amd64
ext: ""
- os: macos-latest
goos: darwin
goarch: amd64
name: darwin-amd64
ext: ""
- os: macos-latest
goos: darwin
goarch: arm64
name: darwin-arm64
ext: ""
- os: windows-latest
goos: windows
goarch: amd64
name: windows-amd64
ext: ".exe"
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Setup Windows build environment
if: matrix.goos == 'windows'
shell: bash
run: |
# Install MSYS2 for complete build environment
choco install msys2 -y
# Initialize MSYS2 and install required packages
C:/tools/msys64/usr/bin/bash -lc 'pacman --noconfirm -S mingw-w64-x86_64-gcc mingw-w64-x86_64-pkg-config mingw-w64-x86_64-sqlite3'
# Add MSYS2 MinGW64 to PATH
echo "C:\\tools\\msys64\\mingw64\\bin" >> $GITHUB_PATH
# Verify installation
C:/tools/msys64/mingw64/bin/gcc --version || echo "GCC not found"
- name: Build binary
shell: bash
run: |
VERSION="${{ needs.release.outputs.version_without_v }}"
BUILD_TIME=$(date -u '+%Y-%m-%d_%H:%M:%S')
GIT_COMMIT=$(git rev-parse --short HEAD)
mkdir -p dist
if [ "${{ matrix.goos }}" = "windows" ]; then
# Set up CGO environment for Windows with MSYS2
export CGO_ENABLED=1
export CC=C:/tools/msys64/mingw64/bin/gcc.exe
export CXX=C:/tools/msys64/mingw64/bin/g++.exe
export PKG_CONFIG_PATH="C:/tools/msys64/mingw64/lib/pkgconfig"
export PATH="C:/tools/msys64/mingw64/bin:$PATH"
fi
CGO_ENABLED=1 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build \
-ldflags "-X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT}" \
-o dist/ml-notes-${{ matrix.name }}${{ matrix.ext }} .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ml-notes-${{ matrix.name }}
path: dist/ml-notes-${{ matrix.name }}${{ matrix.ext }}
retention-days: 1
package:
name: Create Release Packages
if: needs.release.outputs.has_changes == 'true'
needs: [release, build]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create release archives
run: |
VERSION="${{ needs.release.outputs.version }}"
mkdir -p dist/release
# Move artifacts to dist directory and create archives
find artifacts -name "ml-notes-*" -exec cp {} dist/ \;
# Linux AMD64
if [ -f "dist/ml-notes-linux-amd64" ]; then
tar -czf dist/release/ml-notes-${VERSION}-linux-amd64.tar.gz -C dist ml-notes-linux-amd64
fi
# macOS AMD64 (Intel)
if [ -f "dist/ml-notes-darwin-amd64" ]; then
tar -czf dist/release/ml-notes-${VERSION}-darwin-amd64.tar.gz -C dist ml-notes-darwin-amd64
fi
# macOS ARM64 (Apple Silicon)
if [ -f "dist/ml-notes-darwin-arm64" ]; then
tar -czf dist/release/ml-notes-${VERSION}-darwin-arm64.tar.gz -C dist ml-notes-darwin-arm64
fi
# Windows AMD64
if [ -f "dist/ml-notes-windows-amd64.exe" ]; then
cd dist && zip release/ml-notes-${VERSION}-windows-amd64.zip ml-notes-windows-amd64.exe
cd ..
fi
# Create checksums
cd dist/release
sha256sum * > checksums.txt
# Create installation README
cat > README.md << EOF
# ML Notes ${VERSION} - Release Packages
## Download the right package for your platform:
### Linux
- **Linux x64**: \`ml-notes-${VERSION}-linux-amd64.tar.gz\`
### macOS
- **macOS Intel**: \`ml-notes-${VERSION}-darwin-amd64.tar.gz\`
- **macOS Apple Silicon**: \`ml-notes-${VERSION}-darwin-arm64.tar.gz\`
### Windows
- **Windows x64**: \`ml-notes-${VERSION}-windows-amd64.zip\`
## Installation
### Linux/macOS
1. Download the appropriate \`.tar.gz\` file
2. Extract: \`tar -xzf ml-notes-${VERSION}-<platform>.tar.gz\`
3. Install: \`sudo mv ml-notes-<platform> /usr/local/bin/ml-notes\`
4. Initialize: \`ml-notes init\`
### Windows
1. Download \`ml-notes-${VERSION}-windows-amd64.zip\`
2. Extract the ZIP file
3. Add the extracted directory to your PATH
4. Initialize: \`ml-notes init\`
## Verification
Verify your installation:
\`\`\`bash
ml-notes --version
\`\`\`
## Checksums
Verify download integrity using \`checksums.txt\`:
\`\`\`bash
sha256sum -c checksums.txt
\`\`\`
EOF
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
name: release-packages
path: dist/release/
retention-days: 1
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release.outputs.version }}
name: Release ${{ needs.release.outputs.version }}
body: ${{ needs.release.outputs.changelog }}
draft: ${{ github.event.inputs.draft || false }}
prerelease: ${{ github.event.inputs.prerelease || false }}
files: |
dist/release/*.tar.gz
dist/release/*.zip
dist/release/checksums.txt
dist/release/README.md
fail_on_unmatched_files: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}