From 47c292780f4c41e2b7c6469c2f56d81d7e3b8770 Mon Sep 17 00:00:00 2001 From: Riwan Date: Mon, 11 Sep 2023 22:16:15 +0200 Subject: [PATCH 1/8] feat: add build step to flash job when using cloudbuild flags - add parameters verification for flash button - add methods to continuously fetch cloudbuild job status - add build step in flash workflow that query/create build job --- .../flash/steps/FirmwareSelectionStep.tsx | 11 +++- .../pages/flash/steps/OverviewStep.tsx | 11 +++- .../backend/graph/firmware/cloudbuild.ts | 16 ++--- src/shared/backend/graph/flash/index.ts | 59 ++++++++++++++---- src/shared/backend/services/cloudbuild.ts | 31 ++++++++++ src/shared/backend/services/flashJobs.ts | 62 +++++++++++++++++-- 6 files changed, 163 insertions(+), 27 deletions(-) diff --git a/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx b/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx index cc3f8b3..460ffe2 100644 --- a/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx +++ b/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx @@ -73,6 +73,11 @@ const FirmwareStep: StepComponent = ({ onNext }) => { const { selectedFlags, encodeFlags } = useFlags(parseParam("selectedFlags")); const { filters, encodeFilters } = useVersionFilters(parseParam("filters")); + const isCloudBuildValid = + !!version && + !!target && + (selectedFlags?.every((flag) => flag.name && flag.value) ?? true); + const [activeTab, setActiveTab] = useState( selectedFlags ? "cloudbuild" : "releases" ); @@ -238,7 +243,11 @@ const FirmwareStep: StepComponent = ({ onNext }) => { )} { onNext?.(); }} diff --git a/src/renderer/pages/flash/steps/OverviewStep.tsx b/src/renderer/pages/flash/steps/OverviewStep.tsx index 530e94e..77e5406 100644 --- a/src/renderer/pages/flash/steps/OverviewStep.tsx +++ b/src/renderer/pages/flash/steps/OverviewStep.tsx @@ -13,6 +13,7 @@ import useIsMobile from "renderer/hooks/useIsMobile"; import useCreateFlashJob from "renderer/hooks/useCreateFlashJob"; import { exception } from "react-ga"; import { useTranslation } from "react-i18next"; +import useFlags from "renderer/hooks/useFlags"; const Container = styled.div<{ isMobile: boolean }>` display: flex; @@ -33,12 +34,15 @@ const Container = styled.div<{ isMobile: boolean }>` const OverviewStep: StepComponent = ({ onRestart, onPrevious }) => { const isMobile = useIsMobile(); const { t } = useTranslation("flashing"); - const { parseParam } = useQueryParams<"deviceId" | "target" | "version">(); + const { parseParam } = useQueryParams< + "deviceId" | "target" | "version" | "selectedFlags" + >(); const navigate = useNavigate(); const deviceId = parseParam("deviceId"); const target = parseParam("target"); const version = parseParam("version"); + const { selectedFlags } = useFlags(parseParam("selectedFlags")); const invalidState = !deviceId || !target || !version; useEffect(() => { @@ -129,7 +133,10 @@ const OverviewStep: StepComponent = ({ onRestart, onPrevious }) => { disabled={creatingJob} icon={} onClick={() => { - createFlashJob({ firmware: { target, version }, deviceId }) + createFlashJob({ + firmware: { target, version, selectedFlags }, + deviceId, + }) .then((jobId) => { navigate(`./${jobId}`); }) diff --git a/src/shared/backend/graph/firmware/cloudbuild.ts b/src/shared/backend/graph/firmware/cloudbuild.ts index ce0a0a6..afe10ff 100644 --- a/src/shared/backend/graph/firmware/cloudbuild.ts +++ b/src/shared/backend/graph/firmware/cloudbuild.ts @@ -65,19 +65,19 @@ const CloudFirmware = builder.simpleObject("CloudFirmwareStatus", { }), }); +const SelectedFlags = builder.inputType("SelectedFlag", { + fields: (t__) => ({ + name: t__.string({ required: true }), + value: t__.string({ required: true }), + }), +}); + const CloudFirmwareParams = builder.inputType("CloudFirmwareParams", { fields: (t) => ({ release: t.string({ required: true }), target: t.string({ required: true }), flags: t.field({ - type: [ - builder.inputType("SelectedFlag", { - fields: (t__) => ({ - name: t__.string({ required: true }), - value: t__.string({ required: true }), - }), - }), - ], + type: [SelectedFlags], required: true, }), }), diff --git a/src/shared/backend/graph/flash/index.ts b/src/shared/backend/graph/flash/index.ts index f35cab8..77de917 100644 --- a/src/shared/backend/graph/flash/index.ts +++ b/src/shared/backend/graph/flash/index.ts @@ -106,6 +106,13 @@ const waitForNotConnected = async ( } }; +const CloudSelectedFlags = builder.inputType("CloudSelectedFlag", { + fields: (t__) => ({ + name: t__.string(), + value: t__.string(), + }), +}); + builder.mutationType({ fields: (t) => ({ createFlashJob: t.field({ @@ -116,6 +123,7 @@ builder.mutationType({ fields: (t__) => ({ version: t__.string({ required: true }), target: t__.string({ required: true }), + selectedFlags: t__.field({ type: [CloudSelectedFlags] }), }), }), required: true, @@ -125,7 +133,20 @@ builder.mutationType({ resolve: async (_, { firmware, deviceId }, context) => { let firmwareData: Buffer | undefined; let firmwareBundleUrl: string | undefined; - if (firmware.version === "local") { + let fetchCloudbuild = false; + + if (firmware.selectedFlags) { + // check that all flags are set correctly + if ( + firmware.selectedFlags.length > 0 && + !firmware.selectedFlags.every((flag) => flag.name && flag.value) + ) { + throw new GraphQLError("Specified flags are not valid"); + } + // get firmware on cloudbuild + fetchCloudbuild = true; + } else if (firmware.version === "local") { + // local firmware const localFirmware = context.firmwareStore.getLocalFirmwareById( firmware.target ); @@ -153,6 +174,7 @@ builder.mutationType({ firmwareBundleUrl = prBuild.url; } else { + // github firmware firmwareBundleUrl = ( await context.github( "GET /repos/{owner}/{repo}/releases/tags/{tag}", @@ -182,18 +204,29 @@ builder.mutationType({ // If we already have the firmware we don't need to download // So start the state off assuming no download step - const job = firmwareData - ? context.flashJobs.createJob(["connect", "erase", "flash"], { + let job; + if (fetchCloudbuild) { + job = context.flashJobs.createJob( + ["connect", "build", "erase", "flash"], + { firmware, deviceId, - }) - : context.flashJobs.createJob( - ["connect", "download", "erase", "flash"], - { - firmware, - deviceId, - } - ); + } + ); + } else if (firmwareData) { + job = context.flashJobs.createJob(["connect", "erase", "flash"], { + firmware, + deviceId, + }); + } else { + job = context.flashJobs.createJob( + ["connect", "download", "erase", "flash"], + { + firmware, + deviceId, + } + ); + } await context.flashJobs.startExecution( job.id.toString(), @@ -203,6 +236,10 @@ builder.mutationType({ data: firmwareData, url: firmwareBundleUrl, target: firmware.target, + version: firmware.version, + selectedFlags: firmware.selectedFlags as + | { name: string; value: string }[] + | undefined, }, }, context diff --git a/src/shared/backend/services/cloudbuild.ts b/src/shared/backend/services/cloudbuild.ts index bd065b5..663a018 100644 --- a/src/shared/backend/services/cloudbuild.ts +++ b/src/shared/backend/services/cloudbuild.ts @@ -88,6 +88,37 @@ export const createJob = async (params: JobStatusParams): Promise => { return data as Job; }; +// Query a job, if it's not found, create it +export const queryCreateJob = async (params: JobStatusParams): Promise => { + try { + return await queryJobStatus(params); + } catch (error) { + return await createJob(params); + } +}; + +function timeout(ms: number): Promise { + /* eslint-disable-next-line no-promise-executor-return */ + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export const queryJobStatusTillSucess = async ( + params: JobStatusParams +): Promise => { + // number of try, 200 * 5s ~= 16.67 min + /* eslint-disable no-await-in-loop */ + for (let i = 0; i < 200; i += 1) { + const status = await queryJobStatus(params); + console.log("Cloudbuild job status: ", status); + if (status.status === "BUILD_SUCCESS") { + return status; + } + await timeout(5000); + } + /* eslint-enable no-await-in-loop */ + return undefined; +}; + export const downloadBinary = async (downloadUrl: string): Promise => { const response = await ky(downloadUrl, { headers: { diff --git a/src/shared/backend/services/flashJobs.ts b/src/shared/backend/services/flashJobs.ts index d891d99..bac4000 100644 --- a/src/shared/backend/services/flashJobs.ts +++ b/src/shared/backend/services/flashJobs.ts @@ -4,10 +4,10 @@ import { PubSub } from "graphql-subscriptions"; import * as uuid from "uuid"; import type { Context } from "shared/backend/context"; import type { + FlashJobMetaType, FlashJobType, - FlashStageType, FlashStagesType, - FlashJobMetaType, + FlashStageType, } from "shared/backend/graph/flash"; export const jobUpdates = new PubSub(); @@ -42,11 +42,18 @@ export const startExecution = async ( jobId: string, args: { device: USBDevice; - firmware: { data?: Buffer; url?: string; target: string }; + firmware: { + data?: Buffer; + url?: string; + target: string; + version: string; + selectedFlags?: { name: string; value: string }[]; + }; }, - { dfu, firmwareStore }: Context + { dfu, firmwareStore, cloudbuild }: Context ): Promise => { let firmwareData = args.firmware.data; + const fetchCloudbuild = !!args.firmware.selectedFlags; let dfuProcess: WebDFU | undefined; const cleanUp = async (): Promise => { @@ -91,7 +98,52 @@ export const startExecution = async ( completed: true, }); - if (!firmwareData) { + if (fetchCloudbuild) { + updateStageStatus(jobId, "build", { + started: true, + }); + + const params = { + release: args.firmware.version, + target: args.firmware.target, + flags: args.firmware.selectedFlags ?? [], + }; + + let status = await cloudbuild.queryCreateJob(params).catch((e: Error) => { + updateStageStatus(jobId, "build", { + error: e.message, + }); + return undefined; + }); + + if (!status || isCancelled(jobId)) { + return; + } + + // if the build is creating, wait + if (status.status !== "BUILD_SUCCESS") { + updateStageStatus(jobId, "build", {}); + status = await cloudbuild + .queryJobStatusTillSucess(params) + .catch((e: Error) => { + updateStageStatus(jobId, "build", { + error: e.message, + }); + return undefined; + }); + if (!status || isCancelled(jobId)) { + return; + } + } + + // success + firmwareData = await cloudbuild.downloadBinary( + status.artifacts[0].download_url + ); + updateStageStatus(jobId, "build", { + completed: true, + }); + } else if (!firmwareData) { updateStageStatus(jobId, "download", { started: true, }); From c6e8deb446415aad53e1558f0b44147a52be8451 Mon Sep 17 00:00:00 2001 From: Riwan Date: Sun, 17 Sep 2023 11:53:24 +0200 Subject: [PATCH 2/8] fix: wait job success timeout, simplify query job logic - remove queryCreateJob, replaced by createJob - add timeout parameter in waitForJobSuccess, throw err when timeout --- src/shared/backend/services/cloudbuild.ts | 23 ++++++++--------------- src/shared/backend/services/flashJobs.ts | 4 ++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/shared/backend/services/cloudbuild.ts b/src/shared/backend/services/cloudbuild.ts index 663a018..938aed7 100644 --- a/src/shared/backend/services/cloudbuild.ts +++ b/src/shared/backend/services/cloudbuild.ts @@ -88,35 +88,28 @@ export const createJob = async (params: JobStatusParams): Promise => { return data as Job; }; -// Query a job, if it's not found, create it -export const queryCreateJob = async (params: JobStatusParams): Promise => { - try { - return await queryJobStatus(params); - } catch (error) { - return await createJob(params); - } -}; - function timeout(ms: number): Promise { /* eslint-disable-next-line no-promise-executor-return */ return new Promise((resolve) => setTimeout(resolve, ms)); } -export const queryJobStatusTillSucess = async ( - params: JobStatusParams +export const waitForJobSuccess = async ( + params: JobStatusParams, + timeoutMs = 15000 ): Promise => { - // number of try, 200 * 5s ~= 16.67 min + const iterTime = 5000; + const iterNb = Math.ceil(timeoutMs / iterTime); /* eslint-disable no-await-in-loop */ - for (let i = 0; i < 200; i += 1) { + for (let i = 0; i < iterNb; i += 1) { const status = await queryJobStatus(params); console.log("Cloudbuild job status: ", status); if (status.status === "BUILD_SUCCESS") { return status; } - await timeout(5000); + await timeout(iterTime); } /* eslint-enable no-await-in-loop */ - return undefined; + throw new Error("Build process timeout"); }; export const downloadBinary = async (downloadUrl: string): Promise => { diff --git a/src/shared/backend/services/flashJobs.ts b/src/shared/backend/services/flashJobs.ts index bac4000..1c784f2 100644 --- a/src/shared/backend/services/flashJobs.ts +++ b/src/shared/backend/services/flashJobs.ts @@ -109,7 +109,7 @@ export const startExecution = async ( flags: args.firmware.selectedFlags ?? [], }; - let status = await cloudbuild.queryCreateJob(params).catch((e: Error) => { + let status = await cloudbuild.createJob(params).catch((e: Error) => { updateStageStatus(jobId, "build", { error: e.message, }); @@ -124,7 +124,7 @@ export const startExecution = async ( if (status.status !== "BUILD_SUCCESS") { updateStageStatus(jobId, "build", {}); status = await cloudbuild - .queryJobStatusTillSucess(params) + .waitForJobSuccess(params) .catch((e: Error) => { updateStageStatus(jobId, "build", { error: e.message, From 9d295d4167126f645ad7bc5de8d14eaec4467485 Mon Sep 17 00:00:00 2001 From: Riwan Date: Sun, 17 Sep 2023 15:32:29 +0200 Subject: [PATCH 3/8] feat: show build status in flash page - add optional status to flash stage, update graphql schema - add FlashBuildStatus for cloudbuild status rendering - add stories for build step in flash stage --- .../components/flashing/FlashBuildStatus.tsx | 62 +++++++++++++ .../components/flashing/FlashJobTimeline.tsx | 10 +++ src/renderer/hooks/useFlashJobStatus.ts | 8 ++ .../components/FlashJobTimeline.stories.tsx | 90 +++++++++++++++++++ src/shared/backend/graph/flash/index.ts | 9 ++ src/shared/backend/services/cloudbuild.ts | 34 ++++--- src/shared/backend/services/flashJobs.ts | 12 ++- src/shared/backend/types.ts | 7 ++ 8 files changed, 216 insertions(+), 16 deletions(-) create mode 100644 src/renderer/components/flashing/FlashBuildStatus.tsx diff --git a/src/renderer/components/flashing/FlashBuildStatus.tsx b/src/renderer/components/flashing/FlashBuildStatus.tsx new file mode 100644 index 0000000..bb8cf84 --- /dev/null +++ b/src/renderer/components/flashing/FlashBuildStatus.tsx @@ -0,0 +1,62 @@ +import { InfoCircleOutlined } from "@ant-design/icons"; +import React, { useEffect, useState } from "react"; +import { JobStatus } from "shared/backend"; +import type { FlashingBuildStageStatus } from "./FlashJobTimeline"; + +function formatDuration(time: number): string { + const sec = time % 60; + const mn = Math.floor(time / 60); + const formattedSec = String(sec).padStart(2, "0"); + const formattedMn = String(mn).padStart(2, "0"); + if (mn < 1) return `00:${formattedSec}`; + return `${formattedMn}:${formattedSec}`; +} + +function jobStatusText(status: JobStatus): string { + return { + VOID: "Created", + WAITING_FOR_BUILD: "In queue", + BUILD_IN_PROGRESS: "Building on server", + BUILD_SUCCESS: "Build finished", + BUILD_ERROR: "Failed", + }[status]; +} + +type Props = { + status: FlashingBuildStageStatus; +}; + +const FlashBuildStatus: React.FC = ({ status }) => { + const [sinceTime, setSinceTime] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setSinceTime( + Math.round((new Date().getTime() - Number(status.startedAt)) / 1000) + ); + }, 500); + return () => clearInterval(interval); + }, [status]); + + return ( +
+ {" "} +

+ {jobStatusText(status.jobStatus as JobStatus)} since{" "} + {formatDuration(sinceTime)} +

+
+ ); +}; + +export default FlashBuildStatus; diff --git a/src/renderer/components/flashing/FlashJobTimeline.tsx b/src/renderer/components/flashing/FlashJobTimeline.tsx index c43df8c..572759f 100644 --- a/src/renderer/components/flashing/FlashJobTimeline.tsx +++ b/src/renderer/components/flashing/FlashJobTimeline.tsx @@ -11,12 +11,19 @@ import { import { Alert, Button, Progress, Steps, Typography } from "antd"; import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; +import FlashBuildStatus from "./FlashBuildStatus"; + +export type FlashingBuildStageStatus = { + jobStatus: string; + startedAt: string; +}; type FlashingStageStatus = { progress: number; started: boolean; completed: boolean; error?: string | null; + status?: FlashingBuildStageStatus | null; }; type FlashingState = { @@ -298,6 +305,9 @@ const FlashJobTimeline: React.FC = ({ {stageDescription(config, stageStatus)} + {!stageStatus.error && stageStatus.status && ( + + )} {config.showProgess && !isSpecialError && (
{ completed progress error + status { + jobStatus + startedAt + } } `), { @@ -86,6 +90,10 @@ export default (jobId?: string) => { completed progress error + status { + jobStatus + startedAt + } } `), variables: { diff --git a/src/renderer/stories/flashing/components/FlashJobTimeline.stories.tsx b/src/renderer/stories/flashing/components/FlashJobTimeline.stories.tsx index 2a405b5..8a81356 100644 --- a/src/renderer/stories/flashing/components/FlashJobTimeline.stories.tsx +++ b/src/renderer/stories/flashing/components/FlashJobTimeline.stories.tsx @@ -170,6 +170,96 @@ export const downloadError: React.FC = () => ( /> ); +export const cloudbuild: React.FC = () => ( + +); + +export const cloudbuildStatus: React.FC = () => ( + +); + +export const cloudbuildError: React.FC = () => ( + +); + const useFlashingState = () => { const [state, setState] = useState({ connect: { diff --git a/src/shared/backend/graph/flash/index.ts b/src/shared/backend/graph/flash/index.ts index 77de917..8961531 100644 --- a/src/shared/backend/graph/flash/index.ts +++ b/src/shared/backend/graph/flash/index.ts @@ -22,6 +22,15 @@ const FlashStage = builder.simpleObject("FlashStage", { started: t.boolean(), completed: t.boolean(), error: t.string({ nullable: true }), + status: t.field({ + type: builder.simpleObject("FlashStageBuildStatus", { + fields: (t__) => ({ + jobStatus: t__.string(), + startedAt: t__.string(), + }), + }), + nullable: true, + }), }), }); export type FlashStageType = TypeOf; diff --git a/src/shared/backend/services/cloudbuild.ts b/src/shared/backend/services/cloudbuild.ts index 938aed7..c2092d5 100644 --- a/src/shared/backend/services/cloudbuild.ts +++ b/src/shared/backend/services/cloudbuild.ts @@ -1,4 +1,5 @@ import ky from "ky"; +import { JobStatus } from "shared/backend/types"; type Release = { sha: string; @@ -31,13 +32,6 @@ type JobStatusParams = { flags: { name: string; value: string }[]; }; -export type JobStatus = - | "VOID" - | "WAITING_FOR_BUILD" - | "BUILD_IN_PROGRESS" - | "BUILD_SUCCESS" - | "BUILD_ERROR"; - type Artifact = { created_at: string; updated_at: string; @@ -95,16 +89,32 @@ function timeout(ms: number): Promise { export const waitForJobSuccess = async ( params: JobStatusParams, - timeoutMs = 15000 + updateStatus: (statusData: { + jobStatus: JobStatus; + startedAt: string; + }) => void, + timeoutMs = 960000 // 16mn ): Promise => { const iterTime = 5000; const iterNb = Math.ceil(timeoutMs / iterTime); + + // job status data + let startedAt = new Date().getTime().toString(); + let lastStatus: JobStatus | undefined; + /* eslint-disable no-await-in-loop */ for (let i = 0; i < iterNb; i += 1) { - const status = await queryJobStatus(params); - console.log("Cloudbuild job status: ", status); - if (status.status === "BUILD_SUCCESS") { - return status; + const jobStatus = await queryJobStatus(params); + + // notify client of current status + if (lastStatus !== jobStatus.status) { + startedAt = new Date().getTime().toString(); + lastStatus = jobStatus.status; + } + updateStatus({ jobStatus: jobStatus.status, startedAt }); + + if (jobStatus.status === "BUILD_SUCCESS") { + return jobStatus; } await timeout(iterTime); } diff --git a/src/shared/backend/services/flashJobs.ts b/src/shared/backend/services/flashJobs.ts index 1c784f2..b24040c 100644 --- a/src/shared/backend/services/flashJobs.ts +++ b/src/shared/backend/services/flashJobs.ts @@ -99,9 +99,7 @@ export const startExecution = async ( }); if (fetchCloudbuild) { - updateStageStatus(jobId, "build", { - started: true, - }); + updateStageStatus(jobId, "build", { started: true }); const params = { release: args.firmware.version, @@ -124,7 +122,13 @@ export const startExecution = async ( if (status.status !== "BUILD_SUCCESS") { updateStageStatus(jobId, "build", {}); status = await cloudbuild - .waitForJobSuccess(params) + .waitForJobSuccess(params, (statusData) => { + console.log("Job status updated", statusData); + updateStageStatus(jobId, "build", { + status: statusData, + progress: 0, + }); + }) .catch((e: Error) => { updateStageStatus(jobId, "build", { error: e.message, diff --git a/src/shared/backend/types.ts b/src/shared/backend/types.ts index 9b69949..fadaafd 100644 --- a/src/shared/backend/types.ts +++ b/src/shared/backend/types.ts @@ -16,6 +16,13 @@ export type TypeOf< // cloudbuild +export type JobStatus = + | "VOID" + | "WAITING_FOR_BUILD" + | "BUILD_IN_PROGRESS" + | "BUILD_SUCCESS" + | "BUILD_ERROR"; + export type Flags = { id: string; values: string[]; From e24a4fa84fbd90d177682435a87eb71fe514f626 Mon Sep 17 00:00:00 2001 From: Riwan Date: Sun, 15 Oct 2023 00:08:49 +0200 Subject: [PATCH 4/8] feat: cloudbuild download step, timeout with controller signal - add date-fns module, use format in FLashBuildStatus - add download step in cloudbuild flash steps - add controller abort signal with timeout --- package.json | 1 + .../components/flashing/FlashBuildStatus.tsx | 16 ++---- src/shared/backend/graph/flash/index.ts | 2 +- src/shared/backend/services/cloudbuild.ts | 52 +++++++++++++------ src/shared/backend/services/flashJobs.ts | 26 ++++++++-- yarn.lock | 26 ++++++++++ 6 files changed, 90 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 3d42156..0b615a2 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "apollo-link-logger": "^2.0.0", "base64-arraybuffer": "^1.0.1", "copy-text-to-clipboard": "^3.0.1", + "date-fns": "^2.30.0", "debounce": "^1.2.1", "detect-browser": "^5.3.0", "electron-window-controls": "^1.0.23", diff --git a/src/renderer/components/flashing/FlashBuildStatus.tsx b/src/renderer/components/flashing/FlashBuildStatus.tsx index bb8cf84..10bfb8b 100644 --- a/src/renderer/components/flashing/FlashBuildStatus.tsx +++ b/src/renderer/components/flashing/FlashBuildStatus.tsx @@ -1,17 +1,9 @@ import { InfoCircleOutlined } from "@ant-design/icons"; import React, { useEffect, useState } from "react"; -import { JobStatus } from "shared/backend"; +import { JobStatus } from "shared/backend/types"; +import { format } from "date-fns"; import type { FlashingBuildStageStatus } from "./FlashJobTimeline"; -function formatDuration(time: number): string { - const sec = time % 60; - const mn = Math.floor(time / 60); - const formattedSec = String(sec).padStart(2, "0"); - const formattedMn = String(mn).padStart(2, "0"); - if (mn < 1) return `00:${formattedSec}`; - return `${formattedMn}:${formattedSec}`; -} - function jobStatusText(status: JobStatus): string { return { VOID: "Created", @@ -52,8 +44,8 @@ const FlashBuildStatus: React.FC = ({ status }) => { style={{ transform: "translate(0, 2px)", color: "gray" }} />{" "}

- {jobStatusText(status.jobStatus as JobStatus)} since{" "} - {formatDuration(sinceTime)} + {jobStatusText(status.jobStatus as JobStatus)} -{" "} + {format(sinceTime * 1000, "mm:ss")}

); diff --git a/src/shared/backend/graph/flash/index.ts b/src/shared/backend/graph/flash/index.ts index 8961531..4c26d19 100644 --- a/src/shared/backend/graph/flash/index.ts +++ b/src/shared/backend/graph/flash/index.ts @@ -216,7 +216,7 @@ builder.mutationType({ let job; if (fetchCloudbuild) { job = context.flashJobs.createJob( - ["connect", "build", "erase", "flash"], + ["connect", "build", "download", "erase", "flash"], { firmware, deviceId, diff --git a/src/shared/backend/services/cloudbuild.ts b/src/shared/backend/services/cloudbuild.ts index c2092d5..cd694af 100644 --- a/src/shared/backend/services/cloudbuild.ts +++ b/src/shared/backend/services/cloudbuild.ts @@ -54,9 +54,13 @@ export const fetchTargets = async (): Promise => { return firmwares; }; -export const queryJobStatus = async (params: JobStatusParams): Promise => { +export const queryJobStatus = async ( + params: JobStatusParams, + abortSignal: AbortSignal | undefined = undefined +): Promise => { const response = await ky.post("https://cloudbuild.edgetx.org/api/status", { body: JSON.stringify(params), + signal: abortSignal, throwHttpErrors: false, }); @@ -96,29 +100,47 @@ export const waitForJobSuccess = async ( timeoutMs = 960000 // 16mn ): Promise => { const iterTime = 5000; - const iterNb = Math.ceil(timeoutMs / iterTime); + let timedOut = false; // job status data let startedAt = new Date().getTime().toString(); let lastStatus: JobStatus | undefined; - /* eslint-disable no-await-in-loop */ - for (let i = 0; i < iterNb; i += 1) { - const jobStatus = await queryJobStatus(params); + const controller = new AbortController(); + const timeoutId = setTimeout(() => { + controller.abort(); + timedOut = true; + }, timeoutMs); - // notify client of current status - if (lastStatus !== jobStatus.status) { - startedAt = new Date().getTime().toString(); - lastStatus = jobStatus.status; - } - updateStatus({ jobStatus: jobStatus.status, startedAt }); - - if (jobStatus.status === "BUILD_SUCCESS") { - return jobStatus; + /* eslint-disable no-await-in-loop */ + while (!timedOut) { + try { + const jobStatus = await queryJobStatus(params, controller.signal); + + // notify client of current status + if (lastStatus !== jobStatus.status) { + startedAt = new Date().getTime().toString(); + lastStatus = jobStatus.status; + } + updateStatus({ jobStatus: jobStatus.status, startedAt }); + + if (jobStatus.status === "BUILD_SUCCESS") { + clearTimeout(timeoutId); + return jobStatus; + } + + await timeout(iterTime); + } catch (err) { + // ignore controller abort error, it's timeout + if (err instanceof Error && err.name === "AbortError") { + console.error(err); + } else { + throw err; + } } - await timeout(iterTime); } /* eslint-enable no-await-in-loop */ + clearTimeout(timeoutId); throw new Error("Build process timeout"); }; diff --git a/src/shared/backend/services/flashJobs.ts b/src/shared/backend/services/flashJobs.ts index b24040c..fe68b2c 100644 --- a/src/shared/backend/services/flashJobs.ts +++ b/src/shared/backend/services/flashJobs.ts @@ -123,7 +123,6 @@ export const startExecution = async ( updateStageStatus(jobId, "build", {}); status = await cloudbuild .waitForJobSuccess(params, (statusData) => { - console.log("Job status updated", statusData); updateStageStatus(jobId, "build", { status: statusData, progress: 0, @@ -140,13 +139,30 @@ export const startExecution = async ( } } - // success - firmwareData = await cloudbuild.downloadBinary( - status.artifacts[0].download_url - ); updateStageStatus(jobId, "build", { completed: true, }); + + // success, download + updateStageStatus(jobId, "download", { + started: true, + }); + firmwareData = await cloudbuild + .downloadBinary(status.artifacts[0].download_url) + .catch((e: Error) => { + updateStageStatus(jobId, "download", { + error: e.message, + }); + return undefined; + }); + if (!firmwareData || isCancelled(jobId)) { + return; + } + + updateStageStatus(jobId, "download", { + completed: true, + progress: 100, + }); } else if (!firmwareData) { updateStageStatus(jobId, "download", { started: true, diff --git a/yarn.lock b/yarn.lock index f736134..c15c6d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1944,6 +1944,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.21.0": + version: 7.23.2 + resolution: "@babel/runtime@npm:7.23.2" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 271fcfad8574269d9967b8a1c03f2e1eab108a52ad7c96ed136eee0b11f46156f1186637bd5e79a4207163db9a00413cd70a6428e137b982d0ee8ab85eb9f438 + languageName: node + linkType: hard + "@babel/template@npm:^7.12.7, @babel/template@npm:^7.15.4, @babel/template@npm:^7.16.0": version: 7.16.0 resolution: "@babel/template@npm:7.16.0" @@ -10357,6 +10366,15 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:^2.30.0": + version: 2.30.0 + resolution: "date-fns@npm:2.30.0" + dependencies: + "@babel/runtime": ^7.21.0 + checksum: e4b521fbf22bc8c3db332bbfb7b094fd3e7627de0259a9d17c7551e2d2702608a7307a449206065916538e384f37b181565447ce2637ae09828427aed9cb5581 + languageName: node + linkType: hard + "dayjs@npm:1.x": version: 1.10.7 resolution: "dayjs@npm:1.10.7" @@ -11198,6 +11216,7 @@ __metadata: copy-text-to-clipboard: ^3.0.1 cors-anywhere: ^0.4.4 css-loader: ^6.5.1 + date-fns: ^2.30.0 debounce: ^1.2.1 detect-browser: ^5.3.0 directory-tree: ^3.0.1 @@ -21770,6 +21789,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.14.0": + version: 0.14.0 + resolution: "regenerator-runtime@npm:0.14.0" + checksum: e25f062c1a183f81c99681691a342760e65c55e8d3a4d4fe347ebe72433b123754b942b70b622959894e11f8a9131dc549bd3c9a5234677db06a4af42add8d12 + languageName: node + linkType: hard + "regenerator-transform@npm:^0.14.2": version: 0.14.5 resolution: "regenerator-transform@npm:0.14.5" From 75c6dfb42717f84d791c1c31eb1211c91877538d Mon Sep 17 00:00:00 2001 From: Riwan Date: Sun, 15 Oct 2023 00:29:43 +0200 Subject: [PATCH 5/8] feat: add translation for job status --- locales/cs/flashing.json | 5 +++++ locales/de/flashing.json | 5 +++++ locales/es/flashing.json | 5 +++++ locales/fr/flashing.json | 7 ++++++- locales/it/flashing.json | 5 +++++ locales/ru/flashing.json | 5 +++++ locales/zh/flashing.json | 5 +++++ .../components/flashing/FlashBuildStatus.tsx | 19 ++++++++++++------- 8 files changed, 48 insertions(+), 8 deletions(-) diff --git a/locales/cs/flashing.json b/locales/cs/flashing.json index ea47091..034082a 100644 --- a/locales/cs/flashing.json +++ b/locales/cs/flashing.json @@ -4,8 +4,10 @@ "Add new device": "Přidat zařízení", "Available devices": "Dostupná zařízení", "Build": "Sestavit", + "Build finished": "Build finished", "Building": "Sestavuji", "Building firmware with specified configurations": "Sestavuji firmware s vybranou konfigurací", + "Building on server": "Building on server", "Built": "Sestaveno", "Cancel": "Zrušit", "Click here to select firmware file, or drag it here to upload.": "Vyberte firmware nebo ho sem přetáhňete", @@ -30,6 +32,7 @@ "Could not unlock device: {{message}}": "Could not unlock device: {{message}}", "Could not use firmware": "Nemohu použít firmware", "Could not write new firmware to radio": "Nemohu zapsat firmware do rádia", + "Created": "Created", "Details": "Detaily", "Device firmware may be read protected, preventing updates": "Device firmware may be read protected, preventing updates", "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing": "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing", @@ -47,6 +50,7 @@ "Erasing": "Mazání", "Error": "Chyba", "Existing firmware erased": "Stávající firmware smazán", + "Failed": "Failed", "Filters": "Filtry", "Firmware": "Firmware", "Firmware build completed": "Firmware sestaven", @@ -61,6 +65,7 @@ "Flashing done": "Zapisování dokončeno", "Flashing EdgeTX": "Zapisování EdgeTX", "Go back": "Zpět", + "In queue": "In queue", "Include pre-releases": "Include pre-releases", "Loading commits...": "Stahuji commity...", "Loading pull requests...": "Stahuji pull requesty...", diff --git a/locales/de/flashing.json b/locales/de/flashing.json index 77bbc62..bedb3ec 100644 --- a/locales/de/flashing.json +++ b/locales/de/flashing.json @@ -4,8 +4,10 @@ "Add new device": "Neues Gerät hinzufügen", "Available devices": "Verfügbare Geräte", "Build": "Build", + "Build finished": "Build finished", "Building": "Baut", "Building firmware with specified configurations": "Bauen von Firmware mit vorgegebenen Konfigurationen", + "Building on server": "Building on server", "Built": "Gebaut", "Cancel": "Abbrechen", "Click here to select firmware file, or drag it here to upload.": "Klicken Sie hier, um die Firmware-Datei auszuwählen, oder ziehen Sie sie zum Hochladen hierher.", @@ -30,6 +32,7 @@ "Could not unlock device: {{message}}": "Could not unlock device: {{message}}", "Could not use firmware": "Firmware konnte nicht verwendet werden", "Could not write new firmware to radio": "Neue Firmware konnte nicht in den Sender geschrieben werden", + "Created": "Created", "Details": "Einzelheiten", "Device firmware may be read protected, preventing updates": "Device firmware may be read protected, preventing updates", "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing": "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing", @@ -47,6 +50,7 @@ "Erasing": "Lösche", "Error": "Fehler", "Existing firmware erased": "Vorhandene Firmware gelöscht", + "Failed": "Failed", "Filters": "Filter", "Firmware": "Firmware", "Firmware build completed": "Firmware-Bau abgeschlossen", @@ -61,6 +65,7 @@ "Flashing done": "Flashen fertig", "Flashing EdgeTX": "Flashe EdgeTX", "Go back": "Zurück", + "In queue": "In queue", "Include pre-releases": "Vorabversionen einbeziehen", "Loading commits...": "Commits werden geladen...", "Loading pull requests...": "Pull-Requests werden geladen...", diff --git a/locales/es/flashing.json b/locales/es/flashing.json index 6c28117..b19c6a8 100644 --- a/locales/es/flashing.json +++ b/locales/es/flashing.json @@ -4,8 +4,10 @@ "Add new device": "Add new device", "Available devices": "Available devices", "Build": "Build", + "Build finished": "Build finished", "Building": "Building", "Building firmware with specified configurations": "Building firmware with specified configurations", + "Building on server": "Building on server", "Built": "Built", "Cancel": "Cancel", "Click here to select firmware file, or drag it here to upload.": "Click here to select firmware file, or drag it here to upload.", @@ -30,6 +32,7 @@ "Could not unlock device: {{message}}": "Could not unlock device: {{message}}", "Could not use firmware": "Could not use firmware", "Could not write new firmware to radio": "Could not write new firmware to radio", + "Created": "Created", "Details": "Details", "Device firmware may be read protected, preventing updates": "Device firmware may be read protected, preventing updates", "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing": "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing", @@ -47,6 +50,7 @@ "Erasing": "Erasing", "Error": "Error", "Existing firmware erased": "Existing firmware erased", + "Failed": "Failed", "Filters": "Filters", "Firmware": "Firmware", "Firmware build completed": "Firmware build completed", @@ -61,6 +65,7 @@ "Flashing done": "Flashing done", "Flashing EdgeTX": "Flashing EdgeTX", "Go back": "Go back", + "In queue": "In queue", "Include pre-releases": "Include pre-releases", "Loading commits...": "Loading commits...", "Loading pull requests...": "Loading pull requests...", diff --git a/locales/fr/flashing.json b/locales/fr/flashing.json index 6c28117..077ce7a 100644 --- a/locales/fr/flashing.json +++ b/locales/fr/flashing.json @@ -102,5 +102,10 @@ "Writing new firmware to radio, this could take several minutes": "Writing new firmware to radio, this could take several minutes", "You may now want to <1>setup your SD Card": "You may now want to <1>setup your SD Card", "You're all set!": "You're all set!", - "Your radio has been flashed with EdgeTX": "Your radio has been flashed with EdgeTX" + "Your radio has been flashed with EdgeTX": "Your radio has been flashed with EdgeTX", + "Created": "Created", + "In queue": "In queue", + "Building on server": "Building on server", + "Build finished": "Build finished", + "Failed": "Failed" } diff --git a/locales/it/flashing.json b/locales/it/flashing.json index 893192b..89624c0 100644 --- a/locales/it/flashing.json +++ b/locales/it/flashing.json @@ -4,8 +4,10 @@ "Add new device": "Aggiungi un nuovo dispositivo", "Available devices": "Dispositivi disponibili", "Build": "Compila", + "Build finished": "Build finished", "Building": "Compilando", "Building firmware with specified configurations": "Compilando il firmware con le configurazioni specificate", + "Building on server": "Building on server", "Built": "Compilato", "Cancel": "Cancella", "Click here to select firmware file, or drag it here to upload.": "Clicca qui per selezionare il file del firmware, o trascianlo qui per caricarlo.", @@ -30,6 +32,7 @@ "Could not unlock device: {{message}}": "Impossibile sbloccare il dispositivo: {{message}}", "Could not use firmware": "Impossibile usare il firmware", "Could not write new firmware to radio": "Impossibile scrivere il nuovo firmware nella radio", + "Created": "Created", "Details": "Dettagli", "Device firmware may be read protected, preventing updates": "Il firmware del dispositivo potrebbe essere protetto in lettura, prevenendo aggiornamenti", "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing": "Dispositivo sbloccato con successo! Rientra in modalità DFU per continuare il flash", @@ -47,6 +50,7 @@ "Erasing": "Cancellando", "Error": "Errore", "Existing firmware erased": "Firmware esistente cancellato", + "Failed": "Failed", "Filters": "Filtri", "Firmware": "Firmware", "Firmware build completed": "Compilamento Firmware completato", @@ -61,6 +65,7 @@ "Flashing done": "Flash completato", "Flashing EdgeTX": "Flash di EdgeTX", "Go back": "Torna", + "In queue": "In queue", "Include pre-releases": "Includi le pre-releases", "Loading commits...": "Carico i commit...", "Loading pull requests...": "Carico le richieste pull...", diff --git a/locales/ru/flashing.json b/locales/ru/flashing.json index cb8fec6..6326ea4 100644 --- a/locales/ru/flashing.json +++ b/locales/ru/flashing.json @@ -4,8 +4,10 @@ "Add new device": "Добавить новое устройство", "Available devices": "Доступные устройства", "Build": "Build", + "Build finished": "Build finished", "Building": "Сборка", "Building firmware with specified configurations": "Создание встроенного программного обеспечения с заданными конфигурациями", + "Building on server": "Building on server", "Built": "Built", "Cancel": "Отменить", "Click here to select firmware file, or drag it here to upload.": "Нажмите здесь, чтобы выбрать файл прошивки, или перетащите его сюда, чтобы загрузить.", @@ -30,6 +32,7 @@ "Could not unlock device: {{message}}": "Не удалось разблокировать устройство: {{сообщение}}", "Could not use firmware": "Не удалось использовать встроенное ПО", "Could not write new firmware to radio": "Не удалось записать новое ПО на радио", + "Created": "Created", "Details": "Детали", "Device firmware may be read protected, preventing updates": "Встроенное ПО устройства может быть защищено от чтения, что предотвращает обновление", "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing": "Устройство успешно разблокировано! Вам нужно будет повторно войти в режим DFU, чтобы продолжить прошивку", @@ -47,6 +50,7 @@ "Erasing": "Удаляется", "Error": "Ошибка", "Existing firmware erased": "Существующее ПО удалено", + "Failed": "Failed", "Filters": "Фильтры", "Firmware": "ПО", "Firmware build completed": "Сборка по завершена", @@ -61,6 +65,7 @@ "Flashing done": "Перепрошивка завершена", "Flashing EdgeTX": "Прошивка EdgeTX", "Go back": "Назад", + "In queue": "In queue", "Include pre-releases": "Включать пре-релизы", "Loading commits...": "Загрузка коминтов...", "Loading pull requests...": "Загрузка запросов на извлечение...", diff --git a/locales/zh/flashing.json b/locales/zh/flashing.json index 78a9a1d..e19e08b 100644 --- a/locales/zh/flashing.json +++ b/locales/zh/flashing.json @@ -4,8 +4,10 @@ "Add new device": "添加新设备", "Available devices": "可用设备", "Build": "构建", + "Build finished": "Build finished", "Building": "正在编译", "Building firmware with specified configurations": "用指定配置编译固件", + "Building on server": "Building on server", "Built": "编译好了", "Cancel": "取消", "Click here to select firmware file, or drag it here to upload.": "单击此处选择固件文件,或将其拖动到这里来上传。", @@ -30,6 +32,7 @@ "Could not unlock device: {{message}}": "无法解锁设备: {{message}}", "Could not use firmware": "无法使用固件", "Could not write new firmware to radio": "无法写入新的固件到遥控器", + "Created": "Created", "Details": "详情", "Device firmware may be read protected, preventing updates": "设备固件可能被读取保护,防止更新", "Device successfully unlocked! You will need to re-enter DFU mode to continue flashing": "设备已成功解锁!您需要重新进入 DFU 模式来继续刷写", @@ -47,6 +50,7 @@ "Erasing": "正在擦除", "Error": "错误", "Existing firmware erased": "已擦除现有固件", + "Failed": "Failed", "Filters": "过滤器", "Firmware": "固件", "Firmware build completed": "固件编译完成", @@ -61,6 +65,7 @@ "Flashing done": "刷写完成", "Flashing EdgeTX": "正在刷写 EdgeTX", "Go back": "返回", + "In queue": "In queue", "Include pre-releases": "包括预发布版本", "Loading commits...": "正在加载 commits...", "Loading pull requests...": "正在加载 pull requests...", diff --git a/src/renderer/components/flashing/FlashBuildStatus.tsx b/src/renderer/components/flashing/FlashBuildStatus.tsx index 10bfb8b..837503b 100644 --- a/src/renderer/components/flashing/FlashBuildStatus.tsx +++ b/src/renderer/components/flashing/FlashBuildStatus.tsx @@ -3,14 +3,18 @@ import React, { useEffect, useState } from "react"; import { JobStatus } from "shared/backend/types"; import { format } from "date-fns"; import type { FlashingBuildStageStatus } from "./FlashJobTimeline"; +import { TFunction, useTranslation } from "react-i18next"; -function jobStatusText(status: JobStatus): string { +function jobStatusText( + status: JobStatus, + t: TFunction<"flashing", undefined> +): string { return { - VOID: "Created", - WAITING_FOR_BUILD: "In queue", - BUILD_IN_PROGRESS: "Building on server", - BUILD_SUCCESS: "Build finished", - BUILD_ERROR: "Failed", + VOID: t("Created"), + WAITING_FOR_BUILD: t("In queue"), + BUILD_IN_PROGRESS: t("Building on server"), + BUILD_SUCCESS: t("Build finished"), + BUILD_ERROR: t("Failed"), }[status]; } @@ -20,6 +24,7 @@ type Props = { const FlashBuildStatus: React.FC = ({ status }) => { const [sinceTime, setSinceTime] = useState(0); + const { t } = useTranslation("flashing"); useEffect(() => { const interval = setInterval(() => { @@ -44,7 +49,7 @@ const FlashBuildStatus: React.FC = ({ status }) => { style={{ transform: "translate(0, 2px)", color: "gray" }} />{" "}

- {jobStatusText(status.jobStatus as JobStatus)} -{" "} + {jobStatusText(status.jobStatus as JobStatus, t)} -{" "} {format(sinceTime * 1000, "mm:ss")}

From 94b2f7c1fb7807993c14be7f8dc1af9a6875f810 Mon Sep 17 00:00:00 2001 From: Riwan Date: Sun, 15 Oct 2023 00:42:39 +0200 Subject: [PATCH 6/8] chores: fix lint issue with import order --- src/renderer/components/flashing/FlashBuildStatus.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/components/flashing/FlashBuildStatus.tsx b/src/renderer/components/flashing/FlashBuildStatus.tsx index 837503b..84dbbd2 100644 --- a/src/renderer/components/flashing/FlashBuildStatus.tsx +++ b/src/renderer/components/flashing/FlashBuildStatus.tsx @@ -2,8 +2,8 @@ import { InfoCircleOutlined } from "@ant-design/icons"; import React, { useEffect, useState } from "react"; import { JobStatus } from "shared/backend/types"; import { format } from "date-fns"; -import type { FlashingBuildStageStatus } from "./FlashJobTimeline"; import { TFunction, useTranslation } from "react-i18next"; +import type { FlashingBuildStageStatus } from "./FlashJobTimeline"; function jobStatusText( status: JobStatus, From 633c60212d970141b25084544d1aef970307fe10 Mon Sep 17 00:00:00 2001 From: Riwan Date: Mon, 16 Oct 2023 16:00:20 +0200 Subject: [PATCH 7/8] fix: use shared delay function --- src/shared/backend/services/cloudbuild.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/shared/backend/services/cloudbuild.ts b/src/shared/backend/services/cloudbuild.ts index cd694af..c4a1867 100644 --- a/src/shared/backend/services/cloudbuild.ts +++ b/src/shared/backend/services/cloudbuild.ts @@ -1,5 +1,6 @@ import ky from "ky"; import { JobStatus } from "shared/backend/types"; +import { delay } from "shared/tools"; type Release = { sha: string; @@ -86,11 +87,6 @@ export const createJob = async (params: JobStatusParams): Promise => { return data as Job; }; -function timeout(ms: number): Promise { - /* eslint-disable-next-line no-promise-executor-return */ - return new Promise((resolve) => setTimeout(resolve, ms)); -} - export const waitForJobSuccess = async ( params: JobStatusParams, updateStatus: (statusData: { @@ -129,7 +125,7 @@ export const waitForJobSuccess = async ( return jobStatus; } - await timeout(iterTime); + await delay(iterTime); } catch (err) { // ignore controller abort error, it's timeout if (err instanceof Error && err.name === "AbortError") { From 60eb3301ae31c9c944988a219a07a4cee229320a Mon Sep 17 00:00:00 2001 From: Riwan Date: Mon, 16 Oct 2023 18:13:07 +0200 Subject: [PATCH 8/8] chores: rename fetchCloudbuild to isCloudBuild --- src/shared/backend/graph/flash/index.ts | 6 +++--- src/shared/backend/services/flashJobs.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/shared/backend/graph/flash/index.ts b/src/shared/backend/graph/flash/index.ts index 4c26d19..8552667 100644 --- a/src/shared/backend/graph/flash/index.ts +++ b/src/shared/backend/graph/flash/index.ts @@ -142,7 +142,7 @@ builder.mutationType({ resolve: async (_, { firmware, deviceId }, context) => { let firmwareData: Buffer | undefined; let firmwareBundleUrl: string | undefined; - let fetchCloudbuild = false; + let isCloudBuild = false; if (firmware.selectedFlags) { // check that all flags are set correctly @@ -153,7 +153,7 @@ builder.mutationType({ throw new GraphQLError("Specified flags are not valid"); } // get firmware on cloudbuild - fetchCloudbuild = true; + isCloudBuild = true; } else if (firmware.version === "local") { // local firmware const localFirmware = context.firmwareStore.getLocalFirmwareById( @@ -214,7 +214,7 @@ builder.mutationType({ // If we already have the firmware we don't need to download // So start the state off assuming no download step let job; - if (fetchCloudbuild) { + if (isCloudBuild) { job = context.flashJobs.createJob( ["connect", "build", "download", "erase", "flash"], { diff --git a/src/shared/backend/services/flashJobs.ts b/src/shared/backend/services/flashJobs.ts index fe68b2c..830dbc7 100644 --- a/src/shared/backend/services/flashJobs.ts +++ b/src/shared/backend/services/flashJobs.ts @@ -53,7 +53,7 @@ export const startExecution = async ( { dfu, firmwareStore, cloudbuild }: Context ): Promise => { let firmwareData = args.firmware.data; - const fetchCloudbuild = !!args.firmware.selectedFlags; + const isCloudBuild = !!args.firmware.selectedFlags; let dfuProcess: WebDFU | undefined; const cleanUp = async (): Promise => { @@ -98,7 +98,7 @@ export const startExecution = async ( completed: true, }); - if (fetchCloudbuild) { + if (isCloudBuild) { updateStageStatus(jobId, "build", { started: true }); const params = {