This commit is contained in:
Tickbase
2025-05-18 01:50:27 +02:00
parent 38bd9b4f8f
commit 41753fd8aa
4 changed files with 1 additions and 711 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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",

View File

@@ -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)
})