Generating a Trend Report (TGA Report over recent sprints)
If you need to retrieve TGA for several periods in a row you can reuse the following sample code
This shell script produces a CSV file aggregating several iterations of TGA reports
This shell script is written for
linux
and requiresjq
installed on your systemYou must update lines 4-13 with relevant values from your Sealights account and configuration
The output is a CSV file that looks like this
In the script below you have the option to download the detailed coverage for each TGA report (uncomment line 214)
#!/usr/bin/env bash
# Copyright Sealights 2024
DOMAIN="mycompany.sealights.co"
SL_API_TOKEN="123"
APP_NAME="MyApp"
BRANCH_NAME="master"
#CategoryName="Teams"
#LabelName="Backend"
Period_StartDate="2024-05-15"
Report_Frequency="2 weeks" #For monthly reports use "1 month"
Report_Iterations="3"
######## FUNCTIONS ########
getPartialCSVFilePath() {
CSV_FILENAME="${APP_NAME// /_}-${BRANCH_NAME//[\/ ]/_}"
TARGET_FOLDER="${APP_NAME// /_}"
if [ ! -d $TARGET_FOLDER ]; then
mkdir -p $TARGET_FOLDER;
fi
if [ -z "${LabelName}" ] && [ -z "${CategoryName}" ]; then
CSV_FILENAME="${CSV_FILENAME}-NoLabel"
else
CSV_FILENAME="${CSV_FILENAME}-${CategoryName}${LabelName}"
fi
#Preparing CSV file
if [ "$Report_Frequency" = "1 month" ]; then
CSV_FILENAME="${CSV_FILENAME}-Monthly"
elif [ "$Report_Frequency" = "2 weeks" ]; then
CSV_FILENAME="${CSV_FILENAME}-BiWeekly"
fi
echo "./$TARGET_FOLDER/$CSV_FILENAME-From_${Period_StartDate}"
}
rawurlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
#>&2 echo "encode $string"
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
*) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
encode_array_for_curl() {
local comma_separated_list="${1}"
local json_array
local encoded_array
# Convert comma-separated list to JSON array
json_array=$(echo "${comma_separated_list}" | jq -R 'split(",")')
# URL encode the JSON array
encoded_array=$(echo "${json_array}" | jq -sRr @uri)
echo "${encoded_array}" # You can either set a return variable (FASTER)
REPLY="${encoded_array}" #+or echo the result (EASIER)... or both... :p
}
waitForReportReady() {
local REPORT_ID=$1
for ((retries=0;retries<600;retries++)); do
local TGA_DETAILS=$(curl -s -X GET "https://${DOMAIN}/sl-api/v1/tga/report-templates/reports/${REPORT_ID}" -H 'accept: application/csv' -H "Authorization: Bearer $SL_API_TOKEN")
local STATUS=$(echo ${TGA_DETAILS} | jq -r .data.status)
if [[ "${STATUS}" != "In Progress" ]]; then
break
fi
>&2 echo ...
sleep 10
done
if [[ "${STATUS}" == "Ready" ]]; then
echo ${TGA_DETAILS} | jq .data
else
>&2 echo "Report ${REPORT_ID} is not Ready, its status is '${STATUS}'"
exit 1
fi
}
updateTGAReport() {
local REPORT_ID=$1
local PERIOD_FROM=$2
local PERIOD_TO=$3
local DATA="{\"range\":{\"dates\":{\"from\":${PERIOD_FROM},\"to\":${PERIOD_TO}}}}"
local RESPONSE=$(curl -s -X PUT "https://${DOMAIN}/sl-api/v1/tga/report-templates/reports/${REPORT_ID}" -H 'accept: application/json' -H 'Content-Type: application/json' -H "Authorization: Bearer $SL_API_TOKEN" -H "Accept: application/json" -d "${DATA}")
local REPORT_ID=$(echo ${RESPONSE} | jq -r .data.reportId)
if [[ "${REPORT_ID}" == "" || "${REPORT_ID}" == "null" ]]; then
>&2 echo "RESPONSE='${RESPONSE}'"
>&2 echo "Failed to update report ${REPORT_ID} with ${PERIOD_FROM} and ${PERIOD_TO}"
exit 1
fi
waitForReportReady "${REPORT_ID}"
}
downloadTgaReportCsvFile() {
local reportId="${1}"
local fullpath="${2}"
# Define the base URL
local download_url="https://${DOMAIN}/sl-api/v1/tga/report-templates/reports/${reportId}/csv"
# Use curl to download the CSV file and save it to the specified path
curl -sX GET "${download_url}" --output "${fullpath}" -H 'Content-Type: text/csv' -H "Authorization: Bearer $SL_API_TOKEN" -H "Accept: application/json"
# Check if the download was successful
if [ $? -eq 0 ]; then
>&2 echo "CSV file downloaded successfully to ${fullpath}"
else
>&2 echo "Failed to download CSV file from ${download_url}"
fi
}
######## SCRIPT ########
PERIOD_FROM=$(date -d "${Period_StartDate}" +%s%3N)
REPORT_MAX=$(date +%s%3N)
echo "Retrieving TGA Report details for $APP_NAME (Branch $BRANCH_NAME)"
if { [ -z "${LabelName}" ] && [ -n "${CategoryName}" ]; } || { [ -n "${LabelName}" ] && [ -z "${CategoryName}" ]; }; then
echo "> [ERROR] Category and Label: One of them is undefined but not both."
echo "> Category: ${CategoryName}, LabelNames: ${LabelNames}"
echo "> Ending script."
exit 1
fi
echo "> Report Start is ${Period_StartDate} to $PERIOD_FROM"
echo "> Report Frequency is ${Report_Frequency} for ${Report_Iterations} iterations"
TGA_REPORTS_LIST=""
TGA_REPORT_ID=""
APPNAME_ENCODED=$(rawurlencode "${APP_NAME}")
BRANCHNAME_ENCODED=$(rawurlencode "${BRANCH_NAME}")
if [ -z "${LabelName}" ] && [ -z "${CategoryName}" ]; then
echo "> No Label selected"
else
echo "> Group $LabelName selected for the Report scope"
CATEGORYNAME_ENCODED=$(rawurlencode "${CategoryName}")
##TODO: FIX LABEL NAMES - NOT WORKING YET
LABELNAMES_ENCODED=$(encode_array_for_curl "${LabelName}")
APPEND_CAT_AND_LABEL_QUERY="&categoryName=${CATEGORYNAME_ENCODED}&labelNames=${LABELNAMES_ENCODED}"
fi
TGA_REPORTS_LIST=$(curl -sX GET "https://${DOMAIN}/sl-api/v1/tga/report-templates/reports?appName=${APPNAME_ENCODED}&branchName=${BRANCHNAME_ENCODED}${APPEND_CAT_AND_LABEL_QUERY}" -H "Authorization: Bearer $SL_API_TOKEN" -H "Accept: application/json")
NUM_OF_REPORTS=$(echo $TGA_REPORTS_LIST | jq -r .data.total )
if [ $NUM_OF_REPORTS != 1 ]; then
echo "> $NUM_OF_REPORTS report(s) found for $APP_NAME / $BRANCH_NAME / $LabelName"
echo "> Ending script."
exit 1
fi
TGA_REPORT_ID=$(echo $TGA_REPORTS_LIST | jq -r .data.list[0].reportId )
CSV_FULLPATH_FILE=$(getPartialCSVFilePath)
echo "Generating CSV report as $CSV_FULLPATH_FILE"
#headers
echo '"StartDate","EndDate","Name","overall/totalMethods","overall/uncoveredMethods","overall/coveredMethods","overall/coverage","modifiedCode/totalMethods","modifiedCode/uncoveredMethods","modifiedCode/coveredMethods","modifiedCode/coverage"'>$CSV_FULLPATH_FILE
# Preparing variables for While loop
REPORT_FROM=${PERIOD_FROM}
REPORT_TO=$(date -d "${Period_StartDate}+${Report_Frequency}" +%s%3N)
i=1
while [ $i -le $Report_Iterations ] && [ $REPORT_FROM -lt $REPORT_MAX ]; do
if [ $REPORT_TO -gt $REPORT_MAX ]; then
echo "> Report cannot end in the future."
REPORT_TO=$REPORT_MAX
fi
DATE_FROM=$(date -d@"$((${REPORT_FROM}/1000))" +"%Y-%m-%d")
DATE_TO=$(date -d@"$((${REPORT_TO}/1000))" +"%Y-%m-%d")
echo ">> Generate TGA iteration #$i from $DATE_FROM to $DATE_TO"
JSON_TGA_REPORT=$(updateTGAReport ${TGA_REPORT_ID} ${REPORT_FROM} ${REPORT_TO})
#entire build - extract data from json into CSV
echo $JSON_TGA_REPORT | jq --arg DateFrom $DATE_FROM --arg DateTo $DATE_TO -r \
'.coverage.entireBuild | [$DateFrom,$DateTo,"EntireBuild",.overallCoverage.totalMethods,.overallCoverage.uncoveredMethods,.overallCoverage.coveredMethods,.overallCoverage.coverage,.modifiedCodeCoverage.totalMethods,.modifiedCodeCoverage.uncoveredMethods,.modifiedCodeCoverage.coveredMethods,.modifiedCodeCoverage.coverage] | @csv'>>$CSV_FULLPATH_FILE
#stage by stage - extract data from json into CSV
echo $JSON_TGA_REPORT | jq --arg DateFrom $DATE_FROM --arg DateTo $DATE_TO -r \
'.coverage.testStages[] | [$DateFrom,$DateTo,.name,.overallCoverage.totalMethods,.overallCoverage.uncoveredMethods,.overallCoverage.coveredMethods,.overallCoverage.coverage,.modifiedCodeCoverage.totalMethods,.modifiedCodeCoverage.uncoveredMethods,.modifiedCodeCoverage.coveredMethods,.modifiedCodeCoverage.coverage] | @csv'>>$CSV_FULLPATH_FILE
echo
#Next iteration should use recent report
TGA_REPORT_ID=$(echo $JSON_TGA_REPORT | jq -r .reportId )
#Optional - download the CSV file with coverage details
#downloadTgaReportCsvFile $TGA_REPORT_ID "./$TARGET_FOLDER/Report-${i}-CoverageDetails.csv"
((i+=1))
REPORT_FROM=$REPORT_TO
REPORT_TO=$(date -d "${DATE_TO}+${Report_Frequency}" +%s%3N)
done
mv $CSV_FULLPATH_FILE "${CSV_FULLPATH_FILE}_To_${DATE_TO}.csv"
echo script completed
exit 0
If running on Mac OS, the date command syntax differs slightly from regular Linux. Below is a Mac OS equivalent syntax for line 134 above.
PERIOD_FROM=$(date -j -f "%Y-%m-%d %H:%M" "${Period_StartDate}" +%s000)