mirror of https://github.com/harness/drone.git
feat: [AH-687]: Added PR check script for code coverage (#3135)
* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into AH-687-PR-checks * [AH-687]: Updated format * [AH-687]: Updated copyright * [AH-687]: updated script * [AH-687]: updated script * [AH-687]: updated script * [AH-687]: Cleanup * [AH-687]: updated script * []: updated * []: updated script * []: updated script * []: updated script * []: added test * []: Added utils * []: updated script * []: updated script * []: updated script * []: updated script * []: updated script * []: updated script * []: added temp utils files * []: Updated dummy_arvind * []: Updated dummy_arvind * []: Updated dummy_arvindBT-10437
parent
4a55edad29
commit
aaebea0c5d
|
@ -0,0 +1,161 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidatePackageTypes_ValidTypes(t *testing.T) {
|
||||
err := ValidatePackageTypes([]string{"DOCKER", "HELM"})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidatePackageTypes_InvalidTypes(t *testing.T) {
|
||||
err := ValidatePackageTypes([]string{"INVALID"})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "invalid package type", err.Error())
|
||||
}
|
||||
|
||||
func TestValidatePackageType_ValidType(t *testing.T) {
|
||||
err := ValidatePackageType("DOCKER")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidatePackageType_InvalidType(t *testing.T) {
|
||||
err := ValidatePackageType("INVALID")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "invalid package type", err.Error())
|
||||
}
|
||||
|
||||
func TestValidateIdentifier_ValidIdentifier(t *testing.T) {
|
||||
err := ValidateIdentifier("valid-identifier")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateIdentifier_InvalidIdentifier(t *testing.T) {
|
||||
err := ValidateIdentifier("Invalid Identifier")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, RegistryIdentifierErrorMsg, err.Error())
|
||||
}
|
||||
|
||||
func TestCleanURLPath_ValidURL(t *testing.T) {
|
||||
input := "https://example.com/path/"
|
||||
expected := "https://example.com/path"
|
||||
CleanURLPath(&input)
|
||||
assert.Equal(t, expected, input)
|
||||
}
|
||||
|
||||
func TestCleanURLPath_InvalidURL(t *testing.T) {
|
||||
input := "://invalid-url"
|
||||
expected := "://invalid-url"
|
||||
CleanURLPath(&input)
|
||||
assert.Equal(t, expected, input)
|
||||
}
|
||||
|
||||
func TestGetTimeInMs_ValidTime(t *testing.T) {
|
||||
tm := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
expected := "1672531200000"
|
||||
result := GetTimeInMs(tm)
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestGetErrorResponse_ValidError(t *testing.T) {
|
||||
code := 404
|
||||
message := "Not Found"
|
||||
expected := &artifact.Error{
|
||||
Code: "404",
|
||||
Message: message,
|
||||
}
|
||||
result := GetErrorResponse(code, message)
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestGetSortByOrder_ValidOrder(t *testing.T) {
|
||||
assert.Equal(t, "ASC", GetSortByOrder(""))
|
||||
assert.Equal(t, "DESC", GetSortByOrder("DESC"))
|
||||
assert.Equal(t, "ASC", GetSortByOrder("INVALID"))
|
||||
}
|
||||
|
||||
func TestGetSortByField_ValidField(t *testing.T) {
|
||||
assert.Equal(t, "name", GetSortByField("identifier", RepositoryResource))
|
||||
assert.Equal(t, "created_at", GetSortByField("invalid", RepositoryResource))
|
||||
}
|
||||
|
||||
func TestGetPageLimit_ValidPageSize(t *testing.T) {
|
||||
pageSize := artifact.PageSize(20)
|
||||
assert.Equal(t, 20, GetPageLimit(&pageSize))
|
||||
assert.Equal(t, 10, GetPageLimit(nil))
|
||||
}
|
||||
|
||||
func TestGetOffset_ValidOffset(t *testing.T) {
|
||||
pageSize := artifact.PageSize(20)
|
||||
pageNumber := artifact.PageNumber(2)
|
||||
assert.Equal(t, 40, GetOffset(&pageSize, &pageNumber))
|
||||
assert.Equal(t, 0, GetOffset(nil, nil))
|
||||
}
|
||||
|
||||
func TestGetPageNumber_ValidPageNumber(t *testing.T) {
|
||||
pageNumber := artifact.PageNumber(2)
|
||||
assert.Equal(t, int64(2), GetPageNumber(&pageNumber))
|
||||
assert.Equal(t, int64(1), GetPageNumber(nil))
|
||||
}
|
||||
|
||||
func TestGetSuccessResponse_ValidResponse(t *testing.T) {
|
||||
expected := &artifact.Success{
|
||||
Status: artifact.StatusSUCCESS,
|
||||
}
|
||||
result := GetSuccessResponse()
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestGetPageCount_ValidCount(t *testing.T) {
|
||||
assert.Equal(t, int64(5), GetPageCount(50, 10))
|
||||
assert.Equal(t, int64(0), GetPageCount(0, 10))
|
||||
}
|
||||
|
||||
func TestGetRegistryRef_ValidRef(t *testing.T) {
|
||||
assert.Equal(t, "root/registry", GetRegistryRef("root", "registry"))
|
||||
}
|
||||
|
||||
func TestGetRepoURLWithoutProtocol_ValidURL(t *testing.T) {
|
||||
assert.Equal(t, "example.com/path", GetRepoURLWithoutProtocol("https://example.com/path"))
|
||||
assert.Equal(t, "", GetRepoURLWithoutProtocol("://invalid-url"))
|
||||
}
|
||||
|
||||
func TestGetTagURL_ValidURL(t *testing.T) {
|
||||
assert.Equal(t, "https://example.com/artifact/version", GetTagURL("artifact", "version", "https://example.com"))
|
||||
}
|
||||
|
||||
func TestGetPullCommand_ValidCommand(t *testing.T) {
|
||||
assert.Equal(t, "docker pull example.com/image:tag",
|
||||
GetPullCommand("image", "tag", "DOCKER", "https://example.com"))
|
||||
assert.Equal(t, "helm pull oci://example.com/image:tag",
|
||||
GetPullCommand("image", "tag", "HELM", "https://example.com"))
|
||||
assert.Equal(t, "", GetPullCommand("image", "tag", "INVALID", "https://example.com"))
|
||||
}
|
||||
|
||||
func TestGetDockerPullCommand_ValidCommand(t *testing.T) {
|
||||
assert.Equal(t, "docker pull example.com/image:tag", GetDockerPullCommand("image", "tag", "https://example.com"))
|
||||
}
|
||||
|
||||
func TestGetHelmPullCommand_ValidCommand(t *testing.T) {
|
||||
assert.Equal(t, "helm pull oci://example.com/image:tag", GetHelmPullCommand("image", "tag", "https://example.com"))
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Requirements:
|
||||
# Run tests on the current and target branches. The directories are provided on the top.
|
||||
# Find the total coverage of each of them.
|
||||
# Success:
|
||||
# current_branch_total_coverage >= target_branch_total_coverage
|
||||
# for the new files in the provided list of directories, the coverage should be atleast 75%
|
||||
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# This function needs some work!
|
||||
calculate_file_coverage() {
|
||||
local file=$1
|
||||
local total_statements=0
|
||||
local covered_statements=0
|
||||
|
||||
# Parse coverage report for the given file
|
||||
while read -r line; do
|
||||
echo $line
|
||||
# Each line format: "<file>:<line>:<func_name>\t<coverage_percent>"
|
||||
# Extract statements and coverage percentage
|
||||
statements=$(echo "$line" | awk -F: '{print $4}' | awk '{print $2}')
|
||||
coverage=$(echo "$line" | awk -F: '{print $4}' | awk '{print $NF}' | sed 's/%//')
|
||||
|
||||
# Accumulate total statements and covered statements
|
||||
total_statements=$((total_statements + statements))
|
||||
covered_statements=$(echo "$covered_statements + ($statements * $coverage / 100)" | bc)
|
||||
done < <(grep "$file" coverage_report.txt)
|
||||
|
||||
# Calculate and print total coverage for the file
|
||||
if (( total_statements == 0 )); then
|
||||
echo "0.0"
|
||||
else
|
||||
echo "scale=2; ($covered_statements / $total_statements) * 100" | bc
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================
|
||||
# Configuration Section
|
||||
# ============================
|
||||
# Provide the directories for which coverage should be checked.
|
||||
# Directories can be nested. We'll add "/..." to each to ensure all sub-packages are included.
|
||||
# Example: DIRECTORIES="./registry ./another/path"
|
||||
DIRECTORIES="./registry"
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Usage: $0 <target_branch>"
|
||||
exit 1
|
||||
fi
|
||||
TARGET_BRANCH=$1
|
||||
|
||||
# Convert directories into their recursive form (./dir => ./dir/...)
|
||||
# to ensure nested packages are included
|
||||
TEST_DIRS=""
|
||||
for d in $DIRECTORIES; do
|
||||
# If it doesn't already end with "..." then append it
|
||||
if [[ "$d" != *"..." ]]; then
|
||||
d="${d%/}/..."
|
||||
fi
|
||||
TEST_DIRS="$TEST_DIRS $d"
|
||||
done
|
||||
|
||||
# ============================
|
||||
# Setup
|
||||
# ============================
|
||||
git fetch origin "${TARGET_BRANCH}:${TARGET_BRANCH}"
|
||||
git checkout "${TARGET_BRANCH}"
|
||||
|
||||
# Run coverage on the target branch
|
||||
go test -coverprofile=coverage_target.out $TEST_DIRS
|
||||
TARGET_COV=$(go tool cover -func=coverage_target.out | grep total | awk '{print $3}' | sed 's/%//')
|
||||
|
||||
# Go back to the current (feature) branch
|
||||
git checkout -
|
||||
|
||||
# Run coverage on the current (feature) branch
|
||||
go test -coverprofile=coverage_current.out $TEST_DIRS
|
||||
CURRENT_COV=$(go tool cover -func=coverage_current.out | grep total | awk '{print $3}' | sed 's/%//')
|
||||
|
||||
# Ensure the current branch coverage is not lower than the target branch coverage.
|
||||
if (( $(echo "$CURRENT_COV < $TARGET_COV" | bc -l) )); then
|
||||
echo "Coverage decreased from ${TARGET_COV}% to ${CURRENT_COV}%."
|
||||
exit 1
|
||||
fi
|
||||
echo "Coverage checks passed! Current coverage: ${CURRENT_COV}%, Target coverage: ${TARGET_COV}%"
|
||||
|
||||
# Identify newly added files in the current branch compared to the target branch.
|
||||
# NEW_FILES=$(git diff --name-status "${TARGET_BRANCH}...HEAD" | grep '^A' | awk '{print $2}' | grep '\.go$' | grep -v '_test\.go$')
|
||||
# echo "new files: ""$NEW_FILES"
|
||||
|
||||
#go tool cover -func=coverage_current.out > coverage_report.txt
|
||||
#
|
||||
#for file in $NEW_FILES; do
|
||||
# # Check if the file is within one of the specified directories.
|
||||
# echo "new file is: "$file
|
||||
# IN_DIRS=false
|
||||
# for d in $DIRECTORIES; do
|
||||
# # Remove the trailing "/..." from the directory for a direct prefix check
|
||||
# base_dir="${d%/...}"
|
||||
# echo "base_dir value: "$d
|
||||
# normalized_base_dir="${base_dir#./}"
|
||||
# # If file starts with base_dir
|
||||
# if [[ $file == $normalized_base_dir* ]]; then
|
||||
# IN_DIRS=true
|
||||
# break
|
||||
# fi
|
||||
# done
|
||||
#
|
||||
# if [ "$IN_DIRS" = true ]; then
|
||||
# file_coverage=$(calculate_file_coverage "$file")
|
||||
# if (( $(echo "$file_coverage < 75.0" | bc -l) )); then
|
||||
# echo "New file $file has coverage of $file_coverage%, which is less than 75%."
|
||||
# else
|
||||
# echo "New file $file has coverage of $fcov%, which is better than 75%."
|
||||
# fi
|
||||
# fi
|
||||
#done
|
||||
|
||||
echo "All checks passed! Current coverage: ${CURRENT_COV}%, Target coverage: ${TARGET_COV}%"
|
||||
rm -rf coverage_*
|
Loading…
Reference in New Issue