From 1852338eb83500ed0f28178ef86ee724d5385829 Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Sat, 11 Apr 2026 20:38:51 -0400 Subject: [PATCH 1/2] feat: added confirmation prompt to mkosi burn before burning image to device the confirmation prompt runs lsblk to retreive device information and then requests the user types y or yes to proceed and n or no to abort. If the user chooses to proceed, it will continue the burning process as usual, otherwise it prints a message saying the burning process was aborted --- mkosi/burn.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mkosi/burn.py b/mkosi/burn.py index d1233133f5..d89fd70131 100644 --- a/mkosi/burn.py +++ b/mkosi/burn.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later +import logging import os import sys @@ -21,6 +22,25 @@ def run_burn(args: Args, config: Config) -> None: if len(args.cmdline) != 1: die("Expected device argument.") + device = args.cmdline[0] + lsblk_command = [ + "lsblk", + "-o", + "PATH,LABEL,PARTLABEL,FSTYPE,SIZE,HOTPLUG,MOUNTPOINTS", + "--paths", + device, + ] + + logging.info(f"About to burn image to device: {device}") + logging.info("The following block device layout will be overwritten:") + run(lsblk_command) + + sys.stderr.write("Do you want to continue? [y/N] ") + sys.stderr.flush() + reply = sys.stdin.readline().strip().lower() + if reply not in ("y", "yes"): + die("Aborting burning image to device.") + cmd = [ "systemd-repart", "--no-pager", From f1dcb9d470957a4cf081085026008da73b56c201 Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Sun, 12 Apr 2026 14:36:38 -0400 Subject: [PATCH 2/2] feat: added --interactive flag to burn confirmation as requested in PR review 1. Changed reply to use input 2. Registered --interactive in config.py and wrapped the confirmation prompt process to only run when --interactive=true 3. Added relevant tests in test_config.py and updated test_json.py to include interactive arg Co-authored by Claude Code Sonnet 4.6 --- mkosi/burn.py | 14 ++++++-------- mkosi/config.py | 10 ++++++++++ tests/test_config.py | 15 +++++++++++++++ tests/test_json.py | 2 ++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/mkosi/burn.py b/mkosi/burn.py index d89fd70131..bb6697e407 100644 --- a/mkosi/burn.py +++ b/mkosi/burn.py @@ -25,21 +25,19 @@ def run_burn(args: Args, config: Config) -> None: device = args.cmdline[0] lsblk_command = [ "lsblk", - "-o", - "PATH,LABEL,PARTLABEL,FSTYPE,SIZE,HOTPLUG,MOUNTPOINTS", + "-o", "PATH,LABEL,PARTLABEL,FSTYPE,SIZE,HOTPLUG,MOUNTPOINTS", "--paths", device, - ] + ] # fmt: skip logging.info(f"About to burn image to device: {device}") logging.info("The following block device layout will be overwritten:") run(lsblk_command) - sys.stderr.write("Do you want to continue? [y/N] ") - sys.stderr.flush() - reply = sys.stdin.readline().strip().lower() - if reply not in ("y", "yes"): - die("Aborting burning image to device.") + if args.interactive: + reply = input("Do you want to continue? [y/N] ").strip().lower() + if reply not in ("y", "yes"): + die("Aborting burning image to device.") cmd = [ "systemd-repart", diff --git a/mkosi/config.py b/mkosi/config.py index e62091a4f4..af62d75c27 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -1935,6 +1935,7 @@ class Args: json: bool wipe_build_dir: bool rerun_build_scripts: bool + interactive: bool @classmethod def default(cls) -> "Args": @@ -4682,6 +4683,12 @@ def create_argument_parser(chdir: bool = True) -> argparse.ArgumentParser: action="store_true", default=False, ) + parser.add_argument( + "--interactive", + help="Prompt for confirmation before burning the image to a device.", + action="store_true", + default=False, + ) # These can be removed once mkosi v15 is available in LTS distros and compatibility with <= v14 # is no longer needed in build infrastructure (e.g.: OBS). parser.add_argument( @@ -5466,6 +5473,9 @@ def parse_config( if args.rerun_build_scripts and args.force: die("--force cannot be used together with --rerun-build-scripts") + if args.interactive and args.verb != Verb.burn: + die("--interactive can only be used with the 'burn' command") + if args.cmdline and not args.verb.supports_cmdline(): die(f"Arguments after verb are not supported for the '{args.verb}' command") diff --git a/tests/test_config.py b/tests/test_config.py index a3fef072c9..e046278df3 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -544,6 +544,21 @@ def test_parse_load_verb(tmp_path: Path) -> None: parse_config(["invalid"]) +def test_interactive_flag(tmp_path: Path) -> None: + with chdir(tmp_path): + args, _, _ = parse_config(["burn"]) + assert not args.interactive + + args, _, _ = parse_config(["burn", "--interactive"]) + assert args.interactive + + +def test_interactive_only_with_burn(tmp_path: Path) -> None: + with chdir(tmp_path): + with pytest.raises(SystemExit): + parse_config(["build", "--interactive"]) + + def test_os_distribution(tmp_path: Path) -> None: with chdir(tmp_path): for dist in Distribution: diff --git a/tests/test_json.py b/tests/test_json.py index 26f68b14a1..664bc2b680 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -70,6 +70,7 @@ def test_args(path: Optional[Path]) -> None: "Force": 9001, "GenkeyCommonName": "test", "GenkeyValidDays": "100", + "Interactive": false, "Json": false, "Pager": true, "RerunBuildScripts": true, @@ -92,6 +93,7 @@ def test_args(path: Optional[Path]) -> None: force=9001, genkey_common_name="test", genkey_valid_days="100", + interactive=False, json=False, pager=True, rerun_build_scripts=True,