From 6091330ae6d799bcf34d366acda7aff91c609ab1 Mon Sep 17 00:00:00 2001
From: Maksym H <1177472+mordamax@users.noreply.github.com>
Date: Thu, 23 Jan 2025 13:30:26 +0000
Subject: [PATCH] Refactor command bot and drop rejecting non paritytech
 members (#7231)

Aims to
- close #7049
- close https://github.com/paritytech/opstooling/issues/449
- close https://github.com/paritytech/opstooling/issues/463

What's changed:
- removed is paritytech member check as required prerequisite to run a
command
- run the cmd.py script taking it from master, if someone who run this
is not a member of paritytech, and from current branch, if is a member.
That keeps the developer experience & easy testing if paritytech members
are contributing to cmd.py
- isolate the cmd job from being able to access GH App token or PR
token- currently the fmt/bench/prdoc are being run with limited
permissions scope, just to generate output, which then is uploaded to
artifacts, and then the other job which doesn't run any files from repo,
does a commit/push more securely
---
 .github/workflows/cmd.yml | 428 +++++++++++++++++++++-----------------
 1 file changed, 240 insertions(+), 188 deletions(-)

diff --git a/.github/workflows/cmd.yml b/.github/workflows/cmd.yml
index 42b2eab3b9e..50e71f2699d 100644
--- a/.github/workflows/cmd.yml
+++ b/.github/workflows/cmd.yml
@@ -5,7 +5,7 @@ on:
     types: [created]
 
 permissions: # allow the action to comment on the PR
-  contents: write
+  contents: read
   issues: write
   pull-requests: write
   actions: read
@@ -55,38 +55,9 @@ jobs:
 
             return 'false';
 
-  reject-non-members:
-    needs: is-org-member
-    if: ${{ startsWith(github.event.comment.body, '/cmd') && needs.is-org-member.outputs.member != 'true' }}
-    runs-on: ubuntu-latest
-    steps:
-      - name: Add reaction to rejected comment
-        uses: actions/github-script@v7
-        with:
-          github-token: ${{ secrets.GITHUB_TOKEN }}
-          script: |
-            github.rest.reactions.createForIssueComment({
-              comment_id: ${{ github.event.comment.id }},
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              content: 'confused'
-            })
-
-      - name: Comment PR (Rejected)
-        uses: actions/github-script@v7
-        with:
-          github-token: ${{ secrets.GITHUB_TOKEN }}
-          script: |
-            github.rest.issues.createComment({
-              issue_number: context.issue.number,
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              body: `Sorry, only members of the organization ${{ github.event.repository.owner.login }} members can run commands.`
-            })
 
   acknowledge:
-    needs: is-org-member
-    if: ${{ startsWith(github.event.comment.body, '/cmd') && needs.is-org-member.outputs.member == 'true' }}
+    if: ${{ startsWith(github.event.comment.body, '/cmd') }}
     runs-on: ubuntu-latest
     steps:
       - name: Add reaction to triggered comment
@@ -102,12 +73,11 @@ jobs:
             })
 
   clean:
-    needs: is-org-member
     runs-on: ubuntu-latest
     steps:
       - name: Clean previous comments
-        if: ${{ startsWith(github.event.comment.body, '/cmd') && contains(github.event.comment.body, '--clean') && needs.is-org-member.outputs.member == 'true' }}
         uses: actions/github-script@v7
+        if: ${{ startsWith(github.event.comment.body, '/cmd') && contains(github.event.comment.body, '--clean') }}
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
@@ -139,25 +109,72 @@ jobs:
                 }
               }
             })
-  help:
-    needs: [clean, is-org-member]
-    if: ${{ startsWith(github.event.comment.body, '/cmd') && contains(github.event.comment.body, '--help') && needs.is-org-member.outputs.member == 'true' }}
+
+  get-pr-info:
+    if: ${{ startsWith(github.event.comment.body, '/cmd') }}
     runs-on: ubuntu-latest
+    outputs:
+      CMD: ${{ steps.get-comment.outputs.group2 }}
+      pr-branch: ${{ steps.get-pr.outputs.pr_branch }}
+      repo: ${{ steps.get-pr.outputs.repo }}
     steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-
       - name: Get command
         uses: actions-ecosystem/action-regex-match@v2
