Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Enhance the CI Workflow to skip the Unmodified Architectures #13775

Closed
1 task done
lupyuen opened this issue Oct 1, 2024 · 4 comments · Fixed by #13800, #13858, #13862, apache/nuttx-apps#2649 or apache/nuttx-apps#2653
Closed
1 task done

Comments

@lupyuen
Copy link
Member

lupyuen commented Oct 1, 2024

Is your feature request related to a problem? Please describe.

  • NuttX Devs need to wait (2 hours) for the CI Build to complete across all Architectures (Arm32, Arm64, RISC-V, Xtensa), even though they're modifying a Single Architecture
  • We're using too many GitHub Runners and Build Minutes, exceeding the ASF Policy for GitHub Actions
  • Our usage of GitHub Runners is going up ($12K per month), we need to stay within the ASF Budget for GitHub Runners ($8.2K per month)
  • What if CI could build only the Modified Architecture?
  • Right now most of our CI Builds are taking 2 hours 15 mins. Can we complete the build within 1 hour, when we Create / Modify a Simple PR?

Describe the solution you'd like

  • We propose a Partial Solution, based on the Arch and Board Labels (recently added to CI)
  • We target only the Simple PRs: One Arch Label + One Board Label + One Size Label, like "Arch: risc-v, Board: risc-v, Size: XS"
  • If "Arch: arm" is the only non-size label, then we build only arm-01, arm-02, ...
  • Same for "Board: arm"
  • If Arch and Board Labels are both present: They must be the same
  • Similar rules for RISC-V, Simulator, x86_64 and Xtensa
  • Simple PR + Docs is still considered a Simple PR (so devs won't be penalised for adding docs)

Fetch the Arch Labels

This is how we fetch the Arch Labels, and identify as Arm, Arm64, RISC-V, Xtensa:

https://github.com/apache/nuttx/blob/master/.github/workflows/arch.yml#L32-L104

      # Get the Arch for the PR: arm, arm64, risc-v, xtensa, ...
      - name: Get arch
        id: get-arch
        run: |        

          # If PR is Not Created or Modified: Build all targets
          pr=${{github.event.pull_request.number}}
          if [[ "$pr" == "" ]]; then
            echo "Not a Created or Modified PR, will build all targets"
            exit
          fi

          # Ignore the Label "Area: Documentation", because it won't affect the Build Targets
          query='.labels | map(select(.name != "Area: Documentation")) | '
          select_name='.[].name'
          select_length='length'

          # Get the Labels for the PR: "Arch: risc-v \n Board: risc-v \n Size: XS"
          # If GitHub CLI Fails: Build all targets
          labels=$(gh pr view $pr --repo $GITHUB_REPOSITORY --json labels --jq $query$select_name || echo "")
          numlabels=$(gh pr view $pr --repo $GITHUB_REPOSITORY --json labels --jq $query$select_length || echo "")
          echo "numlabels=$numlabels" | tee -a $GITHUB_OUTPUT

          # Identify the Size, Arch and Board Labels
          if [[ "$labels" == *"Size: "* ]]; then
            echo 'labels_contain_size=1' | tee -a $GITHUB_OUTPUT
          fi
          if [[ "$labels" == *"Arch: "* ]]; then
            echo 'labels_contain_arch=1' | tee -a $GITHUB_OUTPUT
          fi
          if [[ "$labels" == *"Board: "* ]]; then
            echo 'labels_contain_board=1' | tee -a $GITHUB_OUTPUT
          fi

          # Get the Arch Label
          if [[ "$labels" == *"Arch: arm64"* ]]; then
            echo 'arch_contains_arm64=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Arch: arm"* ]]; then
            echo 'arch_contains_arm=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Arch: risc-v"* ]]; then
            echo 'arch_contains_riscv=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Arch: simulator"* ]]; then
            echo 'arch_contains_sim=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Arch: x86_64"* ]]; then
            echo 'arch_contains_x86_64=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Arch: xtensa"* ]]; then
            echo 'arch_contains_xtensa=1' | tee -a $GITHUB_OUTPUT
          fi

          # Get the Board Label
          if [[ "$labels" == *"Board: arm64"* ]]; then
            echo 'board_contains_arm64=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Board: arm"* ]]; then
            echo 'board_contains_arm=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Board: risc-v"* ]]; then
            echo 'board_contains_riscv=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Board: simulator"* ]]; then
            echo 'board_contains_sim=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Board: x86_64"* ]]; then
            echo 'board_contains_x86_64=1' | tee -a $GITHUB_OUTPUT
          elif [[ "$labels" == *"Board: xtensa"* ]]; then
            echo 'board_contains_xtensa=1' | tee -a $GITHUB_OUTPUT
          fi

        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Why || echo ""? That's because if the GitHub CLI gh fails for any reason, we will build all targets. This ensures that our CI Workflow won't get disrupted due to errors in GitHub CLI.

Handle Only Simple PRs

We handle only Simple PRs: One Arch Label + One Board Label + One Size Label, like "Arch: risc-v, Board: risc-v, Size: XS". If it's not a Simple PR: We build everything.

https://github.com/apache/nuttx/blob/master/.github/workflows/arch.yml#L127-L169

          # inputs.boards is a JSON Array: ["arm-01", "risc-v-01", "xtensa-01", ...]
          # We compact and remove the newlines
          boards=$( echo '${{ inputs.boards }}' | jq --compact-output ".")
          numboards=$( echo "$boards" | jq "length" )

          # We consider only Simple PRs with:
          # Arch + Size Labels Only
          # Board + Size Labels Only
          # Arch + Board + Size Labels Only
          if [[ "$labels_contain_size" != "1" ]]; then
            echo "Size Label Missing, will build all targets"
            quit=1
          elif [[ "$numlabels" == "2" && "$labels_contain_arch" == "1" ]]; then
            echo "Arch + Size Labels Only"
          elif [[ "$numlabels" == "2" && "$labels_contain_board" == "1" ]]; then
            echo "Board + Size Labels Only"
          elif [[ "$numlabels" == "3" && "$labels_contain_arch" == "1"  && "$labels_contain_board" == "1" ]]; then
            # Arch and Board must be the same
            if [[
              "$arch_contains_arm" != "$board_contains_arm" ||
              "$arch_contains_arm64" != "$board_contains_arm64" ||
              "$arch_contains_riscv" != "$board_contains_riscv" ||
              "$arch_contains_sim" != "$board_contains_sim" ||
              "$arch_contains_x86_64" != "$board_contains_x86_64" ||
              "$arch_contains_xtensa" != "$board_contains_xtensa"
            ]]; then
              echo "Arch and Board are not the same, will build all targets"
              quit=1
            else
              echo "Arch + Board + Size Labels Only"
            fi
          else
            echo "Not a Simple PR, will build all targets"
            quit=1
          fi

          # If Not a Simple PR: Build all targets
          if [[ "$quit" == "1" ]]; then
            echo "selected_builds=$boards" | tee -a $GITHUB_OUTPUT
            exit
          fi

For Arm Arch: Identify the Non-Arm Builds

Suppose the PR says "Arch: arm" or "Board: arm". We filter out the builds that should be skipped (RISC-V, Xtensa, etc):

https://github.com/apache/nuttx/blob/master/.github/workflows/arch.yml#L169-L234

          # For every board
          for (( i=0; i<numboards; i++ ))
          do
            # Fetch the board
            board=$( echo "$boards" | jq ".[$i]" )
            skip_build=0
            
            # For "Arch / Board: arm": Build arm-01, arm-02, ...
            if [[ "$arch_contains_arm" == "1" || "$board_contains_arm" == "1" ]]; then
              if [[ "$board" != *"arm"* ]]; then
                skip_build=1
              fi
            # Omitted: Arm64, RISC-V, Simulator x86_64, Xtensa
            ...
            # For Other Arch: Allow the build
            else
              echo Build by default: $board
            fi
  
            # Add the board to the selected builds
            if [[ "$skip_build" == "0" ]]; then
              echo Add $board to selected_builds
              if [[ "$selected_builds" == "" ]]; then
                selected_builds=$board
              else
                selected_builds=$selected_builds,$board
              fi
            fi
          done

          # Return the selected builds as JSON Array
          # If Selected Builds is empty: Skip all builds
          echo "selected_builds=[$selected_builds]" | tee -a $GITHUB_OUTPUT
          if [[ "$selected_builds" == "" ]]; then
            echo "skip_all_builds=1" | tee -a $GITHUB_OUTPUT
          fi

Skip The Non-Arm Builds

Earlier we saw the code in arch.yml (Reusable Workflow) that identifies the builds to be skipped. The code above is called by build.yml (Build Workflow) which will actually skip the builds:

https://github.com/apache/nuttx/blob/master/.github/workflows/build.yml#L119-L148

  # Select the Linux Builds based on PR Arch Label
  Linux-Arch:
    uses: apache/nuttx/.github/workflows/arch.yml@master
    needs: Fetch-Source
    with:
      os: Linux
      boards: |
        [
          "arm-01", "other", "risc-v-01", "sim-01", "xtensa-01",
          "arm-02", "risc-v-02", "sim-02", "xtensa-02",
          "arm-03", "arm-04", "arm-05", "arm-06", "arm-07", "arm-08", "arm-09", "arm-10", "arm-11", "arm-12", "arm-13"
        ]

  # Run the selected Linux Builds
  Linux:
    needs: Linux-Arch
    if: ${{ needs.Linux-Arch.outputs.skip_all_builds != '1' }}
    runs-on: ubuntu-latest
    env:
      DOCKER_BUILDKIT: 1

    strategy:
      max-parallel: 12
      matrix:
        boards: ${{ fromJSON(needs.Linux-Arch.outputs.selected_builds) }}

    steps:
      ## Omitted: Run cibuild.sh on Linux

Why needs: Fetch-Source? That's because the PR Labeler runs concurrently in the background. When we add Fetch-Source as a Job Dependency, we give the PR Labeler sufficient time to run (1 min), before we read the PR Label in arch.yml.

Same for RISC-V, Simulator, x86_64 and Xtensa Builds

We do the same for RISC-V, Simulator, x86_64 and Xtensa:

https://github.com/apache/nuttx/blob/master/.github/workflows/arch.yml#L105-L129

            # For "Arch / Board: arm64": Build other
            elif [[ "$arch_contains_arm64" == "1" || "$board_contains_arm64" == "1" ]]; then
              if [[ "$board" != *"other"* ]]; then
                skip_build=1
              fi

            # For "Arch / Board: risc-v": Build risc-v-01, risc-v-02
            elif [[ "$arch_contains_riscv" == "1" || "$board_contains_riscv" == "1" ]]; then
              if [[ "$board" != *"risc-v"* ]]; then
                skip_build=1
              fi
  
            # For "Arch / Board: simulator": Build sim-01, sim-02
            elif [[ "$arch_contains_sim" == "1" || "$board_contains_sim" == "1" ]]; then
              if [[ "$board" != *"sim"* ]]; then
                skip_build=1
              fi

            # For "Arch / Board: x86_64": Build other
            elif [[ "$arch_contains_x86_64" == "1" || "$board_contains_x86_64" == "1" ]]; then
              if [[ "$board" != *"other"* ]]; then
                skip_build=1
              fi
  
            # For "Arch / Board: xtensa": Build xtensa-01, xtensa-02
            elif [[ "$arch_contains_xtensa" == "1" || "$board_contains_xtensa" == "1" ]]; then
              if [[ "$board" != *"xtensa"* ]]; then
                skip_build=1
              fi

Skip the macOS and Windows Builds

For these Simple PRs (One Arch Label + One Size Label), we skip the macOS and Windows builds (macos, macos/sim-*, msys2) since these builds are costly:

(macos and macos/sim-* builds will take 2 hours to complete due to the queueing for macOS Runners)

https://github.com/apache/nuttx/blob/master/.github/workflows/build.yml#L194-L281

  # Select the macOS Builds based on PR Arch Label
  macOS-Arch:
    uses: apache/nuttx/.github/workflows/arch.yml@master
    needs: Fetch-Source
    with:
      os: Linux
      boards: |
        ["macos", "sim-01", "sim-02"]

  # Run the selected macOS Builds
  macOS:
    permissions:
      contents: none
    runs-on: macos-13
    needs: macOS-Arch
    if: ${{ needs.macOS-Arch.outputs.skip_all_builds != '1' }}
    strategy:
      max-parallel: 2
      matrix:
        boards: ${{ fromJSON(needs.macOS-Arch.outputs.selected_builds) }}
    steps:
      ## Omitted: Run cibuild.sh on macOS
      ...
  # Select the msys2 Builds based on PR Arch Label
  msys2-Arch:
    uses: apache/nuttx/.github/workflows/arch.yml@master
    needs: Fetch-Source
    with:
      os: Linux
      boards: |
        ["msys2"]

  # Run the selected msys2 Builds
  msys2:
    needs: msys2-Arch
    if: ${{ needs.msys2-Arch.outputs.skip_all_builds != '1' }}
    runs-on: windows-latest
    strategy:
      fail-fast: false
      max-parallel: 1
      matrix:
        boards: ${{ fromJSON(needs.msys2-Arch.outputs.selected_builds) }}

    defaults:
      run:
        shell: msys2 {0}
    steps:
      ## Omitted: Run cibuild.sh on msys2

skip_all_builds will be set to 1 for Simple PRs on macOS and msys2.

(Except for "Arch: Simulator", which will enable the macOS Builds for sim-01 and sim-02)

Ignore the Documentation

NuttX Devs shouldn't be penalised for adding docs! That's why we ignore the label "Area: Documentation", so that Simple PR + Docs is still a Simple PR (which will skip the unnecessary builds).

https://github.com/apache/nuttx/blob/master/.github/workflows/arch.yml#L44-L55

          # Ignore the Label "Area: Documentation", because it won't affect the Build Targets
          query='.labels | map(select(.name != "Area: Documentation")) | '
          select_name='.[].name'
          select_length='length'

          # Get the Labels for the PR: "Arch: risc-v \n Board: risc-v \n Size: XS"
          # If GitHub CLI Fails: Build all targets
          labels=$(gh pr view $pr --repo $GITHUB_REPOSITORY --json labels --jq $query$select_name || echo "")
          numlabels=$(gh pr view $pr --repo $GITHUB_REPOSITORY --json labels --jq $query$select_length || echo "")
          echo "numlabels=$numlabels" | tee -a $GITHUB_OUTPUT

Sync the CI Workflow from nuttx repo to nuttx-apps

Remember to sync build.yml and arch.yml from nuttx repo to nuttx-apps! apache/nuttx-apps#2676

build.yml refers to arch.yml (for the build rules). So when we sync build.yml from nuttx to nuttx-apps, we won't need to remove the references to arch.yml.

We could make nuttx-apps/build.yml point to the nuttx/arch.yml. But that would make the CI fragile: Changes to nuttx/arch.yml might cause nuttx-apps/build.yml to break.

Yep arch.yml is totally not needed in nuttx-apps. I have difficulty keeping nuttx/build.yml and nuttx-apps/build.yml in sync, that's why I simply copied over arch.yml as-is. In future we could extend arch.yml with Build Rules that are specific to nuttx-apps?

If we decide to remove nuttx-apps/arch.yml: This means that we need to rewrite the build.yml logic from this:

  # Select the Linux Builds based on PR Arch Label
  Linux-Arch:
    uses: apache/nuttx-apps/.github/workflows/arch.yml@master
    needs: Fetch-Source
    with:
      boards: |
        [
          "arm-01", "other", "risc-v-01", "sim-01", "xtensa-01", ...
        ]

  # Run the selected Linux Builds
  Linux:
    needs: Linux-Arch
    if: ${{ needs.Linux-Arch.outputs.skip_all_builds != '1' }}
    strategy:
      matrix:
        boards: ${{ fromJSON(needs.Linux-Arch.outputs.selected_builds) }}

Back to this:

  Linux:
    needs: Fetch-Source
    strategy:
      matrix:
        boards: [arm-01, arm-02, arm-03, arm-04, arm-05, arm-06, arm-07, arm-08, arm-09, arm-10, arm-11, arm-12, arm-13, other, risc-v-01, risc-v-02, sim-01, sim-02, xtensa-01, xtensa-02]

Testing

(Note: The timings here are obsolete)

When we test our updated CI Workflow, we see that the irrelevant builds are skipped in seconds. Click "Show All Jobs" to reveal the timings:

Actual Performance

We recorded the CI Build Performance based on Real-World PRs:

  • For Arm32: Simple PRs will build in 2 hours (previously also 2 hours)

  • For Arm64: Simple PRs will build in 49 mins (previously 2 hours 11 mins)

  • For RISC-V: Simple PRs will build in 1 hour 45 mins (previously also 1 hour 45 mins)

  • For Xtensa: Simple PRs will build in 1 hour 17 mins (previously 2 hours 11 mins)

  • For x86_64: Simple PRs will build in 48 mins (previously 2 hours 13 mins)

  • For Simulator: Simple PRs will build in 1 hour 32 mins (previously 2 hours 12 mins)

  • OK no big wow yet. We need to break arm-05, riscv-01 and riscv-02 into multiple smaller jobs. Then things will really zoom! (See the Build Job Details)

    Move the RP2040 jobs from arm-05 to arm-06, then add arm-14. Add jobs riscv-03 to riscv-06.

    (Update: All Done! Check the PRs below)

  • We already see a 27% Reduction in GitHub Runner Hours! From 15 Runner Hours down to 11 Runner Hours per Arm32 Build.

  • Split the Board Labels according to Arch, like "Board: arm". So "Board: arm" should build the exact same way as "Arch: arm". Same for "Board: arm, Arch: arm". Update the Build Rules to use the Board Labels

    (Update: All Done! Check the PRs below)

  • Split the others job into arm64 and x86_64

    (Update: All Done! Check the PRs below)

TODO: Reorg and rename the CI Build Jobs, for better performance and easier maintenance. But how?

  • I have a hunch that CI works better when we pack the jobs into One-Hour Time Slices
  • Kinda like packing yummy goodies into Bento Boxes, making sure they don't overflow the Time Boxes :-)
  • We should probably shift the Riskiest / Most Failure Prone builds into the First Build Job. So we can Fail Faster (in case of problems), and skip the rest of the jobs
  • Recently we see many builds for Arm32 Goldfish. Can we limit the builds to the Goldfish Boards only? To identify Goldfish PRs, we can label the PRs like this: "Arch: arm, SubArch: goldfish" and/or "Board: arm, SubBoard: goldfish"
  • How will we filter out the Build Jobs (e.g. arm-01) that should be built for a SubBoard (e.g. stm32)? Maybe like this

Hi @raiden00pl and @simbit18: Do you think this will work? And keep Our Devs and ASF happy? Thanks!

Describe alternatives you've considered

No response

Verification

  • I have verified before submitting the report.
@simbit18
Copy link
Contributor

simbit18 commented Oct 2, 2024

Hi @lupyuen
Nice system to skip jobs!!!! :)

