chore: bump version 0.2.9 → 0.2.10 - dependency and CI updates #103
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: Build & Release | |
| on: | |
| push: | |
| branches: [main, develop] | |
| paths-ignore: | |
| - 'docs/**' | |
| - 'README.md' | |
| - 'CHANGELOG.md' | |
| - 'LICENSE' | |
| - '*.md' | |
| workflow_dispatch: {} | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # TEST BUILD (develop only) — Verify code compiles and tests pass | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| test-python: | |
| if: github.ref == 'refs/heads/develop' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| matrix: | |
| python-version: ['3.11', '3.12', '3.13'] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: pip | |
| cache-dependency-path: python/requirements.txt | |
| - name: Install and run tests | |
| run: | | |
| cd python | |
| pip install -r requirements.txt -q | |
| pip install pytest pytest-asyncio httpx -q | |
| pytest tests/ -v | |
| test-frontend: | |
| if: github.ref == 'refs/heads/develop' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install and build | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| npm run verify-icons | |
| test-electron: | |
| if: github.ref == 'refs/heads/develop' | |
| needs: test-frontend | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| env: | |
| ELECTRON_CACHE: ${{ github.workspace }}/.electron-cache | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: python/requirements.txt | |
| - name: Install Python | |
| run: | | |
| cd python | |
| pip install -r requirements.txt -q | |
| pip install pyinstaller -q | |
| - name: Build sidecar | |
| run: | | |
| cd python | |
| python -m PyInstaller main.py --onefile --name metalens-sidecar --distpath dist --clean --noconfirm \ | |
| --hidden-import piexif \ | |
| --hidden-import mutagen \ | |
| --hidden-import hachoir \ | |
| --hidden-import olefile \ | |
| --hidden-import openpyxl \ | |
| --hidden-import docx \ | |
| --hidden-import pptx \ | |
| --hidden-import pypdf | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Build frontend | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| - name: Cache Electron download | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.ELECTRON_CACHE }} | |
| key: electron-${{ runner.os }}-${{ hashFiles('electron/package-lock.json') }} | |
| - name: Test electron setup | |
| run: | | |
| cd electron | |
| npm ci --include=dev | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # BETA RELEASE (develop only) — Package and publish a prerelease build | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| get-version-beta: | |
| if: github.ref == 'refs/heads/develop' | |
| needs: [test-python, test-frontend, test-electron] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| base_version: ${{ steps.ver.outputs.base_version }} | |
| beta_version: ${{ steps.ver.outputs.beta_version }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: ver | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| BASE=$(grep -oP 'VERSION\s*=\s*"\K[^"]+' python/config.py) | |
| # Count existing beta releases for this exact base version and increment — | |
| # keeps beta.N scoped to the version instead of the workflow's global run number. | |
| LAST=$(gh release list --repo "${{ github.repository }}" --limit 200 \ | |
| | grep -oP "v${BASE}-beta\.\K[0-9]+" | sort -n | tail -1) | |
| NEXT=$(( ${LAST:-0} + 1 )) | |
| BETA="${BASE}-beta.${NEXT}" | |
| echo "base_version=$BASE" >> "$GITHUB_OUTPUT" | |
| echo "beta_version=$BETA" >> "$GITHUB_OUTPUT" | |
| echo "Building MetaLens beta v$BETA" | |
| build-windows-beta: | |
| if: github.ref == 'refs/heads/develop' | |
| needs: get-version-beta | |
| runs-on: windows-latest | |
| permissions: | |
| contents: read | |
| env: | |
| ELECTRON_CACHE: ${{ github.workspace }}/.electron-cache | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: python/requirements.txt | |
| - name: Build Python sidecar | |
| shell: pwsh | |
| run: | | |
| cd python | |
| pip install -r requirements.txt -q | |
| pip install pyinstaller -q | |
| python -m PyInstaller main.py --onefile --name metalens-sidecar --distpath dist --clean --noconfirm ` | |
| --hidden-import piexif ` | |
| --hidden-import mutagen ` | |
| --hidden-import hachoir ` | |
| --hidden-import olefile ` | |
| --hidden-import openpyxl ` | |
| --hidden-import docx ` | |
| --hidden-import pptx ` | |
| --hidden-import pypdf | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Build React frontend | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| - name: Copy frontend dist into electron | |
| run: cp -r frontend/dist electron/frontend | |
| - name: Sync electron version to beta | |
| run: | | |
| cd electron | |
| npm version ${{ needs.get-version-beta.outputs.beta_version }} --no-git-tag-version --allow-same-version | |
| - name: Cache Electron download | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.ELECTRON_CACHE }} | |
| key: electron-${{ runner.os }}-${{ hashFiles('electron/package-lock.json') }} | |
| - name: Package with Electron Forge | |
| run: | | |
| cd electron | |
| npm ci --include=dev | |
| npx electron-forge make | |
| - name: Upload Windows beta artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: windows-installer-beta | |
| path: electron/out/make/**/*.exe | |
| if-no-files-found: error | |
| build-linux-beta: | |
| if: github.ref == 'refs/heads/develop' | |
| needs: get-version-beta | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| env: | |
| ELECTRON_CACHE: ${{ github.workspace }}/.electron-cache | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install system dependencies | |
| run: sudo apt-get update -qq && sudo apt-get install -y rpm fakeroot | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: python/requirements.txt | |
| - name: Build Python sidecar | |
| run: | | |
| cd python | |
| pip install -r requirements.txt -q | |
| pip install pyinstaller -q | |
| python -m PyInstaller main.py --onefile --name metalens-sidecar --distpath dist --clean --noconfirm \ | |
| --hidden-import piexif \ | |
| --hidden-import mutagen \ | |
| --hidden-import hachoir \ | |
| --hidden-import olefile \ | |
| --hidden-import openpyxl \ | |
| --hidden-import docx \ | |
| --hidden-import pptx \ | |
| --hidden-import pypdf | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Build React frontend | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| - name: Copy frontend dist into electron | |
| run: cp -r frontend/dist electron/frontend | |
| - name: Sync electron version to beta | |
| run: | | |
| cd electron | |
| npm version ${{ needs.get-version-beta.outputs.beta_version }} --no-git-tag-version --allow-same-version | |
| - name: Configure RPM macros | |
| run: echo '%_build_id_links none' >> ~/.rpmmacros | |
| - name: Cache Electron download | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.ELECTRON_CACHE }} | |
| key: electron-${{ runner.os }}-${{ hashFiles('electron/package-lock.json') }} | |
| - name: Package with Electron Forge | |
| run: | | |
| cd electron | |
| npm ci --include=dev | |
| npx electron-forge make | |
| - name: Create Linux tar.gz | |
| run: | | |
| VERSION=${{ needs.get-version-beta.outputs.beta_version }} | |
| APP_DIR=$(find electron/out -maxdepth 1 -type d -name "MetaLens-linux-*" | head -1) | |
| if [ -n "$APP_DIR" ]; then | |
| tar -czf "electron/out/make/MetaLens-${VERSION}-Linux.tar.gz" \ | |
| -C "$(dirname "$APP_DIR")" "$(basename "$APP_DIR")" | |
| echo "Created MetaLens-${VERSION}-Linux.tar.gz" | |
| else | |
| echo "Warning: no MetaLens-linux-* directory found, skipping tar.gz" | |
| fi | |
| - name: Upload Linux beta artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: linux-packages-beta | |
| path: | | |
| electron/out/make/**/*.deb | |
| electron/out/make/**/*.rpm | |
| electron/out/make/**/*.tar.gz | |
| if-no-files-found: error | |
| release-beta: | |
| if: github.ref == 'refs/heads/develop' | |
| needs: [get-version-beta, build-windows-beta, build-linux-beta] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts | |
| - name: List artifacts | |
| run: find artifacts -type f | |
| - name: Create beta GitHub Release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: v${{ needs.get-version-beta.outputs.beta_version }} | |
| target_commitish: ${{ github.sha }} | |
| name: MetaLens v${{ needs.get-version-beta.outputs.beta_version }} (beta) | |
| draft: false | |
| prerelease: true | |
| generate_release_notes: true | |
| make_latest: false | |
| files: | | |
| artifacts/windows-installer-beta/** | |
| artifacts/linux-packages-beta/** | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # STABLE RELEASE (main only) — Rebuild from main with stable metadata | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| get-version: | |
| if: github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| version: ${{ steps.ver.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: ver | |
| run: | | |
| VERSION=$(grep -oP 'VERSION\s*=\s*"\K[^"]+' python/config.py) | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Building MetaLens v$VERSION" | |
| find-latest-beta: | |
| if: github.ref == 'refs/heads/main' | |
| needs: get-version | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| beta_tag: ${{ steps.find.outputs.beta_tag }} | |
| steps: | |
| - id: find | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| VERSION: ${{ needs.get-version.outputs.version }} | |
| run: | | |
| TAG=$(gh release list --repo "$GITHUB_REPOSITORY" --limit 200 --json tagName \ | |
| --jq '.[].tagName' \ | |
| | grep -E "^v${VERSION}-beta\.[0-9]+$" \ | |
| | sort -t. -k4 -n \ | |
| | tail -1) | |
| if [ -z "$TAG" ]; then | |
| echo "::error::Nessuna release beta trovata per v${VERSION}. Genera prima una beta da develop con la stessa VERSION in python/config.py." | |
| exit 1 | |
| fi | |
| echo "beta_tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "Validated matching beta $TAG for stable v${VERSION}" | |
| build-windows-stable: | |
| if: github.ref == 'refs/heads/main' | |
| needs: [get-version, find-latest-beta] | |
| runs-on: windows-latest | |
| permissions: | |
| contents: read | |
| env: | |
| ELECTRON_CACHE: ${{ github.workspace }}/.electron-cache | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: python/requirements.txt | |
| - name: Build Python sidecar | |
| shell: pwsh | |
| run: | | |
| cd python | |
| pip install -r requirements.txt -q | |
| pip install pyinstaller -q | |
| python -m PyInstaller main.py --onefile --name metalens-sidecar --distpath dist --clean --noconfirm ` | |
| --hidden-import piexif ` | |
| --hidden-import mutagen ` | |
| --hidden-import hachoir ` | |
| --hidden-import olefile ` | |
| --hidden-import openpyxl ` | |
| --hidden-import docx ` | |
| --hidden-import pptx ` | |
| --hidden-import pypdf | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Build React frontend | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| - name: Copy frontend dist into electron | |
| run: cp -r frontend/dist electron/frontend | |
| - name: Cache Electron download | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.ELECTRON_CACHE }} | |
| key: electron-${{ runner.os }}-${{ hashFiles('electron/package-lock.json') }} | |
| - name: Package with Electron Forge | |
| run: | | |
| cd electron | |
| npm ci --include=dev | |
| npx electron-forge make | |
| - name: Verify Windows artifacts use stable version | |
| shell: pwsh | |
| run: | | |
| $version = "${{ needs.get-version.outputs.version }}" | |
| $bad = Get-ChildItem electron/out -Recurse -File | Where-Object { $_.Name -match 'beta' } | |
| if ($bad) { | |
| $bad | ForEach-Object { Write-Error "Unexpected beta artifact: $($_.FullName)" } | |
| exit 1 | |
| } | |
| $expected = "electron/out/make/squirrel.windows/x64/MetaLens-$version-win-x64.exe" | |
| if (!(Test-Path $expected)) { | |
| Write-Error "Missing expected stable installer: $expected" | |
| exit 1 | |
| } | |
| - name: Upload Windows stable artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: windows-installer-stable | |
| path: electron/out/make/**/*.exe | |
| if-no-files-found: error | |
| build-linux-stable: | |
| if: github.ref == 'refs/heads/main' | |
| needs: [get-version, find-latest-beta] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| env: | |
| ELECTRON_CACHE: ${{ github.workspace }}/.electron-cache | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install system dependencies | |
| run: sudo apt-get update -qq && sudo apt-get install -y rpm fakeroot | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: python/requirements.txt | |
| - name: Build Python sidecar | |
| run: | | |
| cd python | |
| pip install -r requirements.txt -q | |
| pip install pyinstaller -q | |
| python -m PyInstaller main.py --onefile --name metalens-sidecar --distpath dist --clean --noconfirm \ | |
| --hidden-import piexif \ | |
| --hidden-import mutagen \ | |
| --hidden-import hachoir \ | |
| --hidden-import olefile \ | |
| --hidden-import openpyxl \ | |
| --hidden-import docx \ | |
| --hidden-import pptx \ | |
| --hidden-import pypdf | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Build React frontend | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| - name: Copy frontend dist into electron | |
| run: cp -r frontend/dist electron/frontend | |
| - name: Configure RPM macros | |
| run: echo '%_build_id_links none' >> ~/.rpmmacros | |
| - name: Cache Electron download | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.ELECTRON_CACHE }} | |
| key: electron-${{ runner.os }}-${{ hashFiles('electron/package-lock.json') }} | |
| - name: Package with Electron Forge | |
| run: | | |
| cd electron | |
| npm ci --include=dev | |
| npx electron-forge make | |
| - name: Create Linux tar.gz | |
| run: | | |
| VERSION=${{ needs.get-version.outputs.version }} | |
| APP_DIR=$(find electron/out -maxdepth 1 -type d -name "MetaLens-linux-*" | head -1) | |
| if [ -n "$APP_DIR" ]; then | |
| tar -czf "electron/out/make/MetaLens-${VERSION}-Linux.tar.gz" \ | |
| -C "$(dirname "$APP_DIR")" "$(basename "$APP_DIR")" | |
| echo "Created MetaLens-${VERSION}-Linux.tar.gz" | |
| else | |
| echo "Warning: no MetaLens-linux-* directory found, skipping tar.gz" | |
| fi | |
| - name: Verify Linux artifacts use stable version | |
| run: | | |
| if find electron/out -type f -name '*beta*' | grep -q .; then | |
| find electron/out -type f -name '*beta*' | |
| echo "::error::Stable build produced beta-named artifacts." | |
| exit 1 | |
| fi | |
| - name: Upload Linux stable artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: linux-packages-stable | |
| path: | | |
| electron/out/make/**/*.deb | |
| electron/out/make/**/*.rpm | |
| electron/out/make/**/*.tar.gz | |
| if-no-files-found: error | |
| release-stable: | |
| if: github.ref == 'refs/heads/main' | |
| needs: [get-version, find-latest-beta, build-windows-stable, build-linux-stable] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts | |
| - name: List artifacts | |
| run: find artifacts -type f | |
| - name: Create stable GitHub Release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: v${{ needs.get-version.outputs.version }} | |
| target_commitish: ${{ github.sha }} | |
| name: MetaLens v${{ needs.get-version.outputs.version }} | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: true | |
| make_latest: true | |
| files: | | |
| artifacts/windows-installer-stable/** | |
| artifacts/linux-packages-stable/** |