feat(ci): build desktop app natively
Some checks failed
continuous-integration/drone/push Build is failing

This change uses GitHub's matrix feature to build the desktop app natively. It also moves the build instructions to node.js script, since that runs natively on all OSes.
This commit is contained in:
2025-02-08 19:33:17 +01:00
parent c3111ca41f
commit 8bb33b97f5
4 changed files with 161 additions and 35 deletions

View File

@ -6,20 +6,12 @@ on:
- main
jobs:
version:
docker:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ghd.outputs.describe }}
steps:
- name: Git describe
id: ghd
uses: proudust/gh-describe@v2
docker:
runs-on: ubuntu-latest
needs:
- version
steps:
- name: Login to GHCR
uses: docker/login-action@v3
with:
@ -37,38 +29,39 @@ jobs:
push: true
tags: ghcr.io/go-vikunja/vikunja:unstable
build-args: |
RELEASE_VERSION=${{ needs.version.outputs.version }}
RELEASE_VERSION=${{ steps.ghd.outputs.describe }}
desktop:
runs-on: ubuntu-latest
needs:
- version
container:
image: electronuserland/builder:wine
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Set version
id: version
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${{ github.ref_name}}"
else
VERSION="unstable"
fi
echo version=$VERSION >> "$GITHUB_OUTPUT"
- name: Git describe
id: ghd
uses: proudust/gh-describe@v2
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: desktop/package.json
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: desktop/pnpm-lock.yaml
- name: Build desktop app
working-directory: desktop
run: |
wget "https://dl.vikunja.io/frontend/vikunja-frontend-${{ steps.version.outputs.version }}.zip"
unzip "vikunja-frontend-${{ steps.version.outputs.version }}.zip" -d frontend
sed -i 's/\/api\/v1//g' frontend/index.html
sed -i "s/\${version}/${{ needs.version.outputs.version }}/g" package.json
sed -i "s/\"version\": \".*\"/\"version\": \"${{ needs.version.outputs.version }}\"/" package.json
npm install -g corepack && corepack enable && pnpm config set store-dir .cache/pnpm
pnpm install --fetch-timeout 100000
pnpm dist --linux --windows
# TODO use the built output from a previous frontend build step
node build.js "${{ steps.ghd.outputs.describe }}"
- name: Store release as artifact
uses: actions/upload-artifact@v4
with:
name: desktop-release
path: desktop/dist/Vikunja-Desktop*
name: desktop-release-${{ runner.os }}
path: desktop/dist/Vikunja*

105
desktop/build.js Normal file
View File

@ -0,0 +1,105 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');
const unzipper = require('unzipper');
// Helper function to download a file
async function downloadFile(url, dest) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(dest);
https.get(url, (response) => {
if (response.statusCode !== 200) {
return reject(new Error(`Failed to download file: ${response.statusCode}`));
}
response.pipe(file);
file.on('finish', () => {
file.close(resolve);
});
}).on('error', (err) => {
fs.unlink(dest, () => reject(err));
});
});
}
// Helper function to unzip a file to a directory
async function unzipFile(zipPath, destDir) {
return fs.createReadStream(zipPath)
.pipe(unzipper.Extract({ path: destDir }))
.promise();
}
// Helper function to replace text in a file
async function replaceTextInFile(filePath, searchValue, replaceValue) {
const data = await fs.promises.readFile(filePath, 'utf8');
const result = data.replace(searchValue, replaceValue);
await fs.promises.writeFile(filePath, result, 'utf8');
}
// Main function to execute the script steps
async function main() {
const args = process.argv.slice(2);
if (args.length === 0) {
console.error("Error: Version placeholder argument is required.");
console.error("Usage: node build-script.js <version-placeholder>");
process.exit(1);
}
const versionPlaceholder = args[0];
const frontendZipUrl = "https://dl.vikunja.io/frontend/vikunja-frontend-unstable.zip";
const zipFilePath = path.resolve(__dirname, 'vikunja-frontend-unstable.zip');
const frontendDir = path.resolve(__dirname, 'frontend');
const indexFilePath = path.join(frontendDir, 'index.html');
const packageJsonPath = path.join(__dirname, 'package.json');
console.log(`Building version ${versionPlaceholder}`);
try {
console.log('Step 1: Downloading frontend zip...');
await downloadFile(frontendZipUrl, zipFilePath);
console.log('Step 2: Unzipping frontend package...');
await unzipFile(zipFilePath, frontendDir);
console.log('Step 3: Modifying index.html...');
await replaceTextInFile(indexFilePath, /\/api\/v1/g, '');
console.log('Step 4: Updating version in package.json...');
await replaceTextInFile(packageJsonPath, /\${version}/g, versionPlaceholder);
await replaceTextInFile(
packageJsonPath,
/"version": ".*"/,
`"version": "${versionPlaceholder}"`
);
console.log('Step 5: Installing dependencies and building...');
execSync('pnpm dist', { stdio: 'inherit' });
console.log('All steps completed successfully!');
} catch (err) {
console.error('An error occurred:', err.message);
} finally {
// Cleanup the zip file
if (fs.existsSync(zipFilePath)) {
fs.unlinkSync(zipFilePath);
}
}
}
main();

View File

@ -1,10 +1,11 @@
{
"name": "vikunja-desktop",
"version": "0.21.0",
"version": "v0.1.0",
"description": "Vikunja's frontend as a standalone desktop application.",
"main": "main.js",
"repository": "https://code.vikunja.io/desktop",
"license": "GPL-3.0-or-later",
"packageManager": "pnpm@9.15.4",
"author": {
"email": "maintainers@vikunja.io",
"name": "Vikunja Team"
@ -52,7 +53,8 @@
},
"devDependencies": {
"electron": "34.0.1",
"electron-builder": "25.1.8"
"electron-builder": "25.1.8",
"unzipper": "^0.12.3"
},
"dependencies": {
"connect-history-api-fallback": "2.0.0",

26
desktop/pnpm-lock.yaml generated
View File

@ -21,6 +21,9 @@ importers:
electron-builder:
specifier: 25.1.8
version: 25.1.8(electron-builder-squirrel-windows@24.13.3)
unzipper:
specifier: ^0.12.3
version: 0.12.3
packages:
@ -561,6 +564,9 @@ packages:
resolution: {integrity: sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==}
engines: {node: '>=10'}
duplexer2@0.1.4:
resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@ -1148,6 +1154,9 @@ packages:
engines: {node: ^12.13 || ^14.13 || >=16}
hasBin: true
node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
nopt@6.0.0:
resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@ -1550,6 +1559,9 @@ packages:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
unzipper@0.12.3:
resolution: {integrity: sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==}
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@ -2383,6 +2395,10 @@ snapshots:
dotenv@9.0.2: {}
duplexer2@0.1.4:
dependencies:
readable-stream: 2.3.8
eastasianwidth@0.2.0: {}
ee-first@1.1.1: {}
@ -3074,6 +3090,8 @@ snapshots:
- bluebird
- supports-color
node-int64@0.4.0: {}
nopt@6.0.0:
dependencies:
abbrev: 1.1.1
@ -3497,6 +3515,14 @@ snapshots:
unpipe@1.0.0: {}
unzipper@0.12.3:
dependencies:
bluebird: 3.7.2
duplexer2: 0.1.4
fs-extra: 11.2.0
graceful-fs: 4.2.11
node-int64: 0.4.0
uri-js@4.4.1:
dependencies:
punycode: 2.3.1