--- name: Validate ESPHome permissions: contents: read pull-requests: read on: # yamllint disable-line rule:truthy push: paths: - "**/*.yml" - "**/*.yaml" - "**/*.h" - "**/*.cpp" - "**/*.c" - "**/*.py" pull_request: paths: - "**/*.yml" - "**/*.yaml" - "**/*.h" - "**/*.cpp" - "**/*.c" - "**/*.py" workflow_dispatch: inputs: skip_features: description: 'Skip feature builds (BLE proxy, media player)' required: false default: false type: boolean version_filter: description: 'Test only specific version (latest, beta, dev, or all)' required: false default: 'all' type: choice options: - all - latest - beta - dev concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: code_scan: name: Code scan (YAML) runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@main - name: Setup Python uses: actions/setup-python@main with: python-version: '3.11' - name: Install Yamllint run: pip install yamllint - name: Validate YAML files run: find . -name "*.yaml" -exec yamllint -c ./.rules/yamllint.yml {} + # Determine which versions to test based on input setup_matrix: name: Setup build matrix runs-on: ubuntu-latest outputs: versions: ${{ steps.set-matrix.outputs.versions }} steps: - name: Set version matrix id: set-matrix run: | if [ "${{ inputs.version_filter }}" == "all" ] || [ -z "${{ inputs.version_filter }}" ]; then echo 'versions=["latest", "beta", "dev"]' >> $GITHUB_OUTPUT else echo 'versions=["${{ inputs.version_filter }}"]' >> $GITHUB_OUTPUT fi # Stage 1: Core builds - Foundation (must pass for everything else to continue) build_core: name: "🏗️ Core (${{ matrix.framework }}-${{ matrix.version }})" needs: [code_scan, setup_matrix] runs-on: ubuntu-latest strategy: fail-fast: true # If core fails, stop everything max-parallel: 4 matrix: framework: [idf, ard] version: ${{ fromJson(needs.setup_matrix.outputs.versions) }} steps: - uses: actions/checkout@main - name: Build Core (${{ matrix.framework }}) - ${{ matrix.version }} uses: esphome/build-action@main with: yaml-file: ".test/esphome_${{ matrix.framework }}_core.yaml" version: ${{ matrix.version }} # Stage 2: Hardware builds - Individual components (only if core passed) build_hardware: name: "🔌 ${{ matrix.target }} (${{ matrix.framework }}-${{ matrix.version }})" needs: [build_core, setup_matrix] if: success() # Only run if core builds passed runs-on: ubuntu-latest strategy: fail-fast: false # Hardware components can fail independently max-parallel: 4 matrix: framework: [idf, ard] version: ${{ fromJson(needs.setup_matrix.outputs.versions) }} target: [hw_relays, hw_speaker, hw_vibration] steps: - uses: actions/checkout@main - name: Build ${{ matrix.target }} (${{ matrix.framework }}) - ${{ matrix.version }} uses: esphome/build-action@main with: yaml-file: ".test/esphome_${{ matrix.framework }}_${{ matrix.target }}.yaml" version: ${{ matrix.version }} # Stage 3: Basic builds - Integrated functionality (needs core + hardware) build_basic: name: "📦 Basic (${{ matrix.framework }}-${{ matrix.version }})" needs: [build_core, build_hardware, setup_matrix] if: success() # Only run if both core and hardware passed runs-on: ubuntu-latest strategy: fail-fast: true # Basic should pass if hardware works max-parallel: 4 matrix: framework: [idf, ard] version: ${{ fromJson(needs.setup_matrix.outputs.versions) }} steps: - uses: actions/checkout@main - name: Build Basic (${{ matrix.framework }}) - ${{ matrix.version }} uses: esphome/build-action@main with: yaml-file: ".test/esphome_${{ matrix.framework }}_basic.yaml" version: ${{ matrix.version }} # Stage 4: Feature builds - Advanced functionality (needs everything before) build_features: name: "⚡ ${{ matrix.target }} (${{ matrix.framework }}-${{ matrix.version }})" needs: [build_core, build_hardware, build_basic, setup_matrix] if: success() && !inputs.skip_features # Run only if all previous stages passed AND not skipped runs-on: ubuntu-latest strategy: fail-fast: false # Features can fail independently max-parallel: 4 matrix: framework: [idf, ard] version: ${{ fromJson(needs.setup_matrix.outputs.versions) }} target: [ble_proxy, media_player] steps: - uses: actions/checkout@main - name: Build ${{ matrix.target }} (${{ matrix.framework }}) - ${{ matrix.version }} uses: esphome/build-action@main with: yaml-file: ".test/esphome_${{ matrix.framework }}_${{ matrix.target }}.yaml" version: ${{ matrix.version }} # Results summary build_summary: name: "📊 Build Results Summary" needs: [build_core, build_hardware, build_basic, build_features] if: always() # Always run to show results, even if some stages failed runs-on: ubuntu-latest steps: - name: Generate summary run: | echo "## 🔍 ESPHome Build Results" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Dependency Chain:** code_scan → core → hardware → basic → features" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Stage | Status | Description |" >> $GITHUB_STEP_SUMMARY echo "|-------|--------|-------------|" >> $GITHUB_STEP_SUMMARY echo "| 🏗️ Core | ${{ needs.build_core.result }} | Foundation components (must pass for all others) |" >> $GITHUB_STEP_SUMMARY echo "| 🔌 Hardware | ${{ needs.build_hardware.result }} | Individual hardware components |" >> $GITHUB_STEP_SUMMARY echo "| 📦 Basic | ${{ needs.build_basic.result }} | Integrated core + hardware functionality |" >> $GITHUB_STEP_SUMMARY echo "| ⚡ Features | ${{ needs.build_features.result }} | Advanced features (BLE, media player) |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Determine overall result and provide guidance if [ "${{ needs.build_core.result }}" != "success" ]; then echo "❌ **Core builds failed** - Fundamental issue with core components" >> $GITHUB_STEP_SUMMARY echo "🔧 **Next steps:** Check core YAML configuration and basic component definitions" >> $GITHUB_STEP_SUMMARY exit 1 elif [ "${{ needs.build_hardware.result }}" != "success" ] && [ "${{ needs.build_hardware.result }}" != "skipped" ]; then echo "⚠️ **Hardware builds failed** - Core works but hardware components have issues" >> $GITHUB_STEP_SUMMARY echo "🔧 **Next steps:** Check relay, speaker, or vibration component configurations" >> $GITHUB_STEP_SUMMARY exit 1 elif [ "${{ needs.build_basic.result }}" != "success" ] && [ "${{ needs.build_basic.result }}" != "skipped" ]; then echo "⚠️ **Basic builds failed** - Hardware works individually but integration has issues" >> $GITHUB_STEP_SUMMARY echo "🔧 **Next steps:** Check how hardware components are integrated in basic configuration" >> $GITHUB_STEP_SUMMARY exit 1 elif [ "${{ needs.build_features.result }}" != "success" ] && [ "${{ needs.build_features.result }}" != "skipped" ]; then echo "⚠️ **Feature builds failed** - Core functionality works but advanced features have issues" >> $GITHUB_STEP_SUMMARY echo "🔧 **Next steps:** Check BLE proxy or media player specific configurations" >> $GITHUB_STEP_SUMMARY exit 1 else echo "✅ **All builds completed successfully!** 🎉" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "🚀 **Ready for release** - All components tested and working" >> $GITHUB_STEP_SUMMARY fi ...