Skip to content

feat: add reusable board definitions to image JSON generator#202

Merged
igorpecovnik merged 1 commit intomainfrom
reusable-boards
Jan 31, 2026
Merged

feat: add reusable board definitions to image JSON generator#202
igorpecovnik merged 1 commit intomainfrom
reusable-boards

Conversation

@igorpecovnik
Copy link
Copy Markdown
Member

Summary

Adds ability to define virtual boards that reuse artifact sets from existing boards but with custom metadata (name, vendor, support level).

Features

  • Load board definitions from release-targets/reusable.yml
  • Branch filtering - Include only specific branches (e.g., only edge/current)
  • Custom branding - Apply custom vendor, company logos, and support levels
  • Independent metadata - Each virtual board has its own:
    • Board name, vendor, support level
    • Company information (from vendor slug)
    • Vendor logo URL
    • Platinum support tracking
    • Promotion status

Use Case

Boards without dedicated build configs can now appear in downloads with custom branding. This is useful for:

  • OEM systems that use generic UEFI images
  • System integrators with custom board branding
  • Hardware variants that share identical builds

Example Configuration

boards:
  - board_slug: "minisforum-msr1"
    board_name: "Minisforum MS-R1"
    board_vendor: "minisforum"
    board_support: "conf"
    uses: "uefi-arm64"
    branch: "current"

This creates entries in armbian-images.json for all uefi-arm64 images with:

  • Custom board slug: minisforum-msr1
  • Custom name/vendor: Minisforum branding
  • Only current branch images (filter applied)
  • Minisforum company logo and info

Technical Changes

  • Modified scripts/generate-armbian-images-json.sh:
    • Added reusable board loading from YAML using Python/PyYAML
    • Added board filtering and replication logic in JSON generation loop
    • Changed dependency from yq to python3 for YAML parsing
  • Added release-targets/reusable.yml with 3 example boards

@github-actions github-actions Bot added 02 Milestone: First quarter release size/medium PR with more then 50 and less then 250 lines Needs review Seeking for review labels Jan 31, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 31, 2026

Walkthrough

