mirror of
https://github.com/apache/cloudstack
synced 2026-08-02 13:35:41 +00:00
Some checks failed
Build / build (push) Has been cancelled
Simulator CI / build (push) Has been cancelled
Simulator CI / test (component/find_hosts_for_migration component/test_acl_isolatednetwork component/test_acl_isolatednetwork_delete component/test_acl_listsnapshot) (push) Has been cancelled
Simulator CI / test (component/test_acl_listvm component/test_acl_listvolume) (push) Has been cancelled
Simulator CI / test (component/test_acl_sharednetwork component/test_acl_sharednetwork_deployVM-impersonation component/test_user_private_gateway component/test_user_shared_network) (push) Has been cancelled
Simulator CI / test (component/test_affinity_groups_projects component/test_allocation_states component/test_assign_vm) (push) Has been cancelled
Simulator CI / test (component/test_concurrent_snapshots_limit component/test_cpu_domain_limits component/test_cpu_limits component/test_cpu_max_limits component/test_cpu_project_limits component/test_deploy_vm_userdata_multi_nic component/test_deploy_vm_lease) (push) Has been cancelled
Simulator CI / test (component/test_egress_fw_rules component/test_invalid_gw_nm component/test_ip_reservation) (push) Has been cancelled
Simulator CI / test (component/test_lb_secondary_ip component/test_list_nics component/test_list_pod component/test_memory_limits) (push) Has been cancelled
Simulator CI / test (component/test_mm_domain_limits component/test_mm_max_limits component/test_mm_project_limits component/test_network_offering component/test_non_contiguous_vlan) (push) Has been cancelled
Simulator CI / test (component/test_persistent_networks component/test_project_configs component/test_project_limits component/test_project_resources) (push) Has been cancelled
Simulator CI / test (component/test_project_usage component/test_protocol_number_security_group component/test_public_ip component/test_resource_limits component/test_resource_limit_tags) (push) Has been cancelled
Simulator CI / test (component/test_regions_accounts component/test_routers component/test_snapshots component/test_stopped_vm component/test_tags component/test_templates component/test_updateResourceCount component/test_update_vm) (push) Has been cancelled
Simulator CI / test (component/test_volumes component/test_vpc component/test_vpc_distributed_routing_offering component/test_vpc_network component/test_vpc_offerings component/test_vpc_routers component/test_vpn_users component/test_vpc_network_lbrules) (push) Has been cancelled
Simulator CI / test (smoke/test_accounts smoke/test_account_access smoke/test_affinity_groups smoke/test_affinity_groups_projects smoke/test_annotations smoke/test_async_job smoke/test_attach_multiple_volumes smoke/test_backup_recovery_dummy smoke/test_certauthority_… (push) Has been cancelled
Simulator CI / test (smoke/test_cluster_drs smoke/test_dynamicroles smoke/test_enable_account_settings_for_domain smoke/test_enable_role_based_users_in_projects smoke/test_events_resource smoke/test_global_settings smoke/test_guest_vlan_range smoke/test_host_maintena… (push) Has been cancelled
Simulator CI / test (smoke/test_list_accounts smoke/test_list_disk_offerings smoke/test_list_domains smoke/test_list_hosts smoke/test_list_service_offerings smoke/test_list_storage_pools smoke/test_list_volumes) (push) Has been cancelled
Simulator CI / test (smoke/test_network smoke/test_network_acl smoke/test_network_ipv6 smoke/test_network_permissions smoke/test_nic smoke/test_nic_adapter_type smoke/test_non_contigiousvlan smoke/test_object_stores smoke/test_outofbandmanagement smoke/test_outofband… (push) Has been cancelled
Simulator CI / test (smoke/test_router_dhcphosts smoke/test_router_dns smoke/test_router_dnsservice smoke/test_routers smoke/test_routers_iptables_default_policy smoke/test_routers_network_ops smoke/test_scale_vm smoke/test_secondary_storage smoke/test_service_offeri… (push) Has been cancelled
CodeQL Analysis / CodeQL (actions) (push) Has been cancelled
Docker Image Build / build (push) Has been cancelled
Sonar Quality Check (Main) / Sonar JaCoCo Coverage (push) Has been cancelled
License Check / build (push) Has been cancelled
UI Build / build (push) Has been cancelled
Co-authored-by: Pearl Dsilva <pearl1954@gmail.com>
175 lines
7.2 KiB
Bash
Executable File
175 lines
7.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Licensed to the Apache Software Foundation (ASF) under one
|
||
# or more contributor license agreements. See the NOTICE file
|
||
# distributed with this work for additional information
|
||
# regarding copyright ownership. The ASF licenses this file
|
||
# to you 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.
|
||
#
|
||
# coverage-grade.sh
|
||
#
|
||
# Parses the JaCoCo aggregate XML report and outputs an A–F coverage grade.
|
||
#
|
||
# Usage:
|
||
# ./scripts/coverage-grade.sh [path/to/jacoco.xml]
|
||
#
|
||
# Exit codes:
|
||
# 0 – grade is D or above (line coverage >= 20%)
|
||
# 1 – grade is F (line coverage < 20%)
|
||
#
|
||
# Environment variables (optional, used when writing GitHub outputs):
|
||
# GITHUB_OUTPUT – set automatically by GitHub Actions
|
||
# GITHUB_STEP_SUMMARY – set automatically by GitHub Actions
|
||
|
||
set -euo pipefail
|
||
|
||
JACOCO_XML="${1:-client/target/site/jacoco-aggregate/jacoco.xml}"
|
||
|
||
if [[ ! -f "$JACOCO_XML" ]]; then
|
||
echo "ERROR: JaCoCo report not found at: $JACOCO_XML" >&2
|
||
exit 2
|
||
fi
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Parse LINE and BRANCH counters from the top-level <report> element using
|
||
# Python's built-in xml.etree.ElementTree (no extra dependencies needed).
|
||
# ---------------------------------------------------------------------------
|
||
read -r LINE_COVERED LINE_MISSED BRANCH_COVERED BRANCH_MISSED < <(python3 - "$JACOCO_XML" <<'PYEOF'
|
||
import sys, xml.etree.ElementTree as ET
|
||
|
||
tree = ET.parse(sys.argv[1])
|
||
root = tree.getroot()
|
||
|
||
lc = lm = bc = bm = 0
|
||
# Sum counters from all <package> children so we get the true aggregate,
|
||
# avoiding any duplicate top-level counter that some JaCoCo versions emit.
|
||
for pkg in root.iter('package'):
|
||
for counter in pkg.findall('counter'):
|
||
t = counter.get('type')
|
||
if t == 'LINE':
|
||
lc += int(counter.get('covered', 0))
|
||
lm += int(counter.get('missed', 0))
|
||
elif t == 'BRANCH':
|
||
bc += int(counter.get('covered', 0))
|
||
bm += int(counter.get('missed', 0))
|
||
|
||
print(lc, lm, bc, bm)
|
||
PYEOF
|
||
)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Compute percentages
|
||
# ---------------------------------------------------------------------------
|
||
line_total=$(( LINE_COVERED + LINE_MISSED ))
|
||
branch_total=$(( BRANCH_COVERED + BRANCH_MISSED ))
|
||
|
||
if (( line_total == 0 )); then
|
||
echo "ERROR: No LINE counters found in $JACOCO_XML – was the build run with -P quality?" >&2
|
||
exit 2
|
||
fi
|
||
|
||
# Use awk for floating-point arithmetic
|
||
LINE_PCT=$(awk "BEGIN { printf \"%.2f\", ($LINE_COVERED / $line_total) * 100 }")
|
||
|
||
if (( branch_total > 0 )); then
|
||
BRANCH_PCT=$(awk "BEGIN { printf \"%.2f\", ($BRANCH_COVERED / $branch_total) * 100 }")
|
||
else
|
||
BRANCH_PCT="N/A"
|
||
fi
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Assign grade based on LINE coverage
|
||
#
|
||
# A ≥ 80% Excellent
|
||
# B 60–79% Good
|
||
# C 40–59% Acceptable
|
||
# D 20–39% Marginal (meets minimum gate)
|
||
# F < 20% Failing
|
||
# ---------------------------------------------------------------------------
|
||
LINE_INT=$(awk "BEGIN { printf \"%d\", $LINE_PCT }") # truncate, not round
|
||
|
||
if (( LINE_INT >= 80 )); then GRADE="A"; EMOJI="🟢"; LABEL="Excellent"
|
||
elif (( LINE_INT >= 60 )); then GRADE="B"; EMOJI="🟡"; LABEL="Good"
|
||
elif (( LINE_INT >= 40 )); then GRADE="C"; EMOJI="🟠"; LABEL="Acceptable"
|
||
elif (( LINE_INT >= 20 )); then GRADE="D"; EMOJI="🔴"; LABEL="Marginal"
|
||
else GRADE="F"; EMOJI="⛔"; LABEL="Failing"
|
||
fi
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Human-readable output (always printed to stdout)
|
||
# ---------------------------------------------------------------------------
|
||
echo "┌─────────────────────────────────────────────────┐"
|
||
echo "│ CloudStack Test Coverage Report │"
|
||
echo "├─────────────────────────────────────────────────┤"
|
||
printf "│ Grade : %s %-5s %-20s │\n" "$EMOJI" "$GRADE" "($LABEL)"
|
||
printf "│ Line coverage: %6s%% (%d / %d lines)%*s│\n" \
|
||
"$LINE_PCT" "$LINE_COVERED" "$line_total" \
|
||
$(( 14 - ${#LINE_COVERED} - ${#line_total} )) " "
|
||
if [[ "$BRANCH_PCT" != "N/A" ]]; then
|
||
printf "│ Branch cov. : %6s%% (%d / %d branches)%*s│\n" \
|
||
"$BRANCH_PCT" "$BRANCH_COVERED" "$branch_total" \
|
||
$(( 11 - ${#BRANCH_COVERED} - ${#branch_total} )) " "
|
||
else
|
||
printf "│ Branch cov. : N/A (no branch data) │\n"
|
||
fi
|
||
echo "└─────────────────────────────────────────────────┘"
|
||
echo ""
|
||
echo "Grade scale: A ≥80% B 60-79% C 40-59% D 20-39% F <20% (line coverage)"
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# GitHub Actions: write outputs and step summary
|
||
# ---------------------------------------------------------------------------
|
||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||
{
|
||
echo "coverage_grade=$GRADE"
|
||
echo "coverage_grade_label=$LABEL"
|
||
echo "line_coverage=$LINE_PCT"
|
||
echo "branch_coverage=$BRANCH_PCT"
|
||
} >> "$GITHUB_OUTPUT"
|
||
fi
|
||
|
||
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
|
||
{
|
||
echo "## $EMOJI Test Coverage Grade: **$GRADE** — $LABEL"
|
||
echo ""
|
||
echo "| Metric | Covered | Total | Percentage |"
|
||
echo "|--------|---------|-------|------------|"
|
||
echo "| Line coverage | $LINE_COVERED | $line_total | **${LINE_PCT}%** |"
|
||
if [[ "$BRANCH_PCT" != "N/A" ]]; then
|
||
echo "| Branch coverage | $BRANCH_COVERED | $branch_total | **${BRANCH_PCT}%** |"
|
||
fi
|
||
echo ""
|
||
echo "### Grade Scale"
|
||
echo "| Grade | Line Coverage | Meaning |"
|
||
echo "|-------|--------------|---------|"
|
||
echo "| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |"
|
||
echo "| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |"
|
||
echo "| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |"
|
||
echo "| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |"
|
||
echo "| ⛔ F | < 20% | tests? what tests? 🔥 |"
|
||
echo ""
|
||
echo "> Branch coverage is shown as a secondary signal. Grade is based on line coverage."
|
||
} >> "$GITHUB_STEP_SUMMARY"
|
||
fi
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Exit non-zero for grade F so the CI job can be configured to fail
|
||
# ---------------------------------------------------------------------------
|
||
if [[ "$GRADE" == "F" ]]; then
|
||
echo ""
|
||
echo "⛔ FAIL: Line coverage ${LINE_PCT}% is below the minimum threshold of 20%." >&2
|
||
exit 1
|
||
fi
|
||
|
||
exit 0
|