Github API Create a Pull Request always 422 Error - bash

i wrote a script to create a github pull request by an api. This is part of a gitflow action to merge a hotfix automatically into the develop. Anyway,..
i always got the error 422 Validation failed, or the endpoint has been spammed.
Github API Docu
i cant handle why and what could be wrong.
You can see my code below. May some of you can see my problem.
function create_pr()
{
TITLE="hotfix auto merged by $(jq -r ".pull_request.head.user.login" "$GITHUB_EVENT_PATH" | head -1)."
REPO_FULLNAME=$(jq -r ".repository.full_name" "$GITHUB_EVENT_PATH")
RESPONSE_CODE=$(curl -o $OUTPUT_PATH -s -w "%{http_code}\n" \
--data "{\"title\":\"$TITLE\", \"head\": \"$BASE_BRANCH\", \"base\": \"$TARGET_BRANCH\"}" \
-X POST \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/$REPO_FULLNAME/pulls")
echo "head: $SOURCE_BRANCH, base: $TARGET_BRANCH"
echo "Create PR Response:"
echo "Code : $RESPONSE_CODE"
if [[ "$RESPONSE_CODE" -ne "201" ]];
then
echo "Could not create PR";
exit 1;
else echo "Created PR";
fi
}

Related

Bash script is returning "gh: Not Found (HTTP 404) Error: writing output failed: Invalid argument" when trying multiple actions on GitHub repos

I'm trying to rename a large number of branches at once, and account for three possible scenarios, using the following in Bash:
for REPOSITORY in "${REPOSITORIES[#]}"; do
# no master or main
if [ "$(gh api repos/${REPOSITORYOWNER}/${REPOSITORY}/branches/master | jq -r .message)" = "Branch not found" ] || [ "$(gh api /repos/${REPOSITORYOWNER}/${REPOSITORY}/branches/main | jq -r .message)" = "Branch not found" ]; then
echo "branch doesn't exist"
git branch main
# master exists, rename it
elif [ "$(gh api repos/${REPOSITORYOWNER}/${REPOSITORY}/branches/master | jq -r .message)" = "200" ]; then
echo "Renaming master to main on ${REPOSITORY}"
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
repos/${REPOSITORYOWNER}/${REPOSITORY}/branches/master/rename \
-f new_name='main'
# main exists, do nothing
elif [ "$(gh api repos/${REPOSITORYOWNER}/${REPOSITORY}/branches/main | jq -r .message)" = "200" ]; then
echo "main branch already exists"
:
fi
done
However all I'm getting back is gh: Not Found (HTTP 404) Error: writing output failed: Invalid argument. The gh api calls are correct so I'm assuming this is a syntax error but I'm pretty new to Bash.
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
repos/${REPOSITORYOWNER}/${REPOSITORY}/branches/master/rename \
-f new_name='main'
Works by itself, but none of the if statements work individually. I am expecting it to run through each possible state and move onto the next if statement if the conditions aren't met.
EDIT: I added set -x and it looks like it is returning a lot of null messages, see below:
for REPOSITORY in "${REPOSITORIES[#]}"
++ gh api repos/owner/repo/branches/master
++ jq -r .message
+ '[' null = 'Branch not found' ']'
++ gh api /repos/owner/repo/branches/main
++ jq -r .message
gh: Not Found (HTTP 404)
+ '[' 'Not Found' = 'Branch not found' ']'
++ gh api repos/owner/repo/branches/master
++ jq -r .message
+ '[' null = 200 ']'
++ gh api repos/owner/repo/branches/main
++ jq -r .message
+ '[' null = 200 ']'
You seem to have repeating expressions. Outputs to those should be assigned to variables that make it easier to follow the logic of the program.
Also, you had more paths without the leading "/", so I removed that from the determination for stat_main, but shouldn't they ALL have the leading "/" ??? (N.B. I don't upload to github, so no experience with what is expected by that command.)
OR ... use a proper fullpath definition (rather than relative to the current, possibly unknown or mis-fit, location ?
More importantly, until your logic behaves the way you want, you need to comment out the rename action and replace it with an echo "rename action", to avoid applying that to something that should NOT be renamed.
Here is my modification of that code segment:
for REPOSITORY in "${REPOSITORIES[#]}"; do
repo_path="repos/${REPOSITORYOWNER}/${REPOSITORY}/branches"
stat_master="$(gh api ${repo_path}/master | jq -r .message)"
echo "\t stat_master = ${stat_master}"
stat_main="$(gh api ${repo_path}/main | jq -r .message)"
echo "\t stat_main = ${stat_main}"
# no master or main
if [ "${stat_master}" = "Branch not found" -o " ${stat_main}" = "Branch not found" ]
then
echo "branch doesn't exist"
git branch main
# master exists, rename it
elif [ "${stat_master}" = "200" ]
then
echo "Renaming master to main on ${REPOSITORY}"
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
${repo_path}/master/rename \
-f new_name='main'
# main exists, do nothing
elif [ "${stat_main}" = "200" ]
then
echo "main branch already exists"
:
fi
done

Why is Jenkins shell scripting giving other results than for the same command compared to my local results?

I am trying to capture the response of an http request in a variable. The following question gave me the perfect solution to this (How to evaluate http response codes from bash/shell script?). When I execute this command locally
response=$(curl --write-out '%{http_code}' --silent --output /dev/null http://localhost:8082/url)
echo $response
It gives me the wanted http code (e.g. 400). However in Jenkins I execute the same command, but it gives me an empty response:
sh '''#!/bin/bash
DOCKER_RESPONSE=$(curl --write-out '%{http_code}' --silent --output /dev/null http://localhost:8002/route?json={})
while [[ $DOCKER_RESPONSE != 200 ]]
do
sleep 1
echo "$DOCKER_RESPONSE"
DOCKER_RESPONSE=$(curl --write-out '%{http_code}' --silent --output /dev/null http://localhost:8002/route?json={})
done
'''
you are mixing groovy syntex with bash , it has to be like below
node {
stage('one') {
sh """
res=\$(curl --write-out '%{http_code}' --silent --output /dev/null https://google.com)
echo \$res
while [[ \$res != '301' ]]
do
sleep 1
echo \$res
res=\$(curl --write-out '%{http_code}' --silent --output /dev/null https://google.com)
done
"""
}
}
and The output will be

Read json values from curl GET response

How can I get a specific field from the json response?
#!/bin/bash -
status=`curl -sk -H "api-token: $TOKEN" -H "Content-Type: application/json" https://path_to/values`
The response is
{
"cancelled": false,
"percentage": 0.5,
"state": "running"
}
I want to poll the 'status' that the response percentage is 100 and the cancelled field is always true. Can this be done without another tool like jq?
EDIT
I`m trying to figure out if I can install jq on the system. Is my approach correct using jq?
while
update_status=`curl -sk -H "api-token: $TOKEN" -H "Content-Type: application/json" https://path_to/values`
cancelled=$(jq -r '.cancelled' <<< "$update_status")
percentage_complete=$(jq -r '.percentage_complete' <<< "$update_status")
state=$(jq -r '.state' <<< "$update_status")
[[ $cancelled -eq 1 || $state == 'running' ]]
do true; done
"cancelled" is a boolean and "state" is a string with the values "running" or "not_running".
How can I add a log message which shows if the update fails or not? I`m not pretty sure with the do while loop...
echo "[INFO] Update done" ## depending on the failed var?
Using jq and reading the results into an array:
readarray -t dat <<< "$(curl -sk -H "api-token: $TOKEN" -H "Content-Type: application/json" https://path_to/values | jq -r '.cancelled,.percentage,.state')"
The array can then be used in an if statement:
if [[ "${dat[0]" == "true" && "${dat[1]" == "100" ]]
then
echo "There are no issues"
else
echo "There are issues"
fi
If jq is really not an option and if the json returned is as posted, you can use awk and return back an error code:
if (curl -sk -H "api-token: $TOKEN" -H "Content-Type: application/json" https://path_to/values | awk '/(cancelled)|(percentage)|(state)/ { gsub("[\",:]","",$0);gsub(" ","",$1);map[$1]=$2 } END { if ( map["cancelled"]=="false" && map["percentage"] == 100 ) { exit 0 } else { exit 1 } }');
then
echo "There are no issues"
else
echo "There are issues"
fi
Pipe the output of the curl command into awk and where there is "cancelled", "percentage" or "state" in the line, process. Remove any "," or double quotes or ":" from the line and then remove any spaces from the first space delimited field with gsub and then add to an array called map and use the first field as the index and the second field as the value. At the end, check the indexes of the map array and exit with 0 if all are as expected, otherwise, exit with 0.

What is wrong with the shell script for curl post command

i need help in understanding what is wrong with the below shell script,all its doing is executing a curl script using shell scripting and searching for a string domain_id in the output of curl command ,once it finds the search all it does it simply displays valid url
Here is the full code for shell script below
#!/bin/sh
# Black Box Tester!
url=”https://api.platform.abc.com/auth/oauth/token“
content=”$(curl --location --request POST “$url” --header 'Content-Type:
application/x-www-form-urlencoded' --header 'Authorization: Basic
V0pSWURISA==' --data-raw 'grant_type=password&username=event-
player1#abc.com&password=********' | grep domain_id”
if [ ! -z $content ] && [ $content -eq domain_id ]
then
echo “valid url”
else
echo “invalid url”
fi
Below is the error i get in console after i try executing the script
WS-126691A:loginimagedocker carolyn$ ./login.sh
./login.sh: line 4: unexpected EOF while looking for matching `)'
./login.sh: line 11: syntax error: unexpected end of file
You are trying to pass parameter in multiple line without mentioning end of line.
use \ to pass multi line argument
#!/bin/sh
# Black Box Tester!
url=”http://api.platform.abc.com/auth/oauth/token“
content=”$(curl --location --request POST “$url” --header 'Content-Type: \
application/x-www-form-urlencoded' --header 'Authorization: Basic \
V0pSWURISA==' --data-raw 'grant_type=password&username=event- \
player1#abc.com&password=********' | grep domain_id” )
if [ ! -z $content ] && [ $content -eq domain_id ]
then
echo “valid url”
else
echo “invalid url”
fi

How to deal with HTTP 102 in bash?

From bash/curl I am consuming an API that receives a POST, perform heavy long tasks and returns a 200 on success. As we were facing some timeouts in WAF, API has been improved to accept header:
--header "Expect:102-Processing"
If API receives that header it sends a HTTP 102 every 20 secs until process finishes and sends a HTTP 200. This should be enough to prevent timeouts.
What I have to do to deal with those HTTP 102?
I added that header to my curl command but as soon as it receives first 102, curl command finishes.
I was thinking that maybe there is a parameter in curl to wait until 200 or error.
Another option I have in mind is waiting in a loop querying for status but I don't know how to instruct curl to monitor that connection
This is a test version of my bash script.
#!/bin/bash
clear
function_triggerFooAdapter()
{
pFooUrl=$1
pPayload=$2
pCURLConnectTimeout=$3
pWaitForFooResponse=$4
pAddExpect102Header=$5
rm ./tmpResult.html 2>/dev/null
rm ./tmpResult.txt 2>/dev/null
echo "Triggering internal Foo adapter $pFooAdapterName"
echo "Full URL=$pFooUrl"
echo "Payload to send=$pPayload"
echo "Curl connect-timeout=$pCURLConnectTimeout"
echo "WaitForFooResponse=$pWaitForFooResponse"
echo "AddExpect102Header=$pAddExpect102Header"
if [[ "$pAddExpect102Header" = true ]]; then
text102Header="Expect:102-Processing"
else
text102Header="NoExpect;" # send innofensive custom header
fi
if [[ "$pWaitForFooResponse" = true ]]; then
echo "So DO wait..."
Response=$(curl -k --write-out %{http_code} --header "$text102Header" --header "Content-Type:application/json" --silent --connect-timeout $pCURLConnectTimeout --output ./tmpResult.html -X POST --data "$pPayload" "$pFooUrl" 2>&1 | tee ./tmpResult.txt)
echo "HTTP Response=$Response"
echo "$(cat ./tmpResult.txt)"
if [ "${Response:0:1}" -eq "1" ] || [ "${Response:0:1}" -eq "2" ]; then #if HTTP Response start by 1 or 2 (10x - 20x)...
echo "Adapter sucessfully triggered."
return 0
else
# cat ./tmpResult.html 2>/dev/null
#cat ./tmpResult.txt 2>/dev/null
echo
echo "HTTP error trying to trigger adapter."
return 1
fi
else
echo "So DO NOT wait..."
curl -k --write-out %{http_code} --header "$text102Header" --header "Content-Type:application/json" --silent --connect-timeout $pCURLConnectTimeout --output ./tmpResult.html -X POST --data "$pPayload" "$pFooUrl" > /dev/null 2>&1 &
echo "Adapter sucessfully (hopefully) triggered. NOT reading HTTP response until Foo code is upgraded to respond directly a HTTP 200 Successfully queued or similar."
return 0
fi
}
clear
export http_proxy="http://1.1.1.256:3128/"
export https_proxy="http://1.1.1.256:3128/"
export no_proxy="foo.com"
# Main
clear
echo "STEP 09- Triggering Foo Internal Adapters."
echo "Proxy settings:"
env | grep proxy
function_triggerFooAdapter "http://foo.com/lookups/trigger_foo" "" 600 true true
Run it manually and CHECK what curl -v is sending as the headers; I would expect to see something like
> POST /the/url HTTP/1.1
> Host: thehost.com:80
> User-Agent: curl/7.51.0
> Accept: */*
> Expect: 102-Processing
... some stuff skipped.
If you're not sending the Expect header; then curl is in fact doing the right thing..

Resources