feat: add reusable board definitions to image JSON generator#202
feat: add reusable board definitions to image JSON generator#202igorpecovnik merged 1 commit intomainfrom
Conversation
WalkthroughAdds 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)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
python3but the YAML parsing at line 120 requires thePyYAMLpackage (import yaml). If PyYAML isn't installed, the import will fail silently due to the2>/dev/null || trueon line 136.Consider either:
- Adding an explicit check for PyYAML availability
- 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")"
| 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 |
There was a problem hiding this comment.
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.
| 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: |
There was a problem hiding this comment.
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.
1464838 to
e765734
Compare
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"
e765734 to
f0c6d08
Compare
Summary
Adds ability to define virtual boards that reuse artifact sets from existing boards but with custom metadata (name, vendor, support level).
Features
release-targets/reusable.ymlUse Case
Boards without dedicated build configs can now appear in downloads with custom branding. This is useful for:
Example Configuration
This creates entries in
armbian-images.jsonfor alluefi-arm64images with:minisforum-msr1currentbranch images (filter applied)Technical Changes
scripts/generate-armbian-images-json.sh:yqtopython3for YAML parsingrelease-targets/reusable.ymlwith 3 example boards