From 168ad08e73abe517691087b606c2f41425d0dc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 10:21:17 +0200 Subject: [PATCH 1/9] feat: Add additional_build_args support --- firestarter/cli/parser.py | 8 ++++++++ firestarter/common/firestarter_workflow.py | 5 +++++ .../workflows/build_images/build_images.py | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/firestarter/cli/parser.py b/firestarter/cli/parser.py index 4b4b238f..48f90ac4 100644 --- a/firestarter/cli/parser.py +++ b/firestarter/cli/parser.py @@ -22,15 +22,19 @@ def main(): arg_parser.add_argument('workflow', type=str, help='Name of the workflow to run') arg_parser.add_argument('--vars', type=str, help='Variables to pass to the workflow, in inline table toml format. Example: --vars=\'vars = { var1= "value1", var2= "value2"}\'') arg_parser.add_argument('--secrets', type=str, help='Secrets to pass to the workflow, in inline table toml format. Example: --secrets=\'secrets = { secret1= "foo", secret2= "bar"}\'') + arg_parser.add_argument('--additional_build_args', type=str, help='Additional build_args to pass to the workflow, in inline table toml format. Example: --additional_build_args=\'additional_build_args = { build_arg1= "arg1", build_arg2= "arg2"}\'') arg_parser.add_argument('--config_file', type=str, help='Optional configuration file for the workflow, located in the repository') args = arg_parser.parse_args() input_vars = os.environ.get("INPUT_VARS", None) input_secrets = os.environ.get("INPUT_SECRETS", None) + input_additional_build_args = os.environ.get("INPUT_ADDITIONAL_BUILD_ARGS", None) input_config_file = os.environ.get("INPUT_CONFIG_FILE", None) vars = tomllib.loads(input_vars) if input_vars is not None else {} secrets = tomllib.loads(input_secrets) if input_secrets is not None else {} + additional_build_args =\ + tomllib.loads(input_additional_build_args) if input_additional_build_args is not None else {} config_file = input_config_file if input_config_file is not None else args.config_file if args.vars: @@ -39,6 +43,9 @@ def main(): if args.secrets: secrets.update(tomllib.loads(args.secrets).get("secrets")) logger.debug(f"Inline secrets: {secrets}") + if args.additional_build_args: + additional_build_args.update(tomllib.loads(args.additional_build_args).get("additional_build_args")) + logger.debug(f"Inline additional_build_args: {additional_build_args}") # Import the workflow module from the workflow name workflow = importlib.import_module(f"firestarter.workflows.{args.workflow}") @@ -46,6 +53,7 @@ def main(): result = workflow.run( vars=vars, secrets=secrets, + additional_build_args=additional_build_args, config_file=config_file, ) diff --git a/firestarter/common/firestarter_workflow.py b/firestarter/common/firestarter_workflow.py index 628610a1..7786efb3 100644 --- a/firestarter/common/firestarter_workflow.py +++ b/firestarter/common/firestarter_workflow.py @@ -4,6 +4,7 @@ def __init__(self, **kwargs) -> None: self._config_file = kwargs.get('config_file', None) self._vars = kwargs.get('vars', None) self._secrets = kwargs.get('secrets', None) + self._additional_build_args = kwargs.get('additional_build_args', None) self.__validate_required_vars() def __validate_required_vars(self): @@ -23,6 +24,10 @@ def config_file(self): def vars(self): return self._vars + @property + def additional_build_args(self): + return self._additional_build_args + @property def secrets(self): return self._secrets diff --git a/firestarter/workflows/build_images/build_images.py b/firestarter/workflows/build_images/build_images.py index 10016775..6f11e9b5 100644 --- a/firestarter/workflows/build_images/build_images.py +++ b/firestarter/workflows/build_images/build_images.py @@ -378,6 +378,16 @@ async def compile_images_for_all_flavors(self): f"Using these secrets for all flavors: {self.secrets.keys()}" ) + build_args_for_all_flavors = [] + for key, value in self.additional_build_args.items(): + build_args_for_all_flavors.append( + dagger.BuildArg(name=key, value=value) + ) + + logger.info( + f"Using these build_args for all flavors: {self.additional_build_args.keys()}" + ) + for flavor in self.flavors: registry, full_repo_name, build_args,\ dockerfile, extra_registries,\ @@ -416,6 +426,9 @@ async def compile_images_for_all_flavors(self): for key, value in build_args.items() ] + # Combine generic and custom build_args for this flavor + full_build_args = build_args_for_all_flavors + build_args_list + resolved_secret_refs = self.resolve_secrets( self.config.images[flavor].secrets or {} ) @@ -471,7 +484,7 @@ async def compile_images_for_all_flavors(self): for image in registry_list: await self.compile_image_and_publish( client, - build_args_list, + full_build_args, secrets, dockerfile, image, From 07487cb6592d6cb025efde0ae9df7338ca27788e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 10:31:57 +0200 Subject: [PATCH 2/9] fix: Tests --- firestarter/tests/test_build_images_functionality.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firestarter/tests/test_build_images_functionality.py b/firestarter/tests/test_build_images_functionality.py index 60171782..45c9a281 100644 --- a/firestarter/tests/test_build_images_functionality.py +++ b/firestarter/tests/test_build_images_functionality.py @@ -29,6 +29,7 @@ "platforms": "linux/amd64,linux/arm64", } secrets = {} +additional_build_args = {} config_file_path = f"{os.path.dirname(os.path.realpath(__file__))}/fixtures/build_images.yaml" with open(config_file_path, 'r') as config_file: @@ -57,7 +58,10 @@ def reset_builder_value() -> None: global builder builder = BuildImages( - vars=vars, secrets=secrets, config_file=config_file_path + vars=vars, + secrets=secrets, + additional_build_args=additional_build_args, + config_file=config_file_path ) From b6b47b79879080e3e1b926e387d7264736b2afa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 11:07:30 +0200 Subject: [PATCH 3/9] fix: Add missing param --- firestarter/workflows/build_images/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/firestarter/workflows/build_images/__init__.py b/firestarter/workflows/build_images/__init__.py index 0f5b10da..a18eb722 100644 --- a/firestarter/workflows/build_images/__init__.py +++ b/firestarter/workflows/build_images/__init__.py @@ -4,9 +4,14 @@ logger = logging.getLogger(__name__) -def run(*, vars: dict, secrets: dict, config_file:str): +def run(*, vars: dict, secrets: dict, additional_build_args: dict, config_file:str): try: - wf = BuildImages(vars=vars, secrets=secrets, config_file=config_file) + wf = BuildImages( + vars=vars, + secrets=secrets, + additional_build_args=additional_build_args, + config_file=config_file + ) return wf.execute() except Exception as e: logger.exception("Fatal error encountered during BuildImages execution.") From 9efaf587df0b5d4103eed2677456c7d00b9bae46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 14:18:04 +0200 Subject: [PATCH 4/9] fix: Test new way of passing cmd secrets --- firestarter/cli/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firestarter/cli/parser.py b/firestarter/cli/parser.py index 48f90ac4..a145b1d4 100644 --- a/firestarter/cli/parser.py +++ b/firestarter/cli/parser.py @@ -41,7 +41,7 @@ def main(): vars.update(tomllib.loads(args.vars).get("vars")) logger.debug(f"Inline vars: {vars}") if args.secrets: - secrets.update(tomllib.loads(args.secrets).get("secrets")) + secrets.update(tomllib.loads(args.secrets)) logger.debug(f"Inline secrets: {secrets}") if args.additional_build_args: additional_build_args.update(tomllib.loads(args.additional_build_args).get("additional_build_args")) From 719a03d7eb2b3123d47d901cea845616c364468f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 14:23:12 +0200 Subject: [PATCH 5/9] fix: Test new way of passing cmd secrets --- firestarter/cli/parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/firestarter/cli/parser.py b/firestarter/cli/parser.py index a145b1d4..3723e3b6 100644 --- a/firestarter/cli/parser.py +++ b/firestarter/cli/parser.py @@ -41,6 +41,7 @@ def main(): vars.update(tomllib.loads(args.vars).get("vars")) logger.debug(f"Inline vars: {vars}") if args.secrets: + args.secrets = f"secrets = {args.secrets}" secrets.update(tomllib.loads(args.secrets)) logger.debug(f"Inline secrets: {secrets}") if args.additional_build_args: From 24035c83b3cfc2441454a7b3819fb25f5d74b5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 14:30:31 +0200 Subject: [PATCH 6/9] fix: Test new way of passing cmd secrets --- firestarter/cli/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firestarter/cli/parser.py b/firestarter/cli/parser.py index 3723e3b6..6f8483d5 100644 --- a/firestarter/cli/parser.py +++ b/firestarter/cli/parser.py @@ -42,7 +42,7 @@ def main(): logger.debug(f"Inline vars: {vars}") if args.secrets: args.secrets = f"secrets = {args.secrets}" - secrets.update(tomllib.loads(args.secrets)) + secrets.update(tomllib.loads(args.secrets).get("secrets")) logger.debug(f"Inline secrets: {secrets}") if args.additional_build_args: additional_build_args.update(tomllib.loads(args.additional_build_args).get("additional_build_args")) From 776addaf0224f1360df78e03da6b05ba100e8a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 15:03:05 +0200 Subject: [PATCH 7/9] fix: Simplified command line argument format --- firestarter/cli/parser.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/firestarter/cli/parser.py b/firestarter/cli/parser.py index 6f8483d5..9267b4fe 100644 --- a/firestarter/cli/parser.py +++ b/firestarter/cli/parser.py @@ -20,9 +20,9 @@ def main(): arg_parser = argparse.ArgumentParser() arg_parser.add_argument('workflow', type=str, help='Name of the workflow to run') - arg_parser.add_argument('--vars', type=str, help='Variables to pass to the workflow, in inline table toml format. Example: --vars=\'vars = { var1= "value1", var2= "value2"}\'') - arg_parser.add_argument('--secrets', type=str, help='Secrets to pass to the workflow, in inline table toml format. Example: --secrets=\'secrets = { secret1= "foo", secret2= "bar"}\'') - arg_parser.add_argument('--additional_build_args', type=str, help='Additional build_args to pass to the workflow, in inline table toml format. Example: --additional_build_args=\'additional_build_args = { build_arg1= "arg1", build_arg2= "arg2"}\'') + arg_parser.add_argument('--vars', type=str, help='Variables to pass to the workflow, in inline table toml format. Example: --vars=\'{ var1= "value1", var2= "value2"}\'') + arg_parser.add_argument('--secrets', type=str, help='Secrets to pass to the workflow, in inline table toml format. Example: --secrets=\'{ secret1= "foo", secret2= "bar"}\'') + arg_parser.add_argument('--additional_build_args', type=str, help='Additional build_args to pass to the workflow, in inline table toml format. Example: --additional_build_args=\'{ build_arg1= "arg1", build_arg2= "arg2"}\'') arg_parser.add_argument('--config_file', type=str, help='Optional configuration file for the workflow, located in the repository') args = arg_parser.parse_args() @@ -38,6 +38,7 @@ def main(): config_file = input_config_file if input_config_file is not None else args.config_file if args.vars: + args.vars = f"vars = {args.vars}" vars.update(tomllib.loads(args.vars).get("vars")) logger.debug(f"Inline vars: {vars}") if args.secrets: @@ -45,6 +46,7 @@ def main(): secrets.update(tomllib.loads(args.secrets).get("secrets")) logger.debug(f"Inline secrets: {secrets}") if args.additional_build_args: + args.additional_build_args = f"additional_build_args = {args.additional_build_args}" additional_build_args.update(tomllib.loads(args.additional_build_args).get("additional_build_args")) logger.debug(f"Inline additional_build_args: {additional_build_args}") From 89032f27634cd61b955b8b374bbbb5be37143ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 15:09:38 +0200 Subject: [PATCH 8/9] fix: Improved command help --- firestarter/cli/parser.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firestarter/cli/parser.py b/firestarter/cli/parser.py index 9267b4fe..e1e35657 100644 --- a/firestarter/cli/parser.py +++ b/firestarter/cli/parser.py @@ -20,9 +20,9 @@ def main(): arg_parser = argparse.ArgumentParser() arg_parser.add_argument('workflow', type=str, help='Name of the workflow to run') - arg_parser.add_argument('--vars', type=str, help='Variables to pass to the workflow, in inline table toml format. Example: --vars=\'{ var1= "value1", var2= "value2"}\'') - arg_parser.add_argument('--secrets', type=str, help='Secrets to pass to the workflow, in inline table toml format. Example: --secrets=\'{ secret1= "foo", secret2= "bar"}\'') - arg_parser.add_argument('--additional_build_args', type=str, help='Additional build_args to pass to the workflow, in inline table toml format. Example: --additional_build_args=\'{ build_arg1= "arg1", build_arg2= "arg2"}\'') + arg_parser.add_argument('--vars', type=str, help='Variables to pass to the workflow, as an inline toml format dict. Example: --vars=\'{ var1= "value1", var2= "value2"}\'') + arg_parser.add_argument('--secrets', type=str, help='Secrets to pass to the workflow, as an inline toml format dict. Example: --secrets=\'{ secret1= "foo", secret2= "bar"}\'') + arg_parser.add_argument('--additional_build_args', type=str, help='Additional build_args to pass to the workflow, as an inline toml format dict. Example: --additional_build_args=\'{ build_arg1= "arg1", build_arg2= "arg2"}\'') arg_parser.add_argument('--config_file', type=str, help='Optional configuration file for the workflow, located in the repository') args = arg_parser.parse_args() From 905769cbb46c5bc99236b15e0e265bf052845499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20V=C3=A1zquez=20Gil?= Date: Tue, 28 Apr 2026 16:27:41 +0200 Subject: [PATCH 9/9] fix: Updated README --- firestarter/workflows/build_images/README.md | 17 ++++++++++++++++- .../workflows/build_images/build_images.py | 10 ++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/firestarter/workflows/build_images/README.md b/firestarter/workflows/build_images/README.md index 3d1c9c6c..b58bc7fe 100644 --- a/firestarter/workflows/build_images/README.md +++ b/firestarter/workflows/build_images/README.md @@ -26,7 +26,7 @@ Beyond the configuration file which is mandatory, there are some other extra var Additionally there are some optional variables: * `container_structure_filename`: path of the [container-structure-test](https://github.com/GoogleContainerTools/container-structure-test) filename (if not set, no tests are checked) - + > Highly recommended! ⚠️ * `publish`: publish the docker image to the registry @@ -44,6 +44,21 @@ RUN --mount=type=secret,id=github_token,dst=/run/secrets/github_token \ > Remember to make sure the secret key name and secret id are the same + +## Additional build args + +In addition to those found in the configuration file, additional build args may be set using the command line argument `--additional-build-args` or via the `INPUT_ADDITIONAL_BUILD_ARGS` environment variable. These values can then be used in the Dockerfile, for example: + +```Dockerfile +ARG YOUR_BUILD_ARG +ENV YOUR_BUILD_ARG=$YOUR_BUILD_ARG + +RUN echo "The additional build arg is: $YOUR_BUILD_ARG" +``` + +> [!WARNING] +> Secrets and build args set in the configuration file will overwrite those set via the command line or environment variables. + ## Example 1. Create a repository that uses run-dagger-py (check [docs](https://github.com/prefapp/run-dagger-py/blob/main/docs/index.md) for more details). diff --git a/firestarter/workflows/build_images/build_images.py b/firestarter/workflows/build_images/build_images.py index 6f11e9b5..554e42bd 100644 --- a/firestarter/workflows/build_images/build_images.py +++ b/firestarter/workflows/build_images/build_images.py @@ -427,6 +427,11 @@ async def compile_images_for_all_flavors(self): ] # Combine generic and custom build_args for this flavor + # (Order matters: the args added in the second array will + # overwrite the ones with the same name in the first array. + # In this case, args defined in the flavor configuration will + # overwrite the same args defined as command line arguments + # or environment variables) full_build_args = build_args_for_all_flavors + build_args_list resolved_secret_refs = self.resolve_secrets( @@ -446,6 +451,11 @@ async def compile_images_for_all_flavors(self): flavor_secrets.append(client.set_secret(key, value)) # Combine generic and custom secrets for this flavor + # (Order matters: the secrets added in the second array will + # overwrite the ones with the same name in the first array. + # In this case, secretss defined in the flavor configuration + # will overwrite the same secrets defined as command line + # arguments or environment variables) secrets = secrets_for_all_flavors + flavor_secrets # Set the address for the default registry