I think that a further margin of reduction of the generalized time of the jobs is possible with these simple solutions:

@lupyuen
Copy link
Member Author

lupyuen commented Oct 2, 2024

Thanks @simbit18! Your suggestions are excellent, I think we can implement them carefully after we have rolled out the solution above. I still have lots to learn about the Storage Folder and CMake :-)

lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 2, 2024
This PR proposes to enhance the CI Workflow, to skip the unnecessary NuttX Builds. Currently, NuttX Devs wait for the CI Builds to complete across All Architectures (Arm32, Arm64, RISC-V, Xtensa), even though they modified a Single Architecture. With this PR, the CI Workflow will build only the Modified Architecture.

The solution uses the Arch Labels for PRs. We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- If "Arch: arm / arm64" is the only non-size label, then we build `other`, `arm-01`, `arm-02`, ...
- If "Arch: risc-v" is the only non-size label, then build `risc-v-01`, `risc-v-02`
- If "Arch: xtensa" is the only non-size label, then build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

The code is explained here: apache#13775
@lupyuen lupyuen closed this as completed Oct 3, 2024
xiaoxiang781216 pushed a commit that referenced this issue Oct 3, 2024
This PR proposes to enhance the CI Workflow, to skip the unnecessary NuttX Builds. Currently, NuttX Devs wait for the CI Builds to complete across All Architectures (Arm32, Arm64, RISC-V, Xtensa), even though they modified a Single Architecture. With this PR, the CI Workflow will build only the Modified Architecture.

