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

Python fixes for running on multiple platforms and outside of docker #103

Merged
merged 5 commits into from
Jan 11, 2024

Conversation

bwrsandman
Copy link
Contributor

@bwrsandman bwrsandman commented Nov 25, 2023

This PR is part of an attempt to run clang-tidy-review outside of docker.

The reason why we would want to do this is better control over github runner setup (packages, commands, environment).

Additionally, it grants the ability to run on non-linux platforms which allows the runner to analyze platform specific files/headers/libraries not available on linux in a docker.

The removal of docker also can speed up the analysis of clang-tidy. In my tests, docker runs for 4 minutes while linux without docker runs for 2, though macos and windows take upwards of 10 minutes.

Main fixes:

  1. Use subprocess.run with args list instead of string. This removes the need for shlex and helps running on windows.
  2. Convert the line filter path separators from \ to / on windows. This fixes running on windows.
  3. The split workflow post step returns as an error code, the number of unique clang-tidy warnings. This allows a non-github runner to detect a non-perfect PR.
  4. The split workflow post step allows multiple reviews as input. This allows multiple reviews on different platforms to be posted as one.

In short:

# Run review with token, repo, pr number, clang-tidy (from PATH) and
# with split workflow
review --token=${{ secrets.GITHUB_TOKEN }} \
       --repo=${{ github.repository }} \
       --pr=${{ github.event.pull_request.number }} \
       --clang_tidy_binary=clang-tidy \
       --build_dir=cmake-build-presets/ninja-multi-vcpkg \
       --config_file=.clang-tidy \
       --split_workflow=True

# Run the post step with each review
post --token=${{ secrets.GITHUB_TOKEN }} \
     --repo=${{ github.repository }} \
     ubuntu-latest/clang-tidy-review-output.json \
     macos-latest/clang-tidy-review-output.json \
     windows-latest/clang-tidy-review-output.json

In long:

name: Clang Tidy Review without Docker
on:
  pull_request:
jobs:
  clang-tidy-review: # Runs on each platform
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ ubuntu-latest, macos-latest, windows-latest ]
    steps:
      - uses: actions/checkout@v3
      - name: Get clang-tidy in path
        run: |
          ln -s $(brew --prefix llvm@15)/bin/clang-tidy ~/bin/clang-tidy
          echo "export PATH=$PATH:~/bin" >> $GITHUB_ENV
        if: startsWith(matrix.os, 'macos')
      - name: Configure the source code and genereate compilation database json
      # ...
      - name: Checkout clang-tidy-review
        uses: actions/checkout@v4
        with:
          repository: bwrsandman/clang-tidy-review
          ref: windows_shell_fix
          path: clang-tidy-review
      - name: Non-docker clang-tidy-check
        run: |
          # Install clang-tidy-review python package and dependencies
          python3 -m pip install pip -U && python3 -m pip install ${{github.workspace}}/clang-tidy-review/post/clang_tidy_review
          # Run review with token, repo, pr number, clang-tidy (from PATH) and with split workflow
          review --token=${{ secrets.GITHUB_TOKEN }} \
                 --repo=${{ github.repository }} \
                 --pr=${{ github.event.pull_request.number }} \
                 --clang_tidy_binary=clang-tidy \
                 --build_dir=cmake-build-presets/ninja-multi-vcpkg \
                 --config_file=.clang-tidy \
                 --split_workflow=True
        env:
          USER: ${{ github.event.pull_request.user.login }} # for TODO fixes to include right name  
      - name: Upload metadata and review for next step to pick up
        uses: actions/upload-artifact@v3
        with:
          name: ClangTidyReviewOutputs-${{matrix.os}}
          path: |
            clang-tidy-review-metadata.json
            clang-tidy-review-output.json
            clang_tidy_review.yaml

  clang-tidy-comments: # Only needs one runner
    runs-on: ubuntu-latest
    needs: clang-tidy-review
    steps:
      - name: Checkout clang-tidy-review
        uses: actions/checkout@v4
        with:
          repository: bwrsandman/clang-tidy-review
          ref: windows_shell_fix
          path: clang-tidy-review
      - uses: actions/download-artifact@v3
        with:
          name: ClangTidyReviewOutputs-ubuntu-latest
          path: ubuntu-latest
      - uses: actions/download-artifact@v3
        with:
          name: ClangTidyReviewOutputs-macos-latest
          path: macos-latest
      - uses: actions/download-artifact@v3
        with:
          name: ClangTidyReviewOutputs-windows-latest
          path: windows-latest
      - name: Non-docker clang-tidy-check
        run: |
          # Install clang-tidy-review python package and dependencies
          python3 -m pip install pip -U && python3 -m pip install ${{github.workspace}}/clang-tidy-review/post/clang_tidy_review
          cp ubuntu-latest/clang-tidy-review-metadata.json . # copy one metadata for the PR number
          # Run the post step with each review
          post --token=${{ secrets.GITHUB_TOKEN }} \
               --repo=${{ github.repository }} \
               ubuntu-latest/clang-tidy-review-output.json \
               macos-latest/clang-tidy-review-output.json \
               windows-latest/clang-tidy-review-output.json

image

@bwrsandman bwrsandman force-pushed the windows_shell_fix branch 3 times, most recently from 3891c1c to a60258d Compare November 25, 2023 01:26
@bwrsandman
Copy link
Contributor Author

@ZedThree Could you have a look?

@ZedThree
Copy link
Owner

ZedThree commented Jan 9, 2024

@bwrsandman Apologies, I missed this at the time! Will take a look this week.

Copy link
Owner

@ZedThree ZedThree left a comment

Choose a reason for hiding this comment

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

LGTM! Please could you just update a couple of type hints?

def load_review() -> Optional[PRReview]:
"""Load review output from the standard REVIEW_FILE path.
This file contains
def load_review(review_file) -> Optional[PRReview]:
Copy link
Owner

Choose a reason for hiding this comment

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

Please could you add a type hint for the argument? I know we're not terribly consistent, but it would be nice to add them for new things

return payload or None


def load_and_merge_reviews(review_files) -> Optional[PRReview]:
Copy link
Owner

Choose a reason for hiding this comment

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

And a type hint here too please

def __eq__(self, other):
return type(other) is Comment and self.data == other.data

comments = OrderedSet()
Copy link
Owner

Choose a reason for hiding this comment

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

What does OrderedSet give us over- plain set? Why do we need the comments to be ordered?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When merging the comments, I thought it would be more deterministic if the order wasn't changed but you're right that it's not needed. Shall I remove it?

Copy link
Owner

Choose a reason for hiding this comment

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

That's a good point. Maybe could just replace it with a set and then do sorted(list(comments))?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What will it sort on?

Copy link
Owner

Choose a reason for hiding this comment

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

Oh of course, it uses insertion order, like OrderedDict. On balance though, I think I would still prefer not to use a whole extra dependency just for this.

I think clang-tidy sorts them by filename then line number? I'm not sure beyond that.

Use list of args when calling subprocess
Use Backslashes in line ranges
Use posix slashes when looking up files from PR changeset
This fixes getting the version on windows because the forward slashes are not properly interpreted in `subprocess.run` in shell mode.
@ZedThree
Copy link
Owner

LGTM, thanks @bwrsandman !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants