Merge pull request #10 from streed/update-installer-scripts #31
This file contains hidden or 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
| 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-cli: | |
| name: Build CLI 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 CLI 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 | |
| # Build CLI binary | |
| 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-cli-${{ matrix.name }}${{ matrix.ext }} ./app/cli | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ml-notes-cli-${{ matrix.name }} | |
| path: dist/ml-notes-cli-${{ matrix.name }}${{ matrix.ext }} | |
| retention-days: 1 | |
| build-desktop: | |
| name: Build Desktop Binaries | |
| if: needs.release.outputs.has_changes == 'true' | |
| needs: release | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| platform: linux/amd64 | |
| name: linux-amd64 | |
| - os: macos-latest | |
| platform: darwin/universal | |
| name: darwin-universal | |
| - os: windows-latest | |
| platform: windows/amd64 | |
| name: windows-amd64 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.22" | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| - name: Install Wails | |
| run: go install github.com/wailsapp/wails/v2/cmd/wails@latest | |
| - name: Setup Windows build environment | |
| if: matrix.os == 'windows-latest' | |
| 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 | |
| - name: Setup Linux dependencies | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev | |
| - name: Install frontend dependencies | |
| if: hashFiles('frontend/package.json') != '' | |
| run: | | |
| if [ -d "frontend" ]; then | |
| cd frontend | |
| npm install | |
| fi | |
| - name: Build desktop application | |
| 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) | |
| if [ "${{ matrix.os }}" = "windows-latest" ]; 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 | |
| # Build with Wails | |
| wails build -clean -platform ${{ matrix.platform }} \ | |
| -ldflags "-X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT}" | |
| - name: Prepare desktop artifacts | |
| shell: bash | |
| run: | | |
| mkdir -p dist | |
| if [ "${{ matrix.os }}" = "windows-latest" ]; then | |
| cp build/bin/ml-notes.exe dist/ml-notes-${{ matrix.name }}.exe | |
| elif [ "${{ matrix.os }}" = "darwin-latest" ]; then | |
| # For macOS, copy the app bundle | |
| if [ -d "build/bin/ml-notes.app" ]; then | |
| tar -czf dist/ml-notes-${{ matrix.name }}.tar.gz -C build/bin ml-notes.app | |
| else | |
| cp build/bin/ml-notes dist/ml-notes-${{ matrix.name }} | |
| fi | |
| else | |
| cp build/bin/ml-notes dist/ml-notes-${{ matrix.name }} | |
| fi | |
| - name: Upload desktop artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ml-notes-desktop-${{ matrix.name }} | |
| path: | | |
| dist/ml-notes-${{ matrix.name }}* | |
| retention-days: 1 | |
| package: | |
| name: Create Release Packages | |
| if: needs.release.outputs.has_changes == 'true' | |
| needs: [release, build-cli, build-desktop] | |
| 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 all artifacts to dist directory | |
| find artifacts -type f -name "ml-notes-*" -exec cp {} dist/ \; | |
| # List available files for debugging | |
| echo "Available files:" | |
| ls -la dist/ | |
| # Create CLI packages | |
| # Linux CLI | |
| if [ -f "dist/ml-notes-cli-linux-amd64" ]; then | |
| tar -czf dist/release/ml-notes-cli-${VERSION}-linux-amd64.tar.gz -C dist ml-notes-cli-linux-amd64 | |
| fi | |
| # macOS CLI (Intel) | |
| if [ -f "dist/ml-notes-cli-darwin-amd64" ]; then | |
| tar -czf dist/release/ml-notes-cli-${VERSION}-darwin-amd64.tar.gz -C dist ml-notes-cli-darwin-amd64 | |
| fi | |
| # macOS CLI (Apple Silicon) | |
| if [ -f "dist/ml-notes-cli-darwin-arm64" ]; then | |
| tar -czf dist/release/ml-notes-cli-${VERSION}-darwin-arm64.tar.gz -C dist ml-notes-cli-darwin-arm64 | |
| fi | |
| # Windows CLI | |
| if [ -f "dist/ml-notes-cli-windows-amd64.exe" ]; then | |
| cd dist && zip release/ml-notes-cli-${VERSION}-windows-amd64.zip ml-notes-cli-windows-amd64.exe | |
| cd .. | |
| fi | |
| # Create Desktop packages | |
| # Linux Desktop | |
| if [ -f "dist/ml-notes-linux-amd64" ]; then | |
| tar -czf dist/release/ml-notes-desktop-${VERSION}-linux-amd64.tar.gz -C dist ml-notes-linux-amd64 | |
| fi | |
| # macOS Desktop (Universal) | |
| if [ -f "dist/ml-notes-darwin-universal.tar.gz" ]; then | |
| cp dist/ml-notes-darwin-universal.tar.gz dist/release/ml-notes-desktop-${VERSION}-darwin-universal.tar.gz | |
| elif [ -f "dist/ml-notes-darwin-universal" ]; then | |
| tar -czf dist/release/ml-notes-desktop-${VERSION}-darwin-universal.tar.gz -C dist ml-notes-darwin-universal | |
| fi | |
| # Windows Desktop | |
| if [ -f "dist/ml-notes-windows-amd64.exe" ]; then | |
| cd dist && zip release/ml-notes-desktop-${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 | |
| ML Notes provides two distinct binaries: | |
| - **CLI Binary** (\`ml-notes-cli\`): Command-line interface for terminal usage, automation, and MCP server | |
| - **Desktop App** (\`ml-notes\`): Native desktop application with GUI | |
| ## Download the right package for your platform: | |
| ### Command-Line Interface (CLI) | |
| - **Linux x64**: \`ml-notes-cli-${VERSION}-linux-amd64.tar.gz\` | |
| - **macOS Intel**: \`ml-notes-cli-${VERSION}-darwin-amd64.tar.gz\` | |
| - **macOS Apple Silicon**: \`ml-notes-cli-${VERSION}-darwin-arm64.tar.gz\` | |
| - **Windows x64**: \`ml-notes-cli-${VERSION}-windows-amd64.zip\` | |
| ### Desktop Application | |
| - **Linux x64**: \`ml-notes-desktop-${VERSION}-linux-amd64.tar.gz\` | |
| - **macOS Universal**: \`ml-notes-desktop-${VERSION}-darwin-universal.tar.gz\` | |
| - **Windows x64**: \`ml-notes-desktop-${VERSION}-windows-amd64.zip\` | |
| ## Installation | |
| ### CLI Binary (Linux/macOS) | |
| 1. Download the appropriate CLI \`.tar.gz\` file | |
| 2. Extract: \`tar -xzf ml-notes-cli-${VERSION}-<platform>.tar.gz\` | |
| 3. Install: \`sudo mv ml-notes-cli-<platform> /usr/local/bin/ml-notes-cli\` | |
| 4. Initialize: \`ml-notes-cli init\` | |
| ### CLI Binary (Windows) | |
| 1. Download \`ml-notes-cli-${VERSION}-windows-amd64.zip\` | |
| 2. Extract the ZIP file | |
| 3. Add the extracted directory to your PATH | |
| 4. Initialize: \`ml-notes-cli init\` | |
| ### Desktop Application (Linux/macOS) | |
| 1. Download the appropriate desktop \`.tar.gz\` file | |
| 2. Extract: \`tar -xzf ml-notes-desktop-${VERSION}-<platform>.tar.gz\` | |
| 3. Linux: \`sudo mv ml-notes-<platform> /usr/local/bin/ml-notes\` | |
| 4. macOS: Move \`ml-notes.app\` to \`/Applications/\` | |
| ### Desktop Application (Windows) | |
| 1. Download \`ml-notes-desktop-${VERSION}-windows-amd64.zip\` | |
| 2. Extract the ZIP file | |
| 3. Run \`ml-notes.exe\` or add to PATH | |
| ## Usage | |
| ### CLI Commands | |
| \`\`\`bash | |
| ml-notes-cli --version # Check version | |
| ml-notes-cli init # Initialize configuration | |
| ml-notes-cli add -t "Title" -c "Content" # Add note | |
| ml-notes-cli serve # Start web interface | |
| ml-notes-cli mcp # Run MCP server for Claude | |
| \`\`\` | |
| ### Desktop Application | |
| - Launch the desktop app and enjoy the native GUI experience | |
| - All features available through visual interface | |
| - Shares same configuration and data with CLI | |
| ## Verification | |
| Verify your installation: | |
| \`\`\`bash | |
| ml-notes-cli --version # For CLI binary | |
| ml-notes --version # For desktop binary (if in PATH) | |
| \`\`\` | |
| ## Checksums | |
| Verify download integrity using \`checksums.txt\`: | |
| \`\`\`bash | |
| sha256sum -c checksums.txt | |
| \`\`\` | |
| ## Documentation | |
| - Full documentation: https://github.com/streed/ml-notes | |
| - CLI usage guide: See README.md in the repository | |
| - Desktop app features: Built-in help and tooltips | |
| 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 }} |