Skip to content
This repository was archived by the owner on Nov 23, 2025. It is now read-only.

Conversation

Copy link
Contributor

Copilot AI commented Nov 21, 2025

Adds reusable workflow infrastructure to DRY the Python test workflows by extracting common WSL/non-WSL test steps into parameterized composite actions.

Changes

  • .github/workflows/python-tests-reusable.yml - Reusable workflow accepting matrix as JSON input, delegates to composite actions based on matrix.shell
  • .github/actions/python-tests/test-steps/action.yml - Non-WSL composite action: setup-python, deps, lint, test, conditional coverage upload
  • .github/actions/python-tests/test-steps-wsl/action.yml - WSL composite action: WSL setup, Python install, deps, lint, test, conditional coverage upload
  • .github/workflows/python-tests.yml - Added ci/** to workflow triggers alongside existing copilot/** pattern

Usage

Caller workflows can invoke via:

uses: ./.github/workflows/python-tests-reusable.yml
with:
  matrix: ${{ toJson(matrix-config) }}

Both composite actions accept python-version and os inputs. The reusable workflow's shell defaulting logic routes to the appropriate composite action based on matrix.shell == 'wsl-bash'.

Original prompt

Add a reusable workflow and two composite actions to simplify and DRY the Python test workflows. Create a new branch and open a PR that adds the following files:

Files to add (exact contents):

# Reusable workflow: .github/workflows/python-tests-reusable.yml
# Called by caller workflows via "uses: ./.github/workflows/python-tests-reusable.yml"
on:
  workflow_call:
    inputs:
      matrix:
        required: true
        type: string

jobs:
  test:
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(inputs.matrix) }}
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read

    defaults:
      run:
        shell: ${{ matrix.shell == 'cmd' && 'cmd' || matrix.shell == 'pwsh' && 'pwsh' || matrix.shell == 'wsl-bash' && 'wsl-bash {0}' || 'bash' }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # Delegate all WSL-specific steps into local composite action
      - name: WSL steps (composite)
        if: ${{ matrix.shell == 'wsl-bash' }}
        uses: ./.github/actions/python-tests/test-steps-wsl
        with:
          python-version: ${{ matrix.python-version }}
          os: ${{ matrix.os }}

      # Delegate non-WSL steps into local composite action
      - name: Non-WSL steps (composite)
        if: ${{ matrix.shell != 'wsl-bash' }}
        uses: ./.github/actions/python-tests/test-steps
        with:
          python-version: ${{ matrix.python-version }}
          os: ${{ matrix.os }}
name: "python-tests: non-WSL steps"
description: "Reusable non-WSL steps for tests: setup-python, install deps, lint, test and conditional coverage upload."
inputs:
  python-version:
    description: "Python version to use (e.g. 3.11)"
    required: true
  os:
    description: "OS name from the matrix (e.g. ubuntu-latest) - used for conditional uploads"
    required: true
runs:
  using: "composite"
  steps:
    - name: Set up Python (non-WSL)
      uses: actions/setup-python@v5
      with:
        python-version: ${{ inputs.python-version }}

    - name: Install dependencies (non-WSL)
      run: |
        python -m pip install --upgrade pip setuptools wheel
        pip install -e .
        pip install -r requirements-dev.txt

    - name: Lint (non-WSL)
      run: |
        flake8 src/gitspaces --count --select=E9,F63,F7,F82 --show-source --statistics
        flake8 src/gitspaces --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

    - name: Check code formatting with black (non-WSL)
      run: |
        black --check src/gitspaces tests

    - name: Run tests (non-WSL)
      run: |
        pytest tests/ -v --cov=src/gitspaces --cov-report=xml --cov-report=term

    - name: Upload coverage to Codecov (non-WSL)
      if: ${{ inputs.os == 'ubuntu-latest' && inputs.python-version == '3.11' }}
      uses: codecov/codecov-action@v4
      with:
        file: ./coverage.xml
        flags: unittests
        name: codecov-umbrella
name: "python-tests: WSL steps"
description: "Reusable WSL-specific steps for tests: setup WSL, install Python, install deps, lint, test and conditional coverage upload."
inputs:
  python-version:
    description: "Python version to install/run (e.g. 3.13)"
    required: true
  os:
    description: "OS name from the matrix (e.g. ubuntu-latest) - used for conditional uploads"
    required: true
runs:
  using: "composite"
  steps:
    - name: Set up WSL
      uses: Vampire/setup-wsl@v3
      with:
        distribution: Ubuntu-22.04
        use-cache: false

    - name: Set up Python (WSL)
      shell: wsl-bash {0}
      run: |
        sudo apt-get update
        sudo apt-get install -y software-properties-common
        sudo add-apt-repository -y ppa:deadsnakes/ppa
        sudo apt-get update
        if [ "${{ inputs.python-version }}" = "3.13" ] || [ "${{ inputs.python-version }}" = "3.12" ]; then
          sudo apt-get install -y python${{ inputs.python-version }} python${{ inputs.python-version }}-venv python3-pip python3-setuptools || {
            sudo apt-get install -y python${{ inputs.python-version }} python${{ inputs.python-version }}-venv python3-pip
          }
        else
          sudo apt-get install -y python${{ inputs.python-version }} python${{ inputs.python-version }}-venv python${{ inputs.python-version }}-distutils python3-pip
        fi
        python${{ inputs.python-version }} --version

    - name: Install dependencies (WSL)
      shell: wsl-bash {0}
      run: |
        python${{ inputs.python-version }} -m ensurepip --default-pip 2>/dev/null || true
        python${{ inputs.python-version }} -m pip install --upgrade pip setuptools wheel
        python${{ inputs.python-version }} -m pip install -e .
        python${{ inputs.python-version }} -m pip install -r requirements-dev.txt

    - name: Lint (WSL)
      shel...

</details>

*This pull request was created as a result of the following prompt from Copilot chat.*
> Add a reusable workflow and two composite actions to simplify and DRY the Python test workflows. Create a new branch and open a PR that adds the following files:
> 
> Files to add (exact contents):
> 
> ```yaml name=.github/workflows/python-tests-reusable.yml
> # Reusable workflow: .github/workflows/python-tests-reusable.yml
> # Called by caller workflows via "uses: ./.github/workflows/python-tests-reusable.yml"
> on:
>   workflow_call:
>     inputs:
>       matrix:
>         required: true
>         type: string
> 
> jobs:
>   test:
>     strategy:
>       fail-fast: false
>       matrix: ${{ fromJson(inputs.matrix) }}
>     runs-on: ${{ matrix.os }}
>     permissions:
>       contents: read
> 
>     defaults:
>       run:
>         shell: ${{ matrix.shell == 'cmd' && 'cmd' || matrix.shell == 'pwsh' && 'pwsh' || matrix.shell == 'wsl-bash' && 'wsl-bash {0}' || 'bash' }}
> 
>     steps:
>       - name: Checkout
>         uses: actions/checkout@v4
> 
>       # Delegate all WSL-specific steps into local composite action
>       - name: WSL steps (composite)
>         if: ${{ matrix.shell == 'wsl-bash' }}
>         uses: ./.github/actions/python-tests/test-steps-wsl
>         with:
>           python-version: ${{ matrix.python-version }}
>           os: ${{ matrix.os }}
> 
>       # Delegate non-WSL steps into local composite action
>       - name: Non-WSL steps (composite)
>         if: ${{ matrix.shell != 'wsl-bash' }}
>         uses: ./.github/actions/python-tests/test-steps
>         with:
>           python-version: ${{ matrix.python-version }}
>           os: ${{ matrix.os }}
> ```
> 
> ```yaml name=.github/actions/python-tests/test-steps/action.yml
> name: "python-tests: non-WSL steps"
> description: "Reusable non-WSL steps for tests: setup-python, install deps, lint, test and conditional coverage upload."
> inputs:
>   python-version:
>     description: "Python version to use (e.g. 3.11)"
>     required: true
>   os:
>     description: "OS name from the matrix (e.g. ubuntu-latest) - used for conditional uploads"
>     required: true
> runs:
>   using: "composite"
>   steps:
>     - name: Set up Python (non-WSL)
>       uses: actions/setup-python@v5
>       with:
>         python-version: ${{ inputs.python-version }}
> 
>     - name: Install dependencies (non-WSL)
>       run: |
>         python -m pip install --upgrade pip setuptools wheel
>         pip install -e .
>         pip install -r requirements-dev.txt
> 
>     - name: Lint (non-WSL)
>       run: |
>         flake8 src/gitspaces --count --select=E9,F63,F7,F82 --show-source --statistics
>         flake8 src/gitspaces --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
> 
>     - name: Check code formatting with black (non-WSL)
>       run: |
>         black --check src/gitspaces tests
> 
>     - name: Run tests (non-WSL)
>       run: |
>         pytest tests/ -v --cov=src/gitspaces --cov-report=xml --cov-report=term
> 
>     - name: Upload coverage to Codecov (non-WSL)
>       if: ${{ inputs.os == 'ubuntu-latest' && inputs.python-version == '3.11' }}
>       uses: codecov/codecov-action@v4
>       with:
>         file: ./coverage.xml
>         flags: unittests
>         name: codecov-umbrella
> ```
> 
> ```yaml name=.github/actions/python-tests/test-steps-wsl/action.yml
> name: "python-tests: WSL steps"
> description: "Reusable WSL-specific steps for tests: setup WSL, install Python, install deps, lint, test and conditional coverage upload."
> inputs:
>   python-version:
>     description: "Python version to install/run (e.g. 3.13)"
>     required: true
>   os:
>     description: "OS name from the matrix (e.g. ubuntu-latest) - used for conditional uploads"
>     required: true
> runs:
>   using: "composite"
>   steps:
>     - name: Set up WSL
>       uses: Vampire/setup-wsl@v3
>       with:
>         distribution: Ubuntu-22.04
>         use-cache: false
> 
>     - name: Set up Python (WSL)
>       shell: wsl-bash {0}
>       run: |
>         sudo apt-get update
>         sudo apt-get install -y software-properties-common
>         sudo add-apt-repository -y ppa:deadsnakes/ppa
>         sudo apt-get update
>         if [ "${{ inputs.python-version }}" = "3.13" ] || [ "${{ inputs.python-version }}" = "3.12" ]; then
>           sudo apt-get install -y python${{ inputs.python-version }} python${{ inputs.python-version }}-venv python3-pip python3-setuptools || {
>             sudo apt-get install -y python${{ inputs.python-version }} python${{ inputs.python-version }}-venv python3-pip
>           }
>         else
>           sudo apt-get install -y python${{ inputs.python-version }} python${{ inputs.python-version }}-venv python${{ inputs.python-version }}-distutils python3-pip
>         fi
>         python${{ inputs.python-version }} --version
> 
>     - name: Install dependencies (WSL)
>       shell: wsl-bash {0}
>       run: |
>         python${{ inputs.python-version }} -m ensurepip --default-pip 2>/dev/null || true
>         python${{ inputs.python-version }} -m pip install --upgrade pip setuptools wheel
>         python${{ inputs.python-version }} -m pip install -e .
>         python${{ inputs.python-version }} -m pip install -r requirements-dev.txt
> 
>     - name: Lint (WSL)
>       shell: wsl-bash {0}
>       run: |
>         python${{ inputs.python-version }} -m flake8 src/gitspaces --count --select=E9,F63,F7,F82 --show-source --statistics
>         python${{ inputs.python-version }} -m flake8 src/gitspaces --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
> 
>     - name: Run tests (WSL)
>       shell: wsl-bash {0}
>       run: |
>         python${{ inputs.python-version }} -m pytest tests/ -v --cov=src/gitspaces --cov-report=xml --cov-report=term
> 
>     - name: Upload coverage to Codecov (WSL)
>       if: ${{ inputs.os == 'ubuntu-latest' && inputs.python-version == '3.11' }}
>       uses: codecov/codecov-action@v4
>       with:
>         file: ./coverage.xml
>         flags: unittests
>         name: codecov-umbrella
> ```
> 
> Additional notes for the PR:
> - Branch name: ci/add-python-tests-reusable
> - The reusable workflow delegates WSL vs non-WSL steps to local composite actions stored in .github/actions/python-tests. Each composite action is parameterized by inputs: python-version and os.
> - Caller workflows (python-tests-all.yml and python-tests-3.13.yml) can be left as-is but should call the reusable workflow via uses: ./.github/workflows/python-tests-reusable.yml and pass the matrix input as JSON.
> 
> Please create a branch from main, add these files, commit with message "ci: add reusable python test workflow and composite test-step actions", push the branch, and open a pull request targeting main with title: "Add reusable Python test workflow and composite actions". No assignees.
> 

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/davfive/gitspaces/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.

Co-authored-by: davfive <789595+davfive@users.noreply.github.com>
Copilot AI changed the title [WIP] Add reusable workflow and composite actions for Python tests Add reusable workflow and composite actions for Python tests Nov 21, 2025
Copilot AI requested a review from davfive November 21, 2025 07:03
Copilot finished work on behalf of davfive November 21, 2025 07:03
Copy link
Owner

@davfive davfive left a comment

Choose a reason for hiding this comment

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

requests abstractions

@davfive davfive marked this pull request as ready for review November 21, 2025 07:41
@davfive davfive merged commit c482899 into main Nov 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants