Repository: ansible/ansible-builder

Issue:
empty `build-arg` passthru is broken
The custom `--build-arg` splitter logic in the builder CLI doesn't properly preserve args with an empty value; they are conflated with args without a value. eg:

```
ansible-builder build --build-arg PKGMGR_PRESERVE_CACHE=
```

should force an empty value, but since the trailing `=` is dropped by the splitter logic (`BuildArgAction` in `cli.py`), once passed to the underlying build CLI, it leaves the existing value (if any) or enables it to come from the environment.

Need to update the splitter logic to support preserving empty strings, as well as only splitting on the first `=`. 

Discussion:
nitzmahone: Can also probably fix #520 easily in this same PR while you're "in the neighborhood" :wink: 


Patch:
diff --git a/docs/usage.rst b/docs/usage.rst
index 5033b02..e9f37c6 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -142,6 +142,12 @@ By default, the Containerfile / Dockerfile outputted by Ansible Builder contains
 
    $ ansible-builder build --build-arg FOO=bar
 
+To use different build arguments, you can specify ``--build-arg`` multiple times:
+
+.. code::
+
+   $ ansible-builder build --build-arg FOO=bar --build-arg SIMPLE=sample
+
 To use a custom base image:
 
 .. code::
@@ -249,7 +255,7 @@ Examples
 
 The example in ``test/data/pytz`` requires the ``awx.awx`` collection in
 the execution environment definition. The lookup plugin
-``awx.awx.tower_schedule_rrule`` requires the PyPI ``pytz`` and another
+``awx.awx.schedule_rrule`` requires the PyPI ``pytz`` and another
 library to work. If ``test/data/pytz/execution-environment.yml`` file is
 given to the ``ansible-builder build`` command, then it will install the
 collection inside the image, read ``requirements.txt`` inside of the
@@ -269,7 +275,7 @@ the private data directory.
 
 The ``awx.awx`` collection is a subset of content included in the default
 AWX execution environment. More details can be found at the
-`awx-ee <https://github.com/ansible/awx-ee>`__ repository.
+`awx-ee <https://github.com/ansible/awx-ee>`_ repository.
 
 
 Deprecated Features
diff --git a/src/ansible_builder/cli.py b/src/ansible_builder/cli.py
index 367949d..4f4e3e1 100644
--- a/src/ansible_builder/cli.py
+++ b/src/ansible_builder/cli.py
@@ -202,13 +202,15 @@ def parse_args(args=sys.argv[1:]):
 
 class BuildArgAction(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
-        key, *value = values.split('=')
+        key, sep, value = values.partition("=")
         attr = getattr(namespace, self.dest)
 
         # None signifies that the build-arg will come from the environment.
         # This is currently only supported by Docker. Podman will treat any
         # usage of the $VALUE as a literal string.
         if value:
-            attr[key] = value[0]
+            attr[key] = value
+        elif sep == '=' and value == '':
+            attr[key] = ''
         else:
             attr[key] = None


Test patch:
diff --git a/test/unit/test_cli.py b/test/unit/test_cli.py
index 7eb5be0..f759b5c 100644
--- a/test/unit/test_cli.py
+++ b/test/unit/test_cli.py
@@ -38,6 +38,36 @@ def test_custom_ansible_galaxy_cli_role_opts(exec_env_definition_file, tmp_path)
     assert aee.build_args == {'ANSIBLE_GALAXY_CLI_ROLE_OPTS': '--ignore-errors'}
 
 
+def test_build_args_empty_value(exec_env_definition_file, tmp_path):
+    content = {'version': 3}
+    path = str(exec_env_definition_file(content=content))
+
+    aee = prepare(['build', '-f', path, '--build-arg', 'ANSIBLE_GALAXY_CLI_ROLE_OPTS=', '-c', str(tmp_path)])
+    assert aee.build_args == {'ANSIBLE_GALAXY_CLI_ROLE_OPTS': ''}
+
+
+def test_build_args_no_trailing_equal(exec_env_definition_file, tmp_path):
+    content = {'version': 3}
+    path = str(exec_env_definition_file(content=content))
+
+    aee = prepare(['build', '-f', path, '--build-arg', 'ANSIBLE_GALAXY_CLI_ROLE_OPTS', '-c', str(tmp_path)])
+    assert aee.build_args == {'ANSIBLE_GALAXY_CLI_ROLE_OPTS': None}
+
+
+def test_build_args_multiple_equal_sign_value(exec_env_definition_file, tmp_path):
+    content = {'version': 3}
+    path = str(exec_env_definition_file(content=content))
+
+    aee = prepare(['build', '-f', path,
+                   '--build-arg', 'ANSIBLE_GALAXY_CLI_ROLE_OPTS=',
+                   '--build-arg', 'PYTHON_CONFIG_SETTINGS=--config-setting=--global-option=--tag-build=SUFFIX',
+                   '-c', str(tmp_path)])
+    assert aee.build_args == {
+        'PYTHON_CONFIG_SETTINGS': '--config-setting=--global-option=--tag-build=SUFFIX',
+        'ANSIBLE_GALAXY_CLI_ROLE_OPTS': ''
+    }
+
+
 def test_build_context(good_exec_env_definition_path, tmp_path):
     path = str(good_exec_env_definition_path)
     build_context = str(tmp_path)