The solution uses the Arch Labels for PRs. We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- If "Arch: arm / arm64" is the only non-size label, then we build `other`, `arm-01`, `arm-02`, ...
- If "Arch: risc-v" is the only non-size label, then build `risc-v-01`, `risc-v-02`
- If "Arch: xtensa" is the only non-size label, then build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

The code is explained here: #13775
@raiden00pl
Copy link
Contributor

Great ! That's what I had in mind when creating new labels.
The only problem I see is that I don't quite understand how github chooses the order of workflows in a parallel build. This approach will only work if the labeler is called before the build. Is this always ensured ?

TODO: Should we have Board Labels by Arch also?

I think so. Another approach is to add "Platform" label which detect more precisely the arch used (like "Platform: STM32"), but then the problem of having too many labels may occur. Or we can add "Platform" labels for some of the most popular chips that are most frequently modified or they use CI the most.

@lupyuen
Copy link
Member Author

lupyuen commented Oct 3, 2024

The only problem I see is that I don't quite understand how github chooses the order of workflows in a parallel build. This approach will only work if the labeler is called before the build. Is this always ensured ?

Thanks @raiden00pl! Yep I wonder about the order of workflows. If we look at a Typical CI Run:

Screenshot 2024-10-03 at 2 50 43 PM

  • First thing that runs is build.yml > Fetch-Source, which will take 1 minute
  • Then labeler.yml > Labeler starts concurrently to set the Labels
  • Up next is build.yml > Linux (arm-01). Which will start after Fetch-Source and read the Labels
  • So we are OK (I think) as long as Labeler doesn't exceed 1 minute

