apache / nuttx

Apache NuttX is a mature, real-time embedded operating system (RTOS)
https://nuttx.apache.org/
Apache License 2.0
2.82k stars 1.17k forks source link

[HELP] Running github actions locally with act #14601

Open stbenn opened 3 days ago

stbenn commented 3 days ago

Description

I am looking for ways to better verify my work before doing a pull request, to prevent unsuccessful use of the runners. I came across act, which has an extension for the github cli that claims to run workflows locally.

Has anyone had tried or had success with this before? I have it recognizing the workflows but am having failures from access tokens, password requirements, etc.

Trying to run it on Ubuntu-24.04 in WSL2

Verification

xiaoxiang781216 commented 3 days ago

@lupyuen is our ci guru, could you answer this problem?

lupyuen commented 3 days ago

@stbenn Thank you so much for asking! Yep it's super important to test our PRs before submitting. But our CI Workflow is going through plenty of changes (due to cost cutting), lemme know if anything below isn't quite correct thanks :-)

GitHub ACT is probably too complicated? I recommend 2 ways of testing our PRs:

  1. Run the CI Builds with Docker
  2. Or run the CI Builds with GitHub Actions

(1) might be slower, depending on your PC. With (2) we don't need to worry about Wasting GitHub Runners, so long as the CI Workflow runs entirely in your repo, before submitting to NuttX Repo. (I'll explain)

Option 1: Run the CI Builds with Docker

Suppose our PR is at github.com/USER/nuttx/tree/BRANCH. This is how we compile it with Docker:

## Build a NuttX Target Group with Docker
## Parameter is the Target Group, like "arm-01"
job=arm-01

## TODO: Install Docker Engine
## https://docs.docker.com/engine/install/ubuntu/

## TODO: For WSL, we may need to install Docker on Native Windows
## https://github.com/apache/nuttx/issues/14601#issuecomment-2453595402

## Download the Docker Image for NuttX
sudo docker pull \
  ghcr.io/apache/nuttx/apache-nuttx-ci-linux:latest

## Inside the Docker Container:
## Build the Target Group 
sudo docker run -it \
  ghcr.io/apache/nuttx/apache-nuttx-ci-linux:latest \
  /bin/bash -c "
  cd ;
  pwd ;
  git clone https://github.com/USER/nuttx --branch BRANCH ;
  git clone https://github.com/apache/nuttx-apps apps ;
  pushd nuttx ; echo NuttX Source: https://github.com/apache/nuttx/tree/\$(git rev-parse HEAD) ; popd ;
  pushd apps  ; echo NuttX Apps: https://github.com/apache/nuttx-apps/tree/\$(git rev-parse HEAD) ; popd ;
  cd nuttx/tools/ci ;
  (./cibuild.sh -c -A -N -R testlist/$job.dat || echo '***** BUILD FAILED') ;
"

## Free up the Docker disk space
sudo docker system prune --force

(Based on this)

It the CI Build fails, we will see "BUILD FAILED". Remember I said it's slow? That's because we need to repeat the above for job = arm-01 ... arm-04, risc-v-01 ... risc-v-06, xtensa, arm64, other, etc. (Full List Here)

## Build All Target Groups
## TODO: Add risc-v, xtensa, arm64, other, etc
for job in \
  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 arm-14
do
  ## Build the Target Group
  run_job $job

  ## Watch for for "BUILD FAILED"
  sleep 10
done

(Similar to this)

And it won't run the macOS and Windows Jobs. Quicker Way is probably to use GitHub Actions...

Option 2: Run the CI Builds with GitHub Actions

