1 Commits

Author SHA1 Message Date
Vanessa Sochat
51b1329c52 fixing up GitHub action to work with yaml syntax
Signed-off-by: Vanessa Sochat <vsochat@stanford.edu>
2019-10-19 09:35:46 -04:00
14 changed files with 156 additions and 680 deletions

17
.github/stale.yml vendored
View File

@@ -1,17 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@@ -1,19 +0,0 @@
# CHANGELOG
This is a manually generated log to track changes to the repository for each release.
Each section should include general headers such as **Implemented enhancements**
and **Merged pull requests**. All closed issued and bug fixes should be
represented by the pull requests that fixed them. Critical items to know are:
- renamed commands
- deprecated / removed commands
- changed defaults
- backward incompatible changes
Versions correspond with GitHub releases that can be referenced with @ using actions.
## [master](https://github.com/vsoch/pull-request-action/tree/master) (master)
- output and environment variables for PR number and return codes (1.0.5)
- added support for reviewer (individual and team) assignments (1.0.4)
- added support for maintainer can modify and assignees (1.0.3)

View File

@@ -1,4 +1,4 @@
FROM alpine FROM debian:jessie-slim
# docker build -t vanessa/pull-request-action . # docker build -t vanessa/pull-request-action .
@@ -7,9 +7,8 @@ LABEL "com.github.actions.description"="Create a pull request when a branch is c
LABEL "com.github.actions.icon"="activity" LABEL "com.github.actions.icon"="activity"
LABEL "com.github.actions.color"="yellow" LABEL "com.github.actions.color"="yellow"
RUN apk --no-cache add python3 py3-pip git bash && \ RUN apt-get update && apt-get install -y jq curl wget git
pip3 install requests COPY pull-request.sh /pull-request.sh
COPY pull-request.py /pull-request.py
RUN chmod u+x /pull-request.py RUN chmod u+x /pull-request.sh
ENTRYPOINT ["python3", "/pull-request.py"] ENTRYPOINT ["/pull-request.sh"]

102
README.md
View File

