Repository: ansible/ansible-builder

Issue:
Error when building an EE without requirements.yml
The behaviour of #290 appears to have returned again:

execution-image.yml
```
---
version: 3

images:
  base_image:
    name: quay.io/centos/centos:stream9

dependencies:
    ansible_core:
        package_pip: ansible-core==2.15.0
    ansible_runner:
        package_pip: ansible-runner==2.3.2
    galaxy: requirements.yml

additional_build_files:
    - src: files/ansible.cfg
      dest: configs

additional_build_steps:
    prepend_final:
        - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg

options:
    package_manager_path: /usr/bin/microdnf
```

requirements.yml
```
---
collections: []
```
Error:
```
Error: building at STEP "COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg": checking on sources under [...] copier: stat: "/_build/configs/ansible.cfg": no such file or directory
```

Discussion:

Patch:
diff --git a/src/ansible_builder/containerfile.py b/src/ansible_builder/containerfile.py
index c0c7051..6a516d5 100644
--- a/src/ansible_builder/containerfile.py
+++ b/src/ansible_builder/containerfile.py
@@ -434,6 +434,10 @@ class Containerfile:
             # in the final image.
             env = "ANSIBLE_GALAXY_DISABLE_GPG_VERIFY=1 "
 
+        # If nothing actually gets installed, make sure this directory will exist
+        # to prevent the COPY step from failing later.
+        self.steps.append(f"RUN mkdir -p {os.path.dirname(constants.base_collections_path.rstrip('/'))}")
+
         self.steps.append(
             f"RUN ansible-galaxy role install $ANSIBLE_GALAXY_CLI_ROLE_OPTS "
             f"-r {constants.STD_GALAXY_FILENAME}"


Test patch:
diff --git a/test/data/v3/empty_galaxy_reqs/execution-environment.yml b/test/data/v3/empty_galaxy_reqs/execution-environment.yml
new file mode 100644
index 0000000..bafb6ab
--- /dev/null
+++ b/test/data/v3/empty_galaxy_reqs/execution-environment.yml
@@ -0,0 +1,16 @@
+version: 3
+
+images:
+  base_image:
+    name: quay.io/centos/centos:stream9
+
+dependencies:
+  ansible_core:
+    package_pip: ansible-core
+  ansible_runner:
+    package_pip: ansible-runner
+  galaxy:
+    collections: []
+
+options:
+  package_manager_path: '/bin/true'
diff --git a/test/integration/test_build.py b/test/integration/test_build.py
index ed82b23..2e6b70e 100644
--- a/test/integration/test_build.py
+++ b/test/integration/test_build.py
@@ -282,3 +282,19 @@ def test_extra_build_cli_args(cli, runtime, data_dir, ee_tag, tmp_path):
                  allow_error=True)
 
     assert secret_string in result.stdout
+
+
+@pytest.mark.test_all_runtimes
+def test_empty_galaxy_requirements(cli, runtime, data_dir, ee_tag, tmp_path):
+    """
+    Make sure empty galaxy requirements do not cause the build to fail.
+
+    Bug fix for issues #290 and #641
+    """
+    ee_def = data_dir / 'v3' / 'empty_galaxy_reqs' / 'execution-environment.yml'
+
+    result = cli(f'ansible-builder build --no-cache -c {tmp_path} -f {ee_def} -t {ee_tag} '
+                 f'--container-runtime {runtime} -v 3 ',
+                 allow_error=True)
+
+    assert result.rc == 0
diff --git a/test/unit/test_containerfile.py b/test/unit/test_containerfile.py
index 5cf37cb..aeaae75 100644
--- a/test/unit/test_containerfile.py
+++ b/test/unit/test_containerfile.py
@@ -1,3 +1,5 @@
+import os
+
 from ansible_builder import constants
 from ansible_builder.containerfile import Containerfile
 from ansible_builder.user_definition import UserDefinition
@@ -50,6 +52,7 @@ def test_prepare_galaxy_install_steps(build_dir_and_ee_yml):
     c = make_containerfile(tmpdir, ee_path)
     c._prepare_galaxy_install_steps()
     expected = [
+        f"RUN mkdir -p {os.path.dirname(constants.base_collections_path.rstrip('/'))}",
         f"RUN ansible-galaxy role install $ANSIBLE_GALAXY_CLI_ROLE_OPTS "
         f"-r {constants.STD_GALAXY_FILENAME} --roles-path \"{constants.base_roles_path}\"",
         f"RUN ANSIBLE_GALAXY_DISABLE_GPG_VERIFY=1 ansible-galaxy collection install "
@@ -68,6 +71,7 @@ def test_prepare_galaxy_install_steps_with_keyring(build_dir_and_ee_yml):
     c = make_containerfile(tmpdir, ee_path, galaxy_keyring=constants.default_keyring_name)
     c._prepare_galaxy_install_steps()
     expected = [
+        f"RUN mkdir -p {os.path.dirname(constants.base_collections_path.rstrip('/'))}",
         f"RUN ansible-galaxy role install $ANSIBLE_GALAXY_CLI_ROLE_OPTS "
         f"-r {constants.STD_GALAXY_FILENAME} --roles-path \"{constants.base_roles_path}\"",
         f"RUN ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS "
@@ -89,6 +93,7 @@ def test_prepare_galaxy_install_steps_with_sigcount(build_dir_and_ee_yml):
                            galaxy_required_valid_signature_count=sig_count)
     c._prepare_galaxy_install_steps()
     expected = [
+        f"RUN mkdir -p {os.path.dirname(constants.base_collections_path.rstrip('/'))}",
         f"RUN ansible-galaxy role install $ANSIBLE_GALAXY_CLI_ROLE_OPTS "
         f"-r {constants.STD_GALAXY_FILENAME} --roles-path \"{constants.base_roles_path}\"",
         f"RUN ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS "
@@ -111,6 +116,7 @@ def test_prepare_galaxy_install_steps_with_ignore_code(build_dir_and_ee_yml):
                            galaxy_ignore_signature_status_codes=codes)
     c._prepare_galaxy_install_steps()
     expected = [
+        f"RUN mkdir -p {os.path.dirname(constants.base_collections_path.rstrip('/'))}",
         f"RUN ansible-galaxy role install $ANSIBLE_GALAXY_CLI_ROLE_OPTS "
         f"-r {constants.STD_GALAXY_FILENAME} --roles-path \"{constants.base_roles_path}\"",
         f"RUN ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS "