Merge branch 'main' of https://github.com/trip5/EspHome-Led-PixelClock #7
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Release Firmware | |
| on: | |
| push: | |
| tags: | |
| - '*' | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-firmware: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install yq | |
| run: | | |
| sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 | |
| sudo chmod +x /usr/local/bin/yq | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install ESPHome | |
| run: | | |
| pip install esphome | |
| - name: Download font files | |
| run: | | |
| echo "📥 Downloading font files from Matrix-Fonts repository..." | |
| mkdir -p generated_yamls/fonts | |
| curl -L -o generated_yamls/fonts/MatrixChunky8X.bdf "https://github.com/trip5/Matrix-Fonts/raw/refs/heads/main/8-series/MatrixChunky8X.bdf" | |
| curl -L -o generated_yamls/fonts/MatrixLight8X.bdf "https://github.com/trip5/Matrix-Fonts/raw/refs/heads/main/8-series/MatrixLight8X.bdf" | |
| echo "✅ Downloaded font files to generated_yamls/fonts/:" | |
| ls -la generated_yamls/fonts/ | |
| - name: Get version tag | |
| id: get_version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION=$(yq eval '.substitutions.project_version' EHLPClock.yaml | tr -d '"') | |
| TAG="${VERSION}" | |
| echo "Extracted version from YAML: ${VERSION}" | |
| else | |
| TAG=${GITHUB_REF#refs/tags/} | |
| VERSION=${TAG#v} | |
| echo "Using git tag: ${TAG}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "tag=${TAG}" >> $GITHUB_OUTPUT | |
| echo "Final version: ${VERSION}" | |
| - name: Generate language variants | |
| run: | | |
| echo "🔄 Generating language-specific YAML files..." | |
| mkdir -p generated_yamls | |
| mkdir -p generated_yamls/base | |
| echo "🔧 Preparing base YAML for language merging..." | |
| cp EHLPClock.yaml generated_yamls/base/EHLPClock-base.yaml | |
| cp EHLPClock-HA.yaml generated_yamls/base/EHLPClock-HA-base.yaml | |
| for base_file in generated_yamls/base/EHLPClock-base.yaml generated_yamls/base/EHLPClock-HA-base.yaml; do | |
| sed -i 's/- ssid: !secret wifi_ssid/# - ssid: !secret wifi_ssid/' "$base_file" | |
| sed -i 's/password: !secret wifi_password/# password: !secret wifi_password/' "$base_file" | |
| sed -i '/password: !secret ap_password/d' "$base_file" | |
| sed -i '/password: !secret ota_password/d' "$base_file" | |
| sed -i '/key: !secret encryption_key/d' "$base_file" | |
| done | |
| for base_name in EHLPClock EHLPClock-HA; do | |
| for lang_file in language_filters/*.yaml; do | |
| if [ -f "$lang_file" ]; then | |
| lang_name=$(basename "$lang_file" .yaml) | |
| output_file="generated_yamls/${base_name}-${lang_name}.yaml" | |
| echo "📝 Creating ${output_file} (English + ${lang_name})..." | |
| yq eval-all ' | |
| select(fileIndex == 0) as $base | | |
| select(fileIndex == 1) as $lang | | |
| ($lang.font // [] | map(.id)) as $lang_font_ids | | |
| $base * $lang | | |
| .font = ( | |
| ($base.font // [] | map(select(.id as $id | $lang_font_ids | contains([$id]) | not))) + | |
| ($lang.font // []) | |
| ) | | |
| .text_sensor = ( | |
| ($base.text_sensor // [] | map(select(.id != "time_text" and .id != "date_text" and .id != "dateA_text"))) + | |
| ($lang.text_sensor // []) | |
| ) | |
| ' "generated_yamls/base/${base_name}-base.yaml" "$lang_file" > "$output_file" | |
| echo "✅ Generated ${output_file}" | |
| fi | |
| done | |
| done | |
| echo "🧹 Cleaning timezone offset code from HA versions..." | |
| for ha_file in generated_yamls/EHLPClock-HA-*.yaml; do | |
| if [ -f "$ha_file" ]; then | |
| echo "Cleaning timezone references from $ha_file" | |
| sed -i '/if (id(tzoffset_on)/,/^[[:space:]]*}/d' "$ha_file" | |
| sed -i '/tzoffset_on\|tzoffset\.state/d' "$ha_file" | |
| sed -i '/delete.*HA version/d' "$ha_file" | |
| echo "✅ Cleaned $ha_file" | |
| fi | |
| done | |
| echo "📦 Generated firmware files:" | |
| ls -la firmware/ || echo "No firmware directory created" | |
| - name: Validate YAML files | |
| run: | | |
| echo "🔍 Validating generated YAML files..." | |
| echo "📂 Checking downloaded font files:" | |
| ls -la generated_yamls/fonts/ | |
| file generated_yamls/fonts/* || echo "No font files found" | |
| for yaml_file in generated_yamls/*.yaml; do | |
| echo "Validating $yaml_file..." | |
| esphome config "$yaml_file" | |
| done | |
| echo "✅ All YAML files are valid" | |
| - name: Compile ESPHome firmwares | |
| run: | | |
| echo "🔨 Compiling ESPHome firmwares..." | |
| mkdir -p firmware | |
| for yaml_file in generated_yamls/*.yaml; do | |
| filename=$(basename "$yaml_file" .yaml) | |
| echo "🔨 Building ${filename}..." | |
| # Clean build directory to prevent mix-ups | |
| rm -rf generated_yamls/.esphome/build/* | |
| # Compile the firmware | |
| esphome compile "$yaml_file" | |
| device_name=$(find generated_yamls/.esphome/build/ -maxdepth 1 -type d ! -name "build" -printf "%f\n" 2>/dev/null | head -1) | |
| if [ -z "$device_name" ]; then | |
| device_name=$(yq eval '.substitutions.name' "$yaml_file" | tr -d '"') | |
| fi | |
| possible_paths=( | |
| "generated_yamls/.esphome/build/${device_name}/.pioenvs/${device_name}/firmware.bin" | |
| ".pioenvs/${device_name}/firmware.bin" | |
| "${device_name}/.pioenvs/${device_name}/firmware.bin" | |
| ".esphome/build/${device_name}/.pioenvs/${device_name}/firmware.bin" | |
| ) | |
| binary_found=false | |
| for binary_path in "${possible_paths[@]}"; do | |
| if [ -f "$binary_path" ]; then | |
| cp "$binary_path" "firmware/${filename}.bin" | |
| echo "✅ Copied ${filename}.bin from $binary_path" | |
| binary_found=true | |
| break | |
| fi | |
| done | |
| if [ "$binary_found" = false ]; then | |
| echo "❌ Binary not found for ${filename}" | |
| echo "Searched in:" | |
| for path in "${possible_paths[@]}"; do | |
| echo " - $path" | |
| done | |
| find . -name "firmware.bin" -type f 2>/dev/null || echo "No firmware.bin files found anywhere" | |
| fi | |
| done | |
| echo "🔄 Renaming HA firmware files..." | |
| for bin_file in firmware/EHLPClock-HA-*.bin; do | |
| if [ -f "$bin_file" ]; then | |
| lang=$(basename "$bin_file" | sed 's/EHLPClock-HA-\(.*\)\.bin/\1/') | |
| new_name="firmware/EHLPClock-${lang}-HA.bin" | |
| mv "$bin_file" "$new_name" | |
| echo "Renamed $(basename "$bin_file") -> $(basename "$new_name")" | |
| fi | |
| done | |
| echo "📦 Generated firmware files:" | |
| ls -la firmware/ || echo "No firmware directory created" | |
| - name: Create firmware manifests | |
| run: | | |
| echo "📝 Creating firmware manifests..." | |
| rm -rf docs/manifests | |
| mkdir -p docs/manifests | |
| for bin_file in $(ls -1 firmware/*.bin); do | |
| if [ -f "$bin_file" ]; then | |
| filename=$(basename "$bin_file") | |
| if [[ "$filename" == *"-HA.bin" ]]; then | |
| lang_name=$(echo "$filename" | sed 's/EHLPClock-\(.*\)-HA\.bin/\1/') | |
| variant_id="${lang_name}-HA" | |
| else | |
| lang_name=$(echo "$filename" | sed 's/EHLPClock-\([^.]*\)\.bin/\1/') | |
| variant_id="${lang_name}" | |
| fi | |
| manifest_file="docs/manifests/${variant_id}-manifest.json" | |
| echo '{' > "$manifest_file" | |
| echo ' "name": "EspHome-Led-PixelClock",' >> "$manifest_file" | |
| echo ' "version": "${{ steps.get_version.outputs.version }}",' >> "$manifest_file" | |
| echo ' "home_assistant_domain": "esphome",' >> "$manifest_file" | |
| echo ' "funding_url": "https://github.com/sponsors/trip5",' >> "$manifest_file" | |
| echo ' "builds": [' >> "$manifest_file" | |
| echo ' {' >> "$manifest_file" | |
| echo ' "chipFamily": "ESP8266",' >> "$manifest_file" | |
| echo ' "parts": [' >> "$manifest_file" | |
| echo ' {' >> "$manifest_file" | |
| echo " \"path\": \"../firmware/${filename}\"," >> "$manifest_file" | |
| echo ' "offset": 0' >> "$manifest_file" | |
| echo ' }' >> "$manifest_file" | |
| echo ' ]' >> "$manifest_file" | |
| echo ' }' >> "$manifest_file" | |
| echo ' ]' >> "$manifest_file" | |
| echo '}' >> "$manifest_file" | |
| echo "Created manifest: $manifest_file" | |
| fi | |
| done | |
| BUILD_DATE=$(date -u '+%Y-%m-%d %H:%M:%S UTC') | |
| echo '{' > docs/firmware-info.json | |
| echo ' "project": "EspHome-Led-PixelClock",' >> docs/firmware-info.json | |
| echo ' "version": "${{ steps.get_version.outputs.version }}",' >> docs/firmware-info.json | |
| echo " \"build_date\": \"${BUILD_DATE}\"," >> docs/firmware-info.json | |
| echo ' "variants": [' >> docs/firmware-info.json | |
| FIRST=true | |
| for bin_file in $(ls -1 firmware/*.bin); do | |
| if [ -f "$bin_file" ]; then | |
| filename=$(basename "$bin_file") | |
| if [[ "$filename" == *"-HA.bin" ]]; then | |
| lang_name=$(echo "$filename" | sed 's/EHLPClock-\(.*\)-HA\.bin/\1/') | |
| display_name="${lang_name} - Home Assistant" | |
| variant_id="${lang_name}-HA" | |
| else | |
| lang_name=$(echo "$filename" | sed 's/EHLPClock-\([^.]*\)\.bin/\1/') | |
| display_name="${lang_name}" | |
| variant_id="${lang_name}" | |
| fi | |
| if [ "$FIRST" = "false" ]; then | |
| echo " ," >> docs/firmware-info.json | |
| fi | |
| FIRST=false | |
| echo ' {' >> docs/firmware-info.json | |
| echo " \"name\": \"${display_name}\"," >> docs/firmware-info.json | |
| echo " \"manifest\": \"manifests/${variant_id}-manifest.json\"," >> docs/firmware-info.json | |
| echo " \"description\": \"English + ${lang_name} firmware\"" >> docs/firmware-info.json | |
| echo ' }' >> docs/firmware-info.json | |
| fi | |
| done | |
| echo ' ]' >> docs/firmware-info.json | |
| echo '}' >> docs/firmware-info.json | |
| echo "✅ Created firmware manifests and info" | |
| - name: Commit manifest files to docs | |
| run: | | |
| git fetch origin main | |
| git checkout main | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add docs/manifests/*.json docs/firmware-info.json | |
| git commit -m "Update firmware manifests for ${{ steps.get_version.outputs.version }} [skip ci]" || echo "No changes to commit" | |
| git push origin main || echo "Nothing to push" | |
| - name: Upload firmware artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: firmware-binaries | |
| path: | | |
| firmware/*.bin | |
| docs/firmware-info.json | |
| docs/manifests/*.json | |
| retention-days: 90 | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ steps.get_version.outputs.tag }} | |
| name: "${{ steps.get_version.outputs.tag }}" | |
| body: | | |
| Compiled firmware binaries for EspHome-Led-PixelClock with different second-language options (all have English as a first language). | |
| You can download the firmware and flash yourself or you can use my [Web Installer](https://trip5.github.io/EspHome-Led-PixelClock/firmware.html). | |
| These firmwares can get Wi-fi SSID and password through Improv via Serial or through the captive portal. | |
| You can use the tool provided above or the official one at [Improv-wifi](https://www.improv-wifi.com/) (click on 'Improv via Serial'). | |
| The captive portal will make a hotspot with the name of the clock. Connect to it and visit http://192.168.4.1 to configure the wi-fi. | |
| files: | | |
| firmware/*.bin | |
| fail_on_unmatched_files: false | |
| draft: false | |
| prerelease: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |