mirror of
https://github.com/joelwmale/webhook-action.git
synced 2024-08-25 08:08:00 +00:00
Compare commits
No commits in common. "develop" and "1.0.1" have entirely different histories.
@ -1,2 +0,0 @@
|
|||||||
dist
|
|
||||||
node_nodules
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
"es6": true,
|
|
||||||
"jest": true
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"Atomics": "readonly",
|
|
||||||
"SharedArrayBuffer": "readonly"
|
|
||||||
},
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 9,
|
|
||||||
"sourceType": "module",
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"jest",
|
|
||||||
"@typescript-eslint"
|
|
||||||
],
|
|
||||||
"extends": [
|
|
||||||
"plugin:github/recommended",
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
|
||||||
"github/no-then": "off",
|
|
||||||
"import/no-namespace": "off",
|
|
||||||
"i18n-text/no-en": "off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
@ -1,9 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
# Enable version updates for npm
|
|
||||||
- package-ecosystem: "npm"
|
|
||||||
# Look for `package.json` and `lock` files in the `root` directory
|
|
||||||
directory: "/"
|
|
||||||
# Check the npm registry for updates every day (weekdays)
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
40
.github/workflows/tests.yml
vendored
40
.github/workflows/tests.yml
vendored
@ -1,40 +0,0 @@
|
|||||||
name: Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
release:
|
|
||||||
types:
|
|
||||||
- created
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests:
|
|
||||||
name: Tests
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: true
|
|
||||||
matrix:
|
|
||||||
node-version: [20.x]
|
|
||||||
stability: [prefer-stable]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
cache: 'yarn'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: yarn install --frozen-lockfile --${{ matrix.stability }}
|
|
||||||
|
|
||||||
- name: Execute tests
|
|
||||||
run: yarn test
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
node_modules/*
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
dist/
|
|
||||||
lib/
|
|
||||||
node_modules/
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 80,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false,
|
|
||||||
"semi": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"bracketSpacing": false,
|
|
||||||
"arrowParens": "avoid"
|
|
||||||
}
|
|
||||||
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM debian:9.8-slim
|
||||||
|
|
||||||
|
LABEL "version"="1.0.0"
|
||||||
|
LABEL "repository"="https://github.com/joelwmale/webhook-action"
|
||||||
|
LABEL "homepage"="https://github.com/joelwmale/webhook-action"
|
||||||
|
LABEL "maintainer"="Joel Male <joel@joelmale.com>"
|
||||||
|
LABEL "com.github.actions.name"="Webhook Action"
|
||||||
|
LABEL "com.github.actions.description"="Posts data to an endpoint on any event"
|
||||||
|
LABEL "com.github.actions.icon"="message-square"
|
||||||
|
LABEL "com.github.actions.color"="gray-dark"
|
||||||
|
|
||||||
|
# Install curl
|
||||||
|
RUN apt-get update && apt-get install -y curl
|
||||||
|
|
||||||
|
# Add the entry point
|
||||||
|
ADD entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
# Load the entry point
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
103
README.md
103
README.md
@ -3,7 +3,7 @@
|
|||||||
[![GitHub Release][ico-release]][link-github-release]
|
[![GitHub Release][ico-release]][link-github-release]
|
||||||
[![License][ico-license]](LICENSE)
|
[![License][ico-license]](LICENSE)
|
||||||
|
|
||||||
A Github Action for sending a webhook event any endpoint
|
A Github Action for sending data to an endpoint
|
||||||
|
|
||||||
Supports all [workflow event types](https://developer.github.com/webhooks/#events)
|
Supports all [workflow event types](https://developer.github.com/webhooks/#events)
|
||||||
|
|
||||||
@ -11,96 +11,45 @@ Supports all [workflow event types](https://developer.github.com/webhooks/#event
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Example:
|
Sending a string:
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
- name: Webhook
|
- name: Webhook
|
||||||
uses: joelwmale/webhook-action@master
|
uses: joelwmale/webhook-action@master
|
||||||
with:
|
env:
|
||||||
url: ${{ secrets.WEBHOOK_URL }}
|
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
|
||||||
headers: '{"repository": "joelwmale/webhook-action"}'
|
data: "Hello from github actions!"
|
||||||
body: '{"event": "deployment", "repository": "joelwmale/webhook-action"}'
|
```
|
||||||
github_event_payload: true
|
|
||||||
|
Sending a body of data:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
- name: Webhook
|
||||||
|
uses: joelwmale/webhook-action@master
|
||||||
|
env:
|
||||||
|
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
|
||||||
|
data: "{'deployment': 'finished', 'project': 'actions'}"
|
||||||
```
|
```
|
||||||
|
|
||||||
It is **highly** recommended to use the action is an explicit commit SHA-1:
|
It is **highly** recommended to use the action is an explicit commit SHA-1:
|
||||||
|
|
||||||
`uses = "joelwmale/webhook-action@{SHA-1}"` to find a commit click [here.](https://github.com/joelwmale/webhook-action/commits/master)
|
`uses = "joelwmale/webhook-action@{SHA-1}"` to find a commit click here: https://github.com/joelwmale/webhook-action/commits/master
|
||||||
|
|
||||||
## Action Input
|
### Arguments
|
||||||
|
|
||||||
The action has support for the following input variables (arguments):
|
* ```yml
|
||||||
|
data: "Hello from github actions!"
|
||||||
|
```
|
||||||
|
|
||||||
* **`url`** (**required**): The url to send the webhook to
|
* ```yml
|
||||||
* **`headers`** (**optional**): Any headers you want to be sent with the webhook
|
data: "{'deployment': 'finished', 'project': 'actions'}"
|
||||||
* **`body`** (**optional**): The body of data send with the webhook
|
```
|
||||||
* **`insecure`** (**optional**): Enables calling to known self-signed or invalid SSL certificates
|
|
||||||
* **`github_event_payload`** (**optional**): Enables forwarding the Github event payload to your webhook.
|
|
||||||
|
|
||||||
You can find more information on how to use these input variables below.
|
### Environment
|
||||||
|
|
||||||
## Arguments
|
The action is expecting a single environment variable of your data. This can be pre-encoded json string, or just a message. Format it to how your API is expecting.
|
||||||
|
|
||||||
#### URL
|
* **`WEBHOOK_URL`** (**required**): This is the webhook url to send the payload to.
|
||||||
|
|
||||||
**Required:** true
|
|
||||||
|
|
||||||
The URL to send the webhook to
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url: ${{ secrets.WEBHOOK_URL }}
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url: https://webhook.site/8b1b1b1b-8b1b-8b1b-8b1b-8b1b1b1b1b1b
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Headers
|
|
||||||
|
|
||||||
**Required:** false
|
|
||||||
|
|
||||||
Allows you to send custom headers with the request
|
|
||||||
|
|
||||||
```yml
|
|
||||||
headers: '{"repository": "joelwmale/webhook-action"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Body
|
|
||||||
|
|
||||||
**Required:** false
|
|
||||||
**Must be a stringified JSON payload**
|
|
||||||
|
|
||||||
Allows you to send a custom JSON object to the webhook
|
|
||||||
|
|
||||||
```yml
|
|
||||||
body: '{"event": "deployment", "repository": "joelwmale/webhook-action"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Insecure
|
|
||||||
|
|
||||||
**Required:** false
|
|
||||||
**Default:** false
|
|
||||||
|
|
||||||
Allows you to send a webhook to a known self-signed or invalid SSL certificate
|
|
||||||
|
|
||||||
```yml
|
|
||||||
insecure: true
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Github Event Payload
|
|
||||||
|
|
||||||
**Required:** false
|
|
||||||
**Default:** false
|
|
||||||
|
|
||||||
Allows you to send the Github event payload to your webhook
|
|
||||||
|
|
||||||
The payload will be sent as a JSON object under the key `githubEventPayload` on the root of the payload sent to your webhook
|
|
||||||
|
|
||||||
```yml
|
|
||||||
github_event_payload: true
|
|
||||||
```
|
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
import {http} from '../src/http'
|
|
||||||
import {expect, test} from '@jest/globals'
|
|
||||||
|
|
||||||
test('it makes a post request', async () => {
|
|
||||||
const url = 'https://httpbin.org/post'
|
|
||||||
const body = '{"hello": "world"}'
|
|
||||||
const res = await http.make(url, body)
|
|
||||||
expect(res.status).toBe(200)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('it makes a post request with insecure', async () => {
|
|
||||||
const url = 'https://httpbin.org/post'
|
|
||||||
const body = '{"hello": "world"}'
|
|
||||||
const insecure = true
|
|
||||||
const res = await http.make(url, body, null, insecure)
|
|
||||||
expect(res.status).toBe(200)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('it makes a post request with headers', async () => {
|
|
||||||
const url = 'https://httpbin.org/post'
|
|
||||||
const body = '{"hello": "world"}'
|
|
||||||
const headers = '{"Content-Type": "application/json"}'
|
|
||||||
const res = await http.make(url, body, headers)
|
|
||||||
expect(res.status).toBe(200)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('it doesnt require a body', async () => {
|
|
||||||
const url = 'https://httpbin.org/post'
|
|
||||||
const res = await http.make(url, null)
|
|
||||||
expect(res.status).toBe(200)
|
|
||||||
})
|
|
||||||
28
action.yml
28
action.yml
@ -1,28 +0,0 @@
|
|||||||
name: 'Webhook Action'
|
|
||||||
author: "Joel Male"
|
|
||||||
description: 'Send a webhook event to anywhere!'
|
|
||||||
branding:
|
|
||||||
icon: 'alert-octagon'
|
|
||||||
color: 'gray-dark'
|
|
||||||
inputs:
|
|
||||||
url:
|
|
||||||
description: 'The url to send the webhook event to'
|
|
||||||
required: true
|
|
||||||
headers:
|
|
||||||
description: 'Additional headers to send alongside the defaults'
|
|
||||||
required: false
|
|
||||||
body:
|
|
||||||
description: 'The data sent to the webhook'
|
|
||||||
required: false
|
|
||||||
insecure:
|
|
||||||
description: 'Enables calling to known self-signed or invalid SSL certificates'
|
|
||||||
required: false
|
|
||||||
github_event_payload:
|
|
||||||
description: 'Include the github event payload that triggered the action in the payload'
|
|
||||||
required: false
|
|
||||||
outputs:
|
|
||||||
status:
|
|
||||||
description: 'The status of the webhook event'
|
|
||||||
runs:
|
|
||||||
using: 'node20'
|
|
||||||
main: 'dist/index.js'
|
|
||||||
@ -1 +0,0 @@
|
|||||||
module.exports = {presets: ['@babel/preset-env']}
|
|
||||||
452
dist/37.index.js
vendored
452
dist/37.index.js
vendored
@ -1,452 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
exports.id = 37;
|
|
||||||
exports.ids = [37];
|
|
||||||
exports.modules = {
|
|
||||||
|
|
||||||
/***/ 4037:
|
|
||||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
||||||
|
|
||||||
__webpack_require__.r(__webpack_exports__);
|
|
||||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
||||||
/* harmony export */ "toFormData": () => (/* binding */ toFormData)
|
|
||||||
/* harmony export */ });
|
|
||||||
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2777);
|
|
||||||
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8010);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let s = 0;
|
|
||||||
const S = {
|
|
||||||
START_BOUNDARY: s++,
|
|
||||||
HEADER_FIELD_START: s++,
|
|
||||||
HEADER_FIELD: s++,
|
|
||||||
HEADER_VALUE_START: s++,
|
|
||||||
HEADER_VALUE: s++,
|
|
||||||
HEADER_VALUE_ALMOST_DONE: s++,
|
|
||||||
HEADERS_ALMOST_DONE: s++,
|
|
||||||
PART_DATA_START: s++,
|
|
||||||
PART_DATA: s++,
|
|
||||||
END: s++
|
|
||||||
};
|
|
||||||
|
|
||||||
let f = 1;
|
|
||||||
const F = {
|
|
||||||
PART_BOUNDARY: f,
|
|
||||||
LAST_BOUNDARY: f *= 2
|
|
||||||
};
|
|
||||||
|
|
||||||
const LF = 10;
|
|
||||||
const CR = 13;
|
|
||||||
const SPACE = 32;
|
|
||||||
const HYPHEN = 45;
|
|
||||||
const COLON = 58;
|
|
||||||
const A = 97;
|
|
||||||
const Z = 122;
|
|
||||||
|
|
||||||
const lower = c => c | 0x20;
|
|
||||||
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
class MultipartParser {
|
|
||||||
/**
|
|
||||||
* @param {string} boundary
|
|
||||||
*/
|
|
||||||
constructor(boundary) {
|
|
||||||
this.index = 0;
|
|
||||||
this.flags = 0;
|
|
||||||
|
|
||||||
this.onHeaderEnd = noop;
|
|
||||||
this.onHeaderField = noop;
|
|
||||||
this.onHeadersEnd = noop;
|
|
||||||
this.onHeaderValue = noop;
|
|
||||||
this.onPartBegin = noop;
|
|
||||||
this.onPartData = noop;
|
|
||||||
this.onPartEnd = noop;
|
|
||||||
|
|
||||||
this.boundaryChars = {};
|
|
||||||
|
|
||||||
boundary = '\r\n--' + boundary;
|
|
||||||
const ui8a = new Uint8Array(boundary.length);
|
|
||||||
for (let i = 0; i < boundary.length; i++) {
|
|
||||||
ui8a[i] = boundary.charCodeAt(i);
|
|
||||||
this.boundaryChars[ui8a[i]] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.boundary = ui8a;
|
|
||||||
this.lookbehind = new Uint8Array(this.boundary.length + 8);
|
|
||||||
this.state = S.START_BOUNDARY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Uint8Array} data
|
|
||||||
*/
|
|
||||||
write(data) {
|
|
||||||
let i = 0;
|
|
||||||
const length_ = data.length;
|
|
||||||
let previousIndex = this.index;
|
|
||||||
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
|
|
||||||
const boundaryLength = this.boundary.length;
|
|
||||||
const boundaryEnd = boundaryLength - 1;
|
|
||||||
const bufferLength = data.length;
|
|
||||||
let c;
|
|
||||||
let cl;
|
|
||||||
|
|
||||||
const mark = name => {
|
|
||||||
this[name + 'Mark'] = i;
|
|
||||||
};
|
|
||||||
|
|
||||||
const clear = name => {
|
|
||||||
delete this[name + 'Mark'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const callback = (callbackSymbol, start, end, ui8a) => {
|
|
||||||
if (start === undefined || start !== end) {
|
|
||||||
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const dataCallback = (name, clear) => {
|
|
||||||
const markSymbol = name + 'Mark';
|
|
||||||
if (!(markSymbol in this)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clear) {
|
|
||||||
callback(name, this[markSymbol], i, data);
|
|
||||||
delete this[markSymbol];
|
|
||||||
} else {
|
|
||||||
callback(name, this[markSymbol], data.length, data);
|
|
||||||
this[markSymbol] = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; i < length_; i++) {
|
|
||||||
c = data[i];
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case S.START_BOUNDARY:
|
|
||||||
if (index === boundary.length - 2) {
|
|
||||||
if (c === HYPHEN) {
|
|
||||||
flags |= F.LAST_BOUNDARY;
|
|
||||||
} else if (c !== CR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
break;
|
|
||||||
} else if (index - 1 === boundary.length - 2) {
|
|
||||||
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
|
|
||||||
state = S.END;
|
|
||||||
flags = 0;
|
|
||||||
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
|
|
||||||
index = 0;
|
|
||||||
callback('onPartBegin');
|
|
||||||
state = S.HEADER_FIELD_START;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c !== boundary[index + 2]) {
|
|
||||||
index = -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c === boundary[index + 2]) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.HEADER_FIELD_START:
|
|
||||||
state = S.HEADER_FIELD;
|
|
||||||
mark('onHeaderField');
|
|
||||||
index = 0;
|
|
||||||
// falls through
|
|
||||||
case S.HEADER_FIELD:
|
|
||||||
if (c === CR) {
|
|
||||||
clear('onHeaderField');
|
|
||||||
state = S.HEADERS_ALMOST_DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
if (c === HYPHEN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c === COLON) {
|
|
||||||
if (index === 1) {
|
|
||||||
// empty header field
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataCallback('onHeaderField', true);
|
|
||||||
state = S.HEADER_VALUE_START;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl = lower(c);
|
|
||||||
if (cl < A || cl > Z) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.HEADER_VALUE_START:
|
|
||||||
if (c === SPACE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark('onHeaderValue');
|
|
||||||
state = S.HEADER_VALUE;
|
|
||||||
// falls through
|
|
||||||
case S.HEADER_VALUE:
|
|
||||||
if (c === CR) {
|
|
||||||
dataCallback('onHeaderValue', true);
|
|
||||||
callback('onHeaderEnd');
|
|
||||||
state = S.HEADER_VALUE_ALMOST_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.HEADER_VALUE_ALMOST_DONE:
|
|
||||||
if (c !== LF) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = S.HEADER_FIELD_START;
|
|
||||||
break;
|
|
||||||
case S.HEADERS_ALMOST_DONE:
|
|
||||||
if (c !== LF) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback('onHeadersEnd');
|
|
||||||
state = S.PART_DATA_START;
|
|
||||||
break;
|
|
||||||
case S.PART_DATA_START:
|
|
||||||
state = S.PART_DATA;
|
|
||||||
mark('onPartData');
|
|
||||||
// falls through
|
|
||||||
case S.PART_DATA:
|
|
||||||
previousIndex = index;
|
|
||||||
|
|
||||||
if (index === 0) {
|
|
||||||
// boyer-moore derrived algorithm to safely skip non-boundary data
|
|
||||||
i += boundaryEnd;
|
|
||||||
while (i < bufferLength && !(data[i] in boundaryChars)) {
|
|
||||||
i += boundaryLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
i -= boundaryEnd;
|
|
||||||
c = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < boundary.length) {
|
|
||||||
if (boundary[index] === c) {
|
|
||||||
if (index === 0) {
|
|
||||||
dataCallback('onPartData', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
} else if (index === boundary.length) {
|
|
||||||
index++;
|
|
||||||
if (c === CR) {
|
|
||||||
// CR = part boundary
|
|
||||||
flags |= F.PART_BOUNDARY;
|
|
||||||
} else if (c === HYPHEN) {
|
|
||||||
// HYPHEN = end boundary
|
|
||||||
flags |= F.LAST_BOUNDARY;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
} else if (index - 1 === boundary.length) {
|
|
||||||
if (flags & F.PART_BOUNDARY) {
|
|
||||||
index = 0;
|
|
||||||
if (c === LF) {
|
|
||||||
// unset the PART_BOUNDARY flag
|
|
||||||
flags &= ~F.PART_BOUNDARY;
|
|
||||||
callback('onPartEnd');
|
|
||||||
callback('onPartBegin');
|
|
||||||
state = S.HEADER_FIELD_START;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (flags & F.LAST_BOUNDARY) {
|
|
||||||
if (c === HYPHEN) {
|
|
||||||
callback('onPartEnd');
|
|
||||||
state = S.END;
|
|
||||||
flags = 0;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index > 0) {
|
|
||||||
// when matching a possible boundary, keep a lookbehind reference
|
|
||||||
// in case it turns out to be a false lead
|
|
||||||
lookbehind[index - 1] = c;
|
|
||||||
} else if (previousIndex > 0) {
|
|
||||||
// if our boundary turned out to be rubbish, the captured lookbehind
|
|
||||||
// belongs to partData
|
|
||||||
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
|
|
||||||
callback('onPartData', 0, previousIndex, _lookbehind);
|
|
||||||
previousIndex = 0;
|
|
||||||
mark('onPartData');
|
|
||||||
|
|
||||||
// reconsider the current character even so it interrupted the sequence
|
|
||||||
// it could be the beginning of a new sequence
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.END:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`Unexpected state entered: ${state}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dataCallback('onHeaderField');
|
|
||||||
dataCallback('onHeaderValue');
|
|
||||||
dataCallback('onPartData');
|
|
||||||
|
|
||||||
// Update properties for the next call
|
|
||||||
this.index = index;
|
|
||||||
this.state = state;
|
|
||||||
this.flags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
end() {
|
|
||||||
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
|
|
||||||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
|
|
||||||
this.onPartEnd();
|
|
||||||
} else if (this.state !== S.END) {
|
|
||||||
throw new Error('MultipartParser.end(): stream ended unexpectedly');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _fileName(headerValue) {
|
|
||||||
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
|
|
||||||
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
|
|
||||||
if (!m) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = m[2] || m[3] || '';
|
|
||||||
let filename = match.slice(match.lastIndexOf('\\') + 1);
|
|
||||||
filename = filename.replace(/%22/g, '"');
|
|
||||||
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
|
|
||||||
return String.fromCharCode(code);
|
|
||||||
});
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toFormData(Body, ct) {
|
|
||||||
if (!/multipart/i.test(ct)) {
|
|
||||||
throw new TypeError('Failed to fetch');
|
|
||||||
}
|
|
||||||
|
|
||||||
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
|
|
||||||
|
|
||||||
if (!m) {
|
|
||||||
throw new TypeError('no or bad content-type header, no multipart boundary');
|
|
||||||
}
|
|
||||||
|
|
||||||
const parser = new MultipartParser(m[1] || m[2]);
|
|
||||||
|
|
||||||
let headerField;
|
|
||||||
let headerValue;
|
|
||||||
let entryValue;
|
|
||||||
let entryName;
|
|
||||||
let contentType;
|
|
||||||
let filename;
|
|
||||||
const entryChunks = [];
|
|
||||||
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .Ct();
|
|
||||||
|
|
||||||
const onPartData = ui8a => {
|
|
||||||
entryValue += decoder.decode(ui8a, {stream: true});
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendToFile = ui8a => {
|
|
||||||
entryChunks.push(ui8a);
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendFileToFormData = () => {
|
|
||||||
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .$B(entryChunks, filename, {type: contentType});
|
|
||||||
formData.append(entryName, file);
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendEntryToFormData = () => {
|
|
||||||
formData.append(entryName, entryValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
const decoder = new TextDecoder('utf-8');
|
|
||||||
decoder.decode();
|
|
||||||
|
|
||||||
parser.onPartBegin = function () {
|
|
||||||
parser.onPartData = onPartData;
|
|
||||||
parser.onPartEnd = appendEntryToFormData;
|
|
||||||
|
|
||||||
headerField = '';
|
|
||||||
headerValue = '';
|
|
||||||
entryValue = '';
|
|
||||||
entryName = '';
|
|
||||||
contentType = '';
|
|
||||||
filename = null;
|
|
||||||
entryChunks.length = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderField = function (ui8a) {
|
|
||||||
headerField += decoder.decode(ui8a, {stream: true});
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderValue = function (ui8a) {
|
|
||||||
headerValue += decoder.decode(ui8a, {stream: true});
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderEnd = function () {
|
|
||||||
headerValue += decoder.decode();
|
|
||||||
headerField = headerField.toLowerCase();
|
|
||||||
|
|
||||||
if (headerField === 'content-disposition') {
|
|
||||||
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
|
|
||||||
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
|
|
||||||
|
|
||||||
if (m) {
|
|
||||||
entryName = m[2] || m[3] || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = _fileName(headerValue);
|
|
||||||
|
|
||||||
if (filename) {
|
|
||||||
parser.onPartData = appendToFile;
|
|
||||||
parser.onPartEnd = appendFileToFormData;
|
|
||||||
}
|
|
||||||
} else if (headerField === 'content-type') {
|
|
||||||
contentType = headerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
headerValue = '';
|
|
||||||
headerField = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
for await (const chunk of Body) {
|
|
||||||
parser.write(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.end();
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***/ })
|
|
||||||
|
|
||||||
};
|
|
||||||
;
|
|
||||||
28
dist/http.js
vendored
28
dist/http.js
vendored
@ -1,28 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.http = void 0;
|
|
||||||
const node_fetch_1 = require("node-fetch");
|
|
||||||
const https = require("https");
|
|
||||||
class Http {
|
|
||||||
make(url, body, headers = null, ignoreCertificate = false) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
(0, node_fetch_1.default)(url, this.getOptions('post', headers, body, ignoreCertificate)).then((res) => resolve(res));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
getOptions(method, headers, body, ignoreCertificate) {
|
|
||||||
const options = {
|
|
||||||
headers: headers ? JSON.parse(headers) : {},
|
|
||||||
method
|
|
||||||
};
|
|
||||||
if (body) {
|
|
||||||
options.body = body;
|
|
||||||
}
|
|
||||||
if (ignoreCertificate) {
|
|
||||||
options.agent = new https.Agent({ rejectUnauthorized: false });
|
|
||||||
}
|
|
||||||
options.headers['content-type'] = 'application/json';
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.http = new Http();
|
|
||||||
//# sourceMappingURL=http.js.map
|
|
||||||
1
dist/http.js.map
vendored
1
dist/http.js.map
vendored
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":";;;AAAA,2CAA8B;AAC9B,+BAA+B;AAE/B,MAAM,IAAI;IACR,IAAI,CACF,GAAW,EACX,IAAmB,EACnB,UAAyB,IAAI,EAC7B,oBAAoC,KAAK;QAEzC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAC3B,IAAA,oBAAK,EACH,GAAG,EACH,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAC1D,CAAC,IAAI,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,UAAU,CACR,MAAc,EACd,OAAsB,EACtB,IAAmB,EACnB,iBAAiC;QAEjC,MAAM,OAAO,GAAQ;YACnB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;YAC3C,MAAM;SACP,CAAA;QAED,IAAI,IAAI,EAAE,CAAC;YAET,OAAO,CAAC,IAAI,GAAG,IAAI,CAAA;QACrB,CAAC;QAED,IAAI,iBAAiB,EAAE,CAAC;YAEtB,OAAO,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAC,kBAAkB,EAAE,KAAK,EAAC,CAAC,CAAA;QAC9D,CAAC;QAGD,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAA;QAEpD,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAEY,QAAA,IAAI,GAAG,IAAI,IAAI,EAAE,CAAA"}
|
|
||||||
38600
dist/index.js
vendored
38600
dist/index.js
vendored
File diff suppressed because one or more lines are too long
23
dist/licenses.txt
vendored
23
dist/licenses.txt
vendored
@ -1,23 +0,0 @@
|
|||||||
node-fetch
|
|
||||||
MIT
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 - 2020 Node Fetch Team
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
68
dist/main.js
vendored
68
dist/main.js
vendored
@ -1,68 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const core = require("@actions/core");
|
|
||||||
const http_1 = require("./http");
|
|
||||||
const github_1 = require("@actions/github");
|
|
||||||
function run() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const url = core.getInput('url')
|
|
||||||
? core.getInput('url')
|
|
||||||
: process.env.WEBHOOK_URL
|
|
||||||
? process.env.WEBHOOK_URL
|
|
||||||
: '';
|
|
||||||
const headers = core.getInput('headers')
|
|
||||||
? core.getInput('headers')
|
|
||||||
: process.env.headers
|
|
||||||
? process.env.headers
|
|
||||||
: null;
|
|
||||||
let body = core.getInput('body')
|
|
||||||
? core.getInput('body')
|
|
||||||
: process.env.data
|
|
||||||
? process.env.data
|
|
||||||
: null;
|
|
||||||
const insecure = core.getInput('insecure')
|
|
||||||
? core.getInput('insecure') === 'true'
|
|
||||||
: process.env.insecure
|
|
||||||
? process.env.insecure === 'true'
|
|
||||||
: false;
|
|
||||||
const githubEventPayload = core.getInput('github_event_payload') === 'true';
|
|
||||||
if (githubEventPayload) {
|
|
||||||
const decodedBody = JSON.parse(body || '{}');
|
|
||||||
decodedBody.githubEventPayload = github_1.context.payload || {};
|
|
||||||
body = JSON.stringify(decodedBody);
|
|
||||||
}
|
|
||||||
if (!url) {
|
|
||||||
core.setFailed('A url is required to run this action.');
|
|
||||||
throw new Error('A url is required to run this action.');
|
|
||||||
}
|
|
||||||
core.info(`Sending webhook request to ${url}`);
|
|
||||||
http_1.http
|
|
||||||
.make(url, body, headers, insecure)
|
|
||||||
.then(res => {
|
|
||||||
if (res.status >= 400) {
|
|
||||||
error(res.status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
core.info(`Error: ${err}`);
|
|
||||||
error(err.status);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function error(statusCode) {
|
|
||||||
core.setFailed(`Received status code: ${statusCode}`);
|
|
||||||
throw new Error(`Request failed with status code: ${statusCode}`);
|
|
||||||
}
|
|
||||||
run();
|
|
||||||
//# sourceMappingURL=main.js.map
|
|
||||||
1
dist/main.js.map
vendored
1
dist/main.js.map
vendored
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,sCAAqC;AACrC,iCAA2B;AAC3B,4CAAuC;AAEvC,SAAe,GAAG;;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC9B,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW;gBACvB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW;gBACzB,CAAC,CAAC,EAAE,CAAA;QAER,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;YACtC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC1B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO;gBACnB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO;gBACrB,CAAC,CAAC,IAAI,CAAA;QAEV,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC9B,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACvB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI;gBAChB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI;gBAClB,CAAC,CAAC,IAAI,CAAA;QAEV,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YACxC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM;YACtC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ;gBACpB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;gBACjC,CAAC,CAAC,KAAK,CAAA;QAEX,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,KAAK,MAAM,CAAA;QAG3E,IAAI,kBAAkB,EAAE,CAAC;YAEvB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;YAG5C,WAAW,CAAC,kBAAkB,GAAG,gBAAO,CAAC,OAAO,IAAI,EAAE,CAAA;YAGtD,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QACpC,CAAC;QAED,IAAI,CAAC,GAAG,EAAE,CAAC;YAET,IAAI,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAA;YAEvD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;QAC1D,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAA;QAG9C,WAAI;aACD,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC;aAClC,IAAI,CAAC,GAAG,CAAC,EAAE;YAEV,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAEtB,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBACjB,OAAM;YACR,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,CAAC,EAAE;YACX,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAA;YAC1B,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACjB,OAAM;QACR,CAAC,CAAC,CAAA;IACN,CAAC;CAAA;AAED,SAAS,KAAK,CAAC,UAAU;IAEvB,IAAI,CAAC,SAAS,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAA;IAErD,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAA;AACnE,CAAC;AAED,GAAG,EAAE,CAAA"}
|
|
||||||
4
entrypoint.sh
Normal file
4
entrypoint.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data "{ \"data\": \"$data\" }" $WEBHOOK_URL
|
||||||
@ -1,7 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
transform: {
|
|
||||||
'^.+\\.(ts|tsx)$': 'ts-jest',
|
|
||||||
'^.+\\.(js)$': 'babel-jest'
|
|
||||||
},
|
|
||||||
transformIgnorePatterns: []
|
|
||||||
}
|
|
||||||
10235
package-lock.json
generated
10235
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@ -1,51 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "webhook-action",
|
|
||||||
"version": "2.4.1",
|
|
||||||
"description": "Github Webhook Action",
|
|
||||||
"main": "dist/main.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc && ncc build --license licenses.txt",
|
|
||||||
"format": "prettier --write '**/*.ts'",
|
|
||||||
"format-check": "prettier --check '**/*.ts'",
|
|
||||||
"lint": "eslint src/**/*.ts",
|
|
||||||
"test": "jest",
|
|
||||||
"all": "npm run format && npm run lint && npm run test&& npm run build"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/joelwmale/webhook-action.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"github",
|
|
||||||
"actions",
|
|
||||||
"node",
|
|
||||||
"webhook",
|
|
||||||
"action"
|
|
||||||
],
|
|
||||||
"author": "Joel Male",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@actions/core": "^1.10.1",
|
|
||||||
"@actions/github": "^6.0.0",
|
|
||||||
"@vercel/ncc": "^0.38.1",
|
|
||||||
"node-fetch": "^3.3.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/preset-env": "^7.20.2",
|
|
||||||
"@types/node": "^18.19.26",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
|
||||||
"babel-jest": "^29.3.1",
|
|
||||||
"eslint": "^8.57.0",
|
|
||||||
"eslint-plugin-github": "^4.10.2",
|
|
||||||
"eslint-plugin-jest": "^27.9.0",
|
|
||||||
"https": "^1.0.0",
|
|
||||||
"jest": "^29.7.0",
|
|
||||||
"js-yaml": "^4.1.0",
|
|
||||||
"prettier": "3.2.5",
|
|
||||||
"semver": "^7.6.0",
|
|
||||||
"ts-jest": "^29.0.3",
|
|
||||||
"typescript": "^5.4.3",
|
|
||||||
"uuid": "^9.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
47
src/http.ts
47
src/http.ts
@ -1,47 +0,0 @@
|
|||||||
import fetch from 'node-fetch'
|
|
||||||
import https = require('https')
|
|
||||||
|
|
||||||
class Http {
|
|
||||||
make(
|
|
||||||
url: string,
|
|
||||||
body: string | null,
|
|
||||||
headers: string | null = null,
|
|
||||||
ignoreCertificate: boolean | null = false
|
|
||||||
): Promise<any> {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
fetch(
|
|
||||||
url,
|
|
||||||
this.getOptions('post', headers, body, ignoreCertificate)
|
|
||||||
).then((res: any) => resolve(res))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getOptions(
|
|
||||||
method: string,
|
|
||||||
headers: string | null,
|
|
||||||
body: string | null,
|
|
||||||
ignoreCertificate: boolean | null
|
|
||||||
) {
|
|
||||||
const options: any = {
|
|
||||||
headers: headers ? JSON.parse(headers) : {},
|
|
||||||
method
|
|
||||||
}
|
|
||||||
|
|
||||||
if (body) {
|
|
||||||
// parse the body
|
|
||||||
options.body = body
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ignoreCertificate) {
|
|
||||||
// ignore the certificate by not rejecting authorized servers
|
|
||||||
options.agent = new https.Agent({rejectUnauthorized: false})
|
|
||||||
}
|
|
||||||
|
|
||||||
// set these headers
|
|
||||||
options.headers['content-type'] = 'application/json'
|
|
||||||
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const http = new Http()
|
|
||||||
78
src/main.ts
78
src/main.ts
@ -1,78 +0,0 @@
|
|||||||
import * as core from '@actions/core'
|
|
||||||
import {http} from './http'
|
|
||||||
import {context} from '@actions/github'
|
|
||||||
|
|
||||||
async function run() {
|
|
||||||
const url = core.getInput('url')
|
|
||||||
? core.getInput('url')
|
|
||||||
: process.env.WEBHOOK_URL
|
|
||||||
? process.env.WEBHOOK_URL
|
|
||||||
: ''
|
|
||||||
|
|
||||||
const headers = core.getInput('headers')
|
|
||||||
? core.getInput('headers')
|
|
||||||
: process.env.headers
|
|
||||||
? process.env.headers
|
|
||||||
: null
|
|
||||||
|
|
||||||
let body = core.getInput('body')
|
|
||||||
? core.getInput('body')
|
|
||||||
: process.env.data
|
|
||||||
? process.env.data
|
|
||||||
: null
|
|
||||||
|
|
||||||
const insecure = core.getInput('insecure')
|
|
||||||
? core.getInput('insecure') === 'true'
|
|
||||||
: process.env.insecure
|
|
||||||
? process.env.insecure === 'true'
|
|
||||||
: false
|
|
||||||
|
|
||||||
const githubEventPayload = core.getInput('github_event_payload') === 'true'
|
|
||||||
|
|
||||||
// if github_event is set to true, append it to the body
|
|
||||||
if (githubEventPayload) {
|
|
||||||
// decode the body
|
|
||||||
const decodedBody = JSON.parse(body || '{}')
|
|
||||||
|
|
||||||
// set the github event
|
|
||||||
decodedBody.githubEventPayload = context.payload || {}
|
|
||||||
|
|
||||||
// re-set the body
|
|
||||||
body = JSON.stringify(decodedBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!url) {
|
|
||||||
// validate a url
|
|
||||||
core.setFailed('A url is required to run this action.')
|
|
||||||
// error
|
|
||||||
throw new Error('A url is required to run this action.')
|
|
||||||
}
|
|
||||||
|
|
||||||
core.info(`Sending webhook request to ${url}`)
|
|
||||||
|
|
||||||
// make the request
|
|
||||||
http
|
|
||||||
.make(url, body, headers, insecure)
|
|
||||||
.then(res => {
|
|
||||||
// if the status code is not 2xx
|
|
||||||
if (res.status >= 400) {
|
|
||||||
// throw an error
|
|
||||||
error(res.status)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
core.info(`Error: ${err}`)
|
|
||||||
error(err.status)
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function error(statusCode) {
|
|
||||||
// set the action to failed
|
|
||||||
core.setFailed(`Received status code: ${statusCode}`)
|
|
||||||
// throw an error
|
|
||||||
throw new Error(`Request failed with status code: ${statusCode}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
run()
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es6",
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"strictPropertyInitialization": false,
|
|
||||||
"jsx": "react",
|
|
||||||
"lib": [
|
|
||||||
"dom",
|
|
||||||
"es6"
|
|
||||||
],
|
|
||||||
"module": "commonjs",
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"noImplicitAny": false,
|
|
||||||
"outDir": "./dist/",
|
|
||||||
"rootDir": "./src/",
|
|
||||||
"removeComments": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"strict": true,
|
|
||||||
"skipLibCheck": true
|
|
||||||
},
|
|
||||||
"exclude": ["node_modules", "**/*.test.ts"]
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user