Repository: py-cov-action/python-coverage-comment-action (python)

Issue:
GitHub Actions set-output is deprecated
https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter

We need to change our way of setting an output value.

```python
if settings.OUTPUT_FILE:
    with open(settings.OUTPUT_FILE, "a") as f:
        f.write("a=b")
```

Pull request:
Use environment files instead of `set-output`
Closes #83

Patch:
diff --git a/coverage_comment/github.py b/coverage_comment/github.py
index be21db0..e322d89 100644
--- a/coverage_comment/github.py
+++ b/coverage_comment/github.py
@@ -153,6 +153,8 @@ def post_comment(
             raise CannotPostComment from exc
 
 
-def set_output(**kwargs: bool) -> None:
-    for key, value in kwargs.items():
-        print(f"::set-output name={key}::{json.dumps(value)}")
+def set_output(github_output: pathlib.Path, **kwargs: bool) -> None:
+    if github_output:
+        with github_output.open("a") as f:
+            for key, value in kwargs.items():
+                f.write(f"{key}={json.dumps(value)}\n")
diff --git a/coverage_comment/main.py b/coverage_comment/main.py
index 93b1d78..64d5fac 100644
--- a/coverage_comment/main.py
+++ b/coverage_comment/main.py
@@ -162,10 +162,12 @@ def generate_comment(
             filename=config.COMMENT_FILENAME,
             content=comment,
         )
-        github.set_output(COMMENT_FILE_WRITTEN=True)
+        github.set_output(github_output=config.GITHUB_OUTPUT, COMMENT_FILE_WRITTEN=True)
         log.debug("Comment stored locally on disk")
     else:
-        github.set_output(COMMENT_FILE_WRITTEN=False)
+        github.set_output(
+            github_output=config.GITHUB_OUTPUT, COMMENT_FILE_WRITTEN=False
+        )
         log.debug("Comment not generated")
 
     return 0
diff --git a/coverage_comment/settings.py b/coverage_comment/settings.py
index 667cf79..4673747 100644
--- a/coverage_comment/settings.py
+++ b/coverage_comment/settings.py
@@ -35,6 +35,7 @@ class Config:
     COVERAGE_DATA_BRANCH: str = "python-coverage-comment-action-data"
     COMMENT_ARTIFACT_NAME: str = "python-coverage-comment-action"
     COMMENT_FILENAME: pathlib.Path = pathlib.Path("python-coverage-comment-action.txt")
+    GITHUB_OUTPUT: pathlib.Path | None = None
     MINIMUM_GREEN: float = 100.0
     MINIMUM_ORANGE: float = 70.0
     MERGE_COVERAGE_FILES: bool = False
@@ -71,6 +72,10 @@ class Config:
     def clean_comment_filename(cls, value: str) -> pathlib.Path:
         return path_below(value)
 
+    @classmethod
+    def clean_github_output(cls, value: str) -> pathlib.Path:
+        return pathlib.Path(value)
+
     @property
     def GITHUB_PR_NUMBER(self) -> int | None:
         # "refs/pull/2/merge"


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index 29d9048..2746276 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -385,3 +385,11 @@ def git():
     git = Git()
     yield git
     assert not git.expected_calls
+
+
+@pytest.fixture
+def output_file(tmp_path):
+    file = tmp_path / "temp_output.txt"
+    file.touch()
+
+    return file
diff --git a/tests/integration/test_github.py b/tests/integration/test_github.py
index ea632aa..50404ad 100644
--- a/tests/integration/test_github.py
+++ b/tests/integration/test_github.py
@@ -288,7 +288,7 @@ def test_post_comment__update_error(gh, session):
         )
 
 
