From 8186e5e5a46eccf0e83776d0c1c2ba1ea78f2d83 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 24 Jun 2025 10:28:38 +0200 Subject: [PATCH] ci: add bot to build on comment This has been requested many times, so let's add this to speed up reviews. When a member of the "reviewers" group comments the magic word written below, that specific firmware is created and attached by a bot. build // Members of the "reviewers" group have no extra privileges, they can not commit to the repository nor perform any action outside the `build-on-comment` action. Motivation is to speedup reviews and have a better source for sharing compiled firmware. Signed-off-by: Paul Spooren --- .github/workflows/build-on-comment.yml | 161 +++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 .github/workflows/build-on-comment.yml diff --git a/.github/workflows/build-on-comment.yml b/.github/workflows/build-on-comment.yml new file mode 100644 index 00000000000..ffb20d1f231 --- /dev/null +++ b/.github/workflows/build-on-comment.yml @@ -0,0 +1,161 @@ +name: Build on Comment + +on: + issue_comment: + types: [created, edited] + +concurrency: + group: build-on-comment-${{ github.event.issue.number || github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + check-and-build: + if: github.event.issue.pull_request != null + runs-on: ubuntu-latest + + steps: + - name: Check if user is in reviewers team + id: check-reviewer + run: | + USERNAME="${{ github.event.comment.user.login }}" + + STATUS_CODE=$(curl -s -H "Authorization: token ${{ secrets.LOOKUP_MEMBERS }}" \ + -o response.json -w "%{http_code}" \ + https://api.github.com/orgs/openwrt/teams/reviewers/memberships/$USERNAME) + + if grep -q '"state": "active"' response.json && [ "$STATUS_CODE" -eq 200 ]; then + echo "authorized=true" >> $GITHUB_OUTPUT + else + echo "authorized=false" >> $GITHUB_OUTPUT + fi + + - name: Parse build command + if: steps.check-reviewer.outputs.authorized == 'true' + id: parse-command + run: | + COMMENT="${{ github.event.comment.body }}" + if echo "$COMMENT" | grep -q "build [a-zA-Z0-9_-]\+/[a-zA-Z0-9_-]\+/[a-zA-Z0-9_-]\+"; then + BUILD_PATH=$(echo "$COMMENT" | grep -o "build [a-zA-Z0-9_-]\+/[a-zA-Z0-9_-]\+/[a-zA-Z0-9_-]\+" | sed 's/build //') + TARGET=$(echo "$BUILD_PATH" | cut -d'/' -f1) + SUBTARGET=$(echo "$BUILD_PATH" | cut -d'/' -f2) + PROFILE=$(echo "$BUILD_PATH" | cut -d'/' -f3) + echo "build_requested=true" >> $GITHUB_OUTPUT + echo "target=$TARGET" >> $GITHUB_OUTPUT + echo "subtarget=$SUBTARGET" >> $GITHUB_OUTPUT + echo "profile=$PROFILE" >> $GITHUB_OUTPUT + echo "build_path=$BUILD_PATH" >> $GITHUB_OUTPUT + else + echo "build_requested=false" >> $GITHUB_OUTPUT + fi + + - name: Find existing build comment + if: steps.parse-command.outputs.build_requested == 'true' + id: find-comment + uses: peter-evans/find-comment@v2 + with: + issue-number: ${{ github.event.pull_request.number || github.event.issue.number }} + comment-author: "github-actions[bot]" + + - name: Create early build comment + if: steps.parse-command.outputs.build_requested == 'true' + id: start-comment + uses: peter-evans/create-or-update-comment@v3 + with: + issue-number: ${{ github.event.pull_request.number || github.event.issue.number }} + comment-id: ${{ steps.find-comment.outputs.comment-id }} + body: | + 🚧 **Build in progress for** `${{ steps.parse-command.outputs.build_path }}`... + + You can follow progress [here](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + *Triggered by: @${{ github.event.comment.user.login }}* + edit-mode: replace + + - name: Checkout repository + if: steps.parse-command.outputs.build_requested == 'true' + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + ref: refs/pull/${{ github.event.issue.number }}/merge + + - name: Setup build environment + if: steps.parse-command.outputs.build_requested == 'true' + continue-on-error: true + run: | + sudo apt-get update + sudo apt-get install -y build-essential libncurses5-dev gawk git subversion libssl-dev gettext zlib1g-dev swig unzip time rsync + + - name: Build target + if: steps.parse-command.outputs.build_requested == 'true' + id: build + run: | + make defconfig + echo "CONFIG_DEVEL=y" > .config + echo "CONFIG_BPF_TOOLCHAIN_HOST=y" >> .config + echo "CONFIG_TARGET_${{ steps.parse-command.outputs.target }}=y" >> .config + echo "CONFIG_TARGET_${{ steps.parse-command.outputs.target }}_${{ steps.parse-command.outputs.subtarget }}=y" >> .config + echo "CONFIG_TARGET_${{ steps.parse-command.outputs.target }}_${{ steps.parse-command.outputs.subtarget }}_DEVICE_${{ steps.parse-command.outputs.profile }}=y" >> .config + + make defconfig + make -j$(nproc) BUILD_LOG=1 + + echo "build_success=true" >> $GITHUB_OUTPUT + + - name: Upload log + uses: actions/upload-artifact@v4 + if: steps.check-reviewer.outputs.authorized == 'true' && (success() || failure()) + with: + name: build-log-${{ steps.parse-command.outputs.target }}-${{ steps.parse-command.outputs.subtarget }}-${{ steps.parse-command.outputs.profile }} + path: logs/ + + - name: Create artifact archive + if: steps.build.outputs.build_success == 'true' + run: | + cd bin/ + tar -czf ../build-artifacts.tar.gz * + cd .. + + - name: Upload build artifacts + if: steps.build.outputs.build_success == 'true' + uses: actions/upload-artifact@v4 + with: + name: build-${{ steps.parse-command.outputs.target }}-${{ steps.parse-command.outputs.subtarget }}-${{ steps.parse-command.outputs.profile }} + path: build-artifacts.tar.gz + + - name: Update comment with build results + if: steps.build.outputs.build_success == 'true' + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ steps.start-comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number || github.event.issue.number }} + body: | + ## Build Results for `${{ steps.parse-command.outputs.build_path }}` + + ✅ **Build completed successfully!** + + **Target:** `${{ steps.parse-command.outputs.target }}` + **Subtarget:** `${{ steps.parse-command.outputs.subtarget }}` + **Profile:** `${{ steps.parse-command.outputs.profile }}` + + 📦 **Artifacts:** [Download build-${{ steps.parse-command.outputs.target }}-${{ steps.parse-command.outputs.subtarget }}-${{ steps.parse-command.outputs.profile }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + *Build triggered by: @${{ github.event.comment.user.login }}* + *Last updated: ${{ github.event.comment.created_at }}* + edit-mode: replace + + - name: Update comment on build failure + if: steps.parse-command.outputs.build_requested == 'true' && steps.build.outputs.build_success == 'false' + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ steps.start-comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number || github.event.issue.number }} + body: | + ## Build Results for `${{ steps.parse-command.outputs.build_path }}` + + ❌ **Build failed!** + + Please check the [action logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details. + + *Build triggered by: @${{ github.event.comment.user.login }}* + edit-mode: replace -- 2.47.2