Skip to content

Modify README links for web app and download #33

Modify README links for web app and download

Modify README links for web app and download #33

name: Electron Desktop Build
on:
# Build on every push to main/develop
push:
branches:
- main
- develop
# Attach binaries when release-please (or manual) creates a GitHub Release
release:
types: [published]
workflow_dispatch:
concurrency:
group: electron-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
jobs:
# ── Gate: wait for CI only on release (binaries must be trustworthy) ──
wait-for-ci:
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- name: Wait for CI workflow to succeed
uses: actions/github-script@v7
with:
script: |
const workflowId = 'ci.yml';
const timeoutMinutes = 20;
const pollIntervalMs = 20000;
const deadline = Date.now() + timeoutMinutes * 60 * 1000;
const sha = context.payload.release.target_commitish;
core.info(`Waiting for CI on commit ${sha}...`);
while (true) {
const { data } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: workflowId,
head_sha: sha,
per_page: 1,
});
const run = data.workflow_runs[0];
if (!run) {
core.info('No CI run found yet. Waiting...');
} else if (run.status === 'completed') {
if (run.conclusion === 'success') {
core.info(`CI passed (run #${run.run_number}).`);
return;
}
core.setFailed(`CI failed with conclusion: ${run.conclusion}`);
return;
} else {
core.info(`CI status: ${run.status}. Waiting...`);
}
if (Date.now() > deadline) {
core.setFailed('Timed out waiting for CI.');
return;
}
await new Promise(r => setTimeout(r, pollIntervalMs));
}
# ── Build matrix: macOS / Windows / Linux ─────────────────────────────
build:
# On release: wait for CI gate. On push/dispatch: build immediately.
needs: wait-for-ci
if: always() && (needs.wait-for-ci.result == 'success' || needs.wait-for-ci.result == 'skipped')
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
platform: mac
- os: ubuntu-latest
platform: linux
- os: windows-latest
platform: win
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: electron/package-lock.json
# Linux: install RPM build tools for Fedora package
- name: Install Linux build deps
if: matrix.platform == 'linux'
run: sudo apt-get update && sudo apt-get install -y rpm
- name: Install dependencies
working-directory: electron
run: npm ci
- name: Build Electron app
working-directory: electron
run: npm run build:${{ matrix.platform }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# macOS code signing (set these secrets in repo settings)
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: lumio-desktop-${{ matrix.platform }}
path: |
electron/release/*.dmg
electron/release/*.zip
electron/release/*.exe
electron/release/*.AppImage
electron/release/*.deb
electron/release/*.rpm
electron/release/*.tar.gz
electron/release/*.yml
electron/release/*.yaml
electron/release/latest*.yml
if-no-files-found: warn
retention-days: 30
# ── Attach binaries to GitHub Release ─────────────────────────────────
publish-release:
needs: build
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: false
- name: Upload assets to GitHub Release
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const releaseId = context.payload.release.id;
const artifactsDir = 'artifacts';
const platforms = ['lumio-desktop-mac', 'lumio-desktop-linux', 'lumio-desktop-win'];
for (const platform of platforms) {
const dir = path.join(artifactsDir, platform);
if (!fs.existsSync(dir)) {
core.warning(`No artifacts for ${platform}`);
continue;
}
const files = fs.readdirSync(dir);
for (const file of files) {
// Skip yml metadata files β€” only upload installable binaries
if (file.endsWith('.yml') || file.endsWith('.yaml') || file.endsWith('.blockmap')) continue;
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (!stat.isFile()) continue;
core.info(`Uploading ${file} (${(stat.size / 1024 / 1024).toFixed(1)} MB)...`);
await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: releaseId,
name: file,
data: fs.readFileSync(filePath),
headers: {
'content-type': 'application/octet-stream',
'content-length': stat.size,
},
});
}
}
core.info('All assets uploaded to release.');
# ── Summary: downloadable links (on push builds) ─────────────────────
summary:
needs: build
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Generate download summary
uses: actions/github-script@v7
with:
script: |
const { data: artifacts } = await github.rest.actions.listArtifactsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 10,
});
const relevant = artifacts.artifacts.filter(a =>
a.name.startsWith('lumio-desktop-') &&
a.workflow_run?.head_sha === context.sha
);
let body = '## Lumio Desktop Builds\n\n';
body += '| Platform | Artifact |\n|----------|----------|\n';
const names = { mac: 'macOS', linux: 'Linux (Ubuntu/Fedora)', win: 'Windows' };
for (const [key, label] of Object.entries(names)) {
const art = relevant.find(a => a.name.includes(key));
if (art) {
body += `| ${label} | [${art.name}](${art.archive_download_url}) |\n`;
} else {
body += `| ${label} | Building... |\n`;
}
}
body += '\n*Artifacts available for 30 days. Release builds are permanent.*';
await core.summary.addRaw(body).write();