@@ -22,109 +22,23 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: pull-request-action - name: pull-request-action
uses: vsoch/pull-request-action@1.0.6 uses: vsoch/pull-request-action@master
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: "update/" BRANCH_PREFIX: "update/"
PULL_REQUEST_BRANCH: "master" PULL_REQUEST_BRANCH: "master"
``` ```
## Environment Variable Inputs Environment variables include:
Unlike standard actions, this action just uses variables from the environment. - **BRANCH_PREFIX**: the prefix to filter to. If the branch doesn't start with the prefix, it will be ignored
- **PULL_REQUEST_BRANCH**: the branch to issue the pull request to. Defaults to master.
| Name | Description | Required | Default | - **PULL_REQUEST_BODY**: the body for the pull request (optional)
|------|-------------|----------|---------| - **PULL_REQUEST_TITLE**: the title for the pull request (optional)
| BRANCH_PREFIX | the prefix to filter to. If the branch doesn't start with the prefix, it will be ignored | false | "" | - **PULL_REQUEST_DRAFT**: should the pull request be a draft PR? (optional; unset defaults to `false`)
| PULL_REQUEST_BRANCH | open pull request against this branch | false | master |
| PULL_REQUEST_FROM_BRANCH | if a branch isn't found in your GitHub payload, use this branch | false | |
| PULL_REQUEST_BODY | the body for the pull request | false | |
| PULL_REQUEST_TITLE | the title for the pull request | false | |
| PULL_REQUEST_DRAFT | should this be a draft PR? | false | unset |
| MAINTAINER_CANT_MODIFY | Do not allow the maintainer to modify the PR | false | unset |
| PULL_REQUEST_ASSIGNEES | A list (string with spaces) of users to assign | false | unset |
| PULL_REQUEST_REVIEWERS | A list (string with spaces) of users to assign review | false | unset |
| PULL_REQUEST_TEAM_REVIEWERS | A list (string with spaces) of teams to assign review | false | unset |
| PASS_ON_ERROR | Instead of failing on an error response, pass | unset |
| PASS_IF_EXISTS | Instead of failing if the pull request already exists, pass | unset |
For `PULL_REQUEST_DRAFT`, `PASS_ON_ERROR`, `PASS_IF_EXISTS`, and `MAINTAINER_CANT_MODIFY`, these are
treated as environment booleans. If they are defined in the environment, they trigger the
"true" condition. E.g.,:
- Define `MAINTAINER_CANT_MODIFY` if you don't want the maintainer to be able to modify the pull request.
- Define `PULL_REQUEST_DRAFT` if you want the PR to be a draft.
- Define `PASS_ON_ERROR` if you want the PR to not exit given any non 200/201 response.
- Define `PASS_IF_EXISTS` if you want the PR to not exit given the pull request is already open.
For `PULL_REQUEST_ASSIGNEES`, `PULL_REQUEST_REVIEWERS`, and `PULL_REQUEST_TEAM_REVIEWERS`
you can provide a string of one or more GitHub usernames (or team names) to
assign to the issue. Note that only users with push access can add assigness to
an issue or PR, they are ignored otherwise.
The `GITHUB_TOKEN` secret is required to interact and authenticate with the GitHub API to open The `GITHUB_TOKEN` secret is required to interact and authenticate with the GitHub API to open
the pull request. The example is [deployed here](https://github.com/vsoch/pull-request-action-example) with an example opened (and merged) [pull request here](https://github.com/vsoch/pull-request-action-example/pull/1) if needed. the pull request.
## Outputs
The action sets a few useful output and environment variables. An output can
be referenced later as `${{ steps.<stepname>.outputs.<output-name> }}`.
An environment variable of course can be referenced as you usually would.
| Name | Description | Environment |
|------|-------------|-------------|
| pull_request_number |If the pull request is opened, this is the number for it. | PULL_REQUEST_NUMBER |
| pull_request_url |If the pull request is opened, the html url for it. | PULL_REQUEST_URL |
| pull_request_return_code | Return code for the pull request | PULL_REQUEST_RETURN_CODE |
| assignees_return_code | Return code for the assignees request | ASSIGNEES_RETURN_CODE |
| reviewers_return_code | Return code for the reviewers request | REVIEWERS_RETURN_CODE |
See the [examples/outputs-example.yml](examples/outputs-example.yml) for how this works.
In this example, we can reference `${{ steps.pull_request.outputs.pull_request_url }}`
in either another environment variable declaration, or within a run statement to access
our variable `pull_request_url` that was generated in a step with id `pull_request`.
The screenshot below shows the example in action to interact with outputs in several ways.
![img/outputs.png](img/outputs.png)
## Examples
Example workflows are provided in [examples](examples), and please contribute any
examples that you might have to help other users! We will walk through a basic
example here for a niche case. Let's say that we are opening a pull request on the release event. This would mean
that the payload's branch variable would be null. We would need to define `PULL_REQUEST_FROM`. How would
we do that? We can [set environment variables](https://help.github.com/en/actions/reference/development-tools-for-github-actions#set-an-environment-variable-set-env) for next steps. Here is an example:
```yaml
name: Pull Request on Branch Push
on: [release]
jobs:
pull-request-on-release:
name: PullRequestAction
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Derive from branch name
run: |
# do custom parsing of your code / date to derive a branch from
PR_BRANCH_FROM=release-v$(cat VERSION)
::set-env name=PULL_REQUEST_FROM_BRANCH::${PR_BRANCH_FROM}
- name: pull-request-action
uses: vsoch/pull-request-action@1.0.6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PULL_REQUEST_BRANCH: "master"
```
The above workflow is triggered on a release, so the branch will be null in the GItHub
payload. Since we want the release PR to come from a special branch, we derive it
in the second step, and then set the `PULL_REQUEST_FROM_BRANCH` variable in the environment
for the next step. In the Pull Request Action step, the pull request
will be opened from `PULL_REQUEST_FROM_BRANCH` against `PULL_REQUEST_BRANCH`, which is
master. If we do not set this variable, the job will exit in an error,
as it is not clear what action to take.
## Example use Case: Update Registry ## Example use Case: Update Registry

View File

@@ -1,20 +0,0 @@
name: 'Pull Request Action'
description: 'A GitHub action to open a pull request'
author: 'vsoch'
runs:
using: 'docker'
image: 'Dockerfile'
branding:
icon: 'activity'
color: 'yellow'
outputs:
pull_request_number:
description: 'If the pull request is opened, this is the number for it.'
pull_request_url:
description: 'If the pull request is opened, the html url for it.'
pull_request_return_code:
description: 'The pull request return code.'
assignees_return_code:
description: 'The add assignees post return code.'
reviewers_return_code:
description: 'The add reviewers post return code.'

View File

@@ -1,17 +0,0 @@
name: Pull Request on Branch Push
on:
push:
branches-ignore:
- devel
jobs:
auto-pull-request:
name: PullRequestAction
runs-on: ubuntu-latest
steps:
- name: pull-request-action
uses: vsoch/pull-request-action@1.0.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: "update/"
PULL_REQUEST_BRANCH: "master"
PULL_REQUEST_ASSIGNEES: vsoch

View File

@@ -1,49 +0,0 @@
name: derive-branch-from-environment
on:
schedule:
# Weekly
- cron: 0 0 * * 0
jobs:
DoSomeUpdate:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v1
- name: Install or Do Something to Change repository
run: |
echo "This is a new file." >> newfile.txt
- name: Checkout New Branch
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_AGAINST: "master"
run: |
printf "GitHub Actor: ${GITHUB_ACTOR}\n"
export BRANCH_FROM="update/newfile-$(date '+%Y-%m-%d')"
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git branch
git checkout -b "${BRANCH_FROM}" || git checkout "${BRANCH_FROM}"
git branch
git config --global user.name "github-actions"
git config --global user.email "github-actions@users.noreply.github.com"
git add newfile.txt
if git diff-index --quiet HEAD --; then
printf "No changes\n"
else
printf "Changes\n"
git commit -m "Automated deployment to update software database $(date '+%Y-%m-%d')"
git push origin "${BRANCH_FROM}"
fi
# Here is where we are setting the environment variable!
echo "::set-env name=PULL_REQUEST_FROM_BRANCH::${BRANCH_FROM}"
- name: Open Pull Request
uses: vsoch/pull-request-action@1.0.6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PULL_REQUEST_BRANCH: "master"

View File

@@ -1,28 +0,0 @@
name: Pull Request on Branch Push
on:
push:
branches-ignore:
- devel
jobs:
auto-pull-request:
name: PullRequestAction
runs-on: ubuntu-latest
steps:
- name: pull-request-action
id: pull_request
uses: vsoch/pull-request-action@1.0.6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: "update/"
PULL_REQUEST_BRANCH: "master"
PULL_REQUEST_REVIEWERS: vsoch
- name: Test outputs
env:
pull_request_number_output: ${{ steps.pull_request.outputs.pull_request_number }}
pull_request_url_output: ${{ steps.pull_request.outputs.pull_request_url }}
run: |
echo "Pull request number from output: ${pull_request_number_output}"
echo "Pull request url from output: ${pull_request_url_output}"
echo "Pull request number from environment: ${PULL_REQUEST_NUMBER}"
echo "Pull request url from environment: ${PULL_REQUEST_URL}"
echo "Another way to specify from output ${{ steps.pull_request.outputs.pull_request_number }}"

View File

@@ -1,18 +0,0 @@
name: Pull Request on Branch Push
on:
push:
branches-ignore:
- staging
- launchpad
- production
jobs:
auto-pull-request:
name: PullRequestAction
runs-on: ubuntu-latest
steps:
- name: pull-request-action
uses: vsoch/pull-request-action@add/support-null-branch
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: "update/"
PULL_REQUEST_BRANCH: "master"

View File

@@ -1,48 +0,0 @@
on:
release:
types:
- published
jobs:
persist-new-suite-yml:
name: Commit Suite Release YML
runs-on: ubuntu-latest
steps:
# Likely other steps go here
- name: Set BRANCH_NAME
run: |
tag_name=${{github.event.release.tag_name}}
echo "Tag: $tag_name"
version=$(echo "$tag_name" | sed 's/^v//')
echo "Version: $version"
echo "::set-output name=suite_version::${version}"
echo "::set-output name=suite_update_branch::suite_${version}"
id: data
- name: Permanently save the new suite release
run: |
mkdir -p releases
new_suite_version_yml="releases/suite_${{ steps.data.outputs.suite_version }}.yml"
echo "Suite target file: $new_suite_version_yml"
cp suite.yml "${new_suite_version_yml}"
git add "${new_suite_version_yml}"
git commit -m "Suite v${{ steps.data.outputs.suite_version }} auto-commit of new release files"
- name: Push files
run: |
git push --force "https://${{ github.actor }}:${{secrets.GITHUB_TOKEN}}@github.com/${{ github.repository }}.git" "HEAD:${{ steps.data.outputs.suite_update_branch }}"
- name: Open a PR to the default branch
uses: vsoch/pull-request-action@1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PULL_REQUEST_FROM_BRANCH: "${{ steps.data.outputs.suite_update_branch }}"
PULL_REQUEST_BRANCH: master
PULL_REQUEST_TITLE: "Action: Update suite release file for v${{ steps.data.outputs.suite_version }}"
PULL_REQUEST_BODY: "Auto-generated PR!"

View File

@@ -1,17 +0,0 @@
name: Pull Request on Branch Push
on:
push:
branches-ignore:
- devel
jobs:
auto-pull-request:
name: PullRequestAction
runs-on: ubuntu-latest
steps:
- name: pull-request-action
uses: vsoch/pull-request-action@1.0.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: "update/"
PULL_REQUEST_BRANCH: "master"
PULL_REQUEST_REVIEWERS: vsoch

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,347 +0,0 @@
#!/usr/bin/env python3
import sys
import os
import json
import requests
################################################################################
# Helper Functions
################################################################################
def get_envar(name):
value = os.environ.get(name)
if not value:
sys.exit("%s is required for vsoch/pull-request-action" % name)
return value
def check_events_json():
events = get_envar("GITHUB_EVENT_PATH")
if not os.path.exists(events):
sys.exit("Cannot find Github events file at ${GITHUB_EVENT_PATH}")
print("Found ${GITHUB_EVENT_PATH} at %s" % events)
return events
def abort_if_fail(reason):
"""If PASS_ON_ERROR, don't exit. Otherwise exit with an error and print the reason"""
if os.environ.get("PASS_ON_ERROR"):
print("Error, but PASS_ON_ERROR is set, continuing: %s" % reason)
else:
sys.exit(reason)
def parse_into_list(values):
if values:
values = values.replace('"', "").replace("'", "")
if not values:
return []
return [x.strip() for x in values.split(" ")]
################################################################################
# Global Variables (we can't use GITHUB_ prefix)
################################################################################
API_VERSION = "v3"
BASE = "https://api.github.com"
HEADERS = {
"Authorization": "token %s" % get_envar("GITHUB_TOKEN"),
"Accept": "application/vnd.github.%s+json;application/vnd.github.antiope-preview+json;application/vnd.github.shadow-cat-preview+json"
% API_VERSION,
}
# URLs
REPO_URL = "%s/repos/%s" % (BASE, get_envar("GITHUB_REPOSITORY"))
ISSUE_URL = "%s/issues" % REPO_URL
PULLS_URL = "%s/pulls" % REPO_URL
def create_pull_request(
source,
target,
body,
title,
assignees,
reviewers,
team_reviewers,
is_draft=False,
can_modify=True,
):
# Check if the branch already has a pull request open
params = {"base": target, "head": source, "state": "open"}
data = {"base": target, "head": source, "body": body}
print("Params for checking if pull request exists: %s" % params)
response = requests.get(PULLS_URL, params=params)
# Case 1: 404 might warrant needing a token
if response.status_code == 404:
response = requests.get(PULLS_URL, params=params, headers=HEADERS)
if response.status_code != 200:
abort_if_fail(
"Unable to retrieve information about pull requests: %s: %s"
% (response.status_code, response.reason)
)
response = response.json()
# Option 1: The pull request is already open
is_open = False
if response:
for entry in response:
if entry.get("head", {}).get("ref", "") == source:
print("Pull request from %s to %s is already open!" % (source, target))
is_open = True
# Does the user want to pass if the pull request exists?
if os.environ.get("PASS_IF_EXISTS"):
print("PASS_IF_EXISTS is set, exiting with success status.")
sys.exit(0)
break
# Option 2: Open a new pull request
if not is_open:
print("No pull request from %s to %s is open, continuing!" % (source, target))
# Post the pull request
data = {
"title": title,
"body": body,
"base": target,
"head": source,
"draft": is_draft,
"maintainer_can_modify": can_modify,
}
print("Data for opening pull request: %s" % data)
response = requests.post(PULLS_URL, json=data, headers=HEADERS)
if response.status_code != 201:
abort_if_fail(
"Unable to create pull request: %s: %s, %s"
% (
response.status_code,
response.reason,
response.json().get("message", ""),
)
)
# Expected return codes are 0 for success
pull_request_return_code = (
0 if response.status_code == 201 else response.status_code
)
response = response.json()
print("::group::github response")
print(response)
print("::endgroup::github response")
number = response.get("number")
html_url = response.get("html_url")
print("Number opened for PR is %s" % number)
print("::set-env name=PULL_REQUEST_NUMBER::%s" % number)
print("::set-output name=pull_request_number::%s" % number)
print("::set-env name=PULL_REQUEST_RETURN_CODE::%s" % pull_request_return_code)
print(
"::set-output name=pull_request_return_code::%s" % pull_request_return_code
)
print("::set-env name=PULL_REQUEST_URL::%s" % html_url)
print("::set-output name=pull_request_url::%s" % html_url)
if assignees:
# Remove leading and trailing quotes
assignees = parse_into_list(assignees)
print(
"Attempting to assign %s to pull request with number %s"
% (assignees, number)
)
# POST /repos/:owner/:repo/issues/:issue_number/assignees
data = {"assignees": assignees}
ASSIGNEES_URL = "%s/%s/assignees" % (ISSUE_URL, number)
response = requests.post(ASSIGNEES_URL, json=data, headers=HEADERS)
if response.status_code != 201:
abort_if_fail(
"Unable to create assignees: %s: %s, %s"
% (
response.status_code,
response.reason,
response.json().get("message", ""),
)
)
assignees_return_code = (
0 if response.status_code == 201 else response.status_code
)
print("::set-env name=ASSIGNEES_RETURN_CODE::%s" % assignees_return_code)
print("::set-output name=assignees_return_code::%s" % assignees_return_code)
if reviewers or team_reviewers:
print(
"Found reviewers: %s and team reviewers: %s"
% (reviewers, team_reviewers)
)
team_reviewers = parse_into_list(team_reviewers)
reviewers = parse_into_list(reviewers)
print(
"Parsed reviewers: %s and team reviewers: %s"
% (reviewers, team_reviewers)
)
# POST /repos/:owner/:repo/pulls/:pull_number/requested_reviewers
REVIEWERS_URL = "%s/%s/requested_reviewers" % (PULLS_URL, number)
data = {"reviewers": reviewers, "team_reviewers": team_reviewers}
response = requests.post(REVIEWERS_URL, json=data, headers=HEADERS)
if response.status_code != 201:
abort_if_fail(
"Unable to assign reviewers: %s: %s, %s"
% (
response.status_code,
response.reason,
response.json().get("message", ""),
)
)
reviewers_return_code = (
0 if response.status_code == 201 else response.status_code
)
response = response.json()
print("::group::github reviewers response")
print(response)
print("::endgroup::github reviewers response")
print("::set-env name=REVIEWERS_RETURN_CODE::%s" % reviewers_return_code)
print("::set-output name=reviewers_return_code::%s" % reviewers_return_code)
print("Add reviewers return code: %s" % reviewers_return_code)
def main():
# path to file that contains the POST response of the event
# Example: https://github.com/actions/bin/tree/master/debug
# Value: /github/workflow/event.json
check_events_json()
branch_prefix = os.environ.get("BRANCH_PREFIX", "")
print("Branch prefix is %s" % branch_prefix)
if not branch_prefix:
print("No branch prefix is set, all branches will be used.")
# Default to master to support older, will eventually change to main
pull_request_branch = os.environ.get("PULL_REQUEST_BRANCH", "master")
print("Pull requests will go to %s" % pull_request_branch)
# Pull request draft
pull_request_draft = os.environ.get("PULL_REQUEST_DRAFT")
if not pull_request_draft:
print("No explicit preference for draft PR: created PRs will be normal PRs.")
pull_request_draft = False
else:
print(
"Environment variable PULL_REQUEST_DRAFT set to a value: created PRs will be draft PRs."
)
pull_request_draft = True
# Maintainer can modify, defaults to CAN, unless user sets MAINTAINER_CANT_MODIFY
maintainer_can_modify = os.environ.get("MAINTAINER_CANT_MODIFY")
if not maintainer_can_modify:
print(
"No explicit preference for maintainer being able to modify: default is true."
)
maintainer_can_modify = True
else:
print(
"Environment variable MAINTAINER_CANT_MODIFY set to a value: maintainer will not be able to modify."
)
maintainer_can_modify = False
# Assignees
assignees = os.environ.get("PULL_REQUEST_ASSIGNEES")
if not assignees:
print("PULL_REQUEST_ASSIGNEES is not set, no assignees.")
else:
print("PULL_REQUEST_ASSIGNEES is set, %s" % assignees)
# Reviewers (individual and team)
reviewers = os.environ.get("PULL_REQUEST_REVIEWERS")
team_reviewers = os.environ.get("PULL_REQUEST_TEAM_REVIEWERS")
if not reviewers:
print("PULL_REQUEST_REVIEWERS is not set, no reviewers.")
else:
print("PULL_REQUEST_REVIEWERS is set, %s" % reviewers)
if not team_reviewers:
print("PULL_REQUEST_TEAM_REVIEWERS is not set, no team reviewers.")
else:
print("PULL_REQUEST_TEAM_REVIEWERS is set, %s" % team_reviewers)
# The user is allowed to explicitly set the name of the branch
from_branch = os.environ.get("PULL_REQUEST_FROM_BRANCH")
if not from_branch:
print("PULL_REQUEST_FROM_BRANCH is not set, checking branch in payload.")
with open(check_events_json(), "r") as fd:
from_branch = json.loads(fd.read()).get("ref")
from_branch = from_branch.replace("refs/heads/", "").strip("/")
else:
print("PULL_REQUEST_FROM_BRANCH is set.")
# At this point, we must have a branch
if from_branch:
print("Found branch %s to open PR from" % from_branch)
else:
sys.exit(
"No branch in payload, you are required to define PULL_REQUEST_FROM_BRANCH in the environment."
)
# If it's to the target branch, ignore it
if from_branch == pull_request_branch:
print("Target and current branch are identical (%s), skipping." % from_branch)
else:
# If the prefix for the branch matches
if not branch_prefix or from_branch.startswith(branch_prefix):
# Pull request body (optional)
pull_request_body = os.environ.get(
"PULL_REQUEST_BODY",
"This is an automated pull request to update from branch %s"
% from_branch,
)
print("::group::pull request body")
print(pull_request_body)
print("::endgroup::pull request body")
# Pull request title (optional)
pull_request_title = os.environ.get(
"PULL_REQUEST_TITLE", "Update from %s" % from_branch
)
print("::group::pull request title")
print(pull_request_title)
print("::endgroup::pull request title")
# Create the pull request
create_pull_request(
target=pull_request_branch,
source=from_branch,
body=pull_request_body,
title=pull_request_title,
is_draft=pull_request_draft,
can_modify=maintainer_can_modify,
assignees=assignees,
reviewers=reviewers,
team_reviewers=team_reviewers,
)
if __name__ == "__main__":
print("==========================================================================")
print("START: Running Pull Request on Branch Update Action!")
main()
print("==========================================================================")
print("END: Finished")

143
pull-request.sh Executable file
View File

@@ -0,0 +1,143 @@
#!/bin/bash
# Suggested by Github actions to be strict
set -e
set -o pipefail
################################################################################
# Global Variables (we can't use GITHUB_ prefix)
################################################################################
API_VERSION=v3
BASE=https://api.github.com
AUTH_HEADER="Authorization: token ${GITHUB_TOKEN}"
HEADER="Accept: application/vnd.github.${API_VERSION}+json"
HEADER="${HEADER}; application/vnd.github.antiope-preview+json; application/vnd.github.shadow-cat-preview+json"
# URLs
REPO_URL="${BASE}/repos/${GITHUB_REPOSITORY}"
PULLS_URL=$REPO_URL/pulls
################################################################################
# Helper Functions
################################################################################
check_credentials() {
if [[ -z "${GITHUB_TOKEN}" ]]; then
echo "You must include the GITHUB_TOKEN as an environment variable."
exit 1
fi
}
check_events_json() {
if [[ ! -f "${GITHUB_EVENT_PATH}" ]]; then
echo "Cannot find Github events file at ${GITHUB_EVENT_PATH}";
exit 1;
fi
echo "Found ${GITHUB_EVENT_PATH}";
}
create_pull_request() {
SOURCE="${1}" # from this branch
TARGET="${2}" # pull request TO this target
BODY="${3}" # this is the content of the message
TITLE="${4}" # pull request title
DRAFT="${5}" # if PRs are draft
# Check if the branch already has a pull request open
DATA="{\"base\":\"${TARGET}\", \"head\":\"${SOURCE}\", \"body\":\"${BODY}\"}"
RESPONSE=$(curl -sSL -H "${AUTH_HEADER}" -H "${HEADER}" --user "${GITHUB_ACTOR}" -X GET --data "${DATA}" ${PULLS_URL})
PR=$(echo "${RESPONSE}" | jq --raw-output '.[] | .head.ref')
echo "Response ref: ${PR}"
# Option 1: The pull request is already open
if [[ "${PR}" == "${SOURCE}" ]]; then
echo "Pull request from ${SOURCE} to ${TARGET} is already open!"
# Option 2: Open a new pull request
else
# Post the pull request
DATA="{\"title\":\"${TITLE}\", \"base\":\"${TARGET}\", \"head\":\"${SOURCE}\", \"draft\":\"${DRAFT}\"}"
echo "curl --user ${GITHUB_ACTOR} -X POST --data ${DATA} ${PULLS_URL}"
curl -sSL -H "${AUTH_HEADER}" -H "${HEADER}" --user "${GITHUB_ACTOR}" -X POST --data "${DATA}" ${PULLS_URL}
echo $?
fi
}
main () {
# path to file that contains the POST response of the event
# Example: https://github.com/actions/bin/tree/master/debug
# Value: /github/workflow/event.json
check_events_json;
# User specified branch to PR to, and check
if [ -z "${BRANCH_PREFIX}" ]; then
echo "No branch prefix is set, all branches will be used."
BRANCH_PREFIX=""
echo "Branch prefix is $BRANCH_PREFIX"
fi
if [ -z "${PULL_REQUEST_BRANCH}" ]; then
PULL_REQUEST_BRANCH=master
fi
echo "Pull requests will go to ${PULL_REQUEST_BRANCH}"
if [ -z "${PULL_REQUEST_DRAFT}" ]; then
echo "No explicit preference for draft PR: created PRs will be normal PRs."
PULL_REQUEST_DRAFT="false"
else
echo "Environment variable PULL_REQUEST_DRAFT set to a value: created PRs will be draft PRs."
PULL_REQUEST_DRAFT="true"
fi
# Get the name of the action that was triggered
BRANCH=$(jq --raw-output .ref "${GITHUB_EVENT_PATH}");
BRANCH=$(echo "${BRANCH/refs\/heads\//}")
echo "Found branch $BRANCH"
# If it's to the target branch, ignore it
if [[ "${BRANCH}" == "${PULL_REQUEST_BRANCH}" ]]; then
echo "Target and current branch are identical (${BRANCH}), skipping."
else
# If the prefix for the branch matches
if [[ $BRANCH == ${BRANCH_PREFIX}* ]]; then
# Ensure we have a GitHub token
check_credentials
# Pull request body (optional)
if [ -z "${PULL_REQUEST_BODY}" ]; then
echo "No pull request body is set, will use default."
PULL_REQUEST_BODY="This is an automated pull request to update the container collection ${BRANCH}"
echo "Pull request body is ${PULL_REQUEST_BODY}"
fi
# Pull request title (optional)
if [ -z "${PULL_REQUEST_TITLE}" ]; then
echo "No pull request title is set, will use default."
PULL_REQUEST_TITLE="Update container ${BRANCH}"
echo "Pull request title is ${PULL_REQUEST_TITLE}"
fi
create_pull_request $BRANCH $PULL_REQUEST_BRANCH $PULL_REQUEST_BODY $PULL_REQUEST_TITLE $PULL_REQUEST_DRAFT
fi
fi
}
echo "==========================================================================
START: Running Pull Request on Branch Update Action!";
main;
echo "==========================================================================
END: Finished";