-        id: get-pr-comment
+        id: get-comment
         with:
           text: ${{ github.event.comment.body }}
           regex: "^(\\/cmd )([-\\/\\s\\w.=:]+)$" # see explanation in docs/contributor/commands-readme.md#examples
+      
+      # Get PR branch name, because the issue_comment event does not contain the PR branch name
+      - name: Check if the issue is a PR
+        id: check-pr
+        run: |
+          if [ -n "${{ github.event.issue.pull_request.url }}" ]; then
+            echo "This is a pull request comment"
+          else
+            echo "This is not a pull request comment"
+            exit 1
+          fi
+
+      - name: Get PR Branch Name and Repo
+        if: steps.check-pr.outcome == 'success'
+        id: get-pr
+        uses: actions/github-script@v7
+        with:
+          script: |
+            const pr = await github.rest.pulls.get({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              pull_number: context.issue.number,
+            });
+            const prBranch = pr.data.head.ref;
+            const repo = pr.data.head.repo.full_name;
+            console.log(prBranch, repo)
+            core.setOutput('pr_branch', prBranch);
+            core.setOutput('repo', repo);
+
+      - name: Use PR Branch Name and Repo
+        env:
+          PR_BRANCH: ${{ steps.get-pr.outputs.pr_branch }}
+          REPO: ${{ steps.get-pr.outputs.repo }}
+          CMD: ${{ steps.get-comment.outputs.group2 }}
+        run: |
+          echo "The PR branch is $PR_BRANCH"
+          echo "The repository is $REPO"
+          echo "The CMD is $CMD"
+
+  help:
+    needs: [clean, get-pr-info]
+    if: ${{ startsWith(github.event.comment.body, '/cmd') && contains(github.event.comment.body, '--help') }}
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
 
       - name: Save output of help
         id: help
         env:
-          CMD: ${{ steps.get-pr-comment.outputs.group2 }} # to avoid "" around the command
+          CMD: ${{ needs.get-pr-info.outputs.CMD }} # to avoid "" around the command
         run: |
           python3 -m pip install -r .github/scripts/generate-prdoc.requirements.txt
           echo 'help<<EOF' >> $GITHUB_OUTPUT
@@ -209,9 +226,11 @@ jobs:
             })
 
   set-image:
-    needs: [clean, is-org-member]
-    if: ${{ startsWith(github.event.comment.body, '/cmd') && !contains(github.event.comment.body, '--help') && needs.is-org-member.outputs.member == 'true' }}
+    needs: [clean, get-pr-info]
+    if: ${{ startsWith(github.event.comment.body, '/cmd') && !contains(github.event.comment.body, '--help') }}
     runs-on: ubuntu-latest
+    env: 
+      CMD: ${{ needs.get-pr-info.outputs.CMD }}
     outputs:
       IMAGE: ${{ steps.set-image.outputs.IMAGE }}
       RUNNER: ${{ steps.set-image.outputs.RUNNER }}
@@ -221,7 +240,7 @@ jobs:
 
       - id: set-image
         run: |
-          BODY=$(echo "${{ github.event.comment.body }}" | xargs)
+          BODY=$(echo "$CMD" | xargs) # remove whitespace
           IMAGE_OVERRIDE=$(echo $BODY | grep -oe 'docker.io/paritytech/ci-unified:.*\s' | xargs)
 
           cat .github/env >> $GITHUB_OUTPUT
@@ -243,87 +262,17 @@ jobs:
           echo "RUNNER=${{ steps.set-image.outputs.RUNNER }}"
           echo "IMAGE=${{ steps.set-image.outputs.IMAGE }}"
 
-  # Get PR branch name, because the issue_comment event does not contain the PR branch name
-  get-pr-branch:
-    needs: [set-image]
+  before-cmd:
+    needs: [set-image, get-pr-info]
     runs-on: ubuntu-latest
