-
Notifications
You must be signed in to change notification settings - Fork 0
Fix action failure behavior and exit code capture #13
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
Conversation
Co-authored-by: thoughtparametersllc <194255310+thoughtparametersllc@users.noreply.github.com>
Co-authored-by: thoughtparametersllc <194255310+thoughtparametersllc@users.noreply.github.com>
thoughtparametersllc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Failure condition doesn't work correctly here is the log. Please correct and submit your changes.
Prepare all required actions
Getting action download info
Download action repository 'actions/setup-python@v6' (SHA:e797f83bcb11b83ae66e0230d6156d7c80228e7c)
Run ./
Run actions/setup-python@v6
Installed versions
Run pip3 install pylint black mypy
Collecting pylint
Downloading pylint-4.0.2-py3-none-any.whl.metadata (12 kB)
Collecting black
Downloading black-25.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (85 kB)
Collecting mypy
Downloading mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (2.2 kB)
Collecting astroid<=4.1.dev0,>=4.0.1 (from pylint)
Downloading astroid-4.0.2-py3-none-any.whl.metadata (4.4 kB)
Collecting dill>=0.3.6 (from pylint)
Downloading dill-0.4.0-py3-none-any.whl.metadata (10 kB)
Collecting isort!=5.13,<8,>=5 (from pylint)
Downloading isort-7.0.0-py3-none-any.whl.metadata (11 kB)
Collecting mccabe<0.8,>=0.6 (from pylint)
Downloading mccabe-0.7.0-py2.py3-none-any.whl.metadata (5.0 kB)
Collecting platformdirs>=2.2 (from pylint)
Downloading platformdirs-4.5.0-py3-none-any.whl.metadata (12 kB)
Collecting tomlkit>=0.10.1 (from pylint)
Downloading tomlkit-0.13.3-py3-none-any.whl.metadata (2.8 kB)
Collecting click>=8.0.0 (from black)
Downloading click-8.3.0-py3-none-any.whl.metadata (2.6 kB)
Collecting mypy-extensions>=0.4.3 (from black)
Downloading mypy_extensions-1.1.0-py3-none-any.whl.metadata (1.1 kB)
Collecting packaging>=22.0 (from black)
Downloading packaging-25.0-py3-none-any.whl.metadata (3.3 kB)
Collecting pathspec>=0.9.0 (from black)
Downloading pathspec-0.12.1-py3-none-any.whl.metadata (21 kB)
Collecting pytokens>=0.3.0 (from black)
Downloading pytokens-0.3.0-py3-none-any.whl.metadata (2.0 kB)
Collecting typing_extensions>=4.6.0 (from mypy)
Downloading typing_extensions-4.15.0-py3-none-any.whl.metadata (3.3 kB)
Downloading pylint-4.0.2-py3-none-any.whl (536 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 536.0/536.0 kB 5.4 MB/s 0:00:00
Downloading astroid-4.0.2-py3-none-any.whl (276 kB)
Downloading isort-7.0.0-py3-none-any.whl (94 kB)
Downloading mccabe-0.7.0-py2.py3-none-any.whl (7.3 kB)
Downloading black-25.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.6 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 9.3 MB/s 0:00:00
Downloading mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (13.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.2/13.2 MB 24.9 MB/s 0:00:00
Downloading click-8.3.0-py3-none-any.whl (107 kB)
Downloading dill-0.4.0-py3-none-any.whl (119 kB)
Downloading mypy_extensions-1.1.0-py3-none-any.whl (5.0 kB)
Downloading packaging-25.0-py3-none-any.whl (66 kB)
Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)
Downloading platformdirs-4.5.0-py3-none-any.whl (18 kB)
Downloading pytokens-0.3.0-py3-none-any.whl (12 kB)
Downloading tomlkit-0.13.3-py3-none-any.whl (38 kB)
Downloading typing_extensions-4.15.0-py3-none-any.whl (44 kB)
Installing collected packages: typing_extensions, tomlkit, pytokens, platformdirs, pathspec, packaging, mypy-extensions, mccabe, isort, dill, click, astroid, pylint, mypy, black
Successfully installed astroid-4.0.2 black-25.11.0 click-8.3.0 dill-0.4.0 isort-7.0.0 mccabe-0.7.0 mypy-1.18.2 mypy-extensions-1.1.0 packaging-25.0 pathspec-0.12.1 platformdirs-4.5.0 pylint-4.0.2 pytokens-0.3.0 tomlkit-0.13.3 typing_extensions-4.15.0
Run pylint --reports=y --jobs=0 . 2>&1 | tee pylint_output.txt
************* Module update_badges
update_badges.py:47:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:55:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:76:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:80:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:83:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:93:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:101:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:110:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:137:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:141:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:145:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:151:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:155:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:159:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:163:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:197:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:199:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:205:0: C0301: Line too long (113/100) (line-too-long)
update_badges.py:207:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:215:0: C0303: Trailing whitespace (trailing-whitespace)
update_badges.py:28:4: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)
update_badges.py:84:4: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)
update_badges.py:119:4: W0613: Unused argument 'badge_position' (unused-argument)
update_badges.py:11:0: W0611: Unused import re (unused-import)
************* Module test_project.bad_code
test_project/bad_code.py:3:0: C0116: Missing function or method docstring (missing-function-docstring)
Report
90 statements analysed.
Statistics by type
+---------+-------+-----------+-----------+------------+---------+
|type |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module |2 |NC |NC |100.00 |0.00 |
+---------+-------+-----------+-----------+------------+---------+
|class |0 |NC |NC |0 |0 |
+---------+-------+-----------+-----------+------------+---------+
|method |0 |NC |NC |0 |0 |
+---------+-------+-----------+-----------+------------+---------+
|function |6 |NC |NC |83.33 |0.00 |
+---------+-------+-----------+-----------+------------+---------+
233 lines have been analyzed
Raw metrics
+----------+-------+------+---------+-----------+
|type |number |% |previous |difference |
+==========+=======+======+=========+===========+
|code |128 |54.94 |NC |NC |
+----------+-------+------+---------+-----------+
|docstring |54 |23.18 |NC |NC |
+----------+-------+------+---------+-----------+
|comment |17 |7.30 |NC |NC |
+----------+-------+------+---------+-----------+
|empty |34 |14.59 |NC |NC |
+----------+-------+------+---------+-----------+
Duplication
+-------------------------+------+---------+-----------+
| |now |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines |0 |NC |NC |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |NC |NC |
+-------------------------+------+---------+-----------+
Messages by category
+-----------+-------+---------+-----------+
|type |number |previous |difference |
+===========+=======+=========+===========+
|convention |21 |NC |NC |
+-----------+-------+---------+-----------+
|refactor |2 |NC |NC |
+-----------+-------+---------+-----------+
|warning |2 |NC |NC |
+-----------+-------+---------+-----------+
|error |0 |NC |NC |
+-----------+-------+---------+-----------+
% errors / warnings by module
+----------------------+------+--------+---------+-----------+
|module |error |warning |refactor |convention |
+======================+======+========+=========+===========+
|update_badges |0.00 |100.00 |100.00 |95.24 |
+----------------------+------+--------+---------+-----------+
|test_project.bad_code |0.00 |0.00 |0.00 |4.76 |
+----------------------+------+--------+---------+-----------+
Messages
+---------------------------+------------+
|message id |occurrences |
+===========================+============+
|trailing-whitespace |19 |
+---------------------------+------------+
|no-else-return |2 |
+---------------------------+------------+
|unused-import |1 |
+---------------------------+------------+
|unused-argument |1 |
+---------------------------+------------+
|missing-function-docstring |1 |
+---------------------------+------------+
|line-too-long |1 |
+---------------------------+------------+
Your code has been rated at 7.22/10
Error: Process completed with exit code 28.
Run echo "## Pylint 🎉" >> $GITHUB_STEP_SUMMARY
Run black --check --check . 2>&1 | tee black_output.txt
would reformat /home/runner/work/python-linting/python-linting/test_project/bad_code.py
would reformat /home/runner/work/python-linting/python-linting/update_badges.py
Oh no! 💥 💔 💥
2 files would be reformatted.
Error: Process completed with exit code 1.
Run echo "## Black 🎉" >> $GITHUB_STEP_SUMMARY
Run mypy . 2>&1 | tee mypy_output.txt
Success: no issues found in 2 source files
Run echo "## MyPy 🎉" >> $GITHUB_STEP_SUMMARY
Run if [ "true" == "true" ]; then
✓ Generated SVG badges in .github/test-failure-badges
Run if [ "false" == "true" ]; then
Run if [ "true" == "true" ] || [ "false" == "true" ]; then
[detached HEAD bd8ce62] Update linting badges [skip ci]
3 files changed, 60 insertions(+)
create mode 100644 .github/test-failure-badges/black.svg
create mode 100644 .github/test-failure-badges/mypy.svg
create mode 100644 .github/test-failure-badges/pylint.svg
fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)
state now, use
git push origin HEAD:<name-of-remote-branch>
⚠ Warning: Failed to push changes. This may be due to insufficient permissions or a merge conflict.
Please ensure the workflow has write permissions to the repository.
Run echo "Checking linting results..."
Checking linting results...
✓ Pylint passed
✓ Black passed
✓ MyPy passed
✅ All linting checks passed!
0s
Run if [ "success" != "failure" ]; then
if [ "success" != "failure" ]; then
echo "❌ Error: Action should have failed but didn't"
echo "Outcome was: success"
exit 1
fi
echo "✓ Action correctly failed when linting failed"
shell: /usr/bin/bash -e {0}
env:
pythonLocation: /opt/hostedtoolcache/Python/3.11.14/x64
PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.11.14/x64/lib/pkgconfig
Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.14/x64
Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.14/x64
Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.14/x64
LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.11.14/x64/lib
MYPY_EXIT_CODE: 0
❌ Error: Action should have failed but didn't
Outcome was: success
Error: Process completed with exit code 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a critical bug where the python-linting action was not failing workflows when linting tools reported errors. The root cause was twofold: exit codes were captured from tee instead of the linting tools using $?, and there was no final validation step to fail the action based on those exit codes.
Key changes:
- Changed exit code capture from
$?to${PIPESTATUS[0]}for pylint, black, and mypy to correctly capture the linting tool's exit code instead oftee's - Added a final validation step that checks all exit codes and fails with exit 1 if any linting tool failed
- Added "Behavior" section to README documenting the failure handling semantics
- Added
test-failure-behaviorjob to verify the action fails correctly while still generating badges
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| action.yml | Fixed exit code capture using ${PIPESTATUS[0]} for all three linting tools and added final validation step to fail the action if any tool failed |
| README.md | Added documentation explaining the action's failure handling behavior and workflow execution semantics |
| .github/workflows/test-action.yml | Added comprehensive test job to verify the action fails when linting fails and badges are still generated |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Description
The action was not failing workflows when linting failed due to two bugs: (1) exit codes were never checked after linting steps, and (2)
$?capturedtee's exit code instead of the linting tool's.Type of Change
Related Issue
Fixes #(issue number from problem statement)
Changes Made
Core fixes:
$?to${PIPESTATUS[0]}in all linting steps (pylint, black, mypy)if: always()to ensure it executes after badge/README updatesDocumentation:
Testing:
test-failure-behaviorjob that verifies action fails correctly and badges still generateTechnical detail:
The final check step:
Changelog
[Unreleased]sectionTesting
Documentation
Security
Checklist
Additional Notes
Badge generation and README updates already had
if: always()so they continue to run regardless of linting results. The fix ensures the action still fails the workflow after these steps complete, maintaining proper CI/CD semantics while preserving accurate status reporting.Original prompt
This section details on the original issue you should resolve
<issue_title>[Bug]: Action does not fail on lint error and badges/README are not updated</issue_title>
<issue_description>### Bug Description
The python-linting action does not fail the whole workflow when any step in the linting process fails. Furthermore, when a lint step fails, the badge and README.md are not updated or committed as expected. Both behaviors need to be fixed to maintain accurate status reporting and badge integrity.
Steps to Reproduce
Expected Behavior
Actual Behavior
Action Version
v0.0.8
Python Version
3.10
Runner OS
ubuntu-latest
Workflow Configuration
Relevant Logs
Run thoughtparametersllc/python-linting@v0.0.8 with: python-version: 3.10 requirements-file: dev-requirements.txt pylint_options: --max-line-length=120 black_options: --line-length 120 mypy_options: --strict generate-badges: true badges-directory: .github/badges update-readme: true readme-path: README.md badge-style: path Run actions/setup-python@v6 Installed versions Run pip3 install pylint black mypy Collecting pylint Downloading pylint-4.0.2-py3-none-any.whl.metadata (12 kB) Collecting black Downloading black-25.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (85 kB) Collecting mypy Downloading mypy-1.18.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (2.2 kB) Collecting astroid<=4.1.dev0,>=4.0.1 (from pylint) Downloading astroid-4.0.2-py3-none-any.whl.metadata (4.4 kB) Collecting dill>=0.2 (from pylint) Downloading dill-0.4.0-py3-none-any.whl.metadata (10 kB) Collecting isort!=5.13,<8,>=5 (from pylint) Downloading isort-7.0.0-py3-none-any.whl.metadata (11 kB) Collecting mccabe<0.8,>=0.6 (from pylint) Downloading mccabe-0.7.0-py2.py3-none-any.whl.metadata (5.0 kB) Collecting platformdirs>=2.2 (from pylint) Downloading platformdirs-4.5.0-py3-none-any.whl.metadata (12 kB) Collecting tomli>=1.1 (from pylint) Downloading tomli-2.3.0-py3-none-any.whl.metadata (10 kB) Collecting tomlkit>=0.10.1 (from pylint) Downloading tomlkit-0.13.3-py3-none-any.whl.metadata (2.8 kB) Collecting typing-extensions>=4 (from astroid<=4.1.dev0,>=4.0.1->pylint) Downloading typing_extensions-4.15.0-py3-none-any.whl.metadata (3.3 kB) Collecting click>=8.0.0 (from black) Downloading click-8.3.0-py3-none-any.whl.metadata (2.6 kB) Collecting mypy-extensions>=0.4.3 (from black) Downloading mypy_extensions-1.1.0-py3-none-any.whl.metadata (1.1 kB) Collecting packaging>=22.0 (from black) Downloading packaging-25.0-py3-none-any.whl.metadata (3.3 kB) Collecting pathspec>=0.9.0 (from black) Downloading pathspec-0.12.1-py3-none-any.whl.metadata (21 kB) Collecting pytokens>=0.3.0 (from black) Downloading pytokens-0.3.0-py3-none-any.whl.metadata (2.0 kB) Downloading pylint-4.0.2-py3-none-any.whl (536 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 536.0/536.0 kB 56.5 MB/s 0:00:00 Downloading astroid-4.0.2-py3-none-any.whl (276 kB) Downloading isort-7.0.0-py3-none-any.whl (94 kB) Downloading mccabe-0.7.0-py2.py3-none-any.whl (7.3 kB) Downloading black-25.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.7 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.7/1.7 MB 39.1 MB/s 0:00:00 Downloading mypy-1.18.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (13.2 MB) ━━━━━... </details> - Fixes thoughtparametersllc/python-linting#12 <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/thoughtparametersllc/python-linting/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.