githubgithub-api

How to find which PR lastly touched a file on GitHub?


I have project hosted on GitHub. My repo has disabled push to branch main, only pull requests can be merged to main. I have a requirement that given a file under the repo, I want to identify which PR lastly added/updated/deleted the file. I don't find an GitHub API to do that. Is there a way?


Solution

  • I can think of three options:

    1. Use Git locally to look at the commit title of the latest commit that modified the file (assuming that the PR number hasn't been manually removed from the title):

      grep -Po '#\K\d+(?=\)$)' <<< "$(git log --format=%s --max-count=1 -- FILE)"
      

      The regex looks for # followed by one or more digits, followed by ) and the end of the line. The # and the ) aren't captured. So, a title Add a new feature (#123) would become 123.

    2. Use the REST API to get the most recent commit for a file, and use jq to extract the PR number (again assuming that the commit title wasn't modified to remove it):

      gh api repos/super-linter/super-linter/commits?path=lib/linter.sh \
          --jq '
              first.commit.message
              | split("\n")
              | first
              | capture("\\(#(?<n>\\d+)\\)$").n
          '
      
    3. More robust, as it doesn't rely on string parsing of the commit title, but also more expensive: retrieve pull requests and filter by files they touched, then get the number of the most recent one for the file you're interested in. Again using super-linter and lib/linter.sh as the example:

      gh pr list --base main --state merged --limit=50 \
          --json files,mergedAt,number --jq '
              map(select(
                .files
                | map(.path)
                | select(index("lib/linter.sh") >= 0)
              ))
              | sort_by(.mergedAt)
              | last.number
          '
      

      You might have to tweak the --limit value if a file hasn't been modified for a while. To parametrize the filename, you can set it in the environment and then reference it via the $ENV object, like

      file='lib/linter.sh' gh pr list ... --jq '... $ENV.file ...'