├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── action.yml
└── entrypoint.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine
2 |
3 | LABEL "name"="bash"
4 | LABEL "repository"="https://github.com/distributhor/workflow-webhook"
5 | LABEL "version"="1.0.0"
6 |
7 | LABEL com.github.actions.name="Workflow Webhook"
8 | LABEL com.github.actions.description="An action that will call a webhook from your Github workflow"
9 | LABEL com.github.actions.icon="upload-cloud"
10 | LABEL com.github.actions.color="gray-dark"
11 |
12 | RUN apk add --no-cache bash curl openssl util-linux xxd jq jo
13 |
14 | COPY LICENSE README.md /
15 | COPY entrypoint.sh /entrypoint.sh
16 |
17 | RUN chmod +x /entrypoint.sh
18 |
19 | ENTRYPOINT ["/entrypoint.sh"]
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 distributhor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Workflow Webhook Action
2 |
3 | [![GitHub Release][ico-release]][link-github-release]
4 | [![License][ico-license]](LICENSE)
5 |
6 | A Github workflow action to call a remote webhook endpoint with a JSON or form-urlencoded
7 | payload, and support for BASIC authentication. A hash signature is passed with each request,
8 | derived from the payload and a configurable secret token. The hash signature is
9 | identical to that which a regular Github webhook would generate, and sent in a header
10 | field named `X-Hub-Signature`. Therefore any existing Github webhook signature
11 | validation will continue to work. For more information on how to valiate the signature,
12 | see .
13 |
14 | By default, the values of the following GitHub workflow environment variables are sent in the
15 | payload: `GITHUB_REPOSITORY`, `GITHUB_REF`, `GITHUB_HEAD_REF`, `GITHUB_SHA`, `GITHUB_EVENT_NAME`
16 | and `GITHUB_WORKFLOW`. For more information on what is contained in these variables, see
17 | .
18 |
19 | These values map to the payload as follows:
20 |
21 | ```json
22 | {
23 | "event": "GITHUB_EVENT_NAME",
24 | "repository": "GITHUB_REPOSITORY",
25 | "commit": "GITHUB_SHA",
26 | "ref": "GITHUB_REF",
27 | "head": "GITHUB_HEAD_REF",
28 | "workflow": "GITHUB_WORKFLOW"
29 | }
30 | ```
31 |
32 | If you are interested in receiving more comprehensive data about the GitHub event than just the
33 | above fields, then the action can be configured to send the whole JSON payload of the GitHub event,
34 | as per the `GITHUB_EVENT_PATH` variable in the environment variable documentation referenced above.
35 | The official documentation and reference for the payload itself can be found here:
36 | , and the details on how to configure it,
37 | is further down in the **Usage** section of this README.
38 |
39 | Additional (custom) data can also be added/merged to the payload (see further down).
40 |
41 |
42 | ## Usage
43 |
44 | The following are example snippets for a Github yaml workflow configuration.
45 |
46 | Send the JSON (default) payload to a webhook:
47 |
48 | ```yml
49 | - name: Invoke deployment hook
50 | uses: distributhor/workflow-webhook@v3
51 | with:
52 | webhook_url: ${{ secrets.WEBHOOK_URL }}
53 | webhook_secret: ${{ secrets.WEBHOOK_SECRET }}
54 | ```
55 |
56 | Will deliver a payload with the following properties:
57 |
58 | ```json
59 | {
60 | "event": "push",
61 | "repository": "owner/project",
62 | "commit": "a636b6f0861bbee98039bf3df66ee13d8fbc9c74",
63 | "ref": "refs/heads/master",
64 | "head": "",
65 | "workflow": "Build and deploy",
66 | "requestID": "74b1912d19cfe780f1fada4b525777fd"
67 | }
68 | ```
69 | `requestID` contains a randomly generated identifier for each request.
70 |
71 |
72 |
73 | Add additional data to the payload:
74 |
75 | ```yml
76 | - name: Invoke deployment hook
77 | uses: distributhor/workflow-webhook@v3
78 | with:
79 | webhook_url: ${{ secrets.WEBHOOK_URL }}
80 | webhook_secret: ${{ secrets.WEBHOOK_SECRET }}
81 | data: '{ "weapon": "hammer", "drink" : "beer" }'
82 | ```
83 |
84 | The additional information will become available on a `data` property,
85 | and now look like:
86 |
87 | ```json
88 | {
89 | "event": "push",
90 | "repository": "owner/project",
91 | "commit": "a636b6f0861bbee98039bf3df66ee13d8fbc9c74",
92 | "ref": "refs/heads/master",
93 | "head": "",
94 | "workflow": "Build and deploy",
95 | "data": {
96 | "weapon": "hammer",
97 | "drink": "beer"
98 | },
99 | "requestID": "74b1912d19cfe780f1fada4b525777fd"
100 | }
101 | ```
102 |
103 | Send a form-urlencoded payload instead:
104 |
105 | ```yml
106 | - name: Invoke deployment hook
107 | uses: distributhor/workflow-webhook@v3
108 | with:
109 | webhook_type: 'form-urlencoded'
110 | webhook_url: ${{ secrets.WEBHOOK_URL }}
111 | webhook_secret: ${{ secrets.WEBHOOK_SECRET }}
112 | data: 'weapon=hammer&drink=beer'
113 | ```
114 |
115 | Will set the `Content-Type` header to `application/x-www-form-urlencoded` and deliver:
116 |
117 | ```csv
118 | "event=push&repository=owner/project&commit=a636b6f0....&weapon=hammer&drink=beer"
119 | ```
120 |
121 | Finally, if you prefer to receive the whole original GitHub payload as JSON (as opposed
122 | to the default JSON snippet above), then configure the webhook with a `webhook_type` of
123 | `json-extended`:
124 |
125 | ```yml
126 | - name: Invoke deployment hook
127 | uses: distributhor/workflow-webhook@v3
128 | with:
129 | webhook_type: 'json-extended'
130 | webhook_url: ${{ secrets.WEBHOOK_URL }}
131 | webhook_secret: ${{ secrets.WEBHOOK_SECRET }}
132 | data: '{ "weapon": "hammer", "drink" : "beer" }'
133 | ```
134 |
135 | You can still add custom JSON data, which will be available on a `data` property, included
136 | on the GitHub payload. Importantly, the sending of the whole GitHub payload
137 | is only supported as JSON, and not currently available as urlencoded form parameters.
138 |
139 | ## Arguments
140 |
141 | ```yml
142 | webhook_url: "https://your.webhook"
143 | ```
144 |
145 | *Required*. The HTTP URI of the webhook endpoint to invoke. The endpoint must accept
146 | an HTTP POST request.
147 |
148 |
149 | ```yml
150 | webhook_secret: "Y0uR5ecr3t"
151 | ```
152 |
153 | Optional. The secret with which to generate the signature hash. If no secret is configured,
154 | then the URL itself will be used as the value with which to generate the signature hash.
155 | This is useful for use-cases where the webhook URL might be an obscure, random or temporary
156 | link. In general it is advisable to use a webhook secret.
157 |
158 | ```yml
159 | webhook_auth_type: "bearer"
160 | ```
161 |
162 | The type of authentication to use when invoking the webhook URL. Valid values are `basic`,
163 | `bearer` and `header`. Defaults to `basic` if not specified. In addition, if no value
164 | is set for `webhook_auth`, then it is assumed that no authentication is required, and this
165 | value, even if configured, will have no effect. It only takes effect when used in conjunction
166 | with `webhook_auth`. The expectations for how each option behaves, is explained in the
167 | `webhook_auth` section below.
168 |
169 | ```yml
170 | webhook_auth: "username:password"
171 | webhook_auth: "Token:ABC"
172 | webhook_auth: "ABC"
173 | ```
174 |
175 | The credentials to be used for authentication of the the endpoint. If not configured,
176 | authentication is assumed not to be required.
177 |
178 | If the `webhook_auth_type` is set to `basic`, then this value is expected to be a
179 | `username:password` string, used for BASIC authentication against the endpoint. It must follow
180 | this format, as specified in the `curl` man pages, since it is passed verbatim to the
181 | `curl -u` option.
182 |
183 | If the `webhook_auth_type` is set to `bearer`, then this value is expected to be an
184 | access token. It will set a header named `Authorization` with a value of `Bearer ${webhook_auth}`.
185 |
186 |
187 | If the `webhook_auth_type` is set to `header`, then the expecation is to receive a string similar
188 | in format to `basic`, except that the delimiter (a colon) will delimit a header name and header
189 | value. For example a value of `Token:ABC` will set a header named `Token` with a value of `ABC`.
190 | If no colon is present (no delimiter specified) then it will default to setting a header named
191 | `Authorization` of which the value will be whatever was configured for `${webhook_auth}`,
192 | ie (no 'bearer') prefix. As an example, when configured with a value of `ABC`, a header named
193 | `Authorization` will be set to the value `ABC`.
194 |
195 |
196 | ```yml
197 | webhook_type: "json | form-urlencoded | json-extended"
198 | ```
199 |
200 | The default endpoint type is JSON. The argument is only required if you wish to send urlencoded form data.
201 | Otherwise it's optional.
202 |
203 | ```yml
204 | verbose: true
205 | ```
206 |
207 | To enable verbose output in curl set the argument `verbose` to `true`. The default value is `false`. See also: [`curl` docs on option `-v`](https://curl.se/docs/manpage.html#-v).
208 |
209 | :warning: **Warning:** This might lead to domain and IP leaking, as well as other security issues as the logs are public.
210 | See also [#21](https://github.com/distributhor/workflow-webhook/issues/21) and [#22](https://github.com/distributhor/workflow-webhook/issues/22).
211 |
212 |
213 | ```yml
214 | silent: true
215 | ```
216 |
217 | To hide the output from curl set the argument `silent` to `true`. The default value is `false`.
218 |
219 | ```yml
220 | timeout: 30
221 | ```
222 |
223 | To set a maximum time, in seconds, by which to establish an initial connection to the server. Once a connection has been
224 | established, the option is not used in any further way with regards to the duration of connection.
225 |
226 | ```yml
227 | max_time: 30
228 | ```
229 |
230 | To set a maximum time, in seconds, by which the server needs to respond to the request.
231 | This also includes the time needed for the server to respond. May be used in combination with `timeout`.
232 |
233 | ```yml
234 | curl_opts: '--speed-limit 5000'
235 | curl_opts: '-H "X-Beverage: Beer"'
236 | ```
237 |
238 | You can use `curl_opts` to pass in arbitrary options to the curl request. NOTE: this is an experimental feature and not
239 | guaranteed to work for all options. The string configured here will be passed in verbatim to curl, and it is quite easy to
240 | break things when using it. For simple curl options it should work, but for others it may not suffice. Also, take care with
241 | escaping characters in YAML.
242 |
243 | ```yml
244 | verify_ssl: false
245 | ```
246 |
247 | To disable verification of SSL-certificates in curl set the argument `verify_ssl` to `false`. The default value is `true`.
248 | See also: [`curl` docs on option `-k`](https://curl.se/docs/manpage.html#-k).
249 |
250 |
251 | ```yml
252 | event_name: 'NAME'
253 | ```
254 |
255 | Optional. A custom event name sent to the webhook endpoint
256 |
257 | ```yml
258 | data: "Additional JSON or URL encoded data"
259 | ```
260 |
261 |
262 | Additional data to include in the payload. It is optional. This data will attempted to be
263 | merged 'as-is' with the existing payload, and is expected to already be sanitized and valid.
264 |
265 | In the case of JSON, the custom data will be available on a property named `data`, and it will be
266 | run through a JSON validator. Invalid JSON will cause the action to break and exit. For example, using
267 | single quotes for JSON properties and values instead of double quotes, will show the
268 | following (somewhat confusing) message in your workflow output: `Invalid numeric literal`.
269 | Such messages are the direct output from the validation library .
270 | The supplied JSON must pass the validation run through `jq`.
271 |
272 | ## Output
273 |
274 | ```yml
275 | response-body: 'The body of the webook response'
276 | ```
277 |
278 | ## License
279 |
280 | The MIT License (MIT). Please see [License File](LICENSE) for more information.
281 |
282 | [ico-release]: https://img.shields.io/github/tag/distributhor/workflow-webhook.svg
283 | [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg
284 | [link-github-release]: https://github.com/distributhor/workflow-webhook/releases
285 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: 'Workflow Webhook Action'
2 | description: 'A Github workflow action to call a webhook with payload data from the event. Support for JSON or URL encoded endpoints.'
3 | inputs:
4 | webhook_url:
5 | description: 'The HTTP URI of the webhook endpoint to invoke'
6 | required: true
7 | webhook_secret:
8 | description: 'The secret with which a signature hash is generated. If omitted, the URL itself will be used as the value with which to generate the hash.'
9 | webhook_auth:
10 | description: 'Optional. The BASIC auth credentials (a "username:password" string) OR a bearer access token OR a custom header to be used for authentication'
11 | webhook_auth_type:
12 | description: 'Optional. What type of authentication to use for invoking the webhook URL. Valid values are "basic", "bearer", "header". Defaults to "basic" if not specified.'
13 | default: "basic"
14 | webhook_type:
15 | description: 'json | form-urlencoded | json-extended'
16 | verbose:
17 | description: 'Optional. Set to true to enable verbose output. Warning: this might lead to domain and IP leaking, as well as other security issues as the logs are public.'
18 | silent:
19 | description: 'Optional. Set to true to disable output and therefore IP leaking.'
20 | timeout:
21 | description: 'Optional. Set a maximum time, in seconds, by which to establish a connection to the server.'
22 | max_time:
23 | description: 'Optional. Set a maximum time, in seconds, the request to the server can take, before being cancelled.'
24 | curl_opts:
25 | description: 'Optional (and experimental). Pass arbitrary options to the curl request.'
26 | verify_ssl:
27 | description: 'Optional. Set to false to disable verification of SSL certificates.'
28 | default: true
29 | event_name:
30 | description: 'Optional. Specify a custom event name sent to the webhook endpoint, if not defined it defaults to GITHUB_EVENT_NAME.'
31 | data:
32 | description: 'Optional. Specify additional data to include in the payload.'
33 |
34 | outputs:
35 | response-body:
36 | description: The response body of the webook response
37 |
38 | runs:
39 | using: 'docker'
40 | # image: 'Dockerfile'
41 | image: 'docker://ghcr.io/distributhor/workflow-webhook-container:v3.0.8'
42 |
43 | branding:
44 | icon: 'terminal'
45 | color: 'gray-dark'
46 |
--------------------------------------------------------------------------------
/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Enable the printing of trace messages
4 | set -o errtrace
5 | trap 'echo "Error occurred on line $BASH_LINENO"; exit 1' ERR
6 |
7 | # Github Inputs/Envs Fix: Iterate over environment variables starting with INPUT_ and export them as lowercase variables without input_ prefix.
8 | for var in "${!INPUT_@}"; do
9 | # Remove the INPUT_ prefix
10 | name="${var#INPUT_}"
11 |
12 | # Convert name to lowercase
13 | name_lower="${name,,}"
14 |
15 | # Access the value of the environment variable
16 | value="${!var}"
17 |
18 | # Check if the variable is already exported
19 | if [[ -z "${!name_lower+x}" ]]; then
20 | if [ "$fine" = true ]; then
21 | # Export the variable if it's not already present
22 | echo "INFO: Converting INPUT_${name}=$value to $name_lower=$value"
23 | fi
24 | export "$name_lower"="$value"
25 | else
26 | echo "WARN: Variable already exists with $(env | grep "${name_lower}="), not exporting."
27 | fi
28 | done
29 |
30 | # For backwards compatibility,
31 | # may be deprecated in future major version
32 | if [ -n "$WEBHOOK_AUTH" ]; then
33 | webhook_auth=$WEBHOOK_AUTH
34 | fi
35 |
36 | if [ -n "$WEBHOOK_AUTH_TYPE" ]; then
37 | webhook_auth_type=$WEBHOOK_AUTH_TYPE
38 | fi
39 |
40 | if [ -n "$WEBHOOK_SECRET" ]; then
41 | webhook_secret=$WEBHOOK_SECRET
42 | fi
43 |
44 | if [ -n "$WEBHOOK_TYPE" ]; then
45 | webhook_type=$WEBHOOK_TYPE
46 | fi
47 |
48 | if [ -n "$WEBHOOK_URL" ]; then
49 | webhook_url=$WEBHOOK_URL
50 | fi
51 |
52 | if [ -n "$SILENT" ]; then
53 | silent=$SILENT
54 | fi
55 |
56 | if [ -n "$VERBOSE" ]; then
57 | verbose=$VERBOSE
58 | fi
59 |
60 | if [ -n "$VERIFY_SSL" ]; then
61 | verify_ssl=$VERIFY_SSL
62 | fi
63 |
64 | if [ -n "$TIMEOUT" ]; then
65 | timeout=$TIMEOUT
66 | fi
67 |
68 | if [ -n "$MAX_TIME" ]; then
69 | max_time=$MAX_TIME
70 | fi
71 |
72 | if [ -n "$CURL_OPTS" ]; then
73 | curl_opts=$CURL_OPTS
74 | fi
75 |
76 | if [ -n "$EVENT_NAME" ]; then
77 | event_name=$EVENT_NAME
78 | fi
79 |
80 | if [ -n "$DATA" ]; then
81 | data=$DATA
82 | fi
83 |
84 | urlencode() {
85 | local length="${#1}"
86 | for (( i = 0; i < length; i++ )); do
87 | local c="${1:i:1}"
88 | case $c in
89 | [a-zA-Z0-9.~_-]) printf "$c" ;;
90 | *) printf '%s' "$c" | xxd -p -c1 |
91 | while read c; do printf '%%%s' "$c"; done ;;
92 | esac
93 | done
94 | }
95 |
96 | urldecode() {
97 | local url_encoded="${1//+/ }"
98 | printf '%b' "${url_encoded//%/\\x}"
99 | }
100 |
101 | set -e
102 |
103 | if [ -z "$webhook_url" ]; then
104 | echo "No webhook_url configured"
105 | exit 1
106 | fi
107 |
108 | if [ -z "$webhook_secret" ]; then
109 | webhook_secret=$webhook_url
110 | fi
111 |
112 | #
113 | # This method does not require additional package installation (of util-linux)
114 | # on docker image, resulting in a slightly smaller image file
115 | #
116 | # REQUEST_ID=$(cat /dev/urandom | tr -dc '0-9a-f' | fold -w 32 | head -n 1)
117 |
118 | #
119 | # This method is cleaner, but requires util-linux to be installed on Alpine image,
120 | # resuling in a slightly larger image file
121 | #
122 | REQUEST_ID=$(uuidgen)
123 |
124 | if [ "$silent" != true ]; then
125 | echo "Webhook Request ID: $REQUEST_ID"
126 | fi
127 |
128 | if [ -n "$event_name" ]; then
129 | EVENT_NAME=$event_name
130 | else
131 | EVENT_NAME=$GITHUB_EVENT_NAME
132 | fi
133 |
134 | if [ -n "$webhook_type" ] && [ "$webhook_type" == "form-urlencoded" ]; then
135 | EVENT=`urlencode "$EVENT_NAME"`
136 | REPOSITORY=`urlencode "$GITHUB_REPOSITORY"`
137 | COMMIT=`urlencode "$GITHUB_SHA"`
138 | REF=`urlencode "$GITHUB_REF"`
139 | HEAD=`urlencode "$GITHUB_HEAD_REF"`
140 | WORKFLOW=`urlencode "$GITHUB_WORKFLOW"`
141 |
142 | CONTENT_TYPE="application/x-www-form-urlencoded"
143 | WEBHOOK_DATA="event=$EVENT&repository=$REPOSITORY&commit=$COMMIT&ref=$REF&head=$HEAD&workflow=$WORKFLOW&requestID=$REQUEST_ID"
144 |
145 | if [ -n "$data" ]; then
146 | WEBHOOK_DATA="${WEBHOOK_DATA}&${data}"
147 | fi
148 | else
149 | CONTENT_TYPE="application/json"
150 |
151 | if [ -n "$webhook_type" ] && [ "$webhook_type" == "json-extended" ]; then
152 | RAW_FILE_DATA=`cat $GITHUB_EVENT_PATH`
153 | WEBHOOK_DATA=$(echo -n "$RAW_FILE_DATA" | jq -c '.')
154 | else
155 | WEBHOOK_DATA=$(jo event="$EVENT_NAME" repository="$GITHUB_REPOSITORY" commit="$GITHUB_SHA" ref="$GITHUB_REF" head="$GITHUB_HEAD_REF" workflow="$GITHUB_WORKFLOW")
156 | fi
157 |
158 | if [ -n "$data" ]; then
159 | CUSTOM_JSON_DATA=$(echo -n "$data" | jq -c '.')
160 | WEBHOOK_DATA=$(jq -s '.[0] * .[1]' <(echo $WEBHOOK_DATA) <(jo requestID="$REQUEST_ID" data="$CUSTOM_JSON_DATA"))
161 | else
162 | WEBHOOK_DATA=$(jq -s '.[0] * .[1]' <(echo $WEBHOOK_DATA) <(jo requestID="$REQUEST_ID"))
163 | fi
164 | fi
165 |
166 | WEBHOOK_SIGNATURE=$(echo -n "$WEBHOOK_DATA" | openssl dgst -sha1 -hmac "$webhook_secret" -binary | xxd -p)
167 | WEBHOOK_SIGNATURE_256=$(echo -n "$WEBHOOK_DATA" | openssl dgst -sha256 -hmac "$webhook_secret" -binary | xxd -p |tr -d '\n')
168 | WEBHOOK_ENDPOINT=$webhook_url
169 |
170 | if [ -n "$webhook_auth_type" ] && [ "$webhook_auth_type" == "bearer" ]; then
171 | auth_type="bearer"
172 | elif [ -n "$webhook_auth_type" ] && [ "$webhook_auth_type" == "header" ]; then
173 | auth_type="header"
174 | else
175 | auth_type="basic"
176 | fi
177 |
178 | if [ -n "$webhook_auth" ] && [ "$auth_type" == "basic" ]; then
179 | WEBHOOK_ENDPOINT="-u $webhook_auth $webhook_url"
180 | fi
181 |
182 | options="--http1.1 --fail-with-body"
183 |
184 | if [ "$verbose" = true ]; then
185 | options="$options -v"
186 | options="$options -sS"
187 | elif [ "$silent" = true ]; then
188 | options="$options -s"
189 | else
190 | # The -s disables the progress meter, as well as error messages.
191 | # We want Curl to report errors, which we reenable with -S
192 | options="$options -sS"
193 | fi
194 |
195 | if [ "$verify_ssl" = false ]; then
196 | options="$options -k"
197 | fi
198 |
199 | if [ -n "$timeout" ]; then
200 | options="$options --connect-timeout $timeout"
201 | fi
202 |
203 | if [ -n "$max_time" ]; then
204 | options="$options --max-time $max_time"
205 | fi
206 |
207 | if [ -n "$curl_opts" ]; then
208 | options="$options $curl_opts"
209 | fi
210 |
211 | if [ "$verbose" = true ]; then
212 | echo "curl $options \\"
213 | echo "-H 'Content-Type: $CONTENT_TYPE' \\"
214 | echo "-H 'User-Agent: GitHub-Hookshot/$REQUEST_ID' \\"
215 | echo "-H 'X-Hub-Signature: sha1=$WEBHOOK_SIGNATURE' \\"
216 | echo "-H 'X-Hub-Signature-256: sha256=$WEBHOOK_SIGNATURE_256' \\"
217 | echo "-H 'X-GitHub-Delivery: $REQUEST_ID' \\"
218 | echo "-H 'X-GitHub-Event: $EVENT_NAME' \\"
219 | echo "-H 'Connection: close' \\"
220 | echo "--data '$WEBHOOK_DATA'"
221 | fi
222 |
223 | set +e
224 |
225 | # auth_header=''
226 |
227 | if [ -n "$webhook_auth" ] && [ "$auth_type" == "bearer" ]; then
228 | # auth_header="-H \"Authorization: Bearer $webhook_auth\""
229 | response=$(curl $options \
230 | -H "Authorization: Bearer $webhook_auth" \
231 | -H "Content-Type: $CONTENT_TYPE" \
232 | -H "User-Agent: GitHub-Hookshot/$REQUEST_ID" \
233 | -H "X-Hub-Signature: sha1=$WEBHOOK_SIGNATURE" \
234 | -H "X-Hub-Signature-256: sha256=$WEBHOOK_SIGNATURE_256" \
235 | -H "X-GitHub-Delivery: $REQUEST_ID" \
236 | -H "X-GitHub-Event: $EVENT_NAME" \
237 | -H "Connection: close" \
238 | --data "$WEBHOOK_DATA" $WEBHOOK_ENDPOINT)
239 | elif [ -n "$webhook_auth" ] && [ "$auth_type" == "header" ]; then
240 | header_name=`[[ $webhook_auth =~ ([^:]*) ]] && echo "${BASH_REMATCH[1]}"`
241 | header_value=`[[ $webhook_auth =~ :(.*) ]] && echo "${BASH_REMATCH[1]}"`
242 | if [ -z "$header_value" ]; then
243 | # if the webhook_auth value contains no colon, then it is a configuration error
244 | # we should not handle such cases, but in instead of throwing an error, we try
245 | # and consider a potential fail-safe for user error, and resort to setting the
246 | # entire value as an Authorization token - the attempt at trying to resolve what
247 | # the author meant may or may not be a better approach than just letting it error?
248 | #
249 | # auth_header="-H \"Authorization: $webhook_auth\""
250 | response=$(curl $options \
251 | -H "Authorization: $webhook_auth" \
252 | -H "Content-Type: $CONTENT_TYPE" \
253 | -H "User-Agent: GitHub-Hookshot/$REQUEST_ID" \
254 | -H "X-Hub-Signature: sha1=$WEBHOOK_SIGNATURE" \
255 | -H "X-Hub-Signature-256: sha256=$WEBHOOK_SIGNATURE_256" \
256 | -H "X-GitHub-Delivery: $REQUEST_ID" \
257 | -H "X-GitHub-Event: $EVENT_NAME" \
258 | -H "Connection: close" \
259 | --data "$WEBHOOK_DATA" $WEBHOOK_ENDPOINT)
260 | else
261 | # auth_header="-H \"$header_name: $header_value\""
262 | response=$(curl $options \
263 | -H "$header_name: $header_value" \
264 | -H "Content-Type: $CONTENT_TYPE" \
265 | -H "User-Agent: GitHub-Hookshot/$REQUEST_ID" \
266 | -H "X-Hub-Signature: sha1=$WEBHOOK_SIGNATURE" \
267 | -H "X-Hub-Signature-256: sha256=$WEBHOOK_SIGNATURE_256" \
268 | -H "X-GitHub-Delivery: $REQUEST_ID" \
269 | -H "X-GitHub-Event: $EVENT_NAME" \
270 | -H "Connection: close" \
271 | --data "$WEBHOOK_DATA" $WEBHOOK_ENDPOINT)
272 | fi
273 | else
274 | response=$(curl $options \
275 | -H "Content-Type: $CONTENT_TYPE" \
276 | -H "User-Agent: GitHub-Hookshot/$REQUEST_ID" \
277 | -H "X-Hub-Signature: sha1=$WEBHOOK_SIGNATURE" \
278 | -H "X-Hub-Signature-256: sha256=$WEBHOOK_SIGNATURE_256" \
279 | -H "X-GitHub-Delivery: $REQUEST_ID" \
280 | -H "X-GitHub-Event: $EVENT_NAME" \
281 | -H "Connection: close" \
282 | --data "$WEBHOOK_DATA" $WEBHOOK_ENDPOINT)
283 | fi
284 |
285 | # headers="-H \"Content-Type: $CONTENT_TYPE\""
286 | # headers="$headers -H \"User-Agent: GitHub-Hookshot/$REQUEST_ID\""
287 | # headers="$headers -H \"X-Hub-Signature: sha1=$WEBHOOK_SIGNATURE\""
288 | # headers="$headers -H \"X-Hub-Signature-256: sha256=$WEBHOOK_SIGNATURE_256\""
289 | # headers="$headers -H \"X-GitHub-Delivery: $REQUEST_ID\""
290 | # headers="$headers -H \"X-GitHub-Event: $EVENT_NAME\""
291 | # headers="$headers -H \"Connection: close\""
292 |
293 | # if [ "$verbose" = true ]; then
294 | # echo "curl $options \\"
295 | # if [ -n "$auth_header" ]; then
296 | # echo "$auth_header $headers \\"
297 | # else
298 | # echo "$headers \\"
299 | # fi
300 | # echo "--data '$WEBHOOK_DATA'"
301 | # # some console logs will remove the log statement if its a URL
302 | # # so we need to remove the protocol if we want to display this
303 | # noproto_webhook_url=`echo $WEBHOOK_ENDPOINT | sed -E 's/^\s*.*:\/\///g'`
304 | # echo "WEBHOOK_ENDPOINT: $noproto_webhook_url"
305 | # fi
306 |
307 | # set +e
308 |
309 | # response=$(curl $options $auth_header $headers --data "$WEBHOOK_DATA" $WEBHOOK_ENDPOINT)
310 |
311 | CURL_STATUS=$?
312 |
313 | # echo "response-body=$response" >> $GITHUB_OUTPUT
314 | echo "response-body<<$REQUEST_ID" >> $GITHUB_OUTPUT
315 | echo "$response" >> $GITHUB_OUTPUT
316 | echo "$REQUEST_ID" >> $GITHUB_OUTPUT
317 |
318 | if [ "$verbose" = true ]; then
319 | echo "Webhook Response [$CURL_STATUS]:"
320 | echo "${response}"
321 | fi
322 |
323 | exit $CURL_STATUS
324 |
--------------------------------------------------------------------------------