Initial sanitized SmartSpeaker snapshot
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
# ESP32-S3 Firmware Release Script
|
||||
|
||||
param(
|
||||
[string]$Tag = "",
|
||||
[switch]$SkipBuild,
|
||||
[switch]$NoPush
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
||||
$EimExe = "C:\Users\micha\AppData\Local\Microsoft\WinGet\Packages\Espressif.EIM-CLI_Microsoft.Winget.Source_8wekyb3d8bbwe\eim.exe"
|
||||
$BinName = "esp32s3_audio.bin"
|
||||
$BuildBin = Join-Path $ProjectRoot "build\$BinName"
|
||||
$ReleasesDir = Join-Path $ProjectRoot "releases"
|
||||
$CatalogFile = Join-Path $ReleasesDir "firmware-catalog.json"
|
||||
|
||||
# -- Helpers (Using pure ASCII to prevent encoding parser issues) --
|
||||
|
||||
function Write-Step([string]$msg) {
|
||||
Write-Host "`n>> $msg" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function Write-Ok([string]$msg) {
|
||||
Write-Host " [OK] $msg" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Write-Err([string]$msg) {
|
||||
Write-Host " [ERROR] $msg" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# -- Step 1: Determine version --
|
||||
|
||||
Write-Step "Resolving version..."
|
||||
|
||||
if ($Tag -eq "") {
|
||||
# Try exact tag on current commit first
|
||||
$exactTag = & {
|
||||
$oldEA = $ErrorActionPreference; $ErrorActionPreference = "SilentlyContinue"
|
||||
$t = git tag --points-at HEAD 2>$null
|
||||
$ErrorActionPreference = $oldEA
|
||||
$t
|
||||
} | Select-Object -First 1
|
||||
|
||||
if ($exactTag) {
|
||||
$Tag = $exactTag.Trim()
|
||||
Write-Ok "Using exact commit tag: $Tag"
|
||||
} else {
|
||||
# Fall back to git describe (nearest tag + distance)
|
||||
$described = & {
|
||||
$oldEA = $ErrorActionPreference; $ErrorActionPreference = "SilentlyContinue"
|
||||
$d = git describe --tags --long 2>$null
|
||||
$ErrorActionPreference = $oldEA
|
||||
$d
|
||||
}
|
||||
if ($described) {
|
||||
# If on a tag, described looks like "v1.0.0-0-gabcdef" -> strip -0-g...
|
||||
if ($described -match '^(.+)-0-g[0-9a-f]+$') {
|
||||
$Tag = $Matches[1]
|
||||
Write-Ok "On tagged commit: $Tag"
|
||||
} else {
|
||||
# Not on a clean tag - build a dev version
|
||||
$Tag = $described -replace '-(\d+)-g([0-9a-f]+)$', '+$1.$2'
|
||||
Write-Ok "Dev build version: $Tag"
|
||||
}
|
||||
} else {
|
||||
# No tags at all - generate from commit count
|
||||
$commitCount = & {
|
||||
$oldEA = $ErrorActionPreference; $ErrorActionPreference = "SilentlyContinue"
|
||||
$c = git rev-list HEAD --count
|
||||
$ErrorActionPreference = $oldEA
|
||||
$c
|
||||
}
|
||||
if ($commitCount) { $commitCount = $commitCount.Trim() } else { $commitCount = "0" }
|
||||
$shortHash = & {
|
||||
$oldEA = $ErrorActionPreference; $ErrorActionPreference = "SilentlyContinue"
|
||||
$h = git rev-parse --short HEAD
|
||||
$ErrorActionPreference = $oldEA
|
||||
$h
|
||||
}
|
||||
if ($shortHash) { $shortHash = $shortHash.Trim() } else { $shortHash = "unknown" }
|
||||
$Tag = "v0.0.$commitCount-$shortHash"
|
||||
Write-Ok "Auto-generated version (no tags): $Tag"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Ok "Release version: $Tag"
|
||||
|
||||
# -- Step 2: Build and Package DEV-1 and PROTO-1 --
|
||||
|
||||
# Detect original model from device-config file to restore later
|
||||
$deviceConfigFile = Join-Path $ProjectRoot "device-config"
|
||||
$originalModel = "DEV-1"
|
||||
if (Test-Path $deviceConfigFile) {
|
||||
$configLine = Get-Content $deviceConfigFile | Where-Object { $_ -match '^MODEL=' }
|
||||
if ($configLine) { $originalModel = ($configLine -split '=')[1].Trim() }
|
||||
}
|
||||
|
||||
$SafeTag = $Tag -replace '[+/]', '-'
|
||||
|
||||
if (-not (Test-Path $ReleasesDir)) {
|
||||
New-Item -ItemType Directory -Path $ReleasesDir | Out-Null
|
||||
}
|
||||
|
||||
$DevBinSize = 0
|
||||
$ProtoBinSize = 0
|
||||
|
||||
if (-not $SkipBuild) {
|
||||
# 1. Build and copy DEV-1
|
||||
Write-Step "Building firmware for DEV-1 ($Tag)..."
|
||||
"MODEL=DEV-1" | Set-Content $deviceConfigFile
|
||||
Push-Location $ProjectRoot
|
||||
if (Test-Path "build") {
|
||||
Remove-Item -Path "build" -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
& $EimExe run "idf.py build"
|
||||
if ($LASTEXITCODE -ne 0) { Pop-Location; Write-Err "Build failed for DEV-1 (exit code $LASTEXITCODE)" }
|
||||
Pop-Location
|
||||
|
||||
if (-not (Test-Path $BuildBin)) { Write-Err "Binary not found: $BuildBin" }
|
||||
$DevBinSize = (Get-Item $BuildBin).Length
|
||||
$DestDevBin = Join-Path $ReleasesDir "firmware-$SafeTag-dev1.bin"
|
||||
Copy-Item $BuildBin $DestDevBin -Force
|
||||
Write-Ok "DEV-1 release packaged -> releases/firmware-$SafeTag-dev1.bin"
|
||||
|
||||
# 2. Build and copy PROTO-1
|
||||
Write-Step "Building firmware for PROTO-1 ($Tag)..."
|
||||
"MODEL=PROTO-1" | Set-Content $deviceConfigFile
|
||||
Push-Location $ProjectRoot
|
||||
if (Test-Path "build") {
|
||||
Remove-Item -Path "build" -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
& $EimExe run "idf.py build"
|
||||
if ($LASTEXITCODE -ne 0) { Pop-Location; Write-Err "Build failed for PROTO-1 (exit code $LASTEXITCODE)" }
|
||||
Pop-Location
|
||||
|
||||
if (-not (Test-Path $BuildBin)) { Write-Err "Binary not found: $BuildBin" }
|
||||
$ProtoBinSize = (Get-Item $BuildBin).Length
|
||||
$DestProtoBin = Join-Path $ReleasesDir "firmware-$SafeTag-proto1.bin"
|
||||
Copy-Item $BuildBin $DestProtoBin -Force
|
||||
Write-Ok "PROTO-1 release packaged -> releases/firmware-$SafeTag-proto1.bin"
|
||||
|
||||
# Restore original configuration
|
||||
"MODEL=$originalModel" | Set-Content $deviceConfigFile
|
||||
Push-Location $ProjectRoot
|
||||
if (Test-Path "build") {
|
||||
Remove-Item -Path "build" -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
Pop-Location
|
||||
} else {
|
||||
Write-Host " (skipping build - using existing output in build/)" -ForegroundColor Yellow
|
||||
if (-not (Test-Path $BuildBin)) {
|
||||
Write-Err "Binary not found in build/: $BuildBin"
|
||||
}
|
||||
$DevBinSize = (Get-Item $BuildBin).Length
|
||||
$ProtoBinSize = $DevBinSize
|
||||
Copy-Item $BuildBin (Join-Path $ReleasesDir "firmware-$SafeTag-dev1.bin") -Force
|
||||
Copy-Item $BuildBin (Join-Path $ReleasesDir "firmware-$SafeTag-proto1.bin") -Force
|
||||
Write-Ok "Copied build/esp32s3_audio.bin to both dev1 and proto1 release outputs."
|
||||
}
|
||||
|
||||
# -- Step 5: Build changelog --
|
||||
|
||||
Write-Step "Generating changelog..."
|
||||
|
||||
$prevTag = & {
|
||||
$oldEA = $ErrorActionPreference; $ErrorActionPreference = "SilentlyContinue"
|
||||
$t = git describe --tags --abbrev=0 HEAD~1 2>$null
|
||||
$ErrorActionPreference = $oldEA
|
||||
$t
|
||||
}
|
||||
if ($prevTag) {
|
||||
$logRange = "$($prevTag.Trim())..HEAD"
|
||||
} else {
|
||||
$logRange = "HEAD"
|
||||
}
|
||||
|
||||
$gitLog = git log $logRange --pretty=format:"%s" 2>$null
|
||||
$changelog = @()
|
||||
if ($gitLog) {
|
||||
$changelog = ($gitLog -split "`n") | Where-Object { $_ -match '\S' } | ForEach-Object { $_.Trim() }
|
||||
}
|
||||
if ($changelog.Count -eq 0) {
|
||||
$changelog = @("No changes logged")
|
||||
}
|
||||
Write-Ok "$($changelog.Count) changelog entries"
|
||||
|
||||
# -- Step 6: Read / update firmware-catalog.json --
|
||||
|
||||
Write-Step "Updating firmware-catalog.json..."
|
||||
|
||||
if (Test-Path $CatalogFile) {
|
||||
$catalog = Get-Content $CatalogFile -Raw | ConvertFrom-Json
|
||||
$releases = [System.Collections.Generic.List[object]]@()
|
||||
if ($catalog.releases) {
|
||||
foreach ($item in $catalog.releases) { $releases.Add($item) }
|
||||
}
|
||||
} else {
|
||||
$releases = [System.Collections.Generic.List[object]]@()
|
||||
$catalog = [PSCustomObject]@{ latest = ""; releases = @() }
|
||||
}
|
||||
|
||||
# Remove existing entries for this version if re-releasing
|
||||
$filteredReleases = [System.Collections.Generic.List[object]]::new()
|
||||
foreach ($r in $releases) {
|
||||
if ($r.version -ne $Tag) {
|
||||
$filteredReleases.Add($r)
|
||||
}
|
||||
}
|
||||
$releases = $filteredReleases
|
||||
|
||||
# Prepend new entries (DEV-1 first, then PROTO-1)
|
||||
$newDevEntry = [PSCustomObject]@{
|
||||
version = $Tag
|
||||
filename = "firmware-$SafeTag-dev1.bin"
|
||||
date = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
|
||||
size = $DevBinSize
|
||||
model = "DEV-1"
|
||||
commitHash = (git rev-parse HEAD).Trim()
|
||||
changelog = $changelog
|
||||
}
|
||||
|
||||
$newProtoEntry = [PSCustomObject]@{
|
||||
version = $Tag
|
||||
filename = "firmware-$SafeTag-proto1.bin"
|
||||
date = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
|
||||
size = $ProtoBinSize
|
||||
model = "PROTO-1"
|
||||
commitHash = (git rev-parse HEAD).Trim()
|
||||
changelog = $changelog
|
||||
}
|
||||
|
||||
$releases.Insert(0, $newDevEntry)
|
||||
$releases.Insert(1, $newProtoEntry)
|
||||
|
||||
# Update catalog
|
||||
$catalog.latest = $Tag
|
||||
$catalog.releases = $releases.ToArray()
|
||||
|
||||
$catalog | ConvertTo-Json -Depth 10 | Set-Content $CatalogFile -Encoding UTF8
|
||||
Write-Ok "Catalog written: $CatalogFile"
|
||||
Write-Ok "Latest = $Tag | Total releases = $($releases.Count)"
|
||||
|
||||
# -- Step 7: Git tag (only for clean semver tags) --
|
||||
|
||||
Write-Step "Tagging..."
|
||||
$isCleanTag = $Tag -match '^v\d+\.\d+\.\d+$'
|
||||
if ($isCleanTag) {
|
||||
$existingTag = git tag -l $Tag
|
||||
if (-not $existingTag) {
|
||||
git tag -a $Tag -m "Release $Tag"
|
||||
Write-Ok "Created annotated tag: $Tag"
|
||||
} else {
|
||||
Write-Host " Tag $Tag already exists - skipping" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host " Dev version ($Tag) - skipping tag creation" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# -- Step 8: Commit catalog update --
|
||||
|
||||
Write-Step "Committing catalog..."
|
||||
git add (Join-Path $ReleasesDir "firmware-catalog.json")
|
||||
$hasChanges = git diff --quiet HEAD -- (Join-Path $ReleasesDir "firmware-catalog.json")
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
git commit -m "release: update firmware-catalog.json for $Tag"
|
||||
Write-Ok "Committed catalog update"
|
||||
} else {
|
||||
Write-Host " No catalog changes to commit" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# -- Step 9: Push --
|
||||
|
||||
if (-not $NoPush) {
|
||||
Write-Step "Pushing to origin..."
|
||||
git push origin master
|
||||
if ($isCleanTag) { git push origin $Tag }
|
||||
Write-Ok "Pushed"
|
||||
} else {
|
||||
Write-Host " (skipping push - -NoPush flag set)" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# -- Done --
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=======================================================" -ForegroundColor Magenta
|
||||
Write-Host " Release complete: $Tag" -ForegroundColor Green
|
||||
Write-Host " DEV-1 Bin : releases/firmware-$SafeTag-dev1.bin ($([math]::Round($DevBinSize/1024,1)) KB)" -ForegroundColor White
|
||||
Write-Host " PROTO-1 Bin: releases/firmware-$SafeTag-proto1.bin ($([math]::Round($ProtoBinSize/1024,1)) KB)" -ForegroundColor White
|
||||
Write-Host " Catalog: releases/firmware-catalog.json" -ForegroundColor White
|
||||
Write-Host "=======================================================" -ForegroundColor Magenta
|
||||
Write-Host ""
|
||||
Reference in New Issue
Block a user