We see some improvements: Arm32 builds now complete in 2 hours (instead of 2 hours 15 mins). And we save on runners for RISC-V, Xtensa, Sim.

What's Next:

  • I'll extend build.yml to handle Arch: simulator (as requested by Xiao Xiang) and Arch: x86_64 (because it appears often)
  • Skip macos, macos/sim-*, msys2 for Simple PRs (1 Arch Label + 1 Size Label)
  • Which will require the Get Arch logic to be refactored into a Reusable Workflow
  • Hopefully we can then complete the CI Build within 1 hour! (And make ASF happy)

Update: All Done! Check the PRs below

lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 6, 2024
This PR continues to enhance the CI Workflow, to skip the unnecessary NuttX Builds. The changes in this PR will not take effect until the next PR, which will switch `build.yml` to use the rules in this PR.

In this PR, we refactor the CI Build Rules into a separate Reusable Workflow `arch.yml`. The original rules were migrated to `arch.yml`:
- We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- For "Arch: arm / arm64": Build `other`, `arm-01`, `arm-02`, ...
- For "Arch: risc-v": Build `risc-v-01`, `risc-v-02`
- For "Arch: xtensa": Build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

New and Updated Rules:
- For "Arch: simulator": Build `sim-01`, `sim-02`
- For "Arch: x86_64": Build `other`
- For Simple PRs (One Arch Label + One Size Label): Skip the macOS and Windows builds (`macos`, `macos/sim-*`, `msys2`) since these builds are costly
- Except for "Arch: Simulator", which will enable the macOS Builds for `sim-01` and `sim-02`

The code is explained here: apache#13775
@xiaoxiang781216 xiaoxiang781216 linked a pull request Oct 7, 2024 that will close this issue
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 7, 2024
This PR continues to enhance the CI Workflow, to skip the unnecessary NuttX Builds. The changes in this PR will not take effect until the next PR, which will switch `build.yml` to use the rules in this PR.

In this PR, we refactor the CI Build Rules into a separate Reusable Workflow `arch.yml`. The original rules were migrated to `arch.yml`:
- We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- For "Arch: risc-v": Build `risc-v-01`, `risc-v-02`
- For "Arch: xtensa": Build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

New and Updated Rules:
- For "Arch: arm": Build `arm-01`, `arm-02`, ...
- For "Arch: arm64": Build `other`
- For "Arch: simulator": Build `sim-01`, `sim-02`
- For "Arch: x86_64": Build `other`
- For Simple PRs (One Arch Label + One Size Label): Skip the macOS and Windows builds (`macos`, `macos/sim-*`, `msys2`) since these builds are costly and slow
- Except for "Arch: Simulator", which will enable the macOS Builds for `sim-01` and `sim-02`
- If GitHub CLI Fails: Build all targets

The code is explained here: apache#13775
xiaoxiang781216 pushed a commit that referenced this issue Oct 7, 2024
This PR continues to enhance the CI Workflow, to skip the unnecessary NuttX Builds. The changes in this PR will not take effect until the next PR, which will switch `build.yml` to use the rules in this PR.

In this PR, we refactor the CI Build Rules into a separate Reusable Workflow `arch.yml`. The original rules were migrated to `arch.yml`:
- We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- For "Arch: risc-v": Build `risc-v-01`, `risc-v-02`
- For "Arch: xtensa": Build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

New and Updated Rules:
- For "Arch: arm": Build `arm-01`, `arm-02`, ...
- For "Arch: arm64": Build `other`
- For "Arch: simulator": Build `sim-01`, `sim-02`
- For "Arch: x86_64": Build `other`
- For Simple PRs (One Arch Label + One Size Label): Skip the macOS and Windows builds (`macos`, `macos/sim-*`, `msys2`) since these builds are costly and slow
- Except for "Arch: Simulator", which will enable the macOS Builds for `sim-01` and `sim-02`
- If GitHub CLI Fails: Build all targets

The code is explained here: #13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 7, 2024
This PR continues to enhance the CI Workflow, to skip the unnecessary NuttX Builds. The PR will update the CI Build Workflow `build.yml`, to call the Refactored Build Rules in `arch.yml` (which is a Reusable Workflow).

The original rules were migrated from `build.yml` to `arch.yml`:
- We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- For "Arch: risc-v": Build `risc-v-01`, `risc-v-02`
- For "Arch: xtensa": Build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