Suppose our PR is at github.com/USER/nuttx/tree/BRANCH. We need to patch the CI Workflow in the master branch:

  1. We enable GitHub Actions in our NuttX Repo (which won't be charged to NuttX Project)

    Screenshot 2024-10-19 at 8 18 25 AM

    Screenshot 2024-10-19 at 8 19 05 AM

  2. Edit master branch .github/workflows/build.yml. Modify the 4 references to arch.yml, point them to our own repo at master branch:

    Linux-Arch:
     uses: USER/nuttx/.github/workflows/arch.yml@master
    
    macOS-Arch:
     uses: USER/nuttx/.github/workflows/arch.yml@master
    
    msys2-Arch:
     uses: USER/nuttx/.github/workflows/arch.yml@master
    
    msvc-Arch:
     uses: USER/nuttx/.github/workflows/arch.yml@master

    (Similar to this)

  3. Then edit .github/workflows/arch.yml. Delete this section, to enable the macOS and Windows Builds:

    # Skip all macOS Builds
    if [[ "${{ inputs.os }}" == "macOS" ]]; then
      echo "Skipping all macOS Builds"
      echo "skip_all_builds=1" | tee -a $GITHUB_OUTPUT
      exit
    fi

    (See the script)

  4. Delete this section, to enable All Linux Builds:

    # If PR was Created or Modified: Exclude some boards
    pr=${{github.event.pull_request.number}}
    if [[ "$pr" != "" ]]; then
      echo "Excluding arm-0[1249], arm-1[124-9], risc-v-04..06, sim-03, xtensa-02"
      boards=$(
        echo '${{ inputs.boards }}' |
        jq --compact-output \
        'map(
          select(
            test("arm-0[1249]") == false and test("arm-1[124-9]") == false and
            test("risc-v-0[4-9]") == false and
            test("sim-0[3-9]") == false and
            test("xtensa-0[2-9]") == false
          )
        )'
      )
    fi
  5. Optional: Disable fail-fast so that it runs all builds, regardless of error. Remove max-parallel so that it will use unlimited concurrent runners. Edit .github/workflows/build.yml, change...

    Linux: ...
     strategy:
       max-parallel: 12
    
    macOS: ...
     strategy:
       max-parallel: 2

    To...

    Linux: ...
     strategy:
       fail-fast: false
    
    macOS: ...
     strategy:
       fail-fast: false

    (Like this)

  6. In Our Own Repo: Create a Local PR that will merge BRANCH to our own master. (Not apache/nuttx!) Just create the PR, please don't merge the PR yet.

    The CI Workflow will build everything, including macOS and Windows Builds. It should complete in 2.5 hours.

  7. Optional: master branch will no longer auto-build when we sync with upstream. To fix this: We rename master branch to releases/master...

    Browse to our NuttX Repo, click Settings > Default Branch > Rename Branch > releases/master

    Screenshot 2024-11-04 at 5 36 15 AM

    Hope this works OK :-)

acassis commented 3 days ago

@lupyuen maybe this explanation should be included in our Contributing documentation, like a recommended step before creating the PR.

stbenn commented 3 days ago

@lupyuen I will try the docker version this weekend on a fresh install and take notes if theres any special steps I needed for it to work. In case others want to do this in the future as well

stbenn commented 1 day ago

@lupyuen The running locally with docker was exactly what I was looking for, thank you! :) I am not sure if it is strictly necessary for this, but to get docker working properly for act on WSL2, I needed to do these first:

  1. Install docker desktop on the windows side (not sure why/if this is really necessary)
  2. In docker desktop settings -> Resources Enable integration with the specific WSL2 distro I was using
  3. Install docker engine on the distro with the instructions you linked here: https://docs.docker.com/engine/install/ubuntu/
lupyuen commented 1 day ago

@stbenn Thank you so much! I'll update the instructions :-)

stbenn commented 1 day ago

The only oddity I encountered is when sending the output of the test to a .txt file (with source runci.sh > ci_out.txt ), the encoding appears to be weird: image

lupyuen commented 1 day ago

Yep that's because GCC Compiler helpfully colours the messages with ANSI Escape Codes :-) Try this to remove the Special Characters:

## Strip the control chars
function clean_log {
  local tmp_file=/tmp/release-tmp.log
  cat $log_file \
    | tr -d '\r' \
    | tr -d '\r' \
    | sed 's/\x08/ /g' \
    | sed 's/\x1B(B//g' \
    | sed 's/\x1B\[K//g' \
    | sed 's/\x1B[<=>]//g' \
    | sed 's/\x1B\[[0-9:;<=>?]*[!]*[A-Za-z]//g' \
    | sed 's/\x1B[@A-Z\\\]^_]\|\x1B\[[0-9:;<=>?]*[-!"#$%&'"'"'()*+,.\/]*[][\\@A-Z^_`a-z{|}~]//g' \
    >$tmp_file
  mv $tmp_file $log_file
  echo ----- "Done! $log_file"
}

https://github.com/lupyuen/nuttx-release/blob/main/run-ci.sh#L30-L47