Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
67 changes: 67 additions & 0 deletions AI_INSTRUCTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<command_type>_<timestamp>.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
Expand Down
38 changes: 32 additions & 6 deletions docs/release/RELEASE_SUMMARY_INSTRUCTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
206 changes: 206 additions & 0 deletions scripts/release/generate-firmware-summary.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#!/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 with newer models at top
sorted_models=()
custom_order=(
"HERO13 Black"
"HERO (2024)"
"HERO12 Black"
"HERO11 Black"
"HERO11 Black Mini"
"HERO10 Black"
"HERO9 Black"
"HERO8 Black"
"GoPro Max"
"The Remote"
)

# 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
}

# Separate known and unknown models
known_models=()
unknown_models=()

for model in "${all_models[@]}"; do
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) and add at the top
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 the exact custom order specified
for model in "${custom_order[@]}"; do
for known in "${known_models[@]}"; do
if [[ "$model" == "$known" ]]; then
sorted_models+=("$model")
break
fi
done
done

# 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"

cat << 'EOF'
## Supported GoPro Models

The following GoPro camera models are currently supported by GoProX:

EOF

# 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}"
printf "| %-${model_width}s | %-${official_width}s | %-${labs_width}s |\n" "$model" "$official_ver" "$labs_ver"
done

log_info "Firmware summary generation completed"
Loading
Loading