This PR applies the New and Updated Rules defined in `arch.yml`:
- For "Arch: arm": Build `arm-01`, `arm-02`, ...
- For "Arch: arm64": Build `other`
- For "Arch: simulator": Build `sim-01`, `sim-02`
- For "Arch: x86_64": Build `other`
- For Simple PRs (One Arch Label + One Size Label): Skip the macOS and Windows builds (`macos`, `macos/sim-*`, `msys2`) since these builds are costly and slow
- Except for "Arch: Simulator", which will enable the macOS Builds for `sim-01` and `sim-02`
- If GitHub CLI Fails: Build all targets

The code is explained here: apache#13775
xiaoxiang781216 pushed a commit that referenced this issue Oct 7, 2024
This PR continues to enhance the CI Workflow, to skip the unnecessary NuttX Builds. The PR will update the CI Build Workflow `build.yml`, to call the Refactored Build Rules in `arch.yml` (which is a Reusable Workflow).

The original rules were migrated from `build.yml` to `arch.yml`:
- We target only the Simple PRs: One Arch Label + One Size Label (e.g. "Arch: risc-v, Size: XS")
- For "Arch: risc-v": Build `risc-v-01`, `risc-v-02`
- For "Arch: xtensa": Build `xtensa-01`, `xtensa-02`
- The above rules apply when the PR is Created or Modified
- When the PR is Merged: All targets shall be built

This PR applies the New and Updated Rules defined in `arch.yml`:
- For "Arch: arm": Build `arm-01`, `arm-02`, ...
- For "Arch: arm64": Build `other`
- For "Arch: simulator": Build `sim-01`, `sim-02`
- For "Arch: x86_64": Build `other`
- For Simple PRs (One Arch Label + One Size Label): Skip the macOS and Windows builds (`macos`, `macos/sim-*`, `msys2`) since these builds are costly and slow
- Except for "Arch: Simulator", which will enable the macOS Builds for `sim-01` and `sim-02`
- If GitHub CLI Fails: Build all targets

The code is explained here: #13775
@lupyuen lupyuen linked a pull request Oct 8, 2024 that will close this issue
@lupyuen lupyuen linked a pull request Oct 8, 2024 that will close this issue
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 9, 2024
CI Build Job `arm-05` (runtime 2 hours) has become the Performance Bottleneck for CI Workflow. That's because `arm-05` builds too many targets for nRF, RP2040, SAM 3, SAM A and SAM D. This PR splits `arm-05` into multiple smaller jobs, to reduce the CI Build Duration.

Before the PR: `arm-05` is overloaded, build requires 2 hours
- `arm-05` (2 hours): nRF, RP2040, SAM 3, SAM A, SAM D
- `arm-06` (56 mins): STM32 [a-m]*

After the PR: `arm-05` is offloaded (to `arm-06` and `arm-07`), completes within 1 hour
- `arm-05` (47 mins): nRF
- `arm-06` (1 hour): Reserve for RP2040 exclusively
- `arm-07` (1 hour 15 mins): SAM 3, SAM A, SAM D, STM32 [a-m]*

Build Jobs are sorted by Target Name. So we cascade the changes and rename the Build Jobs: `arm-07` becomes `arm-08`, `arm-08` becomes `arm-09` etc. Then `arm-13` becomes a new job `arm-14`. (Which we added to `build.yml`)

Performance of `arm-05` is discussed in apache#13775 and apache#12773
@lupyuen lupyuen linked a pull request Oct 9, 2024 that will close this issue
xiaoxiang781216 pushed a commit that referenced this issue Oct 9, 2024
CI Build Job `arm-05` (runtime 2 hours) has become the Performance Bottleneck for CI Workflow. That's because `arm-05` builds too many targets for nRF, RP2040, SAM 3, SAM A and SAM D. This PR splits `arm-05` into multiple smaller jobs, to reduce the CI Build Duration.

Before the PR: `arm-05` is overloaded, build requires 2 hours
- `arm-05` (2 hours): nRF, RP2040, SAM 3, SAM A, SAM D
- `arm-06` (56 mins): STM32 [a-m]*

After the PR: `arm-05` is offloaded (to `arm-06` and `arm-07`), completes within 1 hour
- `arm-05` (47 mins): nRF
- `arm-06` (1 hour): Reserve for RP2040 exclusively
- `arm-07` (1 hour 15 mins): SAM 3, SAM A, SAM D, STM32 [a-m]*

Build Jobs are sorted by Target Name. So we cascade the changes and rename the Build Jobs: `arm-07` becomes `arm-08`, `arm-08` becomes `arm-09` etc. Then `arm-13` becomes a new job `arm-14`. (Which we added to `build.yml`)

Performance of `arm-05` is discussed in #13775 and #12773
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 9, 2024
This PR changes the Labeling of PRs so that the Architecture (arm, risc-v, xtensa, ...) is specified in the Board Label. Previously the CI Workflow would set Generic Board Labels like "Area: Board support". Now it will set the Arch-Specific Board Label like "Board: arm".

The Board Label will be used by the upcoming CI Build Rules to skip unnecessary builds. So "Board: arm" will enable only the builds for `arm-01` to `arm-14`. This is explained here: apache#13775
@lupyuen lupyuen linked a pull request Oct 9, 2024 that will close this issue
xiaoxiang781216 pushed a commit that referenced this issue Oct 9, 2024
This PR changes the Labeling of PRs so that the Architecture (arm, risc-v, xtensa, ...) is specified in the Board Label. Previously the CI Workflow would set Generic Board Labels like "Area: Board support". Now it will set the Arch-Specific Board Label like "Board: arm".

