From 378c309e8d617419107823c09ff5b7e36cc15189 Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:16:20 +0200 Subject: [PATCH 1/7] feat: Add firmware summary to AI release instructions (refs #20) - Create generate-firmware-summary.zsh script to automatically generate firmware support table - Add mandatory firmware summary section to release instructions - Include current firmware status at top of all release notes - Provide users with immediate visibility into supported models and latest firmware versions - Generate clean table showing Model | Latest Official | Latest Labs format --- docs/release/RELEASE_SUMMARY_INSTRUCTIONS.md | 38 ++++++-- scripts/release/generate-firmware-summary.zsh | 95 +++++++++++++++++++ 2 files changed, 127 insertions(+), 6 deletions(-) create mode 100755 scripts/release/generate-firmware-summary.zsh diff --git a/docs/release/RELEASE_SUMMARY_INSTRUCTIONS.md b/docs/release/RELEASE_SUMMARY_INSTRUCTIONS.md index fd2aae6..1f0a220 100644 --- a/docs/release/RELEASE_SUMMARY_INSTRUCTIONS.md +++ b/docs/release/RELEASE_SUMMARY_INSTRUCTIONS.md @@ -15,20 +15,46 @@ This document defines the required content and formatting for the major changes - Keep process improvements as a minor part of the summary ## Required Content Sections -- **New GoPro Models**: List any new GoPro camera models added since the base release -- **Official Firmware**: List new official firmware releases added, grouped by model -- **Labs Firmware**: List new GoPro Labs firmware releases added, grouped by model -- **Core Functionality**: SD card management, firmware updates, tool improvements -- **Infrastructure**: CI/CD and process improvements (minor section) + +### 1. Firmware Summary (MANDATORY - Top of Document) +- **MUST** include the current firmware support status at the very top of the release notes +- Run `./scripts/release/generate-firmware-summary.zsh` to generate the firmware table +- This provides users with immediate visibility into supported models and latest firmware versions +- Place this section before any other content + +### 2. New GoPro Models +- List any new GoPro camera models added since the base release + +### 3. Official Firmware +- List new official firmware releases added, grouped by model + +### 4. Labs Firmware +- List new GoPro Labs firmware releases added, grouped by model + +### 5. Core Functionality +- SD card management, firmware updates, tool improvements + +### 6. Infrastructure +- CI/CD and process improvements (minor section) ## Formatting Requirements - **DO NOT** include a main header (e.g., "# Major Changes Since vXX.XX.XX") – the main process creates this -- Start directly with section headers (e.g., `## New GoPro Models`) +- Start directly with the firmware summary table - Use bullet points for all lists - Group firmware by model and type (Official vs Labs) ## Example Structure ```markdown +## Supported GoPro Models + +The following GoPro camera models are currently supported by GoProX: + +| Model | Latest Official | Latest Labs | +|-------|-----------------|-------------| +| GoPro Max | H19.03.02.02.00 | H19.03.02.02.70 | +| HERO10 Black | H21.01.01.62.00 | H21.01.01.62.70 | +| HERO11 Black | H22.01.02.32.00 | H22.01.02.32.70 | + ## New GoPro Models - HERO12 Black diff --git a/scripts/release/generate-firmware-summary.zsh b/scripts/release/generate-firmware-summary.zsh new file mode 100755 index 0000000..50463a6 --- /dev/null +++ b/scripts/release/generate-firmware-summary.zsh @@ -0,0 +1,95 @@ +#!/bin/zsh + +# Generate firmware summary for release notes +# This script creates a comprehensive list of supported GoPro models and their latest firmware versions + +SCRIPT_DIR="${0:A:h}" +source "$SCRIPT_DIR/../core/logger.zsh" +init_logger "generate-firmware-summary" + +log_info "Generating firmware summary for release notes" + +# Function to get latest firmware version for a model +get_latest_firmware() { + local model_dir="$1" + local latest_version="" + + if [[ ! -d "$model_dir" ]]; then + return 1 + fi + + for version_dir in "$model_dir"/*/; do + if [[ -d "$version_dir" ]]; then + local version=$(basename "$version_dir") + if [[ "$version" == ".keep" ]] || [[ "$version" == "README.txt" ]]; then + continue + fi + if [[ "$version" > "$latest_version" ]]; then + latest_version="$version" + fi + fi + done + + echo "$latest_version" +} + +# Initialize associative arrays +typeset -A official_firmware +typeset -A labs_firmware +typeset -a all_models + +# Process official firmware +for model_dir in firmware/official/*/; do + if [[ -d "$model_dir" ]]; then + model_name=$(basename "$model_dir") + model_name=${model_name//\"/} # Remove any embedded quotes + if [[ "$model_name" != ".keep" ]] && [[ "$model_name" != "README.txt" ]]; then + latest_version=$(get_latest_firmware "$model_dir") + official_firmware[$model_name]="$latest_version" + all_models+=("$model_name") + fi + fi +done + +# Process labs firmware +for model_dir in firmware/labs/*/; do + if [[ -d "$model_dir" ]]; then + model_name=$(basename "$model_dir") + model_name=${model_name//\"/} # Remove any embedded quotes + if [[ "$model_name" != ".keep" ]] && [[ "$model_name" != "README.txt" ]]; then + latest_version=$(get_latest_firmware "$model_dir") + labs_firmware[$model_name]="$latest_version" + # Only add to all_models if not already present + if [[ ! " ${all_models[@]} " =~ " ${model_name} " ]]; then + all_models+=("$model_name") + fi + fi + fi +done + +# Sort models for output +sorted_models=() +while IFS= read -r model; do + sorted_models+=("$model") +done < <(printf '%s\n' "${all_models[@]}" | sort) + +# Generate the summary +log_info "Generating firmware summary markdown" + +cat << 'EOF' +## Supported GoPro Models + +The following GoPro camera models are currently supported by GoProX: + +EOF + +# Single table with latest official and labs firmware +echo "| Model | Latest Official | Latest Labs |" +echo "|-------|-----------------|-------------|" +for model in "${sorted_models[@]}"; do + official_ver="${official_firmware[$model]:-N/A}" + labs_ver="${labs_firmware[$model]:-N/A}" + echo "| $model | $official_ver | $labs_ver |" +done + +log_info "Firmware summary generation completed" \ No newline at end of file From a8e0e3d88ba41b054e535a7dc6a487b487b941a1 Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:18:15 +0200 Subject: [PATCH 2/7] fix: Improve table formatting in firmware summary script (refs #20) - Calculate optimal column widths based on content length - Use printf formatting for consistent spacing and alignment - Generate proper separators that match column widths - Ensure headers align with content below - Improve readability with left-aligned content --- scripts/release/generate-firmware-summary.zsh | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/scripts/release/generate-firmware-summary.zsh b/scripts/release/generate-firmware-summary.zsh index 50463a6..d040b92 100755 --- a/scripts/release/generate-firmware-summary.zsh +++ b/scripts/release/generate-firmware-summary.zsh @@ -73,6 +73,30 @@ while IFS= read -r model; do sorted_models+=("$model") done < <(printf '%s\n' "${all_models[@]}" | sort) +# Calculate column widths +model_width=5 # "Model" header length +official_width=15 # "Latest Official" header length +labs_width=11 # "Latest Labs" header length + +for model in "${sorted_models[@]}"; do + model_len=${#model} + if [[ $model_len -gt $model_width ]]; then + model_width=$model_len + fi + + official_ver="${official_firmware[$model]:-N/A}" + official_len=${#official_ver} + if [[ $official_len -gt $official_width ]]; then + official_width=$official_len + fi + + labs_ver="${labs_firmware[$model]:-N/A}" + labs_len=${#labs_ver} + if [[ $labs_len -gt $labs_width ]]; then + labs_width=$labs_len + fi +done + # Generate the summary log_info "Generating firmware summary markdown" @@ -83,13 +107,14 @@ The following GoPro camera models are currently supported by GoProX: EOF -# Single table with latest official and labs firmware -echo "| Model | Latest Official | Latest Labs |" -echo "|-------|-----------------|-------------|" +# Generate properly formatted table +printf "| %-${model_width}s | %-${official_width}s | %-${labs_width}s |\n" "Model" "Latest Official" "Latest Labs" +printf "|%s|%s|%s|\n" "$(printf '%*s' $((model_width + 2)) '' | tr ' ' '-')" "$(printf '%*s' $((official_width + 2)) '' | tr ' ' '-')" "$(printf '%*s' $((labs_width + 2)) '' | tr ' ' '-')" + for model in "${sorted_models[@]}"; do official_ver="${official_firmware[$model]:-N/A}" labs_ver="${labs_firmware[$model]:-N/A}" - echo "| $model | $official_ver | $labs_ver |" + printf "| %-${model_width}s | %-${official_width}s | %-${labs_width}s |\n" "$model" "$official_ver" "$labs_ver" done log_info "Firmware summary generation completed" \ No newline at end of file From b3b8e2136433620edaf0f5c46ceffa66e09f0955 Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:22:07 +0200 Subject: [PATCH 3/7] feat: Add custom sort order for firmware summary table (refs #20) - Sort models in priority order: HERO13, HERO (2024), HERO12, HERO11, HERO11 Mini, HERO10, HERO9, HERO8, GoPro Max, The Remote - Replace alphabetical sorting with custom order for better user experience - Maintain fallback to alphabetical for any models not in custom order --- scripts/release/generate-firmware-summary.zsh | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/scripts/release/generate-firmware-summary.zsh b/scripts/release/generate-firmware-summary.zsh index d040b92..b1ff999 100755 --- a/scripts/release/generate-firmware-summary.zsh +++ b/scripts/release/generate-firmware-summary.zsh @@ -67,11 +67,34 @@ for model_dir in firmware/labs/*/; do fi done -# Sort models for output +# Sort models in custom order sorted_models=() -while IFS= read -r model; do - sorted_models+=("$model") -done < <(printf '%s\n' "${all_models[@]}" | sort) +custom_order=( + "HERO13 Black" + "HERO (2024)" + "HERO12 Black" + "HERO11 Black" + "HERO11 Black Mini" + "HERO10 Black" + "HERO9 Black" + "HERO8 Black" + "GoPro Max" + "The Remote" +) + +# Add models in custom order if they exist +for model in "${custom_order[@]}"; do + if [[ " ${all_models[@]} " =~ " ${model} " ]]; then + sorted_models+=("$model") + fi +done + +# Add any remaining models that weren't in the custom order (alphabetically) +for model in "${all_models[@]}"; do + if [[ ! " ${sorted_models[@]} " =~ " ${model} " ]]; then + sorted_models+=("$model") + fi +done # Calculate column widths model_width=5 # "Model" header length From a5a900722014fa358d71265f588dacb701a79a2e Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:23:24 +0200 Subject: [PATCH 4/7] feat: Auto-sort new models by firmware version at top (refs #20) - Automatically place newer models (higher firmware versions) at the top of the list - Sort unknown models by firmware version in descending order - Maintain custom order for known models (HERO13, HERO12, etc.) - Future-proof design: new models added will automatically appear at the top - HERO (2024) now correctly appears first due to highest firmware version --- scripts/release/generate-firmware-summary.zsh | 68 ++++++++++++++++--- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/scripts/release/generate-firmware-summary.zsh b/scripts/release/generate-firmware-summary.zsh index b1ff999..ec21847 100755 --- a/scripts/release/generate-firmware-summary.zsh +++ b/scripts/release/generate-firmware-summary.zsh @@ -67,7 +67,7 @@ for model_dir in firmware/labs/*/; do fi done -# Sort models in custom order +# Sort models with newer models at top sorted_models=() custom_order=( "HERO13 Black" @@ -82,16 +82,68 @@ custom_order=( "The Remote" ) -# Add models in custom order if they exist -for model in "${custom_order[@]}"; do - if [[ " ${all_models[@]} " =~ " ${model} " ]]; then - sorted_models+=("$model") +# Function to get highest firmware version for a model +get_highest_firmware() { + local model="$1" + local official_ver="${official_firmware[$model]:-}" + local labs_ver="${labs_firmware[$model]:-}" + + if [[ -n "$official_ver" && -n "$labs_ver" ]]; then + if [[ "$official_ver" > "$labs_ver" ]]; then + echo "$official_ver" + else + echo "$labs_ver" + fi + elif [[ -n "$official_ver" ]]; then + echo "$official_ver" + elif [[ -n "$labs_ver" ]]; then + echo "$labs_ver" + else + echo "" fi -done +} + +# Separate known and unknown models +known_models=() +unknown_models=() -# Add any remaining models that weren't in the custom order (alphabetically) for model in "${all_models[@]}"; do - if [[ ! " ${sorted_models[@]} " =~ " ${model} " ]]; then + if [[ " ${custom_order[@]} " =~ " ${model} " ]]; then + known_models+=("$model") + else + unknown_models+=("$model") + fi +done + +# Sort unknown models by firmware version (newest first) +if [[ ${#unknown_models[@]} -gt 0 ]]; then + # Create temporary array with model and version pairs + temp_models=() + for model in "${unknown_models[@]}"; do + version=$(get_highest_firmware "$model") + if [[ -n "$version" ]]; then + temp_models+=("$version|$model") + else + temp_models+=("0000.00.00.00.00|$model") + fi + done + + # Sort by version (descending) and extract model names + sorted_unknown=() + while IFS= read -r line; do + if [[ -n "$line" ]]; then + model=$(echo "$line" | cut -d'|' -f2) + sorted_unknown+=("$model") + fi + done < <(printf '%s\n' "${temp_models[@]}" | sort -r) + + # Add unknown models at the top (newest first) + sorted_models+=("${sorted_unknown[@]}") +fi + +# Add known models in custom order +for model in "${custom_order[@]}"; do + if [[ " ${known_models[@]} " =~ " ${model} " ]]; then sorted_models+=("$model") fi done From e329c1243d3bc128a2e0fa785eae30f6d59da2d9 Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:29:47 +0200 Subject: [PATCH 5/7] fix: Ensure HERO (2024) and all custom order models appear in correct order (refs #20) - Use robust string comparison for custom order matching - Remove all debug output for clean production use - Table now matches user-specified order exactly, including HERO (2024) --- scripts/release/generate-firmware-summary.zsh | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/scripts/release/generate-firmware-summary.zsh b/scripts/release/generate-firmware-summary.zsh index ec21847..8fe2cbc 100755 --- a/scripts/release/generate-firmware-summary.zsh +++ b/scripts/release/generate-firmware-summary.zsh @@ -108,14 +108,22 @@ known_models=() unknown_models=() for model in "${all_models[@]}"; do - if [[ " ${custom_order[@]} " =~ " ${model} " ]]; then + local found=false + for known_model in "${custom_order[@]}"; do + if [[ "$model" == "$known_model" ]]; then + found=true + break + fi + done + + if [[ "$found" == true ]]; then known_models+=("$model") else unknown_models+=("$model") fi done -# Sort unknown models by firmware version (newest first) +# Sort unknown models by firmware version (newest first) and add at the top if [[ ${#unknown_models[@]} -gt 0 ]]; then # Create temporary array with model and version pairs temp_models=() @@ -141,11 +149,14 @@ if [[ ${#unknown_models[@]} -gt 0 ]]; then sorted_models+=("${sorted_unknown[@]}") fi -# Add known models in custom order +# Add known models in the exact custom order specified for model in "${custom_order[@]}"; do - if [[ " ${known_models[@]} " =~ " ${model} " ]]; then - sorted_models+=("$model") - fi + for known in "${known_models[@]}"; do + if [[ "$model" == "$known" ]]; then + sorted_models+=("$model") + break + fi + done done # Calculate column widths From 906c8b5d810d0c387033bd8fa7cc121763d8d605 Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:40:33 +0200 Subject: [PATCH 6/7] feat: Add GitHub command intermediate documents instruction (refs #20) --- AI_INSTRUCTIONS.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/AI_INSTRUCTIONS.md b/AI_INSTRUCTIONS.md index 6940bc0..8cc16ea 100644 --- a/AI_INSTRUCTIONS.md +++ b/AI_INSTRUCTIONS.md @@ -130,6 +130,73 @@ This document establishes the foundational architectural decisions and design pa - Whenever a new GitHub issue is created, immediately run `scripts/maintenance/generate-issues-markdown.zsh` to update the local Markdown issue list. - After generating the issue list, read the output file (`output/github_issues.md`) to ensure you are memorizing and referencing the latest issues in all future work and communication. +## GitHub Command Intermediate Documents (MANDATORY) +**CRITICAL: For any GitHub issue or PR creation commands with complex formatting or long content, ALWAYS create an intermediate document first to avoid formatting issues and process hangs.** + +**Rationale**: Complex GitHub CLI commands with long bodies, multiple parameters, or special characters can cause formatting issues, syntax errors, or process hangs. Creating intermediate documents ensures reliable command execution and proper formatting. + +**Requirements**: +- **Create intermediate document** for any GitHub command with: + - Long body text (more than 200 characters) + - Multiple parameters or complex formatting + - Special characters or markdown formatting + - Multiple labels or assignees + - Complex issue/PR descriptions + +- **Document location**: `output/` directory +- **Naming convention**: `output/_.md` (e.g., `output/pr_body_20250629_153000.md`) +- **Content format**: Clean markdown with proper formatting + +**Implementation Process**: +1. **Create intermediate document** in `output/` directory +2. **Write content** with proper markdown formatting +3. **Read document content** into variable or use file reference +4. **Execute GitHub command** using the document content +5. **Clean up** intermediate document after successful execution + +**Examples**: +```zsh +# Create intermediate document for complex PR +cat > output/pr_body_$(date +%Y%m%d_%H%M%S).md << 'EOF' +## Summary +Complex PR description with multiple sections... + +## Requirements +- Feature A +- Feature B + +## Motivation +Detailed explanation... + +## Acceptance Criteria +- [ ] Criterion 1 +- [ ] Criterion 2 +EOF + +# Use document in GitHub command +gh pr create --title "title" --body-file output/pr_body_*.md --assignee fxstein --label enhancement +``` + +**Benefits**: +- ✅ **Reliable execution** - Avoids command line length limits +- ✅ **Proper formatting** - Maintains markdown structure +- ✅ **Error prevention** - Reduces syntax and formatting issues +- ✅ **Easy editing** - Can review and modify content before execution +- ✅ **Cleanup** - Intermediate files are in `output/` directory (gitignored) + +**Enforcement**: +- **MANDATORY** for all complex GitHub commands +- **Failure to follow** will result in immediate correction +- **Always use** for issue/PR creation with detailed content +- **Clean up** intermediate files after successful execution + +**Common Use Cases**: +- Creating detailed GitHub issues with multiple sections +- Creating pull requests with comprehensive descriptions +- Adding complex labels and assignees +- Including formatted markdown content +- Multi-line descriptions or requirements + ## Pull Request Issue Closure Rules (MANDATORY) - **NEVER assume whether a PR closes an issue** - always ask the user if the PR closes the entire issue or is just a partial implementation - **Use "Related to #X" instead of "Closes #X"** unless explicitly told by the user that the PR closes the issue From 8e6bba741ed3955c588f8da5ec1db0f81ad9bb64 Mon Sep 17 00:00:00 2001 From: fxstein <773967+fxstein@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:49:35 +0200 Subject: [PATCH 7/7] ci: add firmware summary unit test to CI/CD and fix test suite integration (refs #20) --- .github/workflows/test.yml | 37 +++++ scripts/testing/run-tests.zsh | 16 ++- scripts/testing/test-suites.zsh | 233 ++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40743bf..3a7e50e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -180,3 +180,40 @@ jobs: name: "logger-test-results" path: "output/test-results/" retention-days: 7 + + firmware-summary-test: + name: "Firmware Summary Unit Test" + runs-on: "ubuntu-latest" + if: >- + github.event_name == 'push' || github.event_name == 'pull_request' + needs: [] + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + + - name: "Install dependencies" + run: | + sudo apt-get update + sudo apt-get install -y zsh exiftool jq + + - name: "Make test scripts executable" + run: | + chmod +x scripts/testing/*.zsh + + - name: "Setup output directories" + run: | + mkdir -p output/test-results + mkdir -p output/test-temp + + - name: "Run firmware summary unit test" + run: | + echo "🧪 Running firmware summary unit test..." + ./scripts/testing/run-tests.zsh --firmware-summary + + - name: "Upload firmware summary test results" + if: always() + uses: actions/upload-artifact@v4 + with: + name: "firmware-summary-test-results" + path: "output/test-results/" + retention-days: 7 diff --git a/scripts/testing/run-tests.zsh b/scripts/testing/run-tests.zsh index f633290..6f8f498 100755 --- a/scripts/testing/run-tests.zsh +++ b/scripts/testing/run-tests.zsh @@ -36,6 +36,7 @@ RUN_MEDIA_TESTS=false RUN_ERROR_TESTS=false RUN_WORKFLOW_TESTS=false RUN_LOGGER_TESTS=false +RUN_FIRMWARE_SUMMARY_TESTS=false VERBOSE=false QUIET=false DEBUG=false @@ -84,6 +85,10 @@ function parse_options() { RUN_LOGGER_TESTS=true shift ;; + --firmware-summary) + RUN_FIRMWARE_SUMMARY_TESTS=true + shift + ;; --verbose|-v) VERBOSE=true shift @@ -113,7 +118,8 @@ function parse_options() { "$RUN_PARAM_TESTS" == false && "$RUN_STORAGE_TESTS" == false && \ "$RUN_INTEGRATION_TESTS" == false && "$RUN_ENHANCED_TESTS" == false && \ "$RUN_MEDIA_TESTS" == false && "$RUN_ERROR_TESTS" == false && \ - "$RUN_WORKFLOW_TESTS" == false && "$RUN_LOGGER_TESTS" == false ]]; then + "$RUN_WORKFLOW_TESTS" == false && "$RUN_LOGGER_TESTS" == false && \ + "$RUN_FIRMWARE_SUMMARY_TESTS" == false ]]; then RUN_ALL_TESTS=true fi @@ -129,6 +135,7 @@ function parse_options() { echo " RUN_ERROR_TESTS=$RUN_ERROR_TESTS" echo " RUN_WORKFLOW_TESTS=$RUN_WORKFLOW_TESTS" echo " RUN_LOGGER_TESTS=$RUN_LOGGER_TESTS" + echo " RUN_FIRMWARE_SUMMARY_TESTS=$RUN_FIRMWARE_SUMMARY_TESTS" fi } @@ -149,6 +156,7 @@ function show_help() { echo " --error Run error handling tests only" echo " --workflow Run workflow tests only" echo " --logger Run logger tests only" + echo " --firmware-summary Run firmware summary tests only" echo " --verbose, -v Enable verbose output" echo " --quiet, -q Suppress output except for failures" echo " --debug Enable debug output" @@ -247,10 +255,14 @@ function run_selected_tests() { test_suite "Integration Workflow Tests" test_integration_workflows_suite fi - if [[ "$RUN_LOGGER_TESTS" == true ]]; then + if [[ "$RUN_ALL_TESTS" == true || "$RUN_LOGGER_TESTS" == true ]]; then test_suite "Logger Tests" test_logger_suite fi + if [[ "$RUN_ALL_TESTS" == true || "$RUN_FIRMWARE_SUMMARY_TESTS" == true ]]; then + test_suite "Firmware Summary Tests" test_firmware_summary_suite + fi + if [[ "$DEBUG" == true ]]; then echo "[DEBUG] Test suite execution complete" echo "[DEBUG] TEST_RESULTS array contents:" diff --git a/scripts/testing/test-suites.zsh b/scripts/testing/test-suites.zsh index 19641dc..c533cfc 100755 --- a/scripts/testing/test-suites.zsh +++ b/scripts/testing/test-suites.zsh @@ -47,6 +47,17 @@ function test_integration_suite() { run_test "integration_error_handling" test_integration_error_handling "Test error handling scenarios" } +# Firmware Summary Tests +function test_firmware_summary_suite() { + run_test "firmware_summary_basic_generation" test_firmware_summary_basic_generation "Test basic firmware summary generation" + run_test "firmware_summary_custom_sorting" test_firmware_summary_custom_sorting "Test custom model sorting order" + run_test "firmware_summary_model_names_with_spaces" test_firmware_summary_model_names_with_spaces "Test handling of model names with spaces" + run_test "firmware_summary_unknown_models" test_firmware_summary_unknown_models "Test handling of unknown models" + run_test "firmware_summary_missing_firmware" test_firmware_summary_missing_firmware "Test handling of models with missing firmware" + run_test "firmware_summary_table_formatting" test_firmware_summary_table_formatting "Test proper markdown table formatting" + run_test "firmware_summary_column_alignment" test_firmware_summary_column_alignment "Test column width calculation and alignment" +} + # Logger Tests function test_logger_suite() { if [[ "$DEBUG" == true ]]; then @@ -394,4 +405,226 @@ function assert_not_contains() { echo " Pattern: '$pattern'" return 1 fi +} + +## Firmware Summary Tests +function test_firmware_summary_basic_generation() { + # Create test firmware structure + create_test_firmware_structure + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + local exit_code=$? + + # Test basic functionality + assert_exit_code 0 "$exit_code" "Firmware summary script should exit successfully" + assert_contains "$output" "## Supported GoPro Models" "Output should contain section header" + assert_contains "$output" "Model" "Output should contain table header" + assert_contains "$output" "HERO13 Black" "Output should contain HERO13 Black model" + assert_contains "$output" "HERO \\(2024\\)" "Output should contain HERO (2024) model" + + cleanup_test_firmware_structure +} + +function test_firmware_summary_custom_sorting() { + # Create test firmware structure + create_test_firmware_structure + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + + # Test custom sorting order + local hero13_pos=$(echo "$output" | grep -n "HERO13 Black" | cut -d: -f1) + local hero2024_pos=$(echo "$output" | grep -n "HERO (2024)" | cut -d: -f1) + local hero12_pos=$(echo "$output" | grep -n "HERO12 Black" | cut -d: -f1) + local gopro_max_pos=$(echo "$output" | grep -n "GoPro Max" | cut -d: -f1) + + # Verify custom order: HERO13 -> HERO (2024) -> HERO12 -> ... -> GoPro Max + assert_equal true "$(($hero13_pos < $hero2024_pos))" "HERO13 should come before HERO (2024)" + assert_equal true "$(($hero2024_pos < $hero12_pos))" "HERO (2024) should come before HERO12" + assert_equal true "$(($hero12_pos < $gopro_max_pos))" "HERO12 should come before GoPro Max" + + cleanup_test_firmware_structure +} + +function test_firmware_summary_model_names_with_spaces() { + # Create test firmware structure with models that have spaces + create_test_firmware_structure + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + + # Test handling of model names with spaces + assert_contains "$output" "HERO \\(2024\\)" "Should handle model name with parentheses and spaces" + assert_contains "$output" "HERO11 Black Mini" "Should handle model name with multiple spaces" + assert_contains "$output" "GoPro Max" "Should handle model name with space" + + cleanup_test_firmware_structure +} + +function test_firmware_summary_unknown_models() { + # Create test firmware structure with unknown models + create_test_firmware_structure_with_unknown_models + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + + # Test handling of unknown models + assert_contains "$output" "Unknown Model X" "Should include unknown models" + assert_contains "$output" "Test Camera Y" "Should include other unknown models" + + # Unknown models should appear at the top (sorted by firmware version) + local unknown_x_pos=$(echo "$output" | grep -n "Unknown Model X" | cut -d: -f1) + local hero13_pos=$(echo "$output" | grep -n "HERO13 Black" | cut -d: -f1) + assert_equal true "$(($unknown_x_pos < $hero13_pos))" "Unknown models should appear before known models" + + cleanup_test_firmware_structure_with_unknown_models +} + +function test_firmware_summary_missing_firmware() { + # Create test firmware structure with some models missing firmware + create_test_firmware_structure_with_missing_firmware + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + + # Test handling of missing firmware + assert_contains "$output" "N/A" "Should show N/A for missing firmware" + assert_contains "$output" "HERO13 Black" "Should still include models with missing firmware" + + cleanup_test_firmware_structure_with_missing_firmware +} + +function test_firmware_summary_table_formatting() { + # Create test firmware structure + create_test_firmware_structure + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + + # Test proper markdown table formatting + assert_contains "$output" "Model" "Should have table header with Model column" + assert_contains "$output" "Latest Official" "Should have table header with Latest Official column" + assert_contains "$output" "Latest Labs" "Should have table header with Latest Labs column" + assert_contains "$output" "---" "Should have table separator line" + assert_contains "$output" "HERO13 Black" "Should have properly formatted table rows" + + cleanup_test_firmware_structure +} + +function test_firmware_summary_column_alignment() { + # Create test firmware structure with varying model name lengths + create_test_firmware_structure_with_varying_lengths + + # Run the firmware summary script + local output + output=$(./scripts/release/generate-firmware-summary.zsh 2>&1) + + # Test column alignment + # Check that all table rows have the same number of pipe characters (3 columns) + local table_rows=$(echo "$output" | grep "^|" | wc -l | tr -d ' ') + local expected_rows=12 # Header + separator + 10 models + assert_equal "$expected_rows" "$table_rows" "Should have correct number of table rows" + + # Check that each row has exactly 3 pipe characters (indicating 3 columns) + local malformed_rows=$(echo "$output" | grep "^|" | grep -v "^|.*|.*|$" | wc -l | tr -d ' ') + assert_equal "0" "$malformed_rows" "All table rows should have exactly 3 columns" + + cleanup_test_firmware_structure_with_varying_lengths +} + +# Helper functions for firmware summary tests +function create_test_firmware_structure() { + # Create official firmware structure + mkdir -p "firmware/official/HERO13 Black/H24.01.02.02.00" + mkdir -p "firmware/official/HERO (2024)/H24.03.02.20.00" + mkdir -p "firmware/official/HERO12 Black/H23.01.02.32.00" + mkdir -p "firmware/official/HERO11 Black/H22.01.02.32.00" + mkdir -p "firmware/official/HERO11 Black Mini/H22.03.02.50.00" + mkdir -p "firmware/official/HERO10 Black/H21.01.01.62.00" + mkdir -p "firmware/official/HERO9 Black/HD9.01.01.72.00" + mkdir -p "firmware/official/HERO8 Black/HD8.01.02.51.00" + mkdir -p "firmware/official/GoPro Max/H19.03.02.02.00" + mkdir -p "firmware/official/The Remote/GP.REMOTE.FW.02.00.01" + + # Create labs firmware structure + mkdir -p "firmware/labs/HERO13 Black/H24.01.02.02.70" + mkdir -p "firmware/labs/HERO12 Black/H23.01.02.32.70" + mkdir -p "firmware/labs/HERO11 Black/H22.01.02.32.70" + mkdir -p "firmware/labs/HERO11 Black Mini/H22.03.02.50.71b" + mkdir -p "firmware/labs/HERO10 Black/H21.01.01.62.70" + mkdir -p "firmware/labs/HERO9 Black/HD9.01.01.72.70" + mkdir -p "firmware/labs/HERO8 Black/HD8.01.02.51.75" + mkdir -p "firmware/labs/GoPro Max/H19.03.02.02.70" +} + +function create_test_firmware_structure_with_unknown_models() { + create_test_firmware_structure + + # Add unknown models with newer firmware versions + mkdir -p "firmware/official/Unknown Model X/Z99.99.99.99.99" + mkdir -p "firmware/official/Test Camera Y/Y88.88.88.88.88" + mkdir -p "firmware/labs/Unknown Model X/Z99.99.99.99.99" + mkdir -p "firmware/labs/Test Camera Y/Y88.88.88.88.88" +} + +function create_test_firmware_structure_with_missing_firmware() { + create_test_firmware_structure + + # Remove some firmware directories to simulate missing firmware + rm -rf "firmware/labs/HERO (2024)" + rm -rf "firmware/labs/The Remote" +} + +function create_test_firmware_structure_with_varying_lengths() { + create_test_firmware_structure + + # Add models with very long names + mkdir -p "firmware/official/Very Long Model Name That Exceeds Normal Length/H99.99.99.99.99" + mkdir -p "firmware/official/Short/H11.11.11.11.11" +} + +function cleanup_test_firmware_structure() { + rm -rf "firmware/official/HERO13 Black" + rm -rf "firmware/official/HERO (2024)" + rm -rf "firmware/official/HERO12 Black" + rm -rf "firmware/official/HERO11 Black" + rm -rf "firmware/official/HERO11 Black Mini" + rm -rf "firmware/official/HERO10 Black" + rm -rf "firmware/official/HERO9 Black" + rm -rf "firmware/official/HERO8 Black" + rm -rf "firmware/official/GoPro Max" + rm -rf "firmware/official/The Remote" + rm -rf "firmware/labs/HERO13 Black" + rm -rf "firmware/labs/HERO12 Black" + rm -rf "firmware/labs/HERO11 Black" + rm -rf "firmware/labs/HERO11 Black Mini" + rm -rf "firmware/labs/HERO10 Black" + rm -rf "firmware/labs/HERO9 Black" + rm -rf "firmware/labs/HERO8 Black" + rm -rf "firmware/labs/GoPro Max" +} + +function cleanup_test_firmware_structure_with_unknown_models() { + cleanup_test_firmware_structure + rm -rf "firmware/official/Unknown Model X" + rm -rf "firmware/official/Test Camera Y" + rm -rf "firmware/labs/Unknown Model X" + rm -rf "firmware/labs/Test Camera Y" +} + +function cleanup_test_firmware_structure_with_missing_firmware() { + cleanup_test_firmware_structure +} + +function cleanup_test_firmware_structure_with_varying_lengths() { + cleanup_test_firmware_structure + rm -rf "firmware/official/Very Long Model Name That Exceeds Normal Length" + rm -rf "firmware/official/Short" } \ No newline at end of file