Adds release-targets/reusable.yml: a YAML configuration that declares virtual boards which reuse artifact sets from existing base boards while overriding identity metadata (board_slug, board_name, board_vendor, board_support) and allowing optional filters (uses, branch, file_extension). Three virtual boards are defined. Modifies scripts/generate-armbian-images-json.sh to introduce a REUSABLE_FILE variable, require python3, parse reusable.yml into associative maps, apply branch/extension filters, merge reusable metadata (name, vendor, support, company, logo), compute REDI/cache URLs and promotion status for reusable boards, and emit additional asset rows and load/missing-file status messages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding reusable board definitions to the image JSON generator script.
Description check ✅ Passed The description is directly related to the changeset, providing clear summary, features, use cases, configuration examples, and technical changes that align with the file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch reusable-boards

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@scripts/generate-armbian-images-json.sh`:
- Around line 119-136: The Python block swallows parsing errors by writing to
stderr then calling sys.exit(0) and having stderr redirected to /dev/null;
change the exception handling so the error details are visible and the script
returns a non-zero status: replace sys.exit(0) with sys.exit(1) in the Python
try/except (refer to the python3 -c block and sys.exit call), and remove or
avoid the shell-level stderr redirection (the trailing 2>/dev/null || true) so
that exceptions from loading $REUSABLE_FILE are not silently discarded.
- Line 122: The Python heredoc currently interpolates the shell variable
directly in the source ("with open('$REUSABLE_FILE') as f:"), which allows
shell-controlled content to break or inject code; instead pass the filename as
an argument to Python and read it from sys.argv (e.g., invoke the heredoc with
the filename as an extra argument and change the Python line to "import sys" and
"with open(sys.argv[1]) as f:"), referencing the REUSABLE_FILE variable and the
Python snippet containing "with open('$REUSABLE_FILE') as f:" so you only
substitute the value as an argument rather than embedding it in the Python
source.
🧹 Nitpick comments (2)
scripts/generate-armbian-images-json.sh (2)

36-36: Verify PyYAML availability or add graceful fallback.

The script checks for python3 but the YAML parsing at line 120 requires the PyYAML package (import yaml). If PyYAML isn't installed, the import will fail silently due to the 2>/dev/null || true on line 136.

Consider either:

  1. Adding an explicit check for PyYAML availability
  2. Documenting PyYAML as a dependency in a README or script header
🛡️ Option: Add PyYAML availability check
 need rsync gh jq jc python3 find grep sed cut awk sort mktemp curl date
+
+# Verify PyYAML is available for reusable board parsing
+python3 -c "import yaml" 2>/dev/null || echo "WARNING: PyYAML not installed; reusable board definitions will be skipped" >&2

682-693: Consider extracting duplicated platinum logic.

The platinum support calculation (lines 682-693) duplicates the logic from lines 637-647. While this works correctly, extracting it into a helper function would improve maintainability.

♻️ Extract platinum calculation to a function

Add this helper function near the other helpers (around line 335):

# Returns: "plat|expired|until" string
calc_platinum_status() {
  local slug="$1"
  local until="${PLATINUM_UNTIL_BY_BOARD[$slug]:-}"
  local plat="false" expired="false"
  
  if [[ -n "$until" ]]; then
    if [[ "$until" < "$TODAY_UTC" ]]; then
      expired="true"
    else
      plat="true"
    fi
  fi
  printf '%s|%s|%s' "$plat" "$expired" "$until"
}

Then use it in both locations:

IFS='|' read -r PLAT PLAT_EXPIRED PLAT_UNTIL <<< "$(calc_platinum_status "$BOARD_SLUG")"

Comment on lines +119 to +136
python3 -c "
import yaml, sys
try:
with open('$REUSABLE_FILE') as f:
data = yaml.safe_load(f)
for b in data.get('boards', []):
print('\t'.join([
str(b.get('board_slug', '')),
str(b.get('board_name', '')),
str(b.get('board_vendor', '')),
str(b.get('board_support', '')),
str(b.get('uses', '')),
str(b.get('branch', ''))
]))
except Exception as e:
sys.stderr.write(f'Error loading reusable.yml: {e}\n')
sys.exit(0)
" 2>/dev/null || true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Silent error handling may hide parsing failures.

The Python block catches exceptions and exits with sys.exit(0) (line 135), while stderr is redirected to /dev/null (line 136). This combination completely hides any parsing errors—the script will silently continue with zero reusable boards loaded.

Consider preserving error visibility:

🛠️ Proposed fix to improve error visibility
 except Exception as e:
     sys.stderr.write(f'Error loading reusable.yml: {e}\n')
-    sys.exit(0)
-" 2>/dev/null || true
+    sys.exit(1)
+" || echo "WARNING: Failed to parse ${REUSABLE_FILE}; reusable boards skipped" >&2
   )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
python3 -c "
import yaml, sys
try:
with open('$REUSABLE_FILE') as f:
data = yaml.safe_load(f)
for b in data.get('boards', []):
print('\t'.join([
str(b.get('board_slug', '')),
str(b.get('board_name', '')),
str(b.get('board_vendor', '')),
str(b.get('board_support', '')),
str(b.get('uses', '')),
str(b.get('branch', ''))
]))
except Exception as e:
sys.stderr.write(f'Error loading reusable.yml: {e}\n')
sys.exit(0)
" 2>/dev/null || true
python3 -c "
import yaml, sys
try:
with open('$REUSABLE_FILE') as f:
data = yaml.safe_load(f)
for b in data.get('boards', []):
print('\t'.join([
str(b.get('board_slug', '')),
str(b.get('board_name', '')),
str(b.get('board_vendor', '')),
str(b.get('board_support', '')),
str(b.get('uses', '')),
str(b.get('branch', ''))
]))
except Exception as e:
sys.stderr.write(f'Error loading reusable.yml: {e}\n')
sys.exit(1)
" || echo "WARNING: Failed to parse ${REUSABLE_FILE}; reusable boards skipped" >&2
🤖 Prompt for AI Agents
In `@scripts/generate-armbian-images-json.sh` around lines 119 - 136, The Python
block swallows parsing errors by writing to stderr then calling sys.exit(0) and
having stderr redirected to /dev/null; change the exception handling so the
error details are visible and the script returns a non-zero status: replace
sys.exit(0) with sys.exit(1) in the Python try/except (refer to the python3 -c
block and sys.exit call), and remove or avoid the shell-level stderr redirection
(the trailing 2>/dev/null || true) so that exceptions from loading
$REUSABLE_FILE are not silently discarded.

python3 -c "
import yaml, sys
try:
with open('$REUSABLE_FILE') as f:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential command injection via REUSABLE_FILE.

The variable $REUSABLE_FILE is interpolated directly into the Python code string. If REUSABLE_FILE contains quotes or special characters (e.g., from a malicious environment), it could break the Python syntax or execute unintended code.

🛡️ Safer approach: pass filename as argument
-    python3 -c "
-import yaml, sys
-try:
-    with open('$REUSABLE_FILE') as f:
+    python3 - "$REUSABLE_FILE" <<'EOF'
+import yaml, sys
+try:
+    with open(sys.argv[1]) as f:
         data = yaml.safe_load(f)
     for b in data.get('boards', []):
         print('\t'.join([
             str(b.get('board_slug', '')),
             str(b.get('board_name', '')),
             str(b.get('board_vendor', '')),
             str(b.get('board_support', '')),
             str(b.get('uses', '')),
             str(b.get('branch', ''))
         ]))
 except Exception as e:
     sys.stderr.write(f'Error loading reusable.yml: {e}\n')
-    sys.exit(0)
-" 2>/dev/null || true
+    sys.exit(1)
+EOF
🤖 Prompt for AI Agents
In `@scripts/generate-armbian-images-json.sh` at line 122, The Python heredoc
currently interpolates the shell variable directly in the source ("with
open('$REUSABLE_FILE') as f:"), which allows shell-controlled content to break
or inject code; instead pass the filename as an argument to Python and read it
from sys.argv (e.g., invoke the heredoc with the filename as an extra argument
and change the Python line to "import sys" and "with open(sys.argv[1]) as f:"),
referencing the REUSABLE_FILE variable and the Python snippet containing "with
open('$REUSABLE_FILE') as f:" so you only substitute the value as an argument
rather than embedding it in the Python source.

@igorpecovnik igorpecovnik force-pushed the reusable-boards branch 3 times, most recently from 1464838 to e765734 Compare January 31, 2026 21:41
@github-actions github-actions Bot added size/large PR with 250 lines or more and removed size/medium PR with more then 50 and less then 250 lines labels Jan 31, 2026
Adds ability to define virtual boards that reuse artifact sets from
existing boards but with custom metadata (name, vendor, support level).

Features:
- Load board definitions from release-targets/reusable.yml
- Support branch filtering (e.g., only edge branch images)
- Apply custom vendor, company logos, and support levels
- Independent platinum support tracking per virtual board
- Match base board images and replicate with overridden metadata

Use case: Boards without dedicated build configs can now appear in
downloads with custom branding (e.g., minisforum-msr1 reuses uefi-arm64 images)

Example configuration:
  boards:
    - board_slug: "minisforum-msr1"
      board_name: "Minisforum MS-R1"
      board_vendor: "minisforum"
      uses: "uefi-arm64"
      branch: "current"
@igorpecovnik igorpecovnik added the Ready to merge Reviewed, tested and ready for merge label Jan 31, 2026
@igorpecovnik igorpecovnik merged commit 0a24225 into main Jan 31, 2026
1 check passed
@igorpecovnik igorpecovnik deleted the reusable-boards branch January 31, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

02 Milestone: First quarter release Needs review Seeking for review Ready to merge Reviewed, tested and ready for merge size/large PR with 250 lines or more

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant