feat: adding support for a proxy

This commit is contained in:
Michael Shick 2020-07-06 21:47:29 -04:00
parent fdfdba3fa2
commit b62030a7fc
No known key found for this signature in database
GPG key ID: ADF5BC9704BB4A61
3 changed files with 96 additions and 17 deletions

View file

@ -4,9 +4,7 @@
## Limitations
Due to how GitHub handles permissions in PRs coming from forks, this action is limited to PRs based on branches. See this issue: https://github.community/t/github-actions-are-severely-limited-on-prs/18179/4 for more detail.
I'm currently investigating a workaround via a simple bot you can easily deploy. More soon...
Due to how GitHub handles permissions in PRs coming from forks you will need to deploy an app if you want to post comments in those situations. [See below](#proxy-for-fork-based-prs).
## Usage
@ -60,6 +58,31 @@ jobs:
| allow-repeats | with | A boolean flag to allow identical messages to be posted each time this action is run | no | false |
| GITHUB_TOKEN | env | A valid GitHub token, can alternatively be defined in the env | maybe | |
## Proxy for Fork-based PRs
GitHub limits `GITHUB_TOKEN` and other API access token permissions when creating a PR from a fork. This makes it impossible to add comments when your PRs are coming from forks, which is the norm for open source projects. To work around this situation I've created a simple companion app you can deploy to Cloud Run or another environment to proxy the create comment requests and escalate the token privileges.
See this issue: https://github.community/t/github-actions-are-severely-limited-on-prs/18179/4 for more detail.
**Example**
```yaml
on:
pull_request:
jobs:
pr:
runs-on: ubuntu-latest
steps:
- uses: mshick/add-pr-comment@v1
with:
message: |
**Howdie!**
proxy-url: https://add-pr-comment-proxy-94idvmwyie-uc.a.run.app/
proxy-secret: foobar
repo-token: ${{ secrets.GITHUB_TOKEN }}
```
## Features
- Fast, runs in the GitHub Actions node.js runtime; no Docker pull needed.

View file

@ -14,6 +14,12 @@ inputs:
description: "Allow messages to be repeated."
required: false
default: "false"
proxy-url:
description: "Proxy URL for comment creation"
required: false
proxy-secret:
description: "A secret to use for authenticating against the proxy"
required: false
branding:
icon: message-circle
color: purple

View file

@ -4,13 +4,7 @@ import {HttpClient} from '@actions/http-client'
import {Endpoints, RequestHeaders, IssuesListCommentsResponseData} from '@octokit/types'
type ListCommitPullsResponse = Endpoints['GET /repos/:owner/:repo/commits/:commit_sha/pulls']['response']['data']
interface AddPrCommentInputs {
allowRepeats: boolean
message: string
repoToken?: string
repoTokenUserLogin?: string
}
type CreateIssueCommentResponseData = Endpoints['POST /repos/:owner/:repo/issues/:issue_number/comments']['response']['data']
interface ListCommitPullsParams {
repoToken: string
@ -40,6 +34,35 @@ const listCommitPulls = async (params: ListCommitPullsParams): Promise<ListCommi
const getIssueNumberFromCommitPullsList = (commitPullsList: ListCommitPullsResponse): number | null =>
commitPullsList.length ? commitPullsList[0].number : null
interface CreateCommentProxyParams {
repoToken: string
body: string
owner: string
repo: string
issueNumber: number
proxyUrl: string
proxySecret: string
}
const createCommentProxy = async (params: CreateCommentProxyParams): Promise<CreateIssueCommentResponseData | null> => {
const {repoToken, owner, repo, issueNumber, body, proxyUrl, proxySecret} = params
const http = new HttpClient('http-client-add-pr-comment')
const additionalHeaders: RequestHeaders = {
authorization: `basic ${Buffer.from(proxySecret + ':').toString('base64')}`,
['temporary-github-token']: repoToken,
}
const response = await http.postJson<CreateIssueCommentResponseData>(
`${proxyUrl}/repos/${owner}/${repo}/issues/${issueNumber}/comments`,
{body},
additionalHeaders,
)
return response.result
}
const isMessagePresent = (
message: AddPrCommentInputs['message'],
comments: IssuesListCommentsResponseData,
@ -58,10 +81,21 @@ const isMessagePresent = (
})
}
interface AddPrCommentInputs {
allowRepeats: boolean
message: string
proxySecret?: string
proxyUrl?: string
repoToken?: string
repoTokenUserLogin?: string
}
const getInputs = (): AddPrCommentInputs => {
return {
allowRepeats: Boolean(core.getInput('allow-repeats') === 'true'),
message: core.getInput('message'),
proxySecret: core.getInput('proxy-secret'),
proxyUrl: core.getInput('proxy-url'),
repoToken: core.getInput('repo-token') || process.env['GITHUB_TOKEN'],
repoTokenUserLogin: core.getInput('repo-token-user-login'),
}
@ -69,7 +103,7 @@ const getInputs = (): AddPrCommentInputs => {
const run = async (): Promise<void> => {
try {
const {allowRepeats, message, repoToken, repoTokenUserLogin} = getInputs()
const {allowRepeats, message, repoToken, repoTokenUserLogin, proxyUrl, proxySecret} = getInputs()
if (!repoToken) {
throw new Error('no github token provided, set one with the repo-token input or GITHUB_TOKEN env variable')
@ -125,12 +159,28 @@ const run = async (): Promise<void> => {
}
if (shouldCreateComment) {
if (proxyUrl) {
if (!proxySecret) {
throw new Error('proxy-url defined, but proxy-secret is missing')
}
await createCommentProxy({
owner,
repo,
issueNumber,
body: message,
repoToken,
proxyUrl,
proxySecret,
})
} else {
await octokit.issues.createComment({
owner,
repo,
issue_number: issueNumber,
body: message,
})
}
core.setOutput('comment-created', 'true')
} else {