-def test_set_output(capsys):
-    github.set_output(foo=True)
-    captured = capsys.readouterr()
-    assert captured.out.strip() == "::set-output name=foo::true"
+def test_set_output(output_file):
+    github.set_output(github_output=output_file, foo=True)
+
+    assert output_file.read_text() == "foo=true\n"
diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py
index c3e9e7d..13d3184 100644
--- a/tests/integration/test_main.py
+++ b/tests/integration/test_main.py
@@ -83,7 +83,7 @@ def integration_env(integration_dir, write_file, run_coverage):
 
 
 def test_action__pull_request__store_comment(
-    pull_request_config, session, in_integration_env, capsys
+    pull_request_config, session, in_integration_env, output_file
 ):
     # No existing badge in this test
     session.register(
@@ -111,7 +111,7 @@ def test_action__pull_request__store_comment(
     )(status_code=403)
 
     result = main.action(
-        config=pull_request_config(),
+        config=pull_request_config(GITHUB_OUTPUT=output_file),
         github_session=session,
         http_session=session,
         git=None,
@@ -131,12 +131,13 @@ def test_action__pull_request__store_comment(
         in comment
     )
 
-    expected_stdout = "::set-output name=COMMENT_FILE_WRITTEN::true"
-    assert capsys.readouterr().out.strip() == expected_stdout
+    expected_output = "COMMENT_FILE_WRITTEN=true\n"
+
+    assert output_file.read_text() == expected_output
 
 
 def test_action__pull_request__post_comment(
-    pull_request_config, session, in_integration_env, capsys
+    pull_request_config, session, in_integration_env, output_file
 ):
     payload = json.dumps({"coverage": 30.00})
     # There is an existing badge in this test, allowing to test the coverage evolution
@@ -169,7 +170,7 @@ def test_action__pull_request__post_comment(
     )
 
     result = main.action(
-        config=pull_request_config(),
+        config=pull_request_config(GITHUB_OUTPUT=output_file),
         github_session=session,
         http_session=session,
         git=None,
@@ -179,12 +180,13 @@ def test_action__pull_request__post_comment(
     assert not pathlib.Path("python-coverage-comment-action.txt").exists()
     assert "The coverage rate went from `30%` to `86%` :arrow_up:" in comment
 
-    expected_stdout = "::set-output name=COMMENT_FILE_WRITTEN::false"
-    assert capsys.readouterr().out.strip() == expected_stdout
+    expected_output = "COMMENT_FILE_WRITTEN=false\n"
+
+    assert output_file.read_text() == expected_output
 
 
 def test_action__pull_request__force_store_comment(
-    pull_request_config, session, in_integration_env, capsys
+    pull_request_config, session, in_integration_env, output_file
 ):
     payload = json.dumps({"coverage": 30.00})
     # There is an existing badge in this test, allowing to test the coverage evolution
@@ -194,7 +196,7 @@ def test_action__pull_request__force_store_comment(
     )(json={"content": base64.b64encode(payload.encode()).decode()})
 
     result = main.action(
-        config=pull_request_config(FORCE_WORKFLOW_RUN=True),
+        config=pull_request_config(FORCE_WORKFLOW_RUN=True, GITHUB_OUTPUT=output_file),
         github_session=session,
         http_session=session,
         git=None,
@@ -203,8 +205,9 @@ def test_action__pull_request__force_store_comment(
 
     assert pathlib.Path("python-coverage-comment-action.txt").exists()
 
-    expected_stdout = "::set-output name=COMMENT_FILE_WRITTEN::true"
-    assert capsys.readouterr().out.strip() == expected_stdout
+    expected_output = "COMMENT_FILE_WRITTEN=true\n"
+
+    assert output_file.read_text() == expected_output
 
 
 def test_action__pull_request__post_comment__no_marker(
diff --git a/tests/unit/test_settings.py b/tests/unit/test_settings.py
index b693c7f..e482a28 100644
--- a/tests/unit/test_settings.py
+++ b/tests/unit/test_settings.py
@@ -28,6 +28,7 @@ def test_config__from_environ__ok():
             "GITHUB_TOKEN": "foo",
             "GITHUB_REPOSITORY": "owner/repo",
             "GITHUB_REF": "master",
+            "GITHUB_OUTPUT": "foo.txt",
             "GITHUB_EVENT_NAME": "pull",
             "GITHUB_PR_RUN_ID": "123",
             "COMMENT_ARTIFACT_NAME": "baz",
@@ -45,6 +46,7 @@ def test_config__from_environ__ok():
         GITHUB_TOKEN="foo",
         GITHUB_REPOSITORY="owner/repo",
         GITHUB_REF="master",
+        GITHUB_OUTPUT=pathlib.Path("foo.txt"),
         GITHUB_EVENT_NAME="pull",
         GITHUB_PR_RUN_ID=123,
         COMMENT_ARTIFACT_NAME="baz",
@@ -67,6 +69,7 @@ def config():
         "GITHUB_REPOSITORY": "owner/repo",
         "GITHUB_REF": "master",
         "GITHUB_EVENT_NAME": "pull",
+        "GITHUB_OUTPUT": "",
         "GITHUB_PR_RUN_ID": 123,
         "COMMENT_ARTIFACT_NAME": "baz",
         "COMMENT_FILENAME": pathlib.Path("qux"),