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
48 changes: 48 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# EditorConfig for LyreBirdAudio
# https://editorconfig.org

root = true

# Default settings for all files
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

# Shell scripts
[*.sh]
indent_style = space
indent_size = 4

# BATS test files
[*.bats]
indent_style = space
indent_size = 4

# Markdown files
[*.md]
trim_trailing_whitespace = false
indent_size = 2

# YAML files
[*.{yml,yaml}]
indent_size = 2

# JSON files
[*.json]
indent_size = 2

# Makefile (requires tabs)
[Makefile]
indent_style = tab

# Configuration files
[*.conf]
indent_size = 4

# Git config files
[.git*]
indent_size = 4
78 changes: 39 additions & 39 deletions .github/workflows/bash-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ jobs:

while IFS= read -r script; do
if bash -n "$script" 2>&1; then
echo " $script"
echo "[PASS] $script"
success=$((success + 1))
else
echo " $script"
echo "[FAIL] $script"
errors=$((errors + 1))
fi
done < <(find . -name '*.sh' -type f | sort)
Expand Down Expand Up @@ -181,9 +181,9 @@ jobs:
notes=$(shellcheck --format=json "$script" 2>/dev/null | jq '[.[] | select(.level == "info" or .level == "style")] | length' || echo 0)

if [[ "$errors" == "0" && "$warnings" == "0" ]]; then
status=""
status="PASS"
else
status=""
status="FAIL"
fi

echo "| ${status} ${script} | ${errors} | ${warnings} | ${notes} |" >> "$GITHUB_STEP_SUMMARY"
Expand Down Expand Up @@ -226,7 +226,7 @@ jobs:
# -d shows diff, -i 4 = 4 space indent, -bn = binary ops at start of line
# -ci = indent case statements
if diff=$(shfmt -d -i 4 -bn -ci "$script" 2>&1); then
echo ""
echo "[PASS]"
else
echo "needs formatting"
echo "$diff"
Expand Down Expand Up @@ -339,11 +339,11 @@ jobs:

if [[ -n "$dangerous_eval" ]]; then
echo "$dangerous_eval"
echo " Found potentially dangerous eval - review for command injection"
echo " [WARN] Found potentially dangerous eval - review for command injection"
warnings=$((warnings + 1))
warning_details+=("Dangerous eval patterns found")
else
echo " No dangerous eval patterns (safe patterns like 'eval set --' are OK)"
echo " [OK] No dangerous eval patterns (safe patterns like 'eval set --' are OK)"
fi
echo ""

Expand All @@ -356,11 +356,11 @@ jobs:

if [[ -n "$insecure_dl" ]]; then
echo "$insecure_dl"
echo " Found downloads with disabled certificate verification"
echo " [WARN] Found downloads with disabled certificate verification"
warnings=$((warnings + 1))
warning_details+=("Insecure download flags")
else
echo " No insecure download flags found"
echo " [OK] No insecure download flags found"
fi
echo ""

Expand All @@ -375,11 +375,11 @@ jobs:

if [[ -n "$world_writable" ]]; then
echo "$world_writable"
echo " Found world-writable permissions"
echo " [WARN] Found world-writable permissions"
warnings=$((warnings + 1))
warning_details+=("World-writable permissions")
else
echo " No world-writable permissions found"
echo " [OK] No world-writable permissions found"
fi
echo ""

Expand All @@ -396,11 +396,11 @@ jobs:

if [[ -n "$unquoted_cmd" ]]; then
echo "$unquoted_cmd"
echo " Found unquoted command substitution in file operations"
echo " [WARN] Found unquoted command substitution in file operations"
warnings=$((warnings + 1))
warning_details+=("Unquoted command substitution")
else
echo " No unquoted command substitution risks found"
echo " [OK] No unquoted command substitution risks found"
fi
echo ""

Expand All @@ -419,11 +419,11 @@ jobs:

if [[ -n "$hardcoded" ]]; then
echo "$hardcoded"
echo " Found potential hardcoded secrets"
echo " [WARN] Found potential hardcoded secrets"
warnings=$((warnings + 1))
warning_details+=("Hardcoded secrets")
else
echo " No hardcoded secrets found"
echo " [OK] No hardcoded secrets found"
fi
echo ""

