Skip to content
Snippets Groups Projects
Select Git revision
  • af464144d1214dbf2a216eaf3b6216c56f06dee6
  • experimental default protected
  • v2023.2.5-ffs
  • nrb/ex400-remove-wps
  • nrb/airmax-test
  • v2023.2.4-ffs
  • nrb/ar9344-reset-sequence
  • autinerd/experimental-openwrt-24.10
  • v2023.2.3-ffs
  • v2023.2.2-ffs
  • v2023.2-ffs
  • v2023.1-ffs
  • v2022.1.4-ffs
  • feature/addMikrotikwAP
  • v2022.1.3-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • master protected
  • v2021.1.1-ffs
  • nrb/gluon-master-cpe510
  • v2021.1-ffs
  • experimental-2025-07-04
  • experimental-2025-07-04-base
  • experimental-2025-07-01
  • experimental-2025-07-01-base
  • experimental-2025-06-25
  • experimental-2025-06-25-base
  • experimental-2025-06-24
  • experimental-2025-06-24-base
  • experimental-2025-06-22
  • experimental-2025-06-22-base
  • v2023.2.5-ffs0.1
  • experimental-2025-06-08
  • experimental-2025-06-08-base
  • experimental-2025-06-06
  • experimental-2025-06-06-base
  • experimental-2025-05-27
  • experimental-2025-05-27-base
  • experimental-2025-05-18
  • experimental-2025-05-18-base
  • experimental-2025-05-15
41 results

check-image-size.py

Blame
  • check-image-size.py 4.45 KiB
    #!/usr/bin/env python3
    
    import argparse
    import json
    import sys
    from enum import Enum
    
    # Enum Class for checking image size
    class ImageSizeCheck(Enum):
        OK = "OK"
        TOO_BIG = "TOO_BIG"
        IGNORED = "IGNORED"
        UNKNOWN = "UNKNOWN"
    
    
    # Some devices pad their images to IMAGE_SIZE and apply a firmware header.
    # Exclude this from the image size check.
    excluded_devices = [
        "tplink_cpe210-v1",
        "tplink_cpe210-v2",
        "tplink_cpe210-v3",
        "tplink_cpe220-v3",
        "tplink_cpe510-v1",
        "tplink_cpe510-v2",
        "tplink_cpe510-v3",
        "tplink_cpe710-v1",
        "tplink_wbs210-v1",
        "tplink_wbs210-v2",
        "tplink_wbs510-v1"
    ]
    
    
    def open_json(file_path):
        with open(file_path, 'r') as f:
            return json.load(f)
    
    
    def load_openwrt_profile_json(json_path):
        profiles = []
        profile_json = open_json(json_path)
        for profile_name, profile_data in profile_json["profiles"].items():
            device_profile = {
                "name": profile_name,
            }
            if "image" in profile_data.get("file_size_limits", {}):
                device_profile["max_image_size"] = profile_data["file_size_limits"]["image"]
    
            for image in profile_data["images"]:
                if image["type"] != "sysupgrade":
                    continue
                if "size" in image:
                    device_profile["image_size"] = image["size"]
            
            profiles.append(device_profile)
        
        return profiles
    
    
    def check_image_size_below_limit(profile, overhead=0):
        # Skip devices that pad their images
        if profile["name"] in excluded_devices:
            return ImageSizeCheck.IGNORED
    
        if "max_image_size" in profile and "image_size" in profile:
            if profile["image_size"] + (overhead * 1024) > profile["max_image_size"]:
                return ImageSizeCheck.TOO_BIG
            else:	
                return ImageSizeCheck.OK
        
        return ImageSizeCheck.UNKNOWN
    
    
    def print_github_actions_warning(message):
        print('::warning::{}'.format(message))
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser(description='Check image size of OpenWrt profiles')
        parser.add_argument(
            'profile_json',
            help='Path to profile.json',
            nargs='+'
        )
        parser.add_argument(
            '--github-actions',
            help='Generate warnings for use with GitHub Actions',
            action='store_true'
        )
        parser.add_argument(
            '--overhead',
            type=int,
            help='Additional size to add to the image size in kilobyte',
            default=0
        )
        args = parser.parse_args()
    
        if args.profile_json is None:
            print('Error: profile.json not specified')
            sys.exit(1)
        
        # Load all profile.json files
        profiles = []
        for profile_file in args.profile_json:
            profiles.extend(load_openwrt_profile_json(profile_file))
    
        # Initialize results with all available ImageSizeCheck values
        results = {}
        for check_result in ImageSizeCheck:
            results[check_result] = []
    
        for profile in profiles:
            check_result = check_image_size_below_limit(profile, args.overhead)
            results[check_result].append(profile)
        
        for check_result, profiles in results.items():
            if len(profiles) == 0:
                continue
    
            # Group by result type for GitHub Actions
            if args.github_actions:
                print('::group::{}'.format(check_result.value))
    
            for profile in profiles:
                if check_result == ImageSizeCheck.TOO_BIG:
                    msg = 'Image size of profile {} is too big ({} > {})'.format(
                        profile["name"],
                        profile["image_size"] + (args.overhead * 1024),
                        profile["max_image_size"])
                    if args.github_actions:
                        print_github_actions_warning(msg)
                    else:
                        print("Warning: {}".format(msg))
                elif check_result == ImageSizeCheck.UNKNOWN:
                    msg = 'Image size of profile {} is unknown'.format(
                        profile["name"])
                    print(msg)
                elif check_result == ImageSizeCheck.IGNORED:
                    msg = 'Image size of profile {} is ignored (Image size {})'.format(
                        profile["name"], profile.get("image_size", "unknown"))
                    print(msg)
                else:
                    msg = 'Image size of profile {} is OK ({} < {})'.format(
                        profile["name"], 
                        profile["image_size"] + (args.overhead * 1024),
                        profile["max_image_size"])
                    print(msg)