feat: implement beta/stable release channels with update notifications
Add dual-channel release strategy for stable and beta releases: Release Channels: - Stable channel: production-ready releases (stable, latest, v2.3.0) - Beta channel: early access features (beta, v2.3.0-beta.1) - Configurable via PICPEAK_CHANNEL environment variable Update Notifications: - Admin dashboard shows available updates for configured channel - Checks GitHub Releases API with 1-hour cache - Can be disabled with UPDATE_CHECK_ENABLED=false CI/CD Changes: - New release-please-beta.yml workflow for beta prereleases - Docker build workflow produces stable/beta tags based on branch - Beta versions use v2.3.0-beta.1 format New Files: - .github/workflows/release-please-beta.yml - release-please-config-beta.json - .release-please-manifest-beta.json - backend/src/services/updateCheckService.js - frontend/src/components/admin/UpdateNotification.tsx Modified Files: - docker-compose.production.yml (channel selection) - .env.example (PICPEAK_CHANNEL, UPDATE_CHECK_ENABLED) - backend/src/routes/adminSystem.js (/updates endpoint) - frontend components (VersionInfo, AdminDashboard) - i18n locales (en.json, de.json) - README.md and DEPLOYMENT_GUIDE.md (documentation)
This commit is contained in:
@@ -8,10 +8,10 @@ name: Build and Push Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
tags: [ 'v*.*.*' ] # Triggered by Release Please tags
|
||||
branches: [ main, beta ]
|
||||
tags: [ 'v*.*.*', 'v*.*.*-beta.*' ] # Triggered by Release Please tags (stable and beta)
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [ main, beta ]
|
||||
release:
|
||||
types: [ published ] # Triggered when Release Please creates a release
|
||||
workflow_dispatch:
|
||||
@@ -42,6 +42,18 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Determine build context
|
||||
id: context
|
||||
run: |
|
||||
# Determine if this is a beta or stable release
|
||||
if [[ "${{ github.ref }}" == refs/tags/v*-beta* ]] || [[ "${{ github.ref }}" == refs/heads/beta ]]; then
|
||||
echo "channel=beta" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "channel=stable" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Determine build platforms
|
||||
id: platforms
|
||||
run: |
|
||||
@@ -88,10 +100,12 @@ jobs:
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=semver,pattern={{major}}.{{minor}},enable=${{ steps.context.outputs.is_prerelease == 'false' }}
|
||||
type=semver,pattern={{major}},enable=${{ steps.context.outputs.is_prerelease == 'false' }}
|
||||
type=sha,format=short
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=raw,value=stable,enable=${{ github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && steps.context.outputs.is_prerelease == 'false') }}
|
||||
type=raw,value=beta,enable=${{ github.ref == 'refs/heads/beta' || steps.context.outputs.is_prerelease == 'true' }}
|
||||
|
||||
- name: Build and push Backend Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
@@ -139,6 +153,18 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Determine build context
|
||||
id: context
|
||||
run: |
|
||||
# Determine if this is a beta or stable release
|
||||
if [[ "${{ github.ref }}" == refs/tags/v*-beta* ]] || [[ "${{ github.ref }}" == refs/heads/beta ]]; then
|
||||
echo "channel=beta" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "channel=stable" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Determine build platforms
|
||||
id: platforms
|
||||
run: |
|
||||
@@ -185,10 +211,12 @@ jobs:
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=semver,pattern={{major}}.{{minor}},enable=${{ steps.context.outputs.is_prerelease == 'false' }}
|
||||
type=semver,pattern={{major}},enable=${{ steps.context.outputs.is_prerelease == 'false' }}
|
||||
type=sha,format=short
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=raw,value=stable,enable=${{ github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && steps.context.outputs.is_prerelease == 'false') }}
|
||||
type=raw,value=beta,enable=${{ github.ref == 'refs/heads/beta' || steps.context.outputs.is_prerelease == 'true' }}
|
||||
|
||||
- name: Build and push Frontend Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
name: Release Please (Beta)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [beta]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
release-please:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_created: ${{ steps.release.outputs.release_created }}
|
||||
tag_name: ${{ steps.release.outputs.tag_name }}
|
||||
version: ${{ steps.release.outputs.version }}
|
||||
steps:
|
||||
- name: Run Release Please
|
||||
uses: googleapis/release-please-action@v4
|
||||
id: release
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
config-file: release-please-config-beta.json
|
||||
manifest-file: .release-please-manifest-beta.json
|
||||
target-branch: beta
|
||||
|
||||
- name: Output Release Info
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
run: |
|
||||
echo "## Beta Release Created!" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Tag:** ${{ steps.release.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${{ steps.release.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Docker images will be built and tagged with this beta version." >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Sync version to package.json files after release
|
||||
sync-versions:
|
||||
needs: release-please
|
||||
if: ${{ needs.release-please.outputs.release_created }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: beta
|
||||
|
||||
- name: Update package.json versions
|
||||
run: |
|
||||
VERSION="${{ needs.release-please.outputs.version }}"
|
||||
echo "Updating package.json files to version $VERSION"
|
||||
|
||||
# Update backend package.json
|
||||
cd backend
|
||||
npm version $VERSION --no-git-tag-version --allow-same-version
|
||||
cd ..
|
||||
|
||||
# Update frontend package.json
|
||||
cd frontend
|
||||
npm version $VERSION --no-git-tag-version --allow-same-version
|
||||
cd ..
|
||||
|
||||
- name: Commit version updates
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add backend/package.json frontend/package.json
|
||||
git diff --staged --quiet || git commit -m "chore: sync package.json versions to ${{ needs.release-please.outputs.version }}"
|
||||
git push
|
||||
Reference in New Issue
Block a user