feat: solve 49. Group Anagrams with unit testing #29
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Presubmit (Python) | |
| on: # yamllint disable-line rule:truthy | |
| pull_request: | |
| branches: ["main"] | |
| jobs: | |
| build-python: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ["3.10"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Fetch full history for git diff | |
| - name: Detect changed Python files | |
| id: detect-changes | |
| run: | | |
| # Get list of changed files | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| # For PR, compare with base branch | |
| CHANGED_FILES=$(git diff --name-only \ | |
| ${{ github.event.pull_request.base.sha }}..HEAD) | |
| else | |
| # For push, compare with previous commit | |
| if [ "${{ github.event.before }}" = \ | |
| "0000000000000000000000000000000000000000" ]; then | |
| # First commit in repo | |
| CHANGED_FILES=$(git diff --name-only --diff-filter=A HEAD) | |
| else | |
| CHANGED_FILES=$(git diff --name-only \ | |
| ${{ github.event.before }}..HEAD) | |
| fi | |
| fi | |
| echo "All changed files:" | |
| echo "$CHANGED_FILES" | |
| # Filter for Python files only | |
| CHANGED_PYTHON_FILES=$(echo "$CHANGED_FILES" | \ | |
| grep '\.py$' || true) | |
| # Filter for Python files specifically in the problems directory | |
| CHANGED_PYTHON_PROBLEMS_FILES=$(echo "$CHANGED_PYTHON_FILES" | \ | |
| grep -E '^problems/' || true) | |
| # Extract unique problem directories from changed Python files | |
| CHANGED_PROBLEMS=$(echo "$CHANGED_PYTHON_PROBLEMS_FILES" | \ | |
| grep -E '^problems/[^/]+/' | cut -d'/' -f2 | \ | |
| sort -u | tr '\n' ' ' || true) | |
| # Check if requirements.txt or Python-related config files changed | |
| PYTHON_CONFIG_CHANGES=$(echo "$CHANGED_FILES" | \ | |
| grep -E '(requirements\.txt|setup\.py|pyproject\.toml)$' || true) | |
| echo "Changed Python files:" | |
| echo "$CHANGED_PYTHON_FILES" | |
| echo "Changed Python files in problems/:" | |
| echo "$CHANGED_PYTHON_PROBLEMS_FILES" | |
| echo "Changed problems: $CHANGED_PROBLEMS" | |
| echo "Python config changes: $PYTHON_CONFIG_CHANGES" | |
| # Set outputs | |
| echo "changed_problems=$CHANGED_PROBLEMS" >> $GITHUB_OUTPUT | |
| echo "has_python_changes=$([ -n "$CHANGED_PYTHON_PROBLEMS_FILES" ] && \ | |
| echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "has_python_config_changes=$([ -n "$PYTHON_CONFIG_CHANGES" ] && \ | |
| echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "should_run_all_tests=$([ -n "$PYTHON_CONFIG_CHANGES" ] && \ | |
| echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| - name: Set up Python ${{ matrix.python-version }} | |
| if: > | |
| steps.detect-changes.outputs.has_python_changes == 'true' || | |
| steps.detect-changes.outputs.has_python_config_changes == 'true' | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: "pip" | |
| - name: Install dependencies | |
| if: > | |
| steps.detect-changes.outputs.has_python_changes == 'true' || | |
| steps.detect-changes.outputs.has_python_config_changes == 'true' | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Lint Python code | |
| if: steps.detect-changes.outputs.has_python_changes == 'true' | |
| run: make lint-python | |
| - name: Run Python tests for changed problems | |
| if: > | |
| steps.detect-changes.outputs.changed_problems != '' && | |
| steps.detect-changes.outputs.should_run_all_tests == 'false' | |
| run: | | |
| PROBLEMS="${{ steps.detect-changes.outputs.changed_problems }}" | |
| echo "Running tests for changed problems: $PROBLEMS" | |
| for problem in $PROBLEMS; do | |
| echo "Testing problem: $problem" | |
| # Convert snake_case to kebab-case for make target | |
| kebab_case=$(echo "$problem" | sed 's/_/-/g') | |
| make test-py:$kebab_case || exit 1 | |
| done | |
| - name: Run all Python tests (dependencies changed) | |
| if: steps.detect-changes.outputs.should_run_all_tests == 'true' | |
| run: | | |
| echo "Running all tests due to Python configuration changes" | |
| make test-py:all | |
| - name: Summary | |
| if: always() | |
| run: | | |
| echo "## Test Summary" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ steps.detect-changes.outputs.has_python_changes }}" = \ | |
| "false" ] && \ | |
| [ "${{ steps.detect-changes.outputs.has_python_config_changes }}" \ | |
| = "false" ]; then | |
| echo "- No Python files in problems/ changed - skipped all tasks" >> \ | |
| $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.detect-changes.outputs.should_run_all_tests }}" = \ | |
| "true" ]; then | |
| echo "- Ran all tests due to config changes" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.detect-changes.outputs.changed_problems }}" != \ | |
| "" ]; then | |
| problems="${{ steps.detect-changes.outputs.changed_problems }}" | |
| echo "- Ran targeted tests for: $problems" >> \ | |
| $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- No tests needed (no problem files changed)" >> \ | |
| $GITHUB_STEP_SUMMARY | |
| fi |