13 Commits

Author SHA1 Message Date
Vanessasaurus
d987bc1511 Merge pull request #22 from vsoch/add/support-null-branch
Add/support null branch
2020-03-17 11:37:29 -06:00
vsoch
4ae1c5e25c adding examples for push and release
Signed-off-by: vsoch <vsochat@stanford.edu>
2020-03-17 11:36:44 -06:00
vsoch
d0c1b9ddb0 adding PR_BRANCH_FROM to support null use case
Signed-off-by: vsoch <vsochat@stanford.edu>
2020-03-17 10:50:25 -06:00
Srdjan Grubor
a3c90d58a7 Fix action branch logic for pull requests
Without this change, `BRANCH` will be `null` for triggers that don't
have an associated branch like `release: [published]`.

Closes #20
2020-03-17 11:27:27 -05:00
vsoch
a3ee64d51c Merge branch 'master' of github.com:vsoch/pull-request-action 2020-02-05 10:09:47 -07:00
vsoch
a46f168cf9 updating link to example
Signed-off-by: vsoch <vsochat@stanford.edu>
2020-02-05 10:09:33 -07:00
Vanessasaurus
02aa792cc8 Merge pull request #16 from vsoch/add/action.yml
adding action.yml to test
2020-02-05 10:08:38 -07:00
vsoch
d7dede2212 adding action.yml to test
Signed-off-by: vsoch <vsochat@stanford.edu>
2020-02-05 10:00:44 -07:00
Carl Sutton
b94f438ea0 Use alpine instead of ubuntu so the build is faster (#14) 2019-12-07 12:19:22 -08:00
Vanessasaurus
ca8460101c fixing up GitHub action to work with yaml syntax (#11)
Signed-off-by: Vanessa Sochat <vsochat@stanford.edu>
2019-10-19 09:36:46 -04:00
Godfrey Chan
e54bcbb815 Quote JSON Strings (#8)
The previous approach causes problems when there are e.g. newlines in the pull
request body. Also, the `draft` parameter was previously passed as a JSON
string (`"draft": "true"` and `"draft": "false"`, as opposed to `"draft": true`
and `"draft": false`), which I suspect is just a bug.
2019-08-23 11:03:18 -04:00
Vanessasaurus
0b6c3279d5 Adding body 2019-05-21 02:06:27 -07:00
Vanessasaurus
4ffa883947 Adding more quotes, debug prints 2019-05-21 01:59:51 -07:00
6 changed files with 206 additions and 56 deletions

View File

@@ -1,4 +1,4 @@
FROM debian:jessie-slim FROM alpine
# docker build -t vanessa/pull-request-action . # docker build -t vanessa/pull-request-action .
@@ -7,7 +7,7 @@ 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 apt-get update && apt-get install -y jq curl wget git RUN apk --no-cache add curl wget git bash jq
COPY pull-request.sh /pull-request.sh COPY pull-request.sh /pull-request.sh
RUN chmod u+x /pull-request.sh RUN chmod u+x /pull-request.sh

103
README.md
View File

@@ -5,34 +5,87 @@ whenever a branch with some prefix is pushed to. The idea is that you can
set up some workflow that pushes content to branches of the repostory, set up some workflow that pushes content to branches of the repostory,
and you would then want this push reviewed for merge to master. and you would then want this push reviewed for merge to master.
Here is an example of what to put in your `.github/main.workflow` file to Here is an example of what to put in your `.github/workflows/pull-request.yml` file to
trigger the action. trigger the action.
``` ```yaml
workflow "Create Pull Request" { name: Pull Request on Branch Push
on = "push" on:
resolves = "Create New Pull Request" push:
} branches-ignore:
- staging
action "Create New Pull Request" { - launchpad
uses = "vsoch/pull-request-action@master" - production
secrets = [ jobs:
"GITHUB_TOKEN" auto-pull-request:
] name: PullRequestAction
env = { runs-on: ubuntu-latest
BRANCH_PREFIX = "update/" steps:
PULL_REQUEST_BRANCH = "master" - name: pull-request-action
} uses: vsoch/pull-request-action@1.0.2
} env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: "update/"
PULL_REQUEST_BRANCH: "master"
``` ```
Environment variables include: ## Environment Variables
Unlike standard actions, this action just uses variables from the environment.
| Name | Description | Required | Default |
|------|-------------|----------|---------|
| BRANCH_PREFIX | the prefix to filter to. If the branch doesn't start with the prefix, it will be ignored | 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 | false |
All booleans should be lowercase.
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.
## 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.2
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.
- **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.
- **PULL_REQUEST_BODY**: the body for the pull request (optional)
- **PULL_REQUEST_TITLE**: the title for the pull request (optional)
- **PULL_REQUEST_DRAFT**: should the pull request be a draft PR? (optional; unset defaults to `false`)
## Example use Case: Update Registry ## Example use Case: Update Registry
@@ -45,4 +98,6 @@ registry to update it.
- the container collection metadata is pushed to a new branch on the registry repository, with namespace matching the GitHub repository, meaning that each GitHub repository always has a unique branch for its content. - the container collection metadata is pushed to a new branch on the registry repository, with namespace matching the GitHub repository, meaning that each GitHub repository always has a unique branch for its content.
- pushing this branch that starts with the prefix (update/<namespace>) triggers the GitHub actions to open the pull request. - pushing this branch that starts with the prefix (update/<namespace>) triggers the GitHub actions to open the pull request.
If the branch is already open for PR, it updates it. If the branch is already open for PR, it updates it. Take a look at [this example](https://github.com/singularityhub/registry-org/pull/8)
for the pull request opened when we updated the previous GitHub syntax to the new yaml syntax. Although this
doesn't describe the workflow above, it works equivalently in terms of the triggers.

9
action.yml Normal file
View File

@@ -0,0 +1,9 @@
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'

18
examples/push-example.yml Normal file
View File

@@ -0,0 +1,18 @@
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

@@ -0,0 +1,48 @@
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

@@ -26,7 +26,7 @@ PULLS_URL=$REPO_URL/pulls
check_credentials() { check_credentials() {
if [[ -z "${GITHUB_TOKEN}" ]]; then if [[ -z "${GITHUB_TOKEN}" ]]; then
echo "You must include the GITHUB_TOKEN as an environment variable." printf "You must include the GITHUB_TOKEN as an environment variable.\n"
exit 1 exit 1
fi fi
@@ -35,37 +35,44 @@ check_credentials() {
check_events_json() { check_events_json() {
if [[ ! -f "${GITHUB_EVENT_PATH}" ]]; then if [[ ! -f "${GITHUB_EVENT_PATH}" ]]; then
echo "Cannot find Github events file at ${GITHUB_EVENT_PATH}"; printf "Cannot find Github events file at ${GITHUB_EVENT_PATH}\n";
exit 1; exit 1;
fi fi
echo "Found ${GITHUB_EVENT_PATH}"; printf "Found ${GITHUB_EVENT_PATH}\n";
} }
create_pull_request() { create_pull_request() {
SOURCE="${1}" # from this branch # JSON strings
TARGET="${2}" # pull request TO this target SOURCE="$(echo -n "${1}" | jq --raw-input --slurp ".")" # from this branch
BODY="${3}" # this is the content of the message TARGET="$(echo -n "${2}" | jq --raw-input --slurp ".")" # pull request TO this target
TITLE="${4}" # pull request title BODY="$(echo -n "${3}" | jq --raw-input --slurp ".")" # this is the content of the message
DRAFT="${5}" # if PRs are draft TITLE="$(echo -n "${4}" | jq --raw-input --slurp ".")" # pull request title
# Check if the branch already has a pull request open # JSON boolean
if [[ "${5}" == "true" ]]; then # if PRs are draft
DRAFT="true";
else
DRAFT="false";
fi
DATA="{\"base\":\"${TARGET}\", \"head\":\"${SOURCE}\", \"body\":\"${BODY}\"}" # 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}) 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') PR=$(echo "${RESPONSE}" | jq --raw-output '.[] | .head.ref')
echo "Response ref: ${PR}" printf "Response ref: ${PR}\n"
# Option 1: The pull request is already open # Option 1: The pull request is already open
if [[ "${PR}" == "${SOURCE}" ]]; then if [[ "${PR}" == "${SOURCE}" ]]; then
echo "Pull request from ${SOURCE} to ${TARGET} is already open!" printf "Pull request from ${SOURCE} to ${TARGET} is already open!\n"
# Option 2: Open a new pull request # Option 2: Open a new pull request
else else
# Post the pull request # Post the pull request
DATA="{\"title\":\"${TITLE}\", \"base\":\"${TARGET}\", \"head\":\"${SOURCE}\", \"draft\":\"${DRAFT}\"}" DATA="{\"title\":${TITLE}, \"body\":${BODY}, \"base\":${TARGET}, \"head\":${SOURCE}, \"draft\":${DRAFT}}"
echo "curl --user ${GITHUB_ACTOR} -X POST --data ${DATA} ${PULLS_URL}" printf "curl --user ${GITHUB_ACTOR} -X POST --data ${DATA} ${PULLS_URL}\n"
curl -sSL -H "${AUTH_HEADER}" -H "${HEADER}" --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 $? echo $?
fi fi
@@ -81,32 +88,45 @@ main () {
# User specified branch to PR to, and check # User specified branch to PR to, and check
if [ -z "${BRANCH_PREFIX}" ]; then if [ -z "${BRANCH_PREFIX}" ]; then
echo "No branch prefix is set, all branches will be used." printf "No branch prefix is set, all branches will be used.\n"
BRANCH_PREFIX="" BRANCH_PREFIX=""
echo "Branch prefix is $BRANCH_PREFIX" printf "Branch prefix is $BRANCH_PREFIX\n"
fi fi
if [ -z "${PULL_REQUEST_BRANCH}" ]; then if [ -z "${PULL_REQUEST_BRANCH}" ]; then
PULL_REQUEST_BRANCH=master PULL_REQUEST_BRANCH=master
fi fi
echo "Pull requests will go to ${PULL_REQUEST_BRANCH}" printf "Pull requests will go to ${PULL_REQUEST_BRANCH}\n"
if [ -z "${PULL_REQUEST_DRAFT}" ]; then if [ -z "${PULL_REQUEST_DRAFT}" ]; then
echo "No explicit preference for draft PR: created PRs will be normal PRs." printf "No explicit preference for draft PR: created PRs will be normal PRs.\n"
PULL_REQUEST_DRAFT="false" PULL_REQUEST_DRAFT="false"
else else
echo "Environment variable PULL_REQUEST_DRAFT set to a value: created PRs will be draft PRs." printf "Environment variable PULL_REQUEST_DRAFT set to a value: created PRs will be draft PRs.\n"
PULL_REQUEST_DRAFT="true" PULL_REQUEST_DRAFT="true"
fi fi
# Get the name of the action that was triggered # The user is allowed to explicitly set the name of the branch
BRANCH=$(jq --raw-output .ref "${GITHUB_EVENT_PATH}"); if [ -z "${PULL_REQUEST_FROM_BRANCH}" ]; then
BRANCH=$(echo "${BRANCH/refs\/heads\//}") printf "PULL_REQUEST_FROM_BRANCH is not set, checking branch in payload.\n"
echo "Found branch $BRANCH" BRANCH=$(jq --raw-output .ref "${GITHUB_EVENT_PATH}");
BRANCH=$(echo "${BRANCH/refs\/heads\//}")
else
printf "PULL_REQUEST_FROM_BRANCH is set.\n"
BRANCH="${PULL_REQUEST_FROM_BRANCH}"
fi
# At this point, we must have a branch
if [[ "$BRANCH" != "null" ]]; then
printf "Found branch $BRANCH to open PR from\n"
else
printf "No branch in payload, you are required to define PULL_REQUEST_FROM_BRANCH in the environment.\n"
exit 1
fi
# If it's to the target branch, ignore it # If it's to the target branch, ignore it
if [[ "${BRANCH}" == "${PULL_REQUEST_BRANCH}" ]]; then if [[ "${BRANCH}" == "${PULL_REQUEST_BRANCH}" ]]; then
echo "Target and current branch are identical (${BRANCH}), skipping." printf "Target and current branch are identical (${BRANCH}), skipping.\n"
else else
# If the prefix for the branch matches # If the prefix for the branch matches
@@ -119,17 +139,17 @@ main () {
if [ -z "${PULL_REQUEST_BODY}" ]; then if [ -z "${PULL_REQUEST_BODY}" ]; then
echo "No pull request body is set, will use default." 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}" PULL_REQUEST_BODY="This is an automated pull request to update the container collection ${BRANCH}"
echo "Pull request body is ${PULL_REQUEST_BODY}"
fi fi
printf "Pull request body is ${PULL_REQUEST_BODY}\n"
# Pull request title (optional) # Pull request title (optional)
if [ -z "${PULL_REQUEST_TITLE}" ]; then if [ -z "${PULL_REQUEST_TITLE}" ]; then
echo "No pull request title is set, will use default." printf "No pull request title is set, will use default.\n"
PULL_REQUEST_TITLE="Update container ${BRANCH}" PULL_REQUEST_TITLE="Update container ${BRANCH}"
echo "Pull request title is ${PULL_REQUEST_TITLE}"
fi fi
printf "Pull request title is ${PULL_REQUEST_TITLE}\n"
create_pull_request $BRANCH $PULL_REQUEST_BRANCH $PULL_REQUEST_BODY $PULL_REQUEST_TITLE $PULL_REQUEST_DRAFT create_pull_request "${BRANCH}" "${PULL_REQUEST_BRANCH}" "${PULL_REQUEST_BODY}" "${PULL_REQUEST_TITLE}" "${PULL_REQUEST_DRAFT}"
fi fi