diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..e8851c3 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,43 @@ +stages: + - build + +.cache_rust: &cache_rust + cache: + key: + files: + - src-tauri/Cargo.lock + paths: + - src-tauri/target/ + - .cargo/registry/ + - .cargo/git/ + +build:windows: + stage: build + tags: + - saas-windows-medium-amd64 + <<: *cache_rust + variables: + CARGO_HOME: $CI_PROJECT_DIR\.cargo + script: + - npm install + - npm run release:full + artifacts: + paths: + - src-tauri/target/release/bundle/nsis/*.exe + expire_in: 1 week + +build:macos: + stage: build + tags: + - saas-macos-medium-m1 + <<: *cache_rust + variables: + CARGO_HOME: $CI_PROJECT_DIR/.cargo + script: + - npm install + - npm run release:full + artifacts: + paths: + - src-tauri/target/release/bundle/dmg/*.dmg + - src-tauri/target/release/bundle/macos/*.app + expire_in: 1 week \ No newline at end of file diff --git a/package.json b/package.json index 845b018..f1e59c5 100644 --- a/package.json +++ b/package.json @@ -54,4 +54,4 @@ "installerHeaderIcon": "build/icon.ico" } } -} +} \ No newline at end of file diff --git a/release.js b/release.js index 447ce5c..cd453b7 100644 --- a/release.js +++ b/release.js @@ -78,12 +78,12 @@ function uploadFileToGitLabPackage(filePath, packageName, version, fileName) { } function createGitLabRelease(tag, releaseLinks) { - const sendRequest = (method, path, data = null) => { + const sendRequest = (method, reqPath, data = null) => { return new Promise((resolve, reject) => { const options = { hostname: 'gitlab.com', port: 443, - path: path, + path: reqPath, method: method, headers: { 'PRIVATE-TOKEN': TOKEN, @@ -101,19 +101,9 @@ function createGitLabRelease(tag, releaseLinks) { res.on('data', chunk => body += chunk); res.on('end', () => { if (res.statusCode >= 200 && res.statusCode < 300) { - try { - resolve(body ? JSON.parse(body) : {}); - } catch (e) { - resolve({}); - } - } else if (res.statusCode === 409 && method === 'POST') { - console.log(`Release ${tag} already exists, deleting and recreating...`); - sendRequest('DELETE', `/api/v4/projects/${PROJECT_ID}/releases/${encodeURIComponent(tag)}`) - .then(() => sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases`, data)) - .then(resolve) - .catch(reject); + try { resolve(body ? JSON.parse(body) : {}); } catch (e) { resolve({}); } } else { - reject(new Error(`Failed to publish release (HTTP ${res.statusCode}): ${body}`)); + reject(new Error(`HTTP ${res.statusCode}: ${body}`)); } }); }); @@ -133,13 +123,34 @@ function createGitLabRelease(tag, releaseLinks) { name: `Vyla Home Release ${tag}`, tag_name: tag, ref: currentRef, - description: `Automated local release ${tag}`, + description: `Automated Multi-Platform Release ${tag}`, assets: { links: releaseLinks } }; - return sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases`, releaseData); + return sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases`, releaseData) + .catch(err => { + if (err.message.includes('HTTP 409')) { + console.log(`[CI Sync] Release ${tag} already exists. Appending our OS-specific files to it...`); + let promiseChain = Promise.resolve(); + + for (const link of releaseLinks) { + promiseChain = promiseChain.then(() => { + return sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases/${encodeURIComponent(tag)}/assets/links`, { + name: link.name, + url: link.url, + link_type: link.link_type + }).catch(e => { + if (!e.message.includes('HTTP 409')) throw e; + console.log(`[CI Sync] Link ${link.name} already attached. Skipping.`); + }); + }); + } + return promiseChain; + } + throw err; + }); } async function main() { @@ -182,6 +193,27 @@ async function main() { const nsisDir = path.join(__dirname, 'src-tauri/target/release/bundle/nsis'); if (fs.existsSync(nsisDir)) { const targetVersion = version.startsWith('v') ? version.substring(1) : version; + + if (process.platform === 'win32') { + const nsisDir = path.join(__dirname, 'src-tauri/target/release/bundle/nsis'); + if (fs.existsSync(nsisDir)) { + const files = fs.readdirSync(nsisDir).filter(f => f.endsWith('.exe') && f.includes(targetVersion)); + if (files.length > 0) { + installerPath = path.join(nsisDir, files[0]); + installerUploadName = files[0].replace(/\s+/g, '-'); + } + } + } else if (process.platform === 'darwin') { + const dmgDir = path.join(__dirname, 'src-tauri/target/release/bundle/dmg'); + if (fs.existsSync(dmgDir)) { + const files = fs.readdirSync(dmgDir).filter(f => f.endsWith('.dmg') && f.includes(targetVersion)); + if (files.length > 0) { + installerPath = path.join(dmgDir, files[0]); + installerUploadName = files[0].replace(/\s+/g, '-'); + } + } + } + const files = fs.readdirSync(nsisDir).filter(f => f.endsWith('.exe') && f.includes(targetVersion)); if (files.length > 0) {