Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Github action now reports state of execution #3531 #3531

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@

<!-- For example, Docker, GitHub Actions, pre-commit, editors -->

- GitHub Action: adds 2 action outputs to report changes that can be used in other
steps. Outputs: `is-formatted` and `changed-files` (#3531)

### Documentation

<!-- Major changes to documentation and policies. Small docs changes
Expand Down
7 changes: 7 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ inputs:
description: 'Python Version specifier (PEP440) - e.g. "21.5b1"'
required: false
default: ""
outputs:
is-formatted:
description: "Files checked are formatted to the current black formatter style."
value: steps
changed-files:
description: "Number of files black changed"
value: steps
branding:
color: "black"
icon: "check-circle"
Expand Down
27 changes: 25 additions & 2 deletions action/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import shlex
import sys
from pathlib import Path
from re import MULTILINE, search
from subprocess import PIPE, STDOUT, run

ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
GITHUB_OUTPUT = Path(os.environ["GITHUB_OUTPUT"])
ENV_PATH = ACTION_PATH / ".black-env"
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
Expand All @@ -13,6 +15,10 @@
BLACK_ARGS = os.getenv("INPUT_BLACK_ARGS", default="")
VERSION = os.getenv("INPUT_VERSION", default="")

_is_formatted_re = r"\s?(?P<changed-files>[0-9]+)\sfiles?\sreformatted(\.|,)\s?"

_outputs = {"is-formatted": "false", "changed-files": "0"}

run([sys.executable, "-m", "venv", str(ENV_PATH)], check=True)

version_specifier = VERSION
Expand All @@ -38,8 +44,25 @@
base_cmd = [str(ENV_BIN / "black")]
if BLACK_ARGS:
# TODO: remove after a while since this is deprecated in favour of SRC + OPTIONS.
proc = run([*base_cmd, *shlex.split(BLACK_ARGS)])
proc = run([*base_cmd, *shlex.split(BLACK_ARGS)], stderr=PIPE)
else:
proc = run([*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)])
proc = run(
[*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)],
stderr=PIPE
)
# Re-emit stderr back to console so that action output is visible to pipeline
# Do note, click will strip terminal control codes if the output is not TTY
# and thus, this will not show colors anymore.
print(proc.stderr, file=sys.stderr, flush=True)
Copy link
Author

@rasjani rasjani Jan 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im still wondering if i should proc.stderr should match sys.stdout.encoding ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and to give a bit of background, character encoding on github runners with windows as os, is reported to be cp1252 while ubuntu and macos default to utf-8 .. enforcing utf-8 on subprocess.run() feels dirty if the output is going back to windows runner ..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, using sys.stdout.encoding is prob the better thing to do

  • Is there a sys.stderr.encoding? - I just know all our output will always be utf8 compliant ...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I did miss this swallowing of the output, it's prob better to not encode @ subprocess (like you had it - sorry) and only decode for the regex and reprint the raw bytes. That might preserve the colors etc. too


_output = proc.stderr.decode("utf-8")
matches = search(_is_formatted_re, _output, MULTILINE)
if matches:
_outputs["is-formatted"] = "true"
_outputs["changed-files"] = str(matches.group("changed-files"))

with GITHUB_OUTPUT.open("a+", encoding="utf-8") as f:
for k, v in _outputs.items():
f.write(f"{k}={v}\n")

sys.exit(proc.returncode)
40 changes: 40 additions & 0 deletions docs/integrations/github_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,43 @@ If you want to match versions covered by Black's
src: "./src"
version: "~= 22.0"
```

## Outputs

This action will output two variables for further processing of changes black has made
against `src` set.

### `is-formatted`

Defaults to `"false"`, set to `"true"` if black changed any files.

### `changed-files`

Defaults to `"0"`, set to string representation of integer value of how many files black
modified.

### Usage

One could use either of these output variables to further have conditional steps within
the same pipeline, like creating a pull request after black has done changes to the code
base.

```yaml
- uses: psf/black@stable
with:
options: "--verbose"
src: "./src"
id: "action_black"

- name: Create Pull Request
if: steps.action_black.outputs.is-formatted == 'true'
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "Format Python code with psf/black push"
commit-message: ":art: Format Python code with psf/black"
body: |
There appear to be some python formatting errors in ${{ github.sha }}. This pull request
uses the [psf/black](https://github.com/psf/black) formatter to fix these issues.
base: ${{ github.head_ref }} # Creates pull request onto pull request or commit branch
```