Skip to content

Instantly share code, notes, and snippets.

@KyleJamesWalker
Created October 18, 2018 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KyleJamesWalker/f9dcca18712e0482f8dfe4f7ed7b0732 to your computer and use it in GitHub Desktop.
Save KyleJamesWalker/f9dcca18712e0482f8dfe4f7ed7b0732 to your computer and use it in GitHub Desktop.
Files Changed Since Last PR

Files Changed Since Last PR

The Jenkins changeset function didn't seem to work predicably enough, as described in How to access Changelogs in a Pipeline Job? So instead I wrote this quick invoke script to pull the changes directly from the git logs. This assumes changes are done in PRs, so when on run on master the task will look for all changes 2 PRs back, but when developing off master it will look for the first PR it finds.

This of course will have issues, if you've merged a PR into another branch and then merged the branch, but for my use case this should be fine.

import json
import re
from invoke task
def get_change_log(ctx, num: int=None):
"""Get the change log with sha, title, and filenames."""
raw_result = ctx.run(
"git log --pretty=format:'%n%h%n%s' --name-only {}".format(
"" if num is None else "-{}".format(num + 1)
),
hide=True,
).stdout.strip()
result = []
cur_build = {}
for line in raw_result.splitlines():
if not line and cur_build:
result.append(cur_build.copy())
cur_build.clear()
if line:
if 'files' not in cur_build:
cur_build['files'] = []
if 'sha' not in cur_build:
cur_build['sha'] = line
elif 'title' not in cur_build:
cur_build['title'] = line
else:
cur_build['files'].append(line)
return result
def get_files_changes_since_pr_n_back(ctx, pr_max):
"""Get a list of all files changed since last n PR(s)"""
changes = get_change_log(ctx, 100)
files = set()
pr_count = 0
for change in changes:
files.update(change['files'])
if re.match(r"Merge pull request #\d+", change['title']):
pr_count += 1
if pr_count >= pr_max:
break
return list(files)
@task()
def change_log(ctx):
"""Output the change log in json"""
print(json.dumps(get_change_log(ctx, 100)))
@task()
def file_changes_since_last_merged_pr(ctx):
"""List of all files changed since last PR or two"""
branch = ctx.run(
"git rev-parse --abbrev-ref HEAD",
hide=True,
).stdout.strip()
files = get_files_changes_since_pr_n_back(
ctx,
2 if branch == 'master' else 1
)
print(json.dumps(list(files)))
@task()
def folders_changes_since_last_merged_pr(ctx):
"""List of all files changed since last PR or two"""
branch = ctx.run(
"git rev-parse --abbrev-ref HEAD",
hide=True,
).stdout.strip()
files = get_files_changes_since_pr_n_back(
ctx,
2 if branch == 'master' else 1
)
folders = set()
for file in files:
if '/' in file:
folders.add(file.split('/', 2)[0])
print(json.dumps(list(folders)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment