From d1a14f025e343ae54e071e5c5f5641f367f2b0cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:40:42 +0000 Subject: [PATCH 1/4] Initial plan From 511582f71b66dfae62e1372b1f4ec6baf2bef4e3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:44:58 +0000 Subject: [PATCH 2/4] Add final step to fail workflow when linting fails Co-authored-by: thoughtparametersllc <194255310+thoughtparametersllc@users.noreply.github.com> --- .github/workflows/test-action.yml | 64 +++++++++++++++++++++++++++++++ README.md | 17 ++++++++ action.yml | 37 ++++++++++++++++++ 3 files changed, 118 insertions(+) diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index a0a4815..b4325d0 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -310,6 +310,67 @@ jobs: with: python-version: ${{ matrix.python-version }} + # Test that action fails when linting fails + test-failure-behavior: + name: Test Failure Behavior + runs-on: ubuntu-latest + permissions: + contents: write # Need write to test badge commits + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Create badly formatted Python file + run: | + mkdir -p test_project + cat > test_project/bad_code.py << 'EOF' + """Badly formatted Python file to test failure behavior.""" + + def badly_formatted( ): + x=1+2 + y = 3 + 4 + return x+y + + if __name__ == "__main__": + badly_formatted() + EOF + + - name: Run Python Linting (Should Fail) + id: linting + uses: ./ + with: + python-version: '3.11' + black_options: '--check' + generate-badges: 'true' + badges-directory: '.github/test-failure-badges' + update-readme: 'false' + continue-on-error: true + + - name: Verify action failed + run: | + if [ "${{ steps.linting.outcome }}" != "failure" ]; then + echo "❌ Error: Action should have failed but didn't" + echo "Outcome was: ${{ steps.linting.outcome }}" + exit 1 + fi + echo "✓ Action correctly failed when linting failed" + + - name: Verify badges were still generated + run: | + if [ ! -f .github/test-failure-badges/black.svg ]; then + echo "❌ Error: Badges not generated even though they should always be created" + exit 1 + fi + echo "✓ Badges were generated even though linting failed" + + # Verify the badge shows failure status (contains 'failing' text) + if ! grep -q "failing" .github/test-failure-badges/black.svg; then + echo "❌ Error: Badge does not indicate failure" + cat .github/test-failure-badges/black.svg + exit 1 + fi + echo "✓ Badge correctly shows failing status" + # Final summary test-summary: name: Test Summary @@ -324,6 +385,7 @@ jobs: - test-readme-update - test-update-badges-script - test-python-versions + - test-failure-behavior steps: - name: All tests passed run: | @@ -337,3 +399,5 @@ jobs: echo " ✓ README updates" echo " ✓ update_badges.py script" echo " ✓ Multiple Python versions (3.9-3.12)" + echo " ✓ Failure behavior (action fails when linting fails)" + echo " ✓ Badge generation on failure" diff --git a/README.md b/README.md index 1fd894a..5e6fc3b 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,23 @@ When `update-readme` is enabled, the action will automatically insert badge refe ![MyPy](.github/badges/mypy.svg) ``` +## Behavior + +### Failure Handling + +The action is designed to provide comprehensive linting feedback while maintaining proper CI/CD semantics: + +1. **All linting tools always run**: Even if one tool fails, the others will still execute to provide complete feedback +2. **Badges and README are always updated**: Badge generation and README updates happen regardless of linting results, ensuring status badges accurately reflect the current state +3. **The action fails if any linting fails**: After all tools run and badges are updated, the action will fail with a non-zero exit code if any linting tool reported issues +4. **Workflow stops on failure**: When the action fails, subsequent steps in your workflow will not execute (unless they use `if: always()` or `if: failure()`) + +This ensures that: +- You get complete linting feedback in one run +- Status badges are always up-to-date +- Your CI/CD pipeline correctly reports failures +- Failed linting prevents merges when using branch protection rules + ## Inputs | Input | Description | Required | Default | diff --git a/action.yml b/action.yml index 80e9b53..ac24916 100644 --- a/action.yml +++ b/action.yml @@ -253,4 +253,41 @@ runs: shell: bash if: always() + - name: Check linting results and fail if needed + run: | + echo "Checking linting results..." + FAILED=0 + + if [ "${PYLINT_EXIT_CODE:-0}" != "0" ]; then + echo "❌ Pylint failed with exit code ${PYLINT_EXIT_CODE}" + FAILED=1 + else + echo "✓ Pylint passed" + fi + + if [ "${BLACK_EXIT_CODE:-0}" != "0" ]; then + echo "❌ Black failed with exit code ${BLACK_EXIT_CODE}" + FAILED=1 + else + echo "✓ Black passed" + fi + + if [ "${MYPY_EXIT_CODE:-0}" != "0" ]; then + echo "❌ MyPy failed with exit code ${MYPY_EXIT_CODE}" + FAILED=1 + else + echo "✓ MyPy passed" + fi + + if [ "$FAILED" == "1" ]; then + echo "" + echo "❌ Linting failed. Please fix the issues above." + exit 1 + else + echo "" + echo "✅ All linting checks passed!" + fi + shell: bash + if: always() + From 57316c58719dc1f59629501073c79167878ed56f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:48:42 +0000 Subject: [PATCH 3/4] Fix exit code capture using PIPESTATUS instead of $? Co-authored-by: thoughtparametersllc <194255310+thoughtparametersllc@users.noreply.github.com> --- action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index ac24916..f658aa0 100644 --- a/action.yml +++ b/action.yml @@ -81,7 +81,7 @@ runs: - name: Run Pylint run: | pylint ${{ inputs.pylint_options }} --reports=y --jobs=0 . 2>&1 | tee pylint_output.txt - echo "PYLINT_EXIT_CODE=$?" >> $GITHUB_ENV + echo "PYLINT_EXIT_CODE=${PIPESTATUS[0]}" >> $GITHUB_ENV shell: bash if: always() continue-on-error: true @@ -101,7 +101,7 @@ runs: - name: Run Black run: | black --check ${{ inputs.black_options }} . 2>&1 | tee black_output.txt - echo "BLACK_EXIT_CODE=$?" >> $GITHUB_ENV + echo "BLACK_EXIT_CODE=${PIPESTATUS[0]}" >> $GITHUB_ENV shell: bash if: always() continue-on-error: true @@ -121,7 +121,7 @@ runs: - name: Run MyPy run: | mypy ${{ inputs.mypy_options }} . 2>&1 | tee mypy_output.txt - echo "MYPY_EXIT_CODE=$?" >> $GITHUB_ENV + echo "MYPY_EXIT_CODE=${PIPESTATUS[0]}" >> $GITHUB_ENV shell: bash if: always() continue-on-error: true From 8b915394eb8178194c9d48c7bcfaaf9810489936 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Nov 2025 17:45:32 -0800 Subject: [PATCH 4/4] Update action.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index f658aa0..2f18cb4 100644 --- a/action.yml +++ b/action.yml @@ -279,7 +279,7 @@ runs: echo "✓ MyPy passed" fi - if [ "$FAILED" == "1" ]; then + if [ "$FAILED" -eq 1 ]; then echo "" echo "❌ Linting failed. Please fix the issues above." exit 1