Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Merge branch 'master' into validate_sarif
- v3.22.12
- v3.22.11
- v3
- v2.22.12
- v2.22.11
- v2.22.10
- v2.22.9
- v2.22.8
- v2.22.7
- v2.22.6
- v2.22.5
- v2.22.4
- v2.22.3
- v2.22.2
- v2.22.1
- v2.22.0
- v2.21.9
- v2.21.8
- v2.21.7
- v2.21.6
- v2.21.5
- v2.21.4
- v2.21.3
- v2.21.2
- v2.21.1
- v2.21.0
- v2.20.4
- v2.20.3
- v2.20.2
- v2.20.1
- v2.20.0
- v2.3.6
- v2.3.5
- v2.3.4
- v2.3.3
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.12
- v2.2.11
- v2.2.10
- v2.2.9
- v2.2.8
- v2.2.7
- v2.2.6
- v2.2.5
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.39
- v2.1.38
- v2.1.37
- v2.1.36
- v2.1.35
- v2.1.34
- v2.1.33
- v2.1.32
- v2.1.31
- v2.1.30
- v2.1.29
- v2.1.28
- v2.1.27
- v2.1.26
- v2.1.25
- v2.1.24
- v2.1.23
- v2.1.22
- v2.1.21
- v2.1.20
- v2.1.19
- v2.1.18
- v2.1.17
- v2.1.16
- v2.1.15
- v2.1.14
- v2.1.13
- v2.1.12
- v2.1.11
- v2.1.10
- v2.1.9
- v2.1.8
- v2.1.7
- v2.1.6
- v2
- v1.1.39
- v1.1.38
- v1.1.37
- v1.1.36
- v1.1.35
- v1.1.34
- v1.1.33
- v1.1.32
- v1.1.31
- v1.1.30
- v1.1.29
- v1.1.28
- v1.1.27
- v1.1.26
- v1.1.25
- v1.1.24
- v1.1.23
- v1.1.22
- v1.1.21
- v1.1.20
- v1.1.19
- v1.1.18
- v1.1.17
- v1.1.16
- v1.1.15
- v1.1.14
- v1.1.13
- v1.1.12
- v1.1.11
- v1.1.10
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.32
- v1.0.31
- v1.0.30
- v1.0.29
- v1.0.28
- v1.0.27
- v1.0.26
- v1.0.25
- v1.0.24
- v1.0.23
- v1.0.22
- v1.0.21
- v1.0.20
- v1.0.19
- v1.0.18
- v1.0.17
- v1.0.16
- v1.0.15
- v1.0.14
- v1.0.13
- v1.0.12
- v1.0.11
- v1.0.10
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- v1
Showing
29 changed files
with
687 additions
and
481 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import datetime | ||
from github import Github | ||
import random | ||
import requests | ||
import subprocess | ||
import sys | ||
|
||
# The branch being merged from. | ||
# This is the one that contains day-to-day development work. | ||
MASTER_BRANCH = 'master' | ||
# The branch being merged into. | ||
# This is the release branch that users reference. | ||
LATEST_RELEASE_BRANCH = 'v1' | ||
# Name of the remote | ||
ORIGIN = 'origin' | ||
|
||
# Runs git with the given args and returns the stdout. | ||
# Raises an error if git does not exit successfully. | ||
def run_git(*args): | ||
cmd = ['git', *args] | ||
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
if (p.returncode != 0): | ||
raise Exception('Call to ' + ' '.join(cmd) + ' exited with code ' + str(p.returncode) + ' stderr:' + p.stderr.decode('ascii')) | ||
return p.stdout.decode('ascii') | ||
|
||
# Returns true if the given branch exists on the origin remote | ||
def branch_exists_on_remote(branch_name): | ||
return run_git('ls-remote', '--heads', ORIGIN, branch_name).strip() != '' | ||
|
||
# Opens a PR from the given branch to the release branch | ||
def open_pr(repo, all_commits, short_master_sha, branch_name): | ||
# Sort the commits into the pull requests that introduced them, | ||
# and any commits that don't have a pull request | ||
pull_requests = [] | ||
commits_without_pull_requests = [] | ||
for commit in all_commits: | ||
pr = get_pr_for_commit(repo, commit) | ||
|
||
if pr is None: | ||
commits_without_pull_requests.append(commit) | ||
elif not any(p for p in pull_requests if p.number == pr.number): | ||
pull_requests.append(pr) | ||
|
||
print('Found ' + str(len(pull_requests)) + ' pull requests') | ||
print('Found ' + str(len(commits_without_pull_requests)) + ' commits not in a pull request') | ||
|
||
# Sort PRs and commits by age | ||
sorted(pull_requests, key=lambda pr: pr.number) | ||
sorted(commits_without_pull_requests, key=lambda c: c.commit.author.date) | ||
|
||
# Start constructing the body text | ||
body = 'Merging ' + short_master_sha + ' into ' + LATEST_RELEASE_BRANCH | ||
|
||
conductor = get_conductor(repo, pull_requests, commits_without_pull_requests) | ||
body += '\n\nConductor for this PR is @' + conductor | ||
|
||
# List all PRs merged | ||
if len(pull_requests) > 0: | ||
body += '\n\nContains the following pull requests:' | ||
for pr in pull_requests: | ||
merger = get_merger_of_pr(repo, pr) | ||
body += '\n- #' + str(pr.number) | ||
body += ' - ' + pr.title | ||
body += ' (@' + merger + ')' | ||
|
||
# List all commits not part of a PR | ||
if len(commits_without_pull_requests) > 0: | ||
body += '\n\nContains the following commits not from a pull request:' | ||
for commit in commits_without_pull_requests: | ||
body += '\n- ' + commit.sha | ||
body += ' - ' + get_truncated_commit_message(commit) | ||
body += ' (@' + commit.author.login + ')' | ||
|
||
title = 'Merge ' + MASTER_BRANCH + ' into ' + LATEST_RELEASE_BRANCH | ||
|
||
# Create the pull request | ||
pr = repo.create_pull(title=title, body=body, head=branch_name, base=LATEST_RELEASE_BRANCH) | ||
print('Created PR #' + str(pr.number)) | ||
|
||
# Assign the conductor | ||
pr.add_to_assignees(conductor) | ||
print('Assigned PR to ' + conductor) | ||
|
||
# Gets the person who should be in charge of the mergeback PR | ||
def get_conductor(repo, pull_requests, other_commits): | ||
# If there are any PRs then use whoever merged the last one | ||
if len(pull_requests) > 0: | ||
return get_merger_of_pr(repo, pull_requests[-1]) | ||
|
||
# Otherwise take the author of the latest commit | ||
return other_commits[-1].author.login | ||
|
||
# Gets a list of the SHAs of all commits that have happened on master | ||
# since the release branched off. | ||
# This will not include any commits that exist on the release branch | ||
# that aren't on master. | ||
def get_commit_difference(repo): | ||
commits = run_git('log', '--pretty=format:%H', ORIGIN + '/' + LATEST_RELEASE_BRANCH + '...' + MASTER_BRANCH).strip().split('\n') | ||
|
||
# Convert to full-fledged commit objects | ||
commits = [repo.get_commit(c) for c in commits] | ||
|
||
# Filter out merge commits for PRs | ||
return list(filter(lambda c: not is_pr_merge_commit(c), commits)) | ||
|
||
# Is the given commit the automatic merge commit from when merging a PR | ||
def is_pr_merge_commit(commit): | ||
return commit.committer.login == 'web-flow' and len(commit.parents) > 1 | ||
|
||
# Gets a copy of the commit message that should display nicely | ||
def get_truncated_commit_message(commit): | ||
message = commit.commit.message.split('\n')[0] | ||
if len(message) > 60: | ||
return message[:57] + '...' | ||
else: | ||
return message | ||
|
||
# Converts a commit into the PR that introduced it to the master branch. | ||
# Returns the PR object, or None if no PR could be found. | ||
def get_pr_for_commit(repo, commit): | ||
prs = commit.get_pulls() | ||
|
||
if prs.totalCount > 0: | ||
# In the case that there are multiple PRs, return the earliest one | ||
prs = list(prs) | ||
sorted(prs, key=lambda pr: int(pr.number)) | ||
return prs[0] | ||
else: | ||
return None | ||
|
||
# Get the person who merged the pull request. | ||
# For most cases this will be the same as the author, but for PRs opened | ||
# by external contributors getting the merger will get us the GitHub | ||
# employee who reviewed and merged the PR. | ||
def get_merger_of_pr(repo, pr): | ||
return repo.get_commit(pr.merge_commit_sha).author.login | ||
|
||
def main(): | ||
if len(sys.argv) != 3: | ||
raise Exception('Usage: update-release.branch.py <github token> <repository nwo>') | ||
github_token = sys.argv[1] | ||
repository_nwo = sys.argv[2] | ||
|
||
repo = Github(github_token).get_repo(repository_nwo) | ||
|
||
# Print what we intend to go | ||
print('Considering difference between ' + MASTER_BRANCH + ' and ' + LATEST_RELEASE_BRANCH) | ||
short_master_sha = run_git('rev-parse', '--short', MASTER_BRANCH).strip() | ||
print('Current head of ' + MASTER_BRANCH + ' is ' + short_master_sha) | ||
|
||
# See if there are any commits to merge in | ||
commits = get_commit_difference(repo) | ||
if len(commits) == 0: | ||
print('No commits to merge from ' + MASTER_BRANCH + ' to ' + LATEST_RELEASE_BRANCH) | ||
return | ||
|
||
# The branch name is based off of the name of branch being merged into | ||
# and the SHA of the branch being merged from. Thus if the branch already | ||
# exists we can assume we don't need to recreate it. | ||
new_branch_name = 'update-' + LATEST_RELEASE_BRANCH + '-' + short_master_sha | ||
print('Branch name is ' + new_branch_name) | ||
|
||
# Check if the branch already exists. If so we can abort as this script | ||
# has already run on this combination of branches. | ||
if branch_exists_on_remote(new_branch_name): | ||
print('Branch ' + new_branch_name + ' already exists. Nothing to do.') | ||
return | ||
|
||
# Create the new branch and push it to the remote | ||
print('Creating branch ' + new_branch_name) | ||
run_git('checkout', '-b', new_branch_name, MASTER_BRANCH) | ||
run_git('push', ORIGIN, new_branch_name) | ||
|
||
# Open a PR to update the branch | ||
open_pr(repo, commits, short_master_sha, new_branch_name) | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Update release branch | ||
on: | ||
schedule: | ||
- cron: 0 9 * * 1 | ||
repository_dispatch: | ||
types: [update-release-branch] | ||
|
||
jobs: | ||
update: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
# Need full history so we calculate diffs | ||
fetch-depth: 0 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: 3.5 | ||
|
||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install PyGithub==1.51 requests | ||
- name: Update release branch | ||
run: python .github/update-release-branch.py ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} |
This file contains 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.