Skip to content

Commit

Permalink
Merge pull request #1 from jupyterlab/pr-script
Browse files Browse the repository at this point in the history
Add a PR Script Workflow
  • Loading branch information
blink1073 authored Nov 17, 2021
2 parents 1451e75 + cf8dc1e commit 1b43480
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/pr_script.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Run Script on PR
on:
workflow_dispatch:
inputs:
target:
description: Target Pull Request Link
required: true
script:
description: Command(s) to run
required: false
pre_commit:
description: Whether to run the pre-commit script
required: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install Python
uses: actions/setup-python@v1
with:
python-version: "3.9"
architecture: "x64"
- name: Upgrade packaging dependencies
run: |
pip install --upgrade pip setuptools wheel --user
- name: Install dependencies
run: |
pip install ghapi pre-commit
- name: Run the script
env:
GITHUB_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
MAINTAINER: ${{ github.actor }}
TARGET: ${{ github.event.inputs.target }}
SCRIPT: ${{ github.event.inputs.script }}
PRE_COMMIT: ${{ github.event.inputs.pre_commit }}
run: |
python pr_script.py
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
# maintainer-tools

## Workflows

Workflows for use by maintainers. These should be run from your fork of this repository, with
an [encrypted secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) called
`ACCESS_TOKEN` that is a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `repo` and `workflow`
scopes.

### PR Script

The PR Script Workflow allows you to make a commit against a PR as a maintainer without having
to check out the PR locally and push the change. The manual workflow takes as its inputs a link to the PR
and a comma-separated list of quoted commands to run. As a convenience, you can also type "True" for the
option to run pre-commit against the PR to fix up any pre-commit errors.
83 changes: 83 additions & 0 deletions pr_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import json
import os
from pathlib import Path
import re
import shlex
import shutil
from subprocess import check_output, CalledProcessError, PIPE
import sys

from ghapi.core import GhApi


def run(cmd, **kwargs):
"""Run a command as a subprocess and get the output as a string"""
if not kwargs.pop("quiet", False):
print(f"+ {cmd}")
else:
kwargs.setdefault("stderr", PIPE)

parts = shlex.split(cmd)
if "/" not in parts[0]:
executable = shutil.which(parts[0])
if not executable:
raise CalledProcessError(1, f'Could not find executable "{parts[0]}"')
parts[0] = executable

try:
return check_output(parts, **kwargs).decode("utf-8").strip()
except CalledProcessError as e:
print("output:", e.output.decode("utf-8").strip())
if e.stderr:
print("stderr:", e.stderr.decode("utf-8").strip())
raise e


def run_script(target, script):
"""Run a script on the target pull request URL"""
# e.g. https://github.com/foo/bar/pull/81
owner, repo = target.replace("https://github.com/", "").split('/')[:2]
number = target.split("/")[-1]
auth = os.environ['GITHUB_ACCESS_TOKEN']
gh = GhApi(owner=owner, repo=repo, token=auth)
# here we get the target owner and branch so we can check it out below
pull = gh.pulls.get(number)
user_name = pull.head.repo.owner.login
branch = pull.head.ref

if Path("./test").exists():
shutil.rmtree("./test")
run(f"git clone https://{maintainer}:{auth}@github.com/{user_name}/{repo} -b {branch} test")
os.chdir("test")
run("pip install -e '.[test]'")
for cmd in script:
try:
run(cmd)
except Exception:
continue

# Use email address for the GitHub Actions bot
# https://gh.neting.ccmunity/t/github-actions-bot-email-address/17204/6
run(
'git config user.email "41898282+github-actions[bot]@users.noreply.github.com"'
)
run('git config user.name "GitHub Action"')
run(f"git commit -a -m 'Run maintainer script' -m 'by {maintainer}' -m '{json.dumps(script)}'")
run(f"git push origin {branch}")


if __name__ == '__main__':
# https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#inputs
target = os.environ.get('TARGET')
maintainer = os.environ['MAINTAINER']
try:
script = json.loads(os.environ.get('SCRIPT', '[]'))
except Exception:
script = os.environ.get('SCRIPT', [])
if not isinstance(script, list):
script = [script]
if os.environ.get('PRE_COMMIT') == 'true':
script += ['pre-commit run --all-files']
print(f'Running script on {target}:')
print(f' {script}')
run_script(target, script)

0 comments on commit 1b43480

Please sign in to comment.