mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 21:25:04 -07:00
ci: create GitHub Action that squashes all typo PRs into a single PR (#15041)
The action adds all pull-request authors (and Marvim) as a co-author to the newly created PR and also links to the closed PRs.
This commit is contained in:
parent
9ef7003c38
commit
7dbbd5d8b1
32
.github/workflows/squash-typos.yml
vendored
Normal file
32
.github/workflows/squash-typos.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: Squash Typo Pull Requests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: labeled
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
if: github.event.label.name == 'typo'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: master
|
||||||
|
- uses: actions/setup-python@v2
|
||||||
|
|
||||||
|
- name: Setup git config
|
||||||
|
run: |
|
||||||
|
git config --global user.name 'marvim'
|
||||||
|
git config --global user.email 'marvim@users.noreply.github.com'
|
||||||
|
|
||||||
|
- run: python scripts/squash_typos.py
|
148
scripts/squash_typos.py
Normal file
148
scripts/squash_typos.py
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
|
||||||
|
This script squashes a PR tagged with the "typo" label into a single, dedicated
|
||||||
|
"squash PR".
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def get_authors_and_emails_from_pr():
|
||||||
|
"""
|
||||||
|
|
||||||
|
For a given PR number, returns all contributing authors and their emails
|
||||||
|
for that PR. This includes co-authors, meaning that if two authors are
|
||||||
|
credited for a single commit, which is possible with GitHub, then both will
|
||||||
|
get credited.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get a list of all authors involved in the pull request (including co-authors).
|
||||||
|
authors = subprocess.check_output(
|
||||||
|
["gh", "pr", "view", "--json", "commits", "--jq", ".[][].authors.[].name"],
|
||||||
|
text=True,
|
||||||
|
).splitlines()
|
||||||
|
|
||||||
|
# Get a list of emails of the aforementioned authors.
|
||||||
|
emails = subprocess.check_output(
|
||||||
|
["gh", "pr", "view", "--json", "commits", "--jq", ".[][].authors.[].email"],
|
||||||
|
text=True,
|
||||||
|
).splitlines()
|
||||||
|
|
||||||
|
return [(author, mail) for author, mail in zip(authors, emails)]
|
||||||
|
|
||||||
|
|
||||||
|
def rebase_onto_pr(pr, squash_branch):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Add all commits from PR into current branch. This is done by rebasing
|
||||||
|
current branch onto the PR.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check out the pull request.
|
||||||
|
subprocess.call(["gh", "pr", "checkout", pr])
|
||||||
|
|
||||||
|
pr_branch_name = subprocess.check_output(
|
||||||
|
["git", "branch", "--show-current"], text=True
|
||||||
|
).strip()
|
||||||
|
|
||||||
|
# Change back to the original branch.
|
||||||
|
subprocess.call(["git", "switch", squash_branch])
|
||||||
|
|
||||||
|
# Rebase onto the pull request, aka include the commits in the pull
|
||||||
|
# request in the current branch.
|
||||||
|
subprocess.call(["git", "rebase", pr_branch_name])
|
||||||
|
|
||||||
|
|
||||||
|
def squash_all_commits():
|
||||||
|
"""
|
||||||
|
|
||||||
|
Squash all commits into a single commit. Credit all authors by name and
|
||||||
|
email.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
authors_and_emails = get_authors_and_emails_from_pr()
|
||||||
|
subprocess.call(["git", "reset", "--soft", f"{os.environ['GITHUB_BASE_REF']}"])
|
||||||
|
|
||||||
|
authors_and_emails = sorted(set(authors_and_emails))
|
||||||
|
commit_message_coauthors = "\n" + "\n".join(
|
||||||
|
[f"Co-authored-by: {i[0]} <{i[1]}>" for i in authors_and_emails]
|
||||||
|
)
|
||||||
|
subprocess.call(
|
||||||
|
["git", "commit", "-m", "chore: typo fixes", "-m", commit_message_coauthors]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def force_push(branch):
|
||||||
|
gh_actor = os.environ["GITHUB_ACTOR"]
|
||||||
|
gh_token = os.environ["GITHUB_TOKEN"]
|
||||||
|
gh_repo = os.environ["GITHUB_REPOSITORY"]
|
||||||
|
subprocess.call(
|
||||||
|
[
|
||||||
|
"git",
|
||||||
|
"push",
|
||||||
|
"--force",
|
||||||
|
f"https://{gh_actor}:{gh_token}@github.com/{gh_repo}",
|
||||||
|
branch,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
squash_branch = "marvim/squash-typos"
|
||||||
|
all_pr_urls = ""
|
||||||
|
|
||||||
|
pr_number = re.sub(r"\D", "", os.environ["GITHUB_REF"])
|
||||||
|
|
||||||
|
show_ref_output = subprocess.check_output(["git", "show-ref"], text=True).strip()
|
||||||
|
|
||||||
|
if squash_branch in show_ref_output:
|
||||||
|
subprocess.call(
|
||||||
|
["git", "checkout", "-b", squash_branch, f"origin/{squash_branch}"]
|
||||||
|
)
|
||||||
|
squash_branch_exists = True
|
||||||
|
|
||||||
|
all_pr_urls += subprocess.check_output(
|
||||||
|
["gh", "pr", "view", "--json", "body", "--jq", ".body"], text=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
subprocess.call(["git", "checkout", "-b", squash_branch])
|
||||||
|
squash_branch_exists = False
|
||||||
|
|
||||||
|
all_pr_urls += subprocess.check_output(
|
||||||
|
["gh", "pr", "view", pr_number, "--json", "url", "--jq", ".url"], text=True
|
||||||
|
).strip()
|
||||||
|
|
||||||
|
rebase_onto_pr(pr_number, squash_branch)
|
||||||
|
force_push(squash_branch)
|
||||||
|
|
||||||
|
subprocess.call(["gh", "pr", "close", pr_number])
|
||||||
|
|
||||||
|
squash_all_commits()
|
||||||
|
force_push(squash_branch)
|
||||||
|
|
||||||
|
if not squash_branch_exists:
|
||||||
|
subprocess.call(
|
||||||
|
[
|
||||||
|
"gh",
|
||||||
|
"pr",
|
||||||
|
"create",
|
||||||
|
"--fill",
|
||||||
|
"--head",
|
||||||
|
squash_branch,
|
||||||
|
"--title",
|
||||||
|
"Dedicated PR for all typo fixes.",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
subprocess.call(["gh", "pr", "edit", "--add-label", "typo", "--body", all_pr_urls])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user