diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 643d13a..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,305 +0,0 @@ -name: 'Release CreamLinux' - -# Run on manual dispatch with version info and release notes -on: - workflow_dispatch: - inputs: - version_type: - description: 'Version increment type (patch, minor, major)' - required: true - default: 'patch' - type: choice - options: - - patch - - minor - - major - custom_release_notes: - description: 'Custom release notes (leave empty for auto-generated)' - required: false - type: string - dry_run: - description: 'Perform a dry run (no actual release)' - required: false - default: false - type: boolean - -env: - CARGO_TERM_COLOR: always - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: short - -jobs: - version-bump: - runs-on: ubuntu-latest - outputs: - new_version: ${{ steps.version.outputs.new_version }} - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Get all history for changelog - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Calculate New Version - id: version - run: | - # Read current version from package.json - CURRENT_VERSION=$(node -p "require('./package.json').version") - echo "Current version: $CURRENT_VERSION" - - # Split version into major.minor.patch - IFS='.' read -r major minor patch <<< "$CURRENT_VERSION" - - # Increment based on input - if [[ "${{ github.event.inputs.version_type }}" == "major" ]]; then - major=$((major + 1)) - minor=0 - patch=0 - elif [[ "${{ github.event.inputs.version_type }}" == "minor" ]]; then - minor=$((minor + 1)) - patch=0 - else # patch - patch=$((patch + 1)) - fi - - # Create new version - NEW_VERSION="${major}.${minor}.${patch}" - echo "New version: $NEW_VERSION" - - # Set output for later steps - echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT - - - name: Update Version in Files - env: - NEW_VERSION: ${{ steps.version.outputs.new_version }} - run: | - # Update package.json - npm version $NEW_VERSION --no-git-tag-version - - # Update Cargo.toml - sed -i "s/^version = \".*\"/version = \"$NEW_VERSION\"/" src-tauri/Cargo.toml - - # Update tauri.conf.json - sed -i "s/\"version\": \".*\"/\"version\": \"$NEW_VERSION\"/" src-tauri/tauri.conf.json - - - name: Generate Changelog - id: changelog - if: github.event.inputs.custom_release_notes == '' - run: | - # Get all commit messages since the last tag - LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - - if [ -z "$LATEST_TAG" ]; then - COMMITS=$(git log --pretty=format:"- %s" --no-merges) - else - COMMITS=$(git log $LATEST_TAG..HEAD --pretty=format:"- %s" --no-merges) - fi - - # Generate changelog from commits - CHANGELOG="## Changes\n\n$COMMITS" - - # Save changelog to a file (multiline to output) - echo -e "$CHANGELOG" > changelog.md - echo "Generated changelog from commit messages" - - - name: Commit Version Changes - if: ${{ !github.event.inputs.dry_run }} - env: - NEW_VERSION: ${{ steps.version.outputs.new_version }} - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add package.json src-tauri/Cargo.toml src-tauri/tauri.conf.json - git commit -m "chore: bump version to $NEW_VERSION [skip ci]" - git tag -a "v$NEW_VERSION" -m "Version $NEW_VERSION" - git push origin HEAD:${GITHUB_REF#refs/heads/} - git push origin "v$NEW_VERSION" - - # Upload changelog as an artifact for the publish-release job - - name: Upload Changelog - uses: actions/upload-artifact@v4 - with: - name: changelog - path: changelog.md - retention-days: 1 - - build-linux: - needs: version-bump - runs-on: ubuntu-latest - outputs: - appimage_path: ${{ steps.find-assets.outputs.appimage_path }} - deb_path: ${{ steps.find-assets.outputs.deb_path }} - - steps: - - uses: actions/checkout@v4 - with: - ref: v${{ needs.version-bump.outputs.new_version }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2 - with: - workspaces: 'src-tauri -> target' - cache-on-failure: true - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - - - name: Install frontend dependencies - run: npm install - - - name: Quick lint and type-check - run: | - npm run lint - npx tsc --noEmit - - - name: Build the app (optimized) - run: npm run tauri build - - - name: Find build assets - id: find-assets - run: | - echo "appimage_path=$(find src-tauri/target/release/bundle/appimage -name "*.AppImage" | head -n 1)" >> $GITHUB_OUTPUT - echo "deb_path=$(find src-tauri/target/release/bundle/deb -name "*.deb" | head -n 1)" >> $GITHUB_OUTPUT - - - name: Upload Linux builds as artifacts - uses: actions/upload-artifact@v4 - with: - name: linux-builds - path: | - ${{ steps.find-assets.outputs.appimage_path }} - ${{ steps.find-assets.outputs.deb_path }} - retention-days: 1 - - # Build for other platforms in parallel if needed - examples: - build-windows: - needs: version-bump - runs-on: windows-latest - if: false # Disabled until we add Windows build support - outputs: - msi_path: ${{ steps.find-assets.outputs.msi_path }} - - steps: - - uses: actions/checkout@v4 - with: - ref: v${{ needs.version-bump.outputs.new_version }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2 - with: - workspaces: 'src-tauri -> target' - cache-on-failure: true - - - name: Install frontend dependencies - run: npm install - - - name: Build the app - run: npm run tauri build - - - name: Find build assets - id: find-assets - shell: bash - run: | - echo "msi_path=$(find src-tauri/target/release/bundle/msi -name "*.msi" | head -n 1)" >> $GITHUB_OUTPUT - - - name: Upload Windows builds as artifacts - uses: actions/upload-artifact@v4 - with: - name: windows-builds - path: | - ${{ steps.find-assets.outputs.msi_path }} - retention-days: 1 - - # Final job to create the release and upload assets - publish-release: - needs: [version-bump, build-linux] - if: ${{ !github.event.inputs.dry_run }} - runs-on: ubuntu-latest - - steps: - - name: Download changelog - uses: actions/download-artifact@v4 - with: - name: changelog - - - name: Download Linux builds - uses: actions/download-artifact@v4 - with: - name: linux-builds - path: dist - - # Add this step if Windows builds are enabled - # - name: Download Windows builds - # if: needs.build-windows.result == 'success' - # uses: actions/download-artifact@v4 - # with: - # name: windows-builds - # path: dist - - - name: Check downloaded artifacts - run: | - echo "Contents of dist directory:" - find dist -type f | sort - - - name: Create GitHub Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NEW_VERSION: ${{ needs.version-bump.outputs.new_version }} - with: - tag_name: v${{ needs.version-bump.outputs.new_version }} - release_name: CreamLinux v${{ needs.version-bump.outputs.new_version }} - body_path: ${{ github.event.inputs.custom_release_notes == '' && 'changelog.md' || github.event.inputs.custom_release_notes }} - draft: false - prerelease: false - - - name: Get filenames - id: get_filenames - run: | - echo "appimage_filename=$(basename $(find dist -name '*.AppImage' | head -n 1))" >> $GITHUB_OUTPUT - echo "deb_filename=$(basename $(find dist -name '*.deb' | head -n 1))" >> $GITHUB_OUTPUT - - - name: Upload AppImage to release - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist/${{ steps.get_filenames.outputs.appimage_filename }} - asset_name: CreamLinux-${{ needs.version-bump.outputs.new_version }}.AppImage - asset_content_type: application/octet-stream - - - name: Upload Debian Package to release - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist/${{ steps.get_filenames.outputs.deb_filename }} - asset_name: creamlinux_${{ needs.version-bump.outputs.new_version }}_amd64.deb - asset_content_type: application/vnd.debian.binary-package diff --git a/docs/release.md b/docs/release.md deleted file mode 100644 index 1fde4a1..0000000 --- a/docs/release.md +++ /dev/null @@ -1,149 +0,0 @@ -# Release Process for CreamLinux - -This document describes the automated release process for CreamLinux, including version management, changelog generation, and asset publishing. - -## Overview - -CreamLinux uses GitHub Actions to automate the release process. The workflow handles: - -1. Version incrementing (patch, minor, major) -2. Changelog generation from commit messages -3. Building release artifacts (AppImage, Debian package) -4. Publishing these artifacts to GitHub Releases - -## Prerequisites - -To use the release automation, you need: - -- Git installed locally -- GitHub CLI installed and authenticated -- Proper GitHub permissions on the repository -- Optional: `act` for local testing (https://github.com/nektos/act) - -## Starting a Release - -### Method 1: Using the `npm run release` command (Recommended) - -The easiest way to trigger a release is using the npm script: - -```bash -# For a patch release (0.1.0 -> 0.1.1) -npm run release patch - -# For a minor release (0.1.0 -> 0.2.0) -npm run release minor - -# For a major release (0.1.0 -> 2.0.0) -npm run release major -``` - -You can also provide custom release notes: - -```bash -npm run release minor "Added DLC management feature and improved UI" -``` - -If you don't provide custom notes, they will be automatically generated from commit messages since the last release. - -### Advanced Options - -The release script supports several advanced options: - -#### Dry Run - -Run the release process without actually creating a release: - -```bash -npm run release patch --dry-run -``` - -This will perform all the version incrementing and workflow steps but won't create the actual GitHub release. - -#### Local Testing - -Test the workflow locally before running it on GitHub: - -```bash -npm run release minor --local -``` - -This requires the `act` tool to be installed (https://github.com/nektos/act) and runs the workflow locally to check for errors. - -You can combine options: - -```bash -npm run release patch --local --dry-run -``` - -### Method 2: Manually triggering the workflow in GitHub - -You can also manually trigger the workflow from the GitHub Actions tab: - -1. Go to your repository on GitHub -2. Click on the "Actions" tab -3. Select the "Release CreamLinux" workflow -4. Click "Run workflow" -5. Choose the version increment type (patch, minor, major) -6. Optionally enter custom release notes -7. Check the "dry run" option if you want to test without creating a release -8. Click "Run workflow" - -## Release Process Details - -The release process follows these steps: - -1. **Version Calculation**: Determines the new version based on the current version and increment type -2. **File Updates**: Updates version numbers in: - - `package.json` - - `src-tauri/Cargo.toml` - - `src-tauri/tauri.conf.json` -3. **Changelog Generation**: If no custom notes are provided, generates a changelog from commits -4. **Git Operations**: - - Commits the version changes - - Creates a version tag - - Pushes the changes and tag to the repository -5. **Build Process**: Builds the application for Linux (and potentially other platforms) -6. **Release Creation**: Creates a GitHub Release with the changelog after all builds are complete -7. **Asset Upload**: Uploads the AppImage and Debian package to the release - -## Optimizations - -The release workflow includes several optimizations: - -- **Caching**: Uses Rust and npm caches to speed up build times -- **Parallel Builds**: Builds for different platforms in parallel -- **Artifact Management**: Properly manages build artifacts between jobs -- **Error Handling**: Improves error detection and reporting - -## Release Artifacts - -The following artifacts are published to the GitHub release: - -- AppImage (`.AppImage`): Portable Linux executable -- Debian Package (`.deb`): For Debian/Ubuntu-based distributions - -## Versioning Convention - -CreamLinux follows [Semantic Versioning](https://semver.org/): - -- **Major version**: Incompatible API changes -- **Minor version**: Backwards-compatible functionality -- **Patch version**: Backwards-compatible bug fixes - -## Troubleshooting - -If you encounter issues with the release process: - -1. **Check GitHub Actions logs**: Review the workflow logs for detailed error information -2. **Use local testing**: Run with `--local` flag to test locally before triggering on GitHub -3. **Try dry run mode**: Use `--dry-run` to test the process without creating an actual release -4. **Verify permissions**: Ensure you have write permissions to the repository -5. **GitHub CLI authentication**: Run `gh auth status` to verify authentication - -Common errors: - -- **"act not found"**: Install the `act` tool for local testing -- **Upload errors**: Check if the build produced the expected artifacts -- **Permission errors**: Check GitHub permissions and token access - -For technical issues with the release workflow, contact the CreamLinux maintainers. diff --git a/package.json b/package.json index d508dbc..1c6e8f5 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", - "tauri": "tauri", - "release": "node scripts/release.js" + "tauri": "tauri" }, "dependencies": { "@tauri-apps/api": "^2.5.0", diff --git a/scripts/release.js b/scripts/release.js deleted file mode 100644 index 663381e..0000000 --- a/scripts/release.js +++ /dev/null @@ -1,255 +0,0 @@ -#!/usr/bin/env node - -/** - * CreamLinux Release Script - * This script helps automate the release process by triggering the GitHub Actions workflow - * - * Usage: - * node scripts/release.js [patch|minor|major] [options] [release notes] - * - * Options: - * --dry-run Perform a dry run (no actual release) - * --local Test the workflow locally with act before running on GitHub - * --help Show help message - * - * Examples: - * node scripts/release.js patch - * node scripts/release.js minor "Added new feature X" - * node scripts/release.js major "Major redesign with new UI" - * node scripts/release.js patch --dry-run - * node scripts/release.js minor --local - */ - -import { execSync } from 'child_process' -import { existsSync } from 'fs' -import path from 'path' - -// Configuration -const GITHUB_WORKFLOW_NAME = 'release.yml' - -// Check if act is installed for local testing -function isActInstalled() { - try { - execSync('act --version', { stdio: 'ignore' }) - return true - } catch (error) { - return false - } -} - -// Validate environment -function validateEnvironment(isLocal) { - try { - // Check if git is installed - execSync('git --version', { stdio: 'ignore' }) - - if (!isLocal) { - // Check if GitHub CLI is installed - execSync('gh --version', { stdio: 'ignore' }) - - // Check if the user is authenticated with GitHub CLI - execSync('gh auth status', { stdio: 'ignore' }) - } else { - // Check if act is installed for local testing - if (!isActInstalled()) { - console.error('Error: "act" is required for local testing but is not installed.') - console.error('You can install it from: https://github.com/nektos/act') - process.exit(1) - } - } - - // Check if we're in a git repository - execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }) - - // Check if the workflow file exists - const workflowPath = path.join('.github', 'workflows', GITHUB_WORKFLOW_NAME) - if (!existsSync(workflowPath)) { - console.error(`Error: Workflow file not found at ${workflowPath}`) - process.exit(1) - } - - // Check if there are uncommitted changes - const status = execSync('git status --porcelain').toString().trim() - if (status) { - console.error('Error: There are uncommitted changes in the repository.') - console.error('Please commit or stash your changes before running this script.') - process.exit(1) - } - } catch (error) { - console.error(`Environment validation failed: ${error.message}`) - process.exit(1) - } -} - -// Parse arguments -function parseArguments() { - const args = process.argv.slice(2) - - if (args.length === 0 || args[0] === '--help') { - showUsage() - process.exit(args[0] === '--help' ? 0 : 1) - } - - const versionType = args[0].toLowerCase() - if (!['patch', 'minor', 'major'].includes(versionType)) { - console.error(`Error: Invalid version type "${versionType}"`) - showUsage() - process.exit(1) - } - - // Extract options - const options = { - dryRun: args.includes('--dry-run'), - localTest: args.includes('--local'), - } - - // Join remaining arguments as release notes (excluding options) - const releaseNotes = args - .slice(1) - .filter((arg) => !arg.startsWith('--')) - .join(' ') - - return { versionType, releaseNotes, options } -} - -// Show usage information -function showUsage() { - console.log('Usage: node scripts/release.js [patch|minor|major] [options] [release notes]') - console.log('') - console.log('Options:') - console.log(' --dry-run Perform a dry run (no actual release)') - console.log(' --local Test the workflow locally with act before running on GitHub') - console.log(' --help Show this help message') - console.log('') - console.log('Examples:') - console.log(' node scripts/release.js patch') - console.log(' node scripts/release.js minor "Added new feature X"') - console.log(' node scripts/release.js major "Major redesign with new UI"') - console.log(' node scripts/release.js patch --dry-run') - console.log(' node scripts/release.js minor --local') -} - -// Run local test with act -function runLocalTest(versionType, releaseNotes) { - console.log('\n=== Running local workflow test with act ===') - - try { - const actCommand = `act workflow_dispatch -j version-bump -e ./scripts/test-event.json` - - // First create the test event JSON - const testEvent = { - inputs: { - version_type: versionType, - custom_release_notes: releaseNotes || '', - dry_run: true, - }, - } - - // Write the test event to a file - const fs = require('fs') - fs.writeFileSync('./scripts/test-event.json', JSON.stringify(testEvent, null, 2)) - - console.log('Running local test with act (this might take a while)...') - execSync(actCommand, { stdio: 'inherit' }) - - // Clean up - fs.unlinkSync('./scripts/test-event.json') - - console.log('\nāœ… Local test completed successfully!') - return true - } catch (error) { - console.error(`āŒ Local test failed: ${error.message}`) - return false - } -} - -// Trigger GitHub workflow -function triggerWorkflow(versionType, releaseNotes, isDryRun) { - try { - console.log( - `Triggering release workflow with version type: ${versionType}${isDryRun ? ' (dry run)' : ''}` - ) - - let command = `gh workflow run ${GITHUB_WORKFLOW_NAME} -f version_type=${versionType} -f dry_run=${isDryRun}` - - if (releaseNotes) { - command += ` -f custom_release_notes="${releaseNotes}"` - } - - execSync(command, { stdio: 'inherit' }) - - console.log('\nāœ… Release workflow triggered successfully!') - console.log('You can check the progress in the Actions tab of your GitHub repository.') - console.log('https://github.com/yourusername/creamlinux/actions') - } catch (error) { - console.error(`āŒ Failed to trigger workflow: ${error.message}`) - process.exit(1) - } -} - -// Main function -async function main() { - console.log('=== CreamLinux Release Script ===\n') - - const { versionType, releaseNotes, options } = parseArguments() - - // Validate environment based on mode - validateEnvironment(options.localTest) - - console.log(`Version type: ${versionType} (${options.dryRun ? 'dry run' : 'actual release'})`) - if (releaseNotes) { - console.log(`Release notes: "${releaseNotes}"`) - } else { - console.log('Release notes: Auto-generated from commit messages') - } - - if (options.localTest) { - // Run local test first - const success = runLocalTest(versionType, releaseNotes) - - if (options.localTest) { - // Run local test first - const success = runLocalTest(versionType, releaseNotes) - - if (!success) { - console.error('\nLocal test failed. Fix the issues before running on GitHub.') - process.exit(1) - } - - // If it was just a local test, exit here - if (options.dryRun) { - console.log( - '\nLocal test completed successfully. Exiting without triggering GitHub workflow.' - ) - process.exit(0) - } - - // Ask if user wants to continue with actual GitHub workflow - console.log('\nLocal test passed! Do you want to trigger the actual GitHub workflow?') - console.log('Press Ctrl+C to cancel or wait 5 seconds to continue...') - - return new Promise((resolve) => { - setTimeout(() => { - triggerWorkflow(versionType, releaseNotes, options.dryRun) - resolve() - }, 5000) - }) - } else { - // No local test, just confirm and trigger workflow - console.log('\nThis will trigger a GitHub Actions workflow to create a new release.') - console.log('Press Ctrl+C to cancel or wait 5 seconds to continue...') - - return new Promise((resolve) => { - setTimeout(() => { - triggerWorkflow(versionType, releaseNotes, options.dryRun) - resolve() - }, 5000) - }) - } - } -} - -main().catch((err) => { - console.error(err) - process.exit(1) -})