From f22cda78eeda0ae7269cb356091aef25c3472aa5 Mon Sep 17 00:00:00 2001 From: Jaspar Stach Date: Thu, 8 Feb 2024 15:10:49 +0100 Subject: [PATCH] Add: `multiline_output` for github actions --- pontos/github/actions/core.py | 32 +++++++++++++++++++++++++++++++ tests/github/actions/test_core.py | 21 ++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/pontos/github/actions/core.py b/pontos/github/actions/core.py index 337b7bdbe..7bc614fd6 100644 --- a/pontos/github/actions/core.py +++ b/pontos/github/actions/core.py @@ -4,6 +4,7 @@ # import os +import uuid from contextlib import contextmanager from io import TextIOWrapper from pathlib import Path @@ -287,6 +288,37 @@ def output(name: str, value: SupportsStr): with Path(output_filename).open("a", encoding="utf8") as f: f.write(f"{name}={value}\n") + @staticmethod + def multiline_output(name: str, value: SupportsStr): + """ + Set an multiline action output + + An action output can be consumed by another job + + Example: + .. code-block:: python + + from pontos.github.actions import ActionIO + + ActionIO.output("foo", "bar") + + Args: + name: Name of the output variable + value: Value of the output variable + """ + output_filename = os.environ.get("GITHUB_OUTPUT") + if not output_filename: + raise GitHubActionsError( + "GITHUB_OUTPUT environment variable not set. Can't write " + "action output." + ) + + with Path(output_filename).open("a", encoding="utf8") as f: + delimiter = uuid.uuid1() + f.write(f"{name}<<{delimiter}") + f.write(f"{value}") + f.write(str(delimiter)) + @staticmethod def input(name: str, default: Optional[str] = None) -> Optional[str]: """ diff --git a/tests/github/actions/test_core.py b/tests/github/actions/test_core.py index c0a18db6e..b30587503 100644 --- a/tests/github/actions/test_core.py +++ b/tests/github/actions/test_core.py @@ -107,6 +107,27 @@ def test_output(self): self.assertEqual(output, "foo=bar\nlorem=ipsum\n") + @patch("uuid.uuid1") + def test_multiline_output(self, uuid_mock): + deadbeef = "deadbeef" + name = "foo" + ml_string = """bar +baz +boing""" + expected_output = f"{name}<<{deadbeef}{ml_string}{deadbeef}" + uuid_mock.return_value = deadbeef + with temp_directory() as temp_dir: + file_path = temp_dir / "github.output" + + with patch.dict( + "os.environ", {"GITHUB_OUTPUT": str(file_path)}, clear=True + ): + ActionIO.multiline_output("foo", ml_string) + + output = file_path.read_text(encoding="utf8") + + self.assertEqual(output, expected_output) + @patch.dict("os.environ", {}, clear=True) def test_output_no_env(self): with self.assertRaises(GitHubActionsError):