Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

If you need to retrieve TGA for several periods of time 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 requires jq installed on your system

  • You must update lines 24-10 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)

Code Block
languagepowershellbash
#!/usr/bin/env bash
# Copyright Sealights 2024

DOMAIN="mycompany.sealights.co"
SL_API_TOKEN="123"
APP_NAME="MyApp"
BRANCH_NAME="master"
#CategoryName="Teams"
TeamName#LabelName="Backend"

Period_StartDate="20202024-0105-0115"
Report_Frequency="2 weeks" #For monthly reports use "1 month"
Report_Iterations="63"

######## FUNCTIONS ######## 

getPartialCSVFilePath() {
  CSV_FILENAME="${APP_NAME// /_}-${BRANCH_NAME//[\/ ]/_}"
  TARGET_FOLDER="${APP_NAME// /_}"

  if [ ! -d $TARGET_FOLDER ]; then
      mkdir -p $TARGET_FOLDER;
  fi

  
PERIOD_FROM=`date -d "${Period_StartDate}"  +%s%3N`
REPORT_MAX=`date +%s%3N`

echo "Retrieving TGA Report details for $APP_NAME (Branch $BRANCH_NAME)" 
echo "> Report Start is ${Period_StartDate} to $PERIOD_FROM"
echo "> Report Frequency is ${Report_Frequency} for ${Report_Iterations} iterations"

if [ -z ${TeamName} ]; then
    echo "> No Group selected"
    
    CSV_FILENAME="${CSV_FILENAME}-NoGroup"
    
    CONFIG_ID=`curl -sXif [ -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${DOMAIN}/sl-api/v1/tga/configs"/report-templates/reports/${REPORT_ID}" -H 'accept: application/csv' -H "Authorization: Bearer $SL_API_TOKEN")
\    local STATUS=$(echo ${TGA_DETAILS} | jq -H "Accept: application/json" | jq -c --arg APP_PARAM "$APP_NAME" --arg BRANCH_PARAM "$BRANCH_NAME" \r .data.status)
    if [[ "${STATUS}" != "In Progress" ]]; then
      break
    fi
    >&2 echo '..data.configs[] | select( (.appName==$APP_PARAM ) and ( .branchName==$BRANCH_PARAM ) and ( .teamName==null ) )' | jq -r .configId`.
    sleep 10
  done

  if [[ "${STATUS}" == "Ready" ]]; then
    echo ${TGA_DETAILS} | jq .data
  else
    >&2  echo "> Group $TeamName selected for the Report scope"
    
    CSV_FILENAME="${CSV_FILENAME}-${TeamNameReport ${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  
    CONFIG_ID=`curl -sX GETRESPONSE=$(curl -s -X PUT "https://$DOMAIN${DOMAIN}/sl-api/v1/tga/configs/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 -c --arg APP_PARAM "$APP_NAME" --arg BRANCH_PARAM "$BRANCH_NAME" --arg TEAM_PARAM "$TeamName"\r .data.reportId)
  if [[ "${REPORT_ID}" == "" || "${REPORT_ID}" == "null" ]]; then
    >&2 echo "RESPONSE='${RESPONSE}'"
    >&2  '.data.configs[] | select( (.appName==$APP_PARAM ) and ( .branchName==$BRANCH_PARAM ) and ( .teamName==$TEAM_PARAM ) )' | jq -r .configId`
fi

NUM_OF_CONFIG=`echo "$CONFIG_ID" | wc -w `

if [ $NUM_OF_CONFIG != 1 ]; then
  echo "> $NUM_OF_CONFIG config(s) foundecho "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 / $TeamName")" 

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 "> Using configId $CONFIG_ID Report Start is ${Period_StartDate} to $PERIOD_FROM"
echo "> 
#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

CSV_FULLPATH_FILE="./$TARGET_FOLDER/$CSV_FILENAME-From_${Period_StartDate}"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$(date -d "${Period_StartDate}+${Report_Frequency}"  +%s%3N`%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$(date -d@"$((${REPORT_FROM}/1000))" +"%Y-%m-%d"`)
    DATE_TO=`date$(date -d@"$((${REPORT_TO}/1000))"  +"%Y-%m-%d"`)

    echo ">> Generate TGA iteration #$i from $DATE_FROM to $DATE_TO"

      LINK=`curl -sX GET "https://$DOMAIN/sl-api/v1/tga/reports/$CONFIG_ID/regenerate?periodFrom=$REPORT_FROM&periodTo=$REPORT_TO" \
            -H "Authorization: Bearer $SL_API_TOKEN" -H "Accept: application/json" | jq '.data.statusLink'`
    STATUS="\"In Progress\""
    
    while [[ $STATUS != "\"Ready\"" ]]; do
      echo "Current status ${STATUS}. Sleeping 30 sec..."
      sleep 30
      echo -n "Checking report status..."
      REPORT_JSON=`curl -sX GET "https://$DOMAIN/sl-api/v1/tga/reports?configIds=$CONFIG_ID" \
                -H "Authorization: Bearer $SL_API_TOKEN" -H "Accept: application/json"`
      STATUS=`echo $REPORT_JSON | jq '.data.reports[0].status'`
    done
    
    echo "Report Status: Ready."

    #entire build
    echo $REPORT_JSONJSON_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 \
        '.data.reports[0].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 #stagesCSV
    echo $REPORT$JSON_TGA_JSONREPORT | jq --arg DateFrom $DATE_FROM --arg DateTo $DATE_TO -r \
        '.data.reports[0].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 "--"
    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$(date -d "${DATE_TO}+${Report_Frequency}"  +%s%3N`%s%3N)
done

mv $CSV_FULLPATH_FILE "${CSV_FULLPATH_FILE}_To_${DATE_TO}.csv"

echo script completed
exit 0
Info

If running on Mac OS, the date command syntax is differs slightly different from regular Linux. Below is a Mac OS equivalent syntax for line 21 134 above.

PERIOD_FROM=`date $(date -j -f "%Y-%m-%d %H:%M" "2020-01-01 00:00" +%s000`${Period_StartDate}" +%s000)