The Board Label will be used by the upcoming CI Build Rules to skip unnecessary builds. So "Board: arm" will enable only the builds for `arm-01` to `arm-14`. This is explained here: #13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 9, 2024
To speed up the CI Workflow, this PR splits the CI Build Jobs for RISC-V into smaller jobs. Each job will now complete within 1 hour.

Before the PR: There are 2 jobs for RISC-V, each requiring more than 1.5 hours
- `risc-v-01` (1 hour 42 mins): BL602, Ox64, ESP32-C3 / C6 / H2
- `risc-v-02` (1 hour 41 mins): K230, Icicle, QEMU, RV32M1-Vega

After the PR: The build is spread across 6 jobs for RISC-V, each job completes within 1 hour
- `risc-v-01` (19 mins): BL602, Ox64
- `risc-v-02` (44 mins): ESP32-C3
- `risc-v-03` (45 mins): ESP32-C6, ESP32-H2
- `risc-v-04` (31 mins): K230, Icicle
- `risc-v-05` (41 mins): QEMU CITest
- `risc-v-06` (38 mins): Rest of QEMU, RV32M1-Vega

Following the same convention as the Arm32 Build Jobs, the above jobs are sorted by Target Name. Performance of the RISC-V Build Jobs is discussed in apache#13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 9, 2024
To speed up the CI Workflow, this PR splits the CI Build Jobs for RISC-V into smaller jobs. Each job will now complete within 1 hour.

Before the PR: There are 2 jobs for RISC-V, each requiring more than 1.5 hours
- `risc-v-01` (1 hour 42 mins): BL602, Ox64, ESP32-C3 / C6 / H2
- `risc-v-02` (1 hour 41 mins): K230, Icicle, QEMU, RV32M1-Vega

After the PR: The build is spread across 6 jobs for RISC-V, each job completes within 1 hour
- `risc-v-01` (19 mins): BL602, Ox64
- `risc-v-02` (44 mins): ESP32-C3
- `risc-v-03` (45 mins): ESP32-C6, ESP32-H2
- `risc-v-04` (31 mins): K230, Icicle
- `risc-v-05` (41 mins): QEMU CITest
- `risc-v-06` (38 mins): Rest of QEMU, RV32M1-Vega

Following the same convention as the Arm32 Build Jobs, the above jobs are sorted by Target Name. Performance of the RISC-V Build Jobs is discussed in apache#13775
@lupyuen lupyuen linked a pull request Oct 9, 2024 that will close this issue
xiaoxiang781216 pushed a commit that referenced this issue Oct 10, 2024
To speed up the CI Workflow, this PR splits the CI Build Jobs for RISC-V into smaller jobs. Each job will now complete within 1 hour.

Before the PR: There are 2 jobs for RISC-V, each requiring more than 1.5 hours
- `risc-v-01` (1 hour 42 mins): BL602, Ox64, ESP32-C3 / C6 / H2
- `risc-v-02` (1 hour 41 mins): K230, Icicle, QEMU, RV32M1-Vega

After the PR: The build is spread across 6 jobs for RISC-V, each job completes within 1 hour
- `risc-v-01` (19 mins): BL602, Ox64
- `risc-v-02` (44 mins): ESP32-C3
- `risc-v-03` (45 mins): ESP32-C6, ESP32-H2
- `risc-v-04` (31 mins): K230, Icicle
- `risc-v-05` (41 mins): QEMU CITest
- `risc-v-06` (38 mins): Rest of QEMU, RV32M1-Vega

Following the same convention as the Arm32 Build Jobs, the above jobs are sorted by Target Name. Performance of the RISC-V Build Jobs is discussed in #13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 10, 2024
This PR extends the CI Build Rules to eliminate more unnecessary builds. We use the Board Label for PRs:
- Previously: "Arch: arm" will build only `arm-01` to `arm-14`
- Now: "Board: arm" will also build `arm-01` to `arm-14`
- This applies only to Simple PRs: One Arch Label + One Board Label + One Size Label, like "Arch: arm, Board: arm, Size: L"
- If Arch Label and Board Label are both present: They must be the same. Otherwise All Targets shall be built.
- Works with Arm64, RISC-V, Simulator, x86_64 and Xtensa

The updated code is explained here: apache#13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 10, 2024
This PR extends the CI Build Rules to eliminate more unnecessary builds. We use the Board Label for PRs:
- Previously: "Arch: arm" will build only `arm-01` to `arm-14`
- Now: "Board: arm" will also build `arm-01` to `arm-14`
- This applies only to Simple PRs: One Arch Label + One Board Label + One Size Label, like "Arch: arm, Board: arm, Size: L"
- If Arch Label and Board Label are both present: They must be the same. Otherwise All Targets shall be built.
- Works with Arm32, Arm64, RISC-V, Simulator, x86_64 and Xtensa

