#!/usr/bin/env ruby # frozen_string_literal: true require "json" MARKER_FILE = "coverage/coverage.json" unless File.exist?(MARKER_FILE) puts "Coverage check failed: no coverage.json found." puts "Please run `bin/linters/nplus1` or `bin/coverage` first to generate the report." exit 1 end begin data = JSON.parse(File.read(MARKER_FILE)) unless data.key?("groups") puts "Coverage check failed: 'groups' key not found in coverage.json format." exit(1) end failed_groups = [] data["groups"].each do |group_name, group_data| # Depending on SimpleCov format, it might be nested under `lines` # Check both structured formats. percent = group_data.dig("lines", "covered_percent") || group_data["covered_percent"] if percent.nil? puts "Coverage check failed: Could not determine covered_percent for group '#{group_name}'." exit(1) end if percent < 100.0 failed_groups << { name: group_name, percent: percent } end end if failed_groups.any? puts "Coverage check failed: Not all groups have 100% coverage." puts "The following groups need more tests:" failed_groups.sort_by { |fg| fg[:name] }.each do |fg| # Format percentage to 2 decimal places max percent_str = fg[:percent] == fg[:percent].to_i ? fg[:percent].to_i : format("%.2f", fg[:percent]) puts " - #{fg[:name]}: #{percent_str}%" end if data["coverage"] puts "\nUncovered lines:" data["coverage"].each do |file, file_data| next unless file_data["lines"] next if file_data["lines"].compact.all? { |l| l.to_i > 0 } lines = file_data["lines"] missing_lines = [] lines.each_with_index do |visits, idx| missing_lines << (idx + 1) if visits && visits.to_i == 0 end if missing_lines.any? relative_file = file.sub(%r{^#{Regexp.escape(Dir.pwd)}/}, "") puts " - #{relative_file}: #{missing_lines.count} missing lines (#{missing_lines.join(", ")})" end end end exit(1) end puts "Coverage check passed: All groups have 100% coverage." exit(0) rescue JSON::ParserError puts "Coverage check failed: coverage.json is not valid JSON." exit(1) end