Skip to content

Add 'version' command, ping now returns version in response #53

Add 'version' command, ping now returns version in response

Add 'version' command, ping now returns version in response #53

name: ESP32C5 Build (IDF 6.0-beta1)
on:
workflow_dispatch:
inputs:
release_tag:
description: "Optional tag name to upload assets to a release (example 'v1.2.3')"
required: false
push:
branches: [main, feature/handshake-serial, feature/handshake-serial-dev]
paths:
- 'ESP32C5/main/main.c'
- 'ESP32C5/sdkconfig*'
- 'FLIPPER/**'
- '.github/workflows/**'
release:
types: [published, edited]
jobs:
changes:
name: Detect workflow changes
runs-on: ubuntu-24.04
outputs:
workflow_changed: ${{ steps.filter.outputs.workflow_changed }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check workflow diff
id: filter
run: |
set -euo pipefail
if [ "${GITHUB_EVENT_NAME:-}" != "push" ]; then
echo "workflow_changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
base="${{ github.event.before }}"
head="${{ github.sha }}"
if [ -z "$base" ] || [ "$base" = "0000000000000000000000000000000000000000" ]; then
base="$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)"
fi
if git diff --name-only "$base" "$head" | grep -qE '^\.github/workflows/'; then
echo "workflow_changed=true" >> "$GITHUB_OUTPUT"
else
echo "workflow_changed=false" >> "$GITHUB_OUTPUT"
fi
firmware:
name: JanOS (${{ matrix.board }})
permissions:
contents: write
runs-on: ubuntu-24.04
container:
image: espressif/idf:v6.0-beta1
strategy:
fail-fast: false
matrix:
include:
- board: wroom
sdkconfig_extra: ""
bin_suffix: ""
- board: xiao
sdkconfig_extra: "sdkconfig.xiao"
bin_suffix: "-xiao"
outputs:
fw_version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache ESP-IDF artifacts
uses: actions/cache@v4
with:
path: /root/.espressif
key: espidf-6.0-${{ matrix.board }}-${{ runner.os }}-${{ hashFiles('ESP32C5/sdkconfig', 'ESP32C5/sdkconfig.xiao', 'ESP32C5/dependencies.lock') }}
restore-keys: |
espidf-6.0-${{ matrix.board }}-${{ runner.os }}-
espidf-6.0-${{ matrix.board }}-
espidf-6.0-
- name: Apply sdkconfig overlay (${{ matrix.board }})
if: matrix.sdkconfig_extra != ''
run: |
set -e
cd ESP32C5
# Clean previous build to avoid stale sdkconfig cache
rm -rf build
# Append XIAO overlay to sdkconfig so idf.py picks it up
cat "${{ matrix.sdkconfig_extra }}" >> sdkconfig
- name: Build JanOS (IDF 6.0) — ${{ matrix.board }}
run: IDF_PY_FLAGS="--preview" bash .github/scripts/container_build.sh --no-docker
- name: Stamp JanOS with JANOS_VERSION
id: version
run: |
set -e
version=$(python - <<'PY'
from pathlib import Path
import re
text = Path("ESP32C5/main/main.c").read_text()
m = re.search(r'JANOS_VERSION\s*"([^"]+)"', text)
if not m:
raise SystemExit("JANOS_VERSION not found")
print(m.group(1))
PY
)
suffix="${{ matrix.bin_suffix }}"
src="ESP32C5/binaries-esp32c5/projectZerobyLOCOSP.bin"
dst="ESP32C5/binaries-esp32c5/projectZerobyLOCOSP${suffix}-${version}.bin"
if [ ! -f "$src" ]; then
echo "Missing firmware: $src" >&2
exit 1
fi
cp "$src" "$dst"
# Also rename base bin for XIAO so artifacts don't collide
if [ -n "$suffix" ]; then
mv "$src" "ESP32C5/binaries-esp32c5/projectZerobyLOCOSP${suffix}.bin"
fi
echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: Package JanOS zip (${{ matrix.board }})
id: bundle
run: |
set -e
cd ESP32C5/binaries-esp32c5
suffix="${{ matrix.bin_suffix }}"
version="${{ steps.version.outputs.version }}"
out="projectZerobyLOCOSP${suffix}-${version}.zip"
rm -f "$out"
zip -9 "$out" \
bootloader.bin \
partition-table.bin \
flash_board.py \
oui_wifi.bin \
"projectZerobyLOCOSP${suffix}-${version}.bin" \
"projectZerobyLOCOSP${suffix}.bin"
echo "bundle_zip=$(pwd)/$out" >> "$GITHUB_OUTPUT"
- name: Upload JanOS artifacts (${{ matrix.board }})
uses: actions/upload-artifact@v4
with:
name: esp32c5-firmware-${{ matrix.board }}
path: ESP32C5/binaries-esp32c5
if-no-files-found: error
fap:
name: Flipper FAP
needs: firmware
runs-on: ubuntu-24.04
outputs:
fap_version: ${{ steps.fap_version.outputs.fap_version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install FAP build dependencies (ufbt in venv)
run: |
set -e
sudo apt-get update && sudo apt-get install -y python3-venv
python3 -m venv /tmp/ufbt-venv
. /tmp/ufbt-venv/bin/activate
pip install -U pip ufbt
echo "/tmp/ufbt-venv/bin" >> $GITHUB_PATH
- name: Download Flipper SDKs
run: |
set -e
mkdir -p FLIPPER/sdk
cd FLIPPER/sdk
[ -f flipper-z-f7-sdk-unlshd-083.zip ] || curl -L -o flipper-z-f7-sdk-unlshd-083.zip https://github.com/DarkFlippers/unleashed-firmware/releases/download/unlshd-083/flipper-z-f7-sdk-unlshd-083.zip
[ -f flipper-z-f7-sdk-mntm-011.zip ] || curl -L -o flipper-z-f7-sdk-mntm-011.zip https://github.com/Next-Flip/Momentum-Firmware/releases/download/mntm-011/flipper-z-f7-sdk-mntm-011.zip
[ -f flipper-z-f7-sdk-mntm-dev-22408e4c.zip ] || curl -L -o flipper-z-f7-sdk-mntm-dev-22408e4c.zip https://up.momentum-fw.dev/builds/firmware/dev/flipper-z-f7-sdk-mntm-dev-22408e4c.zip
- name: Build Flipper FAP
run: |
set -e
python FLIPPER/build_fap.py --no-upload
- name: Read FAP version
id: fap_version
run: |
set -e
python - <<'PY'
from pathlib import Path
import os
import re
text = Path("FLIPPER/Lab_C5.c").read_text(encoding="utf-8", errors="ignore")
m = re.search(r'#define\s+LAB_C5_VERSION_TEXT\s+"([^"]+)"', text)
if not m:
raise SystemExit("LAB_C5_VERSION_TEXT not found")
version = m.group(1)
print(f"fap_version={version}")
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh:
fh.write(f"fap_version={version}\n")
PY
- name: Upload FAP artifacts
if: ${{ hashFiles('FLIPPER/dist/*.fap') != '' }}
uses: actions/upload-artifact@v4
with:
name: flipper-fap
path: FLIPPER/dist/*.fap
release:
name: Release
needs: [changes, firmware, fap]
runs-on: ubuntu-24.04
permissions:
contents: write
pull-requests: read
if: always() && !cancelled() && needs.changes.outputs.workflow_changed != 'true' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' || github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.release_tag != ''))
steps:
- name: Download WROOM firmware artifacts
uses: actions/download-artifact@v4
with:
name: esp32c5-firmware-wroom
path: release_artifacts/firmware
- name: Download XIAO firmware artifacts
uses: actions/download-artifact@v4
with:
name: esp32c5-firmware-xiao
path: release_artifacts/firmware-xiao
continue-on-error: true
- name: Download FAP artifacts (if present)
uses: actions/download-artifact@v4
with:
name: flipper-fap
path: release_artifacts/fap
merge-multiple: true
continue-on-error: true
- name: Package FAP zip
if: ${{ hashFiles('release_artifacts/fap/*.fap') != '' }}
run: |
set -e
cd release_artifacts/fap
zip -9 "projectZero-faps-${{ needs.fap.outputs.fap_version }}.zip" *.fap
- name: Package full bundle (JanOS + FAPs)
run: |
set -e
cd release_artifacts
mkdir -p bundle
FW_VERSION="${{ needs.firmware.outputs.fw_version }}"
FAP_VERSION="${{ needs.fap.outputs.fap_version }}"
shopt -s nullglob
faps=(fap/*.fap)
files=(
firmware/bootloader.bin
firmware/partition-table.bin
firmware/flash_board.py
firmware/oui_wifi.bin
firmware/projectZerobyLOCOSP.bin
"firmware/projectZerobyLOCOSP-${FW_VERSION}.bin"
)
# Include existing JanOS zip if present
if [ -f "firmware/projectZerobyLOCOSP-${FW_VERSION}.zip" ]; then
files+=("firmware/projectZerobyLOCOSP-${FW_VERSION}.zip")
fi
# Add all FAPs (if any)
if [ ${#faps[@]} -gt 0 ]; then
files+=("${faps[@]}")
fi
out="bundle/projectZerobyLOCOSP-${FW_VERSION}-with-fap-${FAP_VERSION:-unknown}.zip"
zip -9 "$out" "${files[@]}"
- name: Build release notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FW_VERSION: ${{ needs.firmware.outputs.fw_version }}
FAP_VERSION: ${{ needs.fap.outputs.fap_version }}
REPO: ${{ github.repository }}
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag || format('v{0}', needs.firmware.outputs.fw_version) }}
run: |
set -euo pipefail
notes_file="release_notes.md"
TAG="${RELEASE_TAG:-$FW_VERSION}"
FAP_VER="${FAP_VERSION:-unknown}"
BASE_URL="https://github.com/$REPO/releases/download/$TAG"
JANOS_ZIP="$BASE_URL/projectZerobyLOCOSP-${FW_VERSION}.zip"
XIAO_ZIP="$BASE_URL/projectZerobyLOCOSP-xiao-${FW_VERSION}.zip"
FAP_ZIP="$BASE_URL/projectZero-faps-${FAP_VER}.zip"
BUNDLE_ZIP="$BASE_URL/projectZerobyLOCOSP-${FW_VERSION}-with-fap-${FAP_VER}.zip"
RELEASE_PAGE="https://github.com/$REPO/releases/tag/$TAG"
PAGES_LINK="https://${REPO%/*}.github.io/${REPO#*/}/"
{
printf '%s\n\n' "Release ${TAG} published."
printf '%s\n' "Release page: ${RELEASE_PAGE}"
printf '%s\n' "Web flasher: ${PAGES_LINK}"
printf '%s\n' "JanOS WROOM (${FW_VERSION}): ${JANOS_ZIP}"
printf '%s\n' "JanOS XIAO (${FW_VERSION}): ${XIAO_ZIP}"
printf '%s\n' "FAPs (${FAP_VER}): ${FAP_ZIP}"
printf '%s\n\n' "Full package: ${BUNDLE_ZIP}"
} > "$notes_file"
if [ "${GITHUB_EVENT_NAME:-}" = "release" ]; then
if [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -f "${GITHUB_EVENT_PATH:-}" ]; then
release_body="$(jq -r '.release.body // ""' "$GITHUB_EVENT_PATH")"
if [ -n "$(printf '%s' "$release_body" | tr -d '\r\n[:space:]')" ]; then
printf '%s\n' "$release_body" >> "$notes_file"
fi
fi
exit 0
fi
if command -v gh >/dev/null 2>&1; then
api="/repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls"
pr_json="$(gh api -H "Accept: application/vnd.github+json" "$api" 2>/dev/null || echo '[]')"
pr_title="$(printf '%s' "$pr_json" | jq -r '.[0].title // ""')"
pr_body="$(printf '%s' "$pr_json" | jq -r '.[0].body // ""')"
if [ -n "$(printf '%s' "$pr_body" | tr -d '\r\n[:space:]')" ]; then
if [ -n "$pr_title" ]; then
printf '%s\n\n' "$pr_title" >> "$notes_file"
fi
printf '%s\n' "$pr_body" >> "$notes_file"
exit 0
fi
gen_json="$(gh api -X POST -H "Accept: application/vnd.github+json" \
"/repos/${GITHUB_REPOSITORY}/releases/generate-notes" \
-f tag_name="$TAG" -f target_commitish="$GITHUB_SHA" 2>/dev/null || echo '')"
gen_body="$(printf '%s' "$gen_json" | jq -r '.body // ""')"
if [ -n "$(printf '%s' "$gen_body" | tr -d '\r\n[:space:]')" ]; then
printf '%s\n' "$gen_body" >> "$notes_file"
fi
fi
- name: Upload binaries to GitHub Release (notes)
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.release.tag_name || inputs.release_tag || format('v{0}', needs.firmware.outputs.fw_version) }}
name: ${{ format('projectZerobyLOCOSP {0}', needs.firmware.outputs.fw_version) }}
body_path: release_notes.md
fail_on_unmatched_files: false
files: |
release_artifacts/firmware/bootloader.bin
release_artifacts/firmware/partition-table.bin
release_artifacts/firmware/flash_board.py
release_artifacts/firmware/oui_wifi.bin
release_artifacts/firmware/projectZerobyLOCOSP.bin
release_artifacts/firmware/projectZerobyLOCOSP-${{ needs.firmware.outputs.fw_version }}.bin
release_artifacts/firmware/projectZerobyLOCOSP-${{ needs.firmware.outputs.fw_version }}.zip
release_artifacts/firmware-xiao/projectZerobyLOCOSP-xiao.bin
release_artifacts/firmware-xiao/projectZerobyLOCOSP-xiao-${{ needs.firmware.outputs.fw_version }}.bin
release_artifacts/firmware-xiao/projectZerobyLOCOSP-xiao-${{ needs.firmware.outputs.fw_version }}.zip
release_artifacts/fap/projectZero-faps-${{ needs.fap.outputs.fap_version }}.zip
release_artifacts/bundle/projectZerobyLOCOSP-*-with-fap-*.zip
release_artifacts/fap/*.fap
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}