-    outputs:
-      pr-branch: ${{ steps.get-pr.outputs.pr_branch }}
-      repo: ${{ steps.get-pr.outputs.repo }}
-    steps:
-      - name: Check if the issue is a PR
-        id: check-pr
-        run: |
-          if [ -n "${{ github.event.issue.pull_request.url }}" ]; then
-            echo "This is a pull request comment"
-          else
-            echo "This is not a pull request comment"
-            exit 1
-          fi
-
-      - name: Get PR Branch Name and Repo
-        if: steps.check-pr.outcome == 'success'
-        id: get-pr
-        uses: actions/github-script@v7
-        with:
-          script: |
-            const pr = await github.rest.pulls.get({
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              pull_number: context.issue.number,
-            });
-            const prBranch = pr.data.head.ref;
-            const repo = pr.data.head.repo.full_name;
-            console.log(prBranch, repo)
-            core.setOutput('pr_branch', prBranch);
-            core.setOutput('repo', repo);
-
-      - name: Use PR Branch Name and Repo
-        run: |
-          echo "The PR branch is ${{ steps.get-pr.outputs.pr_branch }}"
-          echo "The repository is ${{ steps.get-pr.outputs.repo }}"
-
-  cmd:
-    needs: [set-image, get-pr-branch]
     env:
       JOB_NAME: "cmd"
-    runs-on: ${{ needs.set-image.outputs.RUNNER }}
-    container:
-      image: ${{ needs.set-image.outputs.IMAGE }}
-    timeout-minutes: 1440 # 24 hours per runtime
+      CMD: ${{ needs.get-pr-info.outputs.CMD }}
+      PR_BRANCH: ${{ needs.get-pr-info.outputs.pr-branch }}
+    outputs:
+      job_url: ${{ steps.build-link.outputs.job_url }}
+      run_url: ${{ steps.build-link.outputs.run_url }}
     steps:
-      - name: Generate token
-        uses: actions/create-github-app-token@v1
-        id: generate_token
-        with:
-          app-id: ${{ secrets.CMD_BOT_APP_ID }}
-          private-key: ${{ secrets.CMD_BOT_APP_KEY }}
-
-      - name: Checkout
-        uses: actions/checkout@v4
-        with:
-          token: ${{ steps.generate_token.outputs.token }}
-          repository: ${{ needs.get-pr-branch.outputs.repo }}
-          ref: ${{ needs.get-pr-branch.outputs.pr-branch }}
-
-      - name: Get command
-        uses: actions-ecosystem/action-regex-match@v2
-        id: get-pr-comment
-        with:
-          text: ${{ github.event.comment.body }}
-          regex: "^(\\/cmd )([-\\/\\s\\w.=:]+)$" # see explanation in docs/contributor/commands-readme.md#examples
-
-      # In order to run prdoc without specifying the PR number, we need to add the PR number as an argument automatically
-      - name: Prepare PR Number argument
-        id: pr-arg
-        run: |
-          CMD="${{ steps.get-pr-comment.outputs.group2 }}"
-          if echo "$CMD" | grep -q "prdoc" && ! echo "$CMD" | grep -qE "\-\-pr[[:space:]=][0-9]+"; then
-            echo "arg=--pr ${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
-          else
-            echo "arg=" >> $GITHUB_OUTPUT
-          fi
-
       - name: Build workflow link
         if: ${{ !contains(github.event.comment.body, '--quiet') }}
         id: build-link
@@ -346,40 +295,90 @@ jobs:
 
       - name: Comment PR (Start)
         # No need to comment on prdoc start or if --quiet
-        if: ${{ !contains(github.event.comment.body, '--quiet') && !contains(github.event.comment.body, 'prdoc') }}
+        if: ${{ !contains(github.event.comment.body, '--quiet') && !startsWith(needs.get-pr-info.outputs.CMD, 'prdoc') && !startsWith(needs.get-pr-info.outputs.CMD, 'fmt')}}
         uses: actions/github-script@v7
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
             let job_url = ${{ steps.build-link.outputs.job_url }}
-
+            let cmd = process.env.CMD;
             github.rest.issues.createComment({
               issue_number: context.issue.number,
               owner: context.repo.owner,
               repo: context.repo.repo,
-              body: `Command "${{ steps.get-pr-comment.outputs.group2 }}" has started 🚀 [See logs here](${job_url})`
+              body: `Command "${cmd}" has started 🚀 [See logs here](${job_url})`
             })
+
+  cmd:
+    needs: [before-cmd, set-image, get-pr-info, is-org-member]
+    env:
+      CMD: ${{ needs.get-pr-info.outputs.CMD }}
+      PR_BRANCH: ${{ needs.get-pr-info.outputs.pr-branch }}
+    runs-on: ${{ needs.set-image.outputs.RUNNER }}
+    container:
+      image: ${{ needs.set-image.outputs.IMAGE }}
+    timeout-minutes: 1440 # 24 hours per runtime
+    # lowerdown permissions to separate permissions context for executable parts by contributors
+    permissions:
+      contents: read
+      pull-requests: none
+      actions: none
+      issues: none
+    outputs:
+      cmd_output: ${{ steps.cmd.outputs.cmd_output }}
+      subweight: ${{ steps.subweight.outputs.result }}
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+        with:
+          repository: ${{ needs.get-pr-info.outputs.repo }}
+          ref: ${{ needs.get-pr-info.outputs.pr-branch }}
+
+      # In order to run prdoc without specifying the PR number, we need to add the PR number as an argument automatically
+      - name: Prepare PR Number argument
+        id: pr-arg
+        run: |
+          CMD="${{ needs.get-pr-info.outputs.CMD }}"
+          if echo "$CMD" | grep -q "prdoc" && ! echo "$CMD" | grep -qE "\-\-pr[[:space:]=][0-9]+"; then
+            echo "arg=--pr ${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
+          else
+            echo "arg=" >> $GITHUB_OUTPUT
+          fi
       
       - name: Install dependencies for bench
-        if: startsWith(steps.get-pr-comment.outputs.group2, 'bench')
+        if: startsWith(needs.get-pr-info.outputs.CMD, 'bench')
         run: |
-          cargo install subweight --locked
           cargo install --path substrate/utils/frame/omni-bencher --locked
 
       - name: Run cmd
         id: cmd
         env:
-          CMD: ${{ steps.get-pr-comment.outputs.group2 }} # to avoid "" around the command
           PR_ARG: ${{ steps.pr-arg.outputs.arg }}
+          IS_ORG_MEMBER: ${{ needs.is-org-member.outputs.member }}
         run: |
           echo "Running command: '$CMD $PR_ARG' on '${{ needs.set-image.outputs.RUNNER }}' runner, container: '${{ needs.set-image.outputs.IMAGE }}'"
           echo "RUST_NIGHTLY_VERSION: $RUST_NIGHTLY_VERSION"
-          # Fixes "detected dubious ownership" error in the ci
-          git config --global --add safe.directory '*'
-          git remote -v
-          cat /proc/cpuinfo
-          python3 -m pip install -r .github/scripts/generate-prdoc.requirements.txt
-          python3 .github/scripts/cmd/cmd.py $CMD $PR_ARG
+          echo "IS_ORG_MEMBER: $IS_ORG_MEMBER"
+
+          git config --global --add safe.directory $GITHUB_WORKSPACE
+          git config user.name "cmd[bot]"
+          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+            
+          
+          # if the user is not an org member, we need to use the bot's path from master to avoid unwanted modifications
+          if [ "$IS_ORG_MEMBER" = "true" ]; then
+            # safe to run commands from current branch
+            BOT_PATH=.github
+          else
+            # going to run commands from master
+            TMP_DIR=/tmp/polkadot-sdk
+            git clone --depth 1 --branch master https://github.com/paritytech/polkadot-sdk $TMP_DIR
+            BOT_PATH=$TMP_DIR/.github
+          fi
+
+          # install deps and run a command from master
+          python3 -m pip install -r $BOT_PATH/scripts/generate-prdoc.requirements.txt
+          python3 $BOT_PATH/scripts/cmd/cmd.py $CMD $PR_ARG
           git status
           git diff
 
@@ -393,6 +392,11 @@ jobs:
             echo 'EOF' >> $GITHUB_OUTPUT
           fi
 
+          git add -A
+          git diff HEAD > /tmp/cmd/command_diff.patch -U0
+          git commit -m "tmp cmd: $CMD" || true
+          # without push, as we're saving the diff to an artifact and subweight will compare the local branch with the remote branch
+
       - name: Upload command output
         if: ${{ always() }}
         uses: actions/upload-artifact@v4
@@ -400,38 +404,100 @@ jobs:
           name: command-output
           path: /tmp/cmd/command_output.log
 
-      # Generate token for commit, as the earlier token expires after 1 hour, while cmd can take longer
-      - name: Generate token for commit
-        uses: actions/create-github-app-token@v1
-        id: generate_token_commit
+      - name: Upload command diff
+        uses: actions/upload-artifact@v4
+        with:
+          name: command-diff
+          path: /tmp/cmd/command_diff.patch
+
+      - name: Install subweight for bench
+        if: startsWith(needs.get-pr-info.outputs.CMD, 'bench')
+        run: cargo install subweight
+
+      - name: Run Subweight for bench
+        id: subweight
+        if: startsWith(needs.get-pr-info.outputs.CMD, 'bench')
+        shell: bash
+        run: |
+          git fetch
+          git remote -v
+          echo $(git log -n 2 --oneline)
+
+          result=$(subweight compare commits \
+            --path-pattern "./**/weights/**/*.rs,./**/weights.rs" \
+            --method asymptotic \
+            --format markdown \
+            --no-color \
+            --change added changed \
+            --ignore-errors \
+            refs/remotes/origin/master $PR_BRANCH)
+
+          # Save the multiline result to the output
+          {
+            echo "result<<EOF"
+            echo "$result"
+            echo "EOF"
+          } >> $GITHUB_OUTPUT
+
+  after-cmd:
+    needs: [cmd, get-pr-info, before-cmd]
+    env:
+      CMD: ${{ needs.get-pr-info.outputs.CMD }}
+      PR_BRANCH: ${{ needs.get-pr-info.outputs.pr-branch }}
+    runs-on: ubuntu-latest
+    steps:
+      # needs to be able to trigger CI, as default token does not retrigger
+      - uses: actions/create-github-app-token@v1
+        id: generate_token
         with:
           app-id: ${{ secrets.CMD_BOT_APP_ID }}
           private-key: ${{ secrets.CMD_BOT_APP_KEY }}
 
-      - name: Commit changes
+      - name: Checkout
+        uses: actions/checkout@v4
+        with:
+          token: ${{ steps.generate_token.outputs.token }}
+          repository: ${{ needs.get-pr-info.outputs.repo }}
+          ref: ${{ needs.get-pr-info.outputs.pr-branch }}
+
+      - name: Download all artifacts
+        uses: actions/download-artifact@v4
+        with: 
+          name: command-diff
+          path: command-diff
+
+      - name: Apply & Commit changes
         run: |
+          ls -lsa .
+
+          git config --global --add safe.directory $GITHUB_WORKSPACE
+          git config user.name "cmd[bot]"
+          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+          git config --global pull.rebase false
+          
+          echo "Applying $file"
+          git apply "command-diff/command_diff.patch" --unidiff-zero --allow-empty
+
+          rm -rf command-diff
+
+          git status
+          
           if [ -n "$(git status --porcelain)" ]; then
-            git config --global user.name command-bot
-            git config --global user.email "<>"
-            git config --global pull.rebase false
 
-            # Push the results to the target branch
-            git remote add \
-              github \
-              "https://x-access-token:${{ steps.generate_token_commit.outputs.token }}@github.com/${{ needs.get-pr-branch.outputs.repo }}.git" || :
+            git remote -v
 
             push_changes() {
-              git push github "HEAD:${{ needs.get-pr-branch.outputs.pr-branch }}"
+              git push origin "HEAD:$PR_BRANCH"
             }
 
             git add .
             git restore --staged Cargo.lock # ignore changes in Cargo.lock
-            git commit -m "Update from ${{ github.actor }} running command '${{ steps.get-pr-comment.outputs.group2 }}'" || true
+            git commit -m "Update from ${{ github.actor }} running command '$CMD'" || true
             
             # Attempt to push changes
             if ! push_changes; then
               echo "Push failed, trying to rebase..."
-              git pull --rebase github "${{ needs.get-pr-branch.outputs.pr-branch }}"
+              git pull --rebase origin $PR_BRANCH
               # After successful rebase, try pushing again
               push_changes
             fi
@@ -439,41 +505,20 @@ jobs:
             echo "Nothing to commit";
           fi
 
-      - name: Run Subweight
-        id: subweight
-        if: startsWith(steps.get-pr-comment.outputs.group2, 'bench')
-        shell: bash
-        run: |
-          git fetch
-          result=$(subweight compare commits \
-            --path-pattern "./**/weights/**/*.rs,./**/weights.rs" \
-            --method asymptotic \
-            --format markdown \
-            --no-color \
-            --change added changed \
-            --ignore-errors \
-            refs/remotes/origin/master refs/heads/${{ needs.get-pr-branch.outputs.pr-branch }})
-
-          # Save the multiline result to the output
-          {
-            echo "result<<EOF"
-            echo "$result"
-            echo "EOF"
-          } >> $GITHUB_OUTPUT
-
       - name: Comment PR (End)
         # No need to comment on prdoc success or --quiet
