From 306919e180aa4a68c914626ed714b73a7d05fd47 Mon Sep 17 00:00:00 2001 From: Dennis Klappe Date: Wed, 20 May 2026 16:21:46 +0200 Subject: [PATCH] Make Download config files button fetch full configs from cloud build --- tools/firmware-builder/js/app.js | 41 ++++++++++++++++--------- tools/firmware-builder/worker/worker.js | 41 +++++++++++++++---------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/tools/firmware-builder/js/app.js b/tools/firmware-builder/js/app.js index 0fa5832..a1355c5 100644 --- a/tools/firmware-builder/js/app.js +++ b/tools/firmware-builder/js/app.js @@ -879,24 +879,35 @@ async function copyConfig() { /** * Download configuration files */ -function downloadConfigFiles() { - const config = wizardState.config; +async function downloadConfigFiles() { + const buildId = window.currentBuildId; + if (!buildId) { + if (typeof showToast === 'function') { + showToast('Click "Build firmware.bin" first to generate the full config files', 'error'); + } + return; + } - // Also save the JSON config so they can reload it later + // Save the JSON config (lets the user reload these exact settings later) exportConfig(false); - if (typeof ConfigGenerator !== 'undefined') { - // Generate Configuration.h - setTimeout(() => { - const configH = ConfigGenerator.generateConfigurationH(config); - downloadConfigFile('Configuration.h', configH); - }, 300); - - // Generate Configuration_adv.h - setTimeout(() => { - const configAdvH = ConfigGenerator.generateConfigurationAdvH(config); - downloadConfigFile('Configuration_adv.h', configAdvH); - }, 600); + try { + const [hResp, advResp] = await Promise.all([ + fetch(`${BUILDER_URL}/download/${buildId}/Configuration.h`), + fetch(`${BUILDER_URL}/download/${buildId}/Configuration_adv.h`) + ]); + if (!hResp.ok || !advResp.ok) { + throw new Error('Configs not ready'); + } + const hBlob = await hResp.blob(); + const advBlob = await advResp.blob(); + downloadBlob(hBlob, 'Configuration.h'); + setTimeout(() => downloadBlob(advBlob, 'Configuration_adv.h'), 300); + } catch (err) { + console.error('Config download failed:', err); + if (typeof showToast === 'function') { + showToast('Config files not ready yet — wait for the build to finish, then try again', 'error'); + } } } diff --git a/tools/firmware-builder/worker/worker.js b/tools/firmware-builder/worker/worker.js index c7f84b2..80c7b60 100644 --- a/tools/firmware-builder/worker/worker.js +++ b/tools/firmware-builder/worker/worker.js @@ -42,10 +42,12 @@ export default { return await handleStatusRequest(buildId, env, corsHeaders); } - // GET /download/:buildId - Download firmware + // GET /download/:buildId[/:filename] - Download firmware or config files if (url.pathname.startsWith('/download/') && request.method === 'GET') { - const buildId = url.pathname.split('/download/')[1]; - return await handleDownloadRequest(buildId, env, corsHeaders); + const parts = url.pathname.split('/').filter(Boolean); + const buildId = parts[1]; + const filename = parts[2] || 'firmware.bin'; + return await handleDownloadRequest(buildId, filename, env, corsHeaders); } // POST /webhook - GitHub Actions callback (internal) @@ -223,32 +225,39 @@ async function handleStatusRequest(buildId, env, corsHeaders) { } /** - * Handle firmware download request + * Handle download request for firmware.bin or config files. + * Config files are uploaded to R2 by the workflow even on build failure, + * so they don't require a complete build; firmware.bin does. */ -async function handleDownloadRequest(buildId, env, corsHeaders) { - // Check build status - const buildData = await env.BUILDS.get(`build:${buildId}`, 'json'); +async function handleDownloadRequest(buildId, filename, env, corsHeaders) { + const ALLOWED = ['firmware.bin', 'Configuration.h', 'Configuration_adv.h']; + if (!ALLOWED.includes(filename)) { + return new Response('File not allowed', { status: 400, headers: corsHeaders }); + } + const buildData = await env.BUILDS.get(`build:${buildId}`, 'json'); if (!buildData) { return new Response('Build not found', { status: 404, headers: corsHeaders }); } - if (buildData.status !== 'complete') { + if (filename === 'firmware.bin' && buildData.status !== 'complete') { return new Response('Build not ready', { status: 400, headers: corsHeaders }); } - // Get firmware from R2 - const firmware = await env.FIRMWARE.get(`${buildId}/firmware.bin`); - - if (!firmware) { - return new Response('Firmware file not found', { status: 404, headers: corsHeaders }); + const file = await env.FIRMWARE.get(`${buildId}/${filename}`); + if (!file) { + return new Response('File not found', { status: 404, headers: corsHeaders }); } - return new Response(firmware.body, { + const contentType = filename.endsWith('.bin') + ? 'application/octet-stream' + : 'text/plain'; + + return new Response(file.body, { headers: { ...corsHeaders, - 'Content-Type': 'application/octet-stream', - 'Content-Disposition': `attachment; filename="firmware.bin"` + 'Content-Type': contentType, + 'Content-Disposition': `attachment; filename="${filename}"` } }); }