name: Platform Build
on: 
  push:
    branches: 
      - '**4.3'
  workflow_dispatch:
    inputs:
      ui_build:
        description: 'Force Rebuilding the UI. When not forced, the system will check for [ui-build] in the last commit message to trigger a ui rebuild'
        required: true
        type: boolean
      release_build:
        description: 'Force a Release build. When not forced, the system will check for release word in the last commit message to trigger a release'
        required: true
        type: boolean
jobs:
  bootstrap:
    name: Global setup
    runs-on: ubuntu-latest
    container:
      image: sle118/squeezelite-esp32-idfv435
    outputs:
      build_number: ${{ steps.buildnumber.outputs.build_number }}
      ui_build: ${{ steps.build_flags.outputs.ui_build }}
      release_flag: ${{ steps.build_flags.outputs.release_flag }}      
      mock: ${{ steps.build_flags.outputs.mock }}            
    steps:
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0
        submodules: true
    - name: Generate common build number
      id: buildnumber
      uses: einaregilsson/build-number@v3
      with:
        token: ${{secrets.github_token}}

    - name: Set build flags
      id: build_flags
      run: |
        git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32   
        [ ${{github.event.inputs.ui_build}} ] && ui_build_option="--ui_build" || ui_build_option="" 
        [ ${{github.event.inputs.release_build}}  ] && release_build_option="--force" || release_build_option=""
        echo "ui_build_option=$ui_build_option" >> "$GITHUB_OUTPUT"
        echo "release_build_option=$release_build_option" >> "$GITHUB_OUTPUT"
        echo "Dumping environment"
        env
        . /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
        # build_flags support the following options
        # --mock - to mock the compilation part - this is to be used for testing only
        # --force - to force a release build even if the last commit message doesn't contain the word "release"
        # --ui_build - to force a ui_build even if the last commit message doesn't contain "[ui-build]"
        build_tools.py build_flags $ui_build_option $release_build_option
    - name: Show Build Flags        
      run: |
          echo "Running with the following options" 
          echo "Web Build Flag=${{steps.build_flags.outputs.ui_build}}"
          echo "Mock flag=${{steps.build_flags.outputs.mock}}"
          echo "Release Flag=${{steps.build_flags.outputs.release_flag}}"      
    - name: Refresh certificates
      if: ${{ steps.build_flags.outputs.release_flag }}
      run: |
        git update-index --chmod=+x ./server_certs/getcert.sh
        cd server_certs;./getcert.sh;cat github.pem;cd ..        
    - name: Setup Node.js dependencies
      if: ${{ !env.ACT }}
      uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'
        cache-dependency-path: components/wifi-manager/webapp/package.json   
    - name: Build Web Application
      if: ${{ steps.build_flags.outputs.ui_build == 1 }} 
      run: |
        cd components/wifi-manager/webapp/ 
        npm install 
        npm run-script build
    - name: Update repository with prebuilt items
      if:  ${{ steps.build_flags.outputs.ui_build == 1 || steps.build_flags.outputs.release_flag == 1 }} 
      run: |
        git config user.name github-actions
        git config user.email github-actions@github.com
        git add server_certs 
        git add components/wifi-manager/webapp/*.h 
        git add components/wifi-manager/webapp/*.c 
        git add components/wifi-manager/webapp/*.cmake 
        git add components/wifi-manager/webapp/dist/*
        git commit -m "Update prebuilt objects [skip actions]"
        git push  https://${{secrets.github_token}}@github.com/sle118/squeezelite-esp32.git
    - name: Locally store commonly built objects
      uses: actions/upload-artifact@v4
      with:
        name: prebuilt_objects
        path: |
          server_certs 
          components/wifi-manager/webapp/*.h
          components/wifi-manager/webapp/*.c
          components/wifi-manager/webapp/dist/*
          components/wifi-manager/webapp/*.cmake 
  build:
    runs-on: ubuntu-latest
    container:
      image: sle118/squeezelite-esp32-idfv435
    needs: [bootstrap]
    strategy:
      matrix:
        node: [I2S-4MFlash, SqueezeAmp, Muse]
        depth: [16, 32]
        exclude:
          - node: Muse
            depth: 32      
          - node: bootstrap
            depth: 32
    steps:
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0
        submodules: true
    - name: Show Build Flags        
      run: |
          echo "Running with the following options" 
          echo "Web Build Flag=${{needs.bootstrap.outputs.ui_build}}"
          echo "Mock flag=${{needs.bootstrap.outputs.mock}}"
          echo "Release Flag=${{needs.bootstrap.outputs.release_flag}}"
          echo Environment File name: $GITHUB_ENV        
    - name: Set build parameters
      run: |
        . /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
        git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32   
        git status
        build_tools.py environment --build ${{ needs.bootstrap.outputs.build_number }} --env_file "$GITHUB_ENV" --node "${{matrix.node}}" --depth ${{matrix.depth}} --major 2 --docker sle118/squeezelite-esp32-idfv435 
        
    - uses: actions/download-artifact@v4
      name: Restore common objects
      with:
        name: prebuilt_objects
    - name: Build the firmware
      if: ${{ needs.bootstrap.outputs.mock == 0 }} 
      run: |
        . ${IDF_PYTHON_ENV_PATH}/bin/activate
        echo "Copying target sdkconfig"
        cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig
        echo "Building project"
        idf.py build -DDEPTH=${DEPTH} -DBUILD_NUMBER=${BUILD_NUMBER}-${DEPTH} 
    - name: Build Mock firmware
      if: ${{ needs.bootstrap.outputs.mock == 1 }} 
      run: |
        mkdir -p build
        cd build
        mkdir -p partition_table
        mkdir -p bootloader
        echo \\"mock content\\"> ./squeezelite.bin
        echo \"mock content\"> ./recovery.bin
        echo \"mock content\"> ./bootloader/bootloader.bin
        echo \"mock content\"> ./partition_table/partition-table.bin 
        echo \"mock content\"> ./ota_data_initial.bin
        echo \"mock content\"> ./flash_project_args 
        echo \"mock content\"> ./size_comp1.txt
        echo \"mock content\"> ./size_comp2.txt
        echo \"mock content\"> ./partitions.csv        
        echo {  \"write_flash_args\" : [ \"--flash_mode\", \"dio\", \"--flash_size\", \"detect\", \"--flash_freq\", \"80m\" ],  \"flash_settings\" : {      \"flash_mode\": \"dio\",      \"flash_size\": \"detect\",      \"flash_freq\": \"80m\"  },  \"flash_files\" : {      \"0x8000\" : \"partition_table/partition-table.bin\",      \"0xd000\" : \"ota_data_initial.bin\",      \"0x1000\" : \"bootloader/bootloader.bin\",      \"0x10000\" : \"recovery.bin\",      \"0x150000\" : \"squeezelite.bin\"  },  \"partition_table\" : { \"offset\" : \"0x8000\", \"file\" : \"partition_table/partition-table.bin\" },  \"otadata\" : { \"offset\" : \"0xd000\", \"file\" : \"ota_data_initial.bin\" },  \"bootloader\" : { \"offset\" : \"0x1000\", \"file\" : \"bootloader/bootloader.bin\" },  \"app\" : { \"offset\" : \"0x10000\", \"file\" : \"recovery.bin\" },  \"squeezelite\" : { \"offset\" : \"0x150000\", \"file\" : \"squeezelite.bin\" },  \"extra_esptool_args\" : {      \"after\"  : \"hard_reset\",      \"before\" : \"default_reset\"  }  }  > ./flasher_args.json
    - name: Create Release Artifact Zip 
      if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
      run: |
        if [ -z "${artifact_file_name}" ]
        then
            echo "No artifact file name set.  Will not generate zip file."
        else
            echo "Generating build artifact zip file"
            zip -r build_output.zip build
            zip build/${artifact_file_name} partitions*.csv components/ build/*.bin build/bootloader/bootloader.bin build/partition_table/partition-table.bin build/flash_project_args build/size_*.txt
        fi
    - name: Upload Build Artifacts
      uses: actions/upload-artifact@v3
      if: ${{ needs.bootstrap.outputs.mock == 0 }}
      with:
        name: ${{ env.artifact_prefix }}
        path: |
          build/flash_project_args 
          build/size_comp1.txt
          build/size_comp2.txt
          partitions.csv
          sdkconfig
          server_certs/github.pem
          build/*.bin 
          build/bootloader/bootloader.bin 
          build/partition_table/partition-table.bin
          build_output.zip
    - name: Create Release
      if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
      id: create_release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
      with:
        tag_name: ${{ env.tag }}
        release_name: ${{ env.name }}
        body: ${{ env.description }}
        draft: false
        prerelease: false
    - name: Upload Release Asset - Squeezelite binary file
      if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
      id: upload-release-asset 
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 
        asset_path: build/squeezelite.bin
        asset_name: ${{ env.artifact_bin_file_name }}
        asset_content_type: application/octet-stream        
    - name: Upload Release Asset - Zip file
      if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
      id: upload-release-asset-zip
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 
        asset_path: build/${{ env.artifact_file_name }}
        asset_name: ${{ env.artifact_file_name }}
        asset_content_type: application/octet-stream     
  update_web_installer:
    name: Update Web Installer After Release
    needs: [ bootstrap, build ]
    if: ${{ always() && !cancelled() && needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
    uses: ./.github/workflows/web_deploy.yml
    secrets:
      WEB_INSTALLER: ${{ secrets.WEB_INSTALLER }}