-        if: ${{ !failure() && !contains(github.event.comment.body, '--quiet') && !contains(github.event.comment.body, 'prdoc') }}
+        if: ${{ needs.cmd.result == 'success' && !contains(github.event.comment.body, '--quiet') && !startsWith(needs.get-pr-info.outputs.CMD, 'prdoc') && !startsWith(needs.get-pr-info.outputs.CMD, 'fmt') }}
         uses: actions/github-script@v7
         env:
-          SUBWEIGHT: "${{ steps.subweight.outputs.result }}"
-          CMD_OUTPUT: "${{ steps.cmd.outputs.cmd_output }}"
+          SUBWEIGHT: "${{ needs.cmd.outputs.subweight }}"
+          CMD_OUTPUT: "${{ needs.cmd.outputs.cmd_output }}"
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
-            let runUrl = ${{ steps.build-link.outputs.run_url }}
-            let subweight = process.env.SUBWEIGHT;
-            let cmdOutput = process.env.CMD_OUTPUT;
+            let runUrl = ${{ needs.before-cmd.outputs.run_url }}
+            let subweight = process.env.SUBWEIGHT || '';
+            let cmdOutput = process.env.CMD_OUTPUT || '';
+            let cmd = process.env.CMD;
             console.log(cmdOutput);
 
             let subweightCollapsed = subweight.trim() !== '' 
@@ -488,34 +533,41 @@ jobs:
               issue_number: context.issue.number,
               owner: context.repo.owner,
               repo: context.repo.repo,
-              body: `Command "${{ steps.get-pr-comment.outputs.group2 }}" has finished ✅ [See logs here](${runUrl})${subweightCollapsed}${cmdOutputCollapsed}`
+              body: `Command "${cmd}" has finished ✅ [See logs here](${runUrl})${subweightCollapsed}${cmdOutputCollapsed}`
             })
 
+  finish:
+    needs: [get-pr-info, before-cmd, after-cmd, cmd]
+    if: ${{ always() }}
+    runs-on: ubuntu-latest
+    env:
+      CMD_OUTPUT: "${{ needs.cmd.outputs.cmd_output }}"
+      CMD: ${{ needs.get-pr-info.outputs.CMD }}
+    steps:
       - name: Comment PR (Failure)
-        if: ${{ failure() && !contains(github.event.comment.body, '--quiet') }}
+        if: ${{ needs.cmd.result == 'failure' || needs.after-cmd.result == 'failure' }}
         uses: actions/github-script@v7
-        env:
-          CMD_OUTPUT: "${{ steps.cmd.outputs.cmd_output }}"
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
-            let jobUrl = ${{ steps.build-link.outputs.job_url }}
+            let jobUrl = ${{ needs.before-cmd.outputs.job_url }}
             let cmdOutput = process.env.CMD_OUTPUT;
-
-            let cmdOutputCollapsed = cmdOutput.trim() !== ''
-              ? `<details>\n\n<summary>Command output:</summary>\n\n${cmdOutput}\n\n</details>` 
-              : '';
+            let cmd = process.env.CMD;
+            let cmdOutputCollapsed = '';
+            if (cmdOutput && cmdOutput.trim() !== '') {
+              cmdOutputCollapsed = `<details>\n\n<summary>Command output:</summary>\n\n${cmdOutput}\n\n</details>` 
+            }
 
             github.rest.issues.createComment({
               issue_number: context.issue.number,
               owner: context.repo.owner,
               repo: context.repo.repo,
-              body: `Command "${{ steps.get-pr-comment.outputs.group2 }}" has failed ❌! [See logs here](${jobUrl})${cmdOutputCollapsed}`
+              body: `Command "${cmd}" has failed ❌! [See logs here](${jobUrl})${cmdOutputCollapsed}`
             })
 
       - name: Add 😕 reaction on failure
+        if: ${{ needs.cmd.result == 'failure' || needs.after-cmd.result == 'failure' }}
         uses: actions/github-script@v7
-        if: ${{ failure() }}
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
@@ -527,8 +579,8 @@ jobs:
             })
 
       - name: Add 👍 reaction on success
+        if: ${{ needs.cmd.result == 'success' && needs.after-cmd.result == 'success' }}
         uses: actions/github-script@v7
-        if: ${{ !failure() }}
         with:
           github-token: ${{ secrets.GITHUB_TOKEN }}
           script: |
-- 
GitLab