The updated code is explained here: apache#13775
@lupyuen lupyuen linked a pull request Oct 10, 2024 that will close this issue
xiaoxiang781216 pushed a commit that referenced this issue Oct 10, 2024
This PR extends the CI Build Rules to eliminate more unnecessary builds. We use the Board Label for PRs:
- Previously: "Arch: arm" will build only `arm-01` to `arm-14`
- Now: "Board: arm" will also build `arm-01` to `arm-14`
- This applies only to Simple PRs: One Arch Label + One Board Label + One Size Label, like "Arch: arm, Board: arm, Size: L"
- If Arch Label and Board Label are both present: They must be the same. Otherwise All Targets shall be built.
- Works with Arm32, Arm64, RISC-V, Simulator, x86_64 and Xtensa

The updated code is explained here: #13775
@lupyuen lupyuen linked a pull request Oct 10, 2024 that will close this issue
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 15, 2024
This PR creates the new CI Build Jobs `arm64-01` and `x86_64-01`. The new jobs will split and offload the Arm64 and x86_64 Build Targets from `other`. This will reduce our usage of GitHub Runners, to comply with the ASF Policy for GitHub Actions. (Recently we see more PRs for Arm64 and x86_64)

Before the Split: Simple PRs (One Arch and/or One Board) for Arm64 and x86_64 require almost 1 hour for CI Build
- `other` (57 mins): AVR, SPARC, x86, PinePhone, QEMU Arm64, QEMU x86_64

After the Split: Simple PRs for Arm64 and x86_64 will complete under 30 mins
- `other` (24 mins): AVR, SPARC, x86
- `arm64-01` (29 mins): PinePhone, QEMU Arm64
- `x86_64-01` (9 mins): QEMU x86_64

To skip more unnecessary builds: Our Build Rules `arch.yml` shall ignore the label "Area: Documentation", so that a Simple PR + Docs is still a Simple PR. Previously we experienced longer CI Build Times, just because we added docs to our Simple PR. (Now our PR shall be built exactly like a Simple PR)

The updated CI code is explained here: apache#13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 15, 2024
This PR creates the new CI Build Jobs `arm64-01` and `x86_64-01`. The new jobs will split and offload the Arm64 and x86_64 Build Targets from `other`. This will reduce our usage of GitHub Runners, to comply with the ASF Policy for GitHub Actions. (Recently we see more PRs for Arm64 and x86_64)

Before the Split: Simple PRs (One Arch and/or One Board) for Arm64 and x86_64 require almost 1 hour for CI Build
- `other` (57 mins): AVR, SPARC, x86, PinePhone, QEMU Arm64, QEMU x86_64

After the Split: Simple PRs for Arm64 and x86_64 will complete under 30 mins
- `other` (24 mins): AVR, SPARC, x86
- `arm64-01` (29 mins): PinePhone, QEMU Arm64
- `x86_64-01` (9 mins): QEMU x86_64

To skip more unnecessary builds: Our Build Rules `arch.yml` shall ignore the label "Area: Documentation", so that a Simple PR + Docs is still a Simple PR. Previously we experienced longer CI Build Times, just because we added docs to our Simple PR. (Now our PR shall be built exactly like a Simple PR)

The updated CI code is explained here: apache#13775
lupyuen added a commit to lupyuen2/wip-nuttx that referenced this issue Oct 19, 2024
This PR creates the new CI Build Jobs `arm64-01` and `x86_64-01`. The new jobs will split and offload the Arm64 and x86_64 Build Targets from `other`. This will reduce our usage of GitHub Runners, to comply with the ASF Policy for GitHub Actions. (Recently we see more PRs for Arm64 and x86_64)

Before the Split: Simple PRs (One Arch and/or One Board) for Arm64 and x86_64 require almost 1 hour for CI Build
- `other` (57 mins): AVR, SPARC, x86, PinePhone, QEMU Arm64, QEMU x86_64

After the Split: Simple PRs for Arm64 and x86_64 will complete under 30 mins
- `other` (24 mins): AVR, SPARC, x86
- `arm64-01` (29 mins): PinePhone, QEMU Arm64
- `x86_64-01` (9 mins): QEMU x86_64

To skip more unnecessary builds: Our Build Rules `arch.yml` shall ignore the label "Area: Documentation", so that a Simple PR + Docs is still a Simple PR. Previously we experienced longer CI Build Times, just because we added docs to our Simple PR. (Now our PR shall be built exactly like a Simple PR)

The updated CI code is explained here: apache#13775
xiaoxiang781216 pushed a commit that referenced this issue Oct 20, 2024
This PR creates the new CI Build Jobs `arm64-01` and `x86_64-01`. The new jobs will split and offload the Arm64 and x86_64 Build Targets from `other`. This will reduce our usage of GitHub Runners, to comply with the ASF Policy for GitHub Actions. (Recently we see more PRs for Arm64 and x86_64)

Before the Split: Simple PRs (One Arch and/or One Board) for Arm64 and x86_64 require almost 1 hour for CI Build
- `other` (57 mins): AVR, SPARC, x86, PinePhone, QEMU Arm64, QEMU x86_64

After the Split: Simple PRs for Arm64 and x86_64 will complete under 30 mins
- `other` (24 mins): AVR, SPARC, x86
- `arm64-01` (29 mins): PinePhone, QEMU Arm64
- `x86_64-01` (9 mins): QEMU x86_64

To skip more unnecessary builds: Our Build Rules `arch.yml` shall ignore the label "Area: Documentation", so that a Simple PR + Docs is still a Simple PR. Previously we experienced longer CI Build Times, just because we added docs to our Simple PR. (Now our PR shall be built exactly like a Simple PR)

The updated CI code is explained here: #13775
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment