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