Expand All @@ -441,11 +441,11 @@ jobs:

if [[ -n "$insecure_tmp" ]]; then
echo "$insecure_tmp"
echo " Found predictable temp file names (consider using mktemp)"
echo " [WARN] Found predictable temp file names (consider using mktemp)"
warnings=$((warnings + 1))
warning_details+=("Predictable temp files")
else
echo " No insecure temp file patterns found"
echo " [OK] No insecure temp file patterns found"
fi
echo ""

Expand All @@ -472,12 +472,12 @@ jobs:
echo ""
echo "| Check | Status |"
echo "|-------|--------|"
echo "| Dangerous eval patterns | |"
echo "| Insecure downloads (-k/--insecure) | |"
echo "| World-writable permissions (777/666) | |"
echo "| Unquoted command substitutions | |"
echo "| Hardcoded secrets | |"
echo "| Predictable temp files | |"
echo "| Dangerous eval patterns | OK |"
echo "| Insecure downloads (-k/--insecure) | OK |"
echo "| World-writable permissions (777/666) | OK |"
echo "| Unquoted command substitutions | OK |"
echo "| Hardcoded secrets | OK |"
echo "| Predictable temp files | OK |"
echo ""
echo "_Note: This scan uses pattern matching and may have false positives/negatives._"
echo "_ShellCheck provides more comprehensive variable quoting analysis._"
Expand All @@ -496,7 +496,7 @@ jobs:
run: |
{
# Header
echo "# 🔍 Bash CI Pipeline Results"
echo "# Bash CI Pipeline Results"
echo ""
echo "---"
echo ""
Expand All @@ -507,9 +507,9 @@ jobs:

# Determine overall result
if [[ "${{ needs.bash-syntax.result }}" == "success" && "${{ needs.shellcheck.result }}" == "success" ]]; then
echo "### All Required Checks Passed"
echo "### All Required Checks Passed"
else
echo "### Required Checks Failed"
echo "### Required Checks Failed"
fi
echo ""

Expand All @@ -518,21 +518,21 @@ jobs:
echo ""
echo "| Check | Type | Status | Description |"
echo "|-------|------|--------|-------------|"
echo "| **Bash Syntax** | 🔴 Required | ${{ needs.bash-syntax.result == 'success' && 'Passed' || 'Failed' }} | Validates script syntax with \`bash -n\` |"
echo "| **ShellCheck** | 🔴 Required | ${{ needs.shellcheck.result == 'success' && 'Passed' || 'Failed' }} | Static analysis for bugs and issues |"
echo "| **shfmt** | 🟡 Advisory | ${{ needs.shfmt.result == 'success' && 'Passed' || '⚠️ Warnings' }} | Code formatting consistency |"
echo "| **bashate** | 🟡 Advisory | ${{ needs.bashate.result == 'success' && 'Passed' || '⚠️ Warnings' }} | OpenStack style guidelines |"
echo "| **Security** | 🟡 Advisory | ${{ needs.security-scan.result == 'success' && 'Passed' || '⚠️ Warnings' }} | Security anti-pattern detection |"
echo "| **Bash Syntax** | Required | ${{ needs.bash-syntax.result == 'success' && 'Passed' || 'Failed' }} | Validates script syntax with \`bash -n\` |"
echo "| **ShellCheck** | Required | ${{ needs.shellcheck.result == 'success' && 'Passed' || 'Failed' }} | Static analysis for bugs and issues |"
echo "| **shfmt** | Advisory | ${{ needs.shfmt.result == 'success' && 'Passed' || 'Warnings' }} | Code formatting consistency |"
echo "| **bashate** | Advisory | ${{ needs.bashate.result == 'success' && 'Passed' || 'Warnings' }} | OpenStack style guidelines |"
echo "| **Security** | Advisory | ${{ needs.security-scan.result == 'success' && 'Passed' || 'Warnings' }} | Security anti-pattern detection |"
echo ""

# Legend
echo "<details>"
echo "<summary>📋 Check Type Legend</summary>"
echo "<summary>Check Type Legend</summary>"
echo ""
echo "| Type | Meaning |"
echo "|------|---------|"
echo "| 🔴 Required | Must pass for PR to be merged |"
echo "| 🟡 Advisory | Informational only, does not block merge |"
echo "| Required | Must pass for PR to be merged |"
echo "| Advisory | Informational only, does not block merge |"
echo ""
echo "</details>"
echo ""
Expand Down Expand Up @@ -588,7 +588,7 @@ jobs:
echo ""

# Quick Fix Guide
echo "## 🛠️ Quick Fix Guide"
echo "## Quick Fix Guide"
echo ""
echo "<details>"
echo "<summary>How to fix common issues</summary>"
Expand Down Expand Up @@ -635,17 +635,17 @@ jobs:
failed=0

if [[ "${{ needs.bash-syntax.result }}" != "success" ]]; then
echo "::error::Bash syntax validation failed"
echo "::error::Bash syntax validation failed"
failed=1
else
echo "Bash syntax: passed"
echo "Bash syntax: passed"
fi

if [[ "${{ needs.shellcheck.result }}" != "success" ]]; then
echo "::error::ShellCheck found errors or warnings"
echo "::error::ShellCheck found errors or warnings"
failed=1
else
echo "ShellCheck: passed"
echo "ShellCheck: passed"
fi

echo ""
Expand Down
48 changes: 47 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ brew install shellcheck bats-core
```bash
# Check all scripts pass syntax validation
for script in *.sh; do
bash -n "$script" && echo " $script"
bash -n "$script" && echo "[OK] $script"
done

# Run ShellCheck on all scripts
Expand Down Expand Up @@ -196,11 +196,57 @@ if ! command -v ffmpeg &>/dev/null; then
fi
```

#### Logging

LyreBirdAudio provides standardized logging through `lyrebird-common.sh`. Both patterns are acceptable:

```bash
# Wrapper functions (preferred for new code)
log_info "Starting service..."
log_warn "Configuration missing, using defaults"
log_error "Failed to connect"
log_debug "Variable value: ${value}"

# Direct log calls (also acceptable)
log INFO "Starting service..."
log WARN "Configuration missing"
```

The logging functions write to both stderr and a log file when available.

#### Variable Naming Prefixes

Configuration variables follow these prefix conventions:

- **`LYREBIRD_*`**: LyreBirdAudio-specific settings (alerts, storage, orchestrator)
- **`MEDIAMTX_*`**: MediaMTX-related settings (API, ports, paths)

```bash
# LyreBirdAudio settings
LYREBIRD_ALERT_ENABLED=true
LYREBIRD_RECORDING_DIR=/var/lib/recordings

# MediaMTX settings
MEDIAMTX_API_PORT=9997
MEDIAMTX_CONFIG_DIR=/etc/mediamtx
```

#### Comments

- Comment complex logic, not obvious code
- Use TODO for future work
- Explain regex patterns and complex commands
- Use section headers to organize code:

```bash
# ============================================================================
# Section Name
# ============================================================================

# Inline comment for complex logic
```

Example:

```bash
# Match USB device path format: /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.3
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ sudo ./lyrebird-diagnostics.sh quick
# rtsp://your-ip:8554/device-name
```

**Reboot Recommended:** After initial and after each individual USB device mapping, reboot for udev rules to take full effect. You will manually have to start the Orcestrator again after each reboot: cd LyreBirdAudio && sudo ./lyrebird-orchestrator.sh
**Reboot Recommended:** After initial and after each individual USB device mapping, reboot for udev rules to take full effect. You will manually have to start the Orchestrator again after each reboot: cd LyreBirdAudio && sudo ./lyrebird-orchestrator.sh

### Post-Installation

Expand Down Expand Up @@ -1426,7 +1426,7 @@ This modular design prevents duplicate business logic and ensures maintainabilit
|--------|---------|---------|
| lyrebird-orchestrator.sh | 2.1.2 | Unified management interface |
| lyrebird-updater.sh | 1.5.1 | Version management with rollback |
| mediamtx-stream-manager.sh | 1.4.2 | Stream lifecycle management |
| mediamtx-stream-manager.sh | 1.4.3 | Stream lifecycle management |
| usb-audio-mapper.sh | 1.2.1 | USB device persistence via udev |
| lyrebird-mic-check.sh | 1.0.0 | Hardware capability detection |
| lyrebird-diagnostics.sh | 1.0.2 | System diagnostics |
Expand Down
Loading
Loading