diff --git a/src/commands/build/handler.ts b/src/commands/build/handler.ts index d7cd1bca..9c036595 100644 --- a/src/commands/build/handler.ts +++ b/src/commands/build/handler.ts @@ -1,4 +1,5 @@ import Listr from "listr"; +import { Architecture, architectures } from "@dappnode/types"; import { buildAndUpload } from "../../tasks/buildAndUpload/index.js"; import { ListrContextBuild } from "../../types.js"; import { @@ -23,6 +24,7 @@ export async function buildHandler({ variants_dir_name: variantsDirName = defaultVariantsDirName, variants, skip_compose_validation: skipComposeValidation, + arch, // Global options dir = defaultDir, compose_file_name: composeFileName = defaultComposeFileName, @@ -33,6 +35,27 @@ export async function buildHandler({ const variantsDirPath = path.join(dir, variantsDirName); + const architecture = arch ? normalizeArchitecture(arch) : undefined; + + const packagesToBuildProps = getPackagesToBuildProps({ + allVariants: Boolean(allVariants), + commaSeparatedVariants: variants, + rootDir: dir, + variantsDirPath, + composeFileName + }); + + // Filter architectures if --arch flag is provided + if (architecture) { + for (const pkg of packagesToBuildProps) { + if (!pkg.architectures.includes(architecture)) + throw Error( + `Architecture '${architecture}' is not supported by package ${pkg.manifest.name}. Supported: ${pkg.architectures.join(", ")}` + ); + pkg.architectures = [architecture]; + } + } + const buildOptions: BuildAndUploadOptions = { dir, contentProvider, @@ -45,13 +68,7 @@ export async function buildHandler({ deleteOldPins, variantsDirPath, skipComposeValidation, - packagesToBuildProps: getPackagesToBuildProps({ - allVariants: Boolean(allVariants), - commaSeparatedVariants: variants, - rootDir: dir, - variantsDirPath, - composeFileName - }) + packagesToBuildProps }; const verbosityOptions: VerbosityOptions = { @@ -62,3 +79,21 @@ export async function buildHandler({ return await buildTasks.run(); } + +const archShorthands: Record = { + amd64: "linux/amd64", + x86_64: "linux/amd64", + x64: "linux/amd64", + arm64: "linux/arm64", + aarch64: "linux/arm64", + arm: "linux/arm64" +}; + +export function normalizeArchitecture(arch: string): Architecture { + const normalized = archShorthands[arch] ?? arch; + if (!architectures.includes(normalized as Architecture)) + throw Error( + `Invalid architecture '${arch}', allowed values: ${architectures.join(", ")} (or shorthands: ${Object.keys(archShorthands).join(", ")})` + ); + return normalized as Architecture; +} diff --git a/src/commands/build/index.ts b/src/commands/build/index.ts index bf36a861..c56f1018 100644 --- a/src/commands/build/index.ts +++ b/src/commands/build/index.ts @@ -58,6 +58,10 @@ export const build: CommandModule = { alias: "skip-compose-validation", description: `Skip the Dappnode compose validation step`, type: "boolean" + }, + arch: { + description: `Specify the architecture to build for: "linux/amd64" or "linux/arm64"`, + type: "string" } }, diff --git a/src/commands/build/types.ts b/src/commands/build/types.ts index eaa8f813..1c234c92 100644 --- a/src/commands/build/types.ts +++ b/src/commands/build/types.ts @@ -13,6 +13,7 @@ export interface BuildCommandOptions extends CliGlobalOptions { variants?: string; all_variants?: boolean; skip_compose_validation?: boolean; + arch?: string; } export interface VerbosityOptions {