diff --git a/conda_build/metadata.py b/conda_build/metadata.py index 6c01fbd041..22c191ee75 100644 --- a/conda_build/metadata.py +++ b/conda_build/metadata.py @@ -2228,6 +2228,15 @@ def extract_single_output_text( if not outputs: outputs = [{"name": self.name()}] + if len(output_matches) != len(outputs): + # See https://github.com/conda/conda-build/issues/5571 + utils.get_logger(__name__).warning( + "Number of parsed outputs does not match detected raw metadata blocks. " + "Identified output block may be wrong! " + "If you are using Jinja conditionals to include or exclude outputs, " + "consider using `skip: true # [condition]` instead." + ) + try: if output_type: output_tuples = [ @@ -2250,7 +2259,8 @@ def extract_single_output_text( except ValueError: if not self.path and self.meta.get("extra", {}).get("parent_recipe"): utils.get_logger(__name__).warning( - f"Didn't match any output in raw metadata. Target value was: {output_name}" + "Didn't match any output in raw metadata. Target value was: %s", + output_name, ) output = "" else: diff --git a/news/5601-warn-mismatches b/news/5601-warn-mismatches new file mode 100644 index 0000000000..2dab94aec3 --- /dev/null +++ b/news/5601-warn-mismatches @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* Warn about parsed and raw output block mismatches. This can cause issues with custom build strings, among others. The recommendation is to avoid Jinja flow control to build the output list. Use `skip: true` as necessary. (#5571 via #5601) + +### Deprecations + +* + +### Docs + +* + +### Other + +* diff --git a/tests/test-recipes/metadata/_jinja_outputs/meta.yaml b/tests/test-recipes/metadata/_jinja_outputs/meta.yaml new file mode 100644 index 0000000000..aad25f74f5 --- /dev/null +++ b/tests/test-recipes/metadata/_jinja_outputs/meta.yaml @@ -0,0 +1,60 @@ +package: + name: test_jinja_outputs + version: 1.0 + +outputs: + - name: output1 + build: + script: echo "weeee" + noarch: generic + requirements: + build: + - zlib + host: + - jpeg + run: + - bzip2 + + test: + requires: + - xz + commands: + - echo "steve" + + {% if false %} + - name: output2 + build: + script: echo "weeee" + noarch: generic + requirements: + build: + - zlib + host: + - jpeg + run: + - bzip2 + + test: + requires: + - xz + commands: + - echo "steve" + {% endif %} + + - name: output3 + build: + script: echo "weeee" + noarch: generic + requirements: + build: + - zlib + host: + - jpeg + run: + - bzip2 + + test: + requires: + - xz + commands: + - echo "steve" \ No newline at end of file diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 21f1a5b226..6f5238d9ce 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -708,3 +708,19 @@ def test_parse_until_resolved_missing_jinja_in_spec( ) else: print("did not parse OK!") + + +def test_extract_single_output_text_with_jinja_is_broken(): + """ + Given a recipe with three outputs 1, 2, and 3, where 2 is guarded by a falsy Jinja-if, + MetaData.extract_single_output_text() returns 2 when asked for 3. + + This is a bug that should be fixed. + """ + metadata = MetaData(os.path.join(metadata_dir, "_jinja_outputs")) + output = metadata.extract_single_output_text( + "output3", getattr(metadata, "type", None) + ) + # We of course want to obtain output3, but the buggy behaviour gave us output2. + assert "output3" not in output + assert "output2" in output