diff --git a/.changeset/red-balloons-decide.md b/.changeset/red-balloons-decide.md new file mode 100644 index 00000000..dd6d9509 --- /dev/null +++ b/.changeset/red-balloons-decide.md @@ -0,0 +1,7 @@ +--- +"llm-action-error-reporter": minor +--- + +following 0.3.1 patch, this pivots to use github scripts to update specific +comment id instead of deciding to update the last message if it's made by the +script, which has low spam reduction effect in bot-busy environments diff --git a/actions/llm-action-error-reporter/action.yml b/actions/llm-action-error-reporter/action.yml index 305f1663..eb44c5be 100644 --- a/actions/llm-action-error-reporter/action.yml +++ b/actions/llm-action-error-reporter/action.yml @@ -134,6 +134,7 @@ runs: echo "$response_content" | sed -e 's/^ -/ -/g' > chatgpt_output.txt - name: Generate Error Report + id: generate_error_comment if: ${{ env.SKIP_ACTION == 'false' && inputs.parent-workflow-conclusion == 'failure' }} @@ -160,10 +161,11 @@ runs: $(cat chatgpt_output.txt) " - # post the error report to the PR + # prepare the report message ${{ github.action_path }}/update_pr_comment.sh - name: Generate Success Report + id: generate_success_comment if: ${{ env.SKIP_ACTION == 'false' && inputs.parent-workflow-conclusion != 'failure' }} @@ -189,5 +191,49 @@ runs: " - # post the error report to the PR + # prepare the report message ${{ github.action_path }}/update_pr_comment.sh + + - name: post pr comment + if: ${{ env.SKIP_ACTION == 'false' }} + uses: actions/github-script@v7 + env: + GH_TOKEN: ${{ inputs.gh-token }} + PR_NUMBER: ${{ steps.get_pr_number.outputs.pr_number }} + COMMENT_ID: + ${{ steps.generate_error_comment.outputs.comment_id || + steps.generate_success_comment.outputs.comment_id }} + WORKFLOW_STATUS: ${{ inputs.parent-workflow-conclusion }} + with: + script: | + const prNumber = process.env.PR_NUMBER; + const fs = require('fs'); + const message = fs.readFileSync('pr_message.md', 'utf8'); + const commentId = process.env.COMMENT_ID; + + // Create new comment if COMMENT_ID is empty + if ((!commentId || commentId.trim() === '')) { + // but only if the parent workflow failed or if the parent workflow succeeded and skip-on-success is false + if (process.env.WORKFLOW_STATUS === 'failure' + || (process.env.WORKFLOW_STATUS === 'success' && process.env.SKIP_ON_SUCCESS === 'false')) { + const newComment = await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: message + }); + console.log(`Created new comment with ID: ${newComment.data.id}`); + return newComment.data.id; + } + return ''; + } else { + // Edit existing comment if COMMENT_ID is present + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: commentId, + body: message + }); + console.log(`Updated existing comment with ID: ${commentId}`); + return commentId; + } diff --git a/actions/llm-action-error-reporter/update_pr_comment.sh b/actions/llm-action-error-reporter/update_pr_comment.sh index 62e402b2..691e2fcc 100755 --- a/actions/llm-action-error-reporter/update_pr_comment.sh +++ b/actions/llm-action-error-reporter/update_pr_comment.sh @@ -9,21 +9,22 @@ set -euo pipefail # - SKIP_ON_SUCCESS # Fetch the comments on the pull request and filter for comments by github.actor -author_comments=$(gh pr view "$PR_NUMBER" --json comments --jq '.comments | map(select(.author.login == "github-actions" and (.body | contains("## AER Report:"))))') +last_author_comment=$(gh pr view "$PR_NUMBER" --json comments --jq '( + .comments + | map(select(.author.login == "github-actions" and (.body | contains("## AER Report:")))) + | sort_by(.createdAt) + | reverse + | .[0] + )') # Get the latest comment body -latest_comment_body=$(gh pr view "$PR_NUMBER" --json comments --jq '( - .comments - | sort_by(.createdAt) - | last - | select(.author.login == "github-actions" and (.body | contains("## AER Report:"))) - | .body - ) - // "" - ') +last_comment_body=$(echo "$last_author_comment" | jq -r '.body // ""') +comment_id=$(echo "$last_author_comment" | jq -r '.url // ""' | perl -nle 'print $1 if /#issuecomment-(\d+)/') + +echo "found existing comment: $comment_id" # Check if comment exists and contains <$WORKFLOW_ID>... -if [[ "$latest_comment_body" == *"<$WORKFLOW_ID>"* && "$latest_comment_body" == *""* ]]; then +if [[ "$last_comment_body" == *"<$WORKFLOW_ID>"* && "$last_comment_body" == *""* ]]; then # Create a temporary sed script file sed_script=$(mktemp) @@ -38,19 +39,25 @@ if [[ "$latest_comment_body" == *"<$WORKFLOW_ID>"* && "$latest_comment_body" == echo "${PR_MESSAGE}" >> "$sed_script" # Perform the replacement using sed with the temporary script - PR_MESSAGE=$(echo "$latest_comment_body" | sed -f "$sed_script") + PR_MESSAGE=$(echo "$last_comment_body" | sed -f "$sed_script") # Remove the temporary sed script rm "$sed_script" - - gh pr comment $PR_NUMBER -b "$PR_MESSAGE" --edit-last else - # if no prior error(s) then don't clutter the PR with success message - if [ "${SKIP_ON_SUCCESS:-false}" == "false" ] && [[ "{{ inputs.parent-workflow-conclusion }}" != "failure" ]]; then - gh pr comment $PR_NUMBER -b "$PR_MESSAGE" + if [[ "$last_comment_body" != "" ]]; then + # AER comment already exists, edit the existing comment + PR_MESSAGE="${last_comment_body} + + ${PR_MESSAGE}" else - gh pr comment $PR_NUMBER -b "**Below is an analysis created by an LLM ($OPENAI_MODEL). Be mindful of hallucinations and verify accuracy.** - - $PR_MESSAGE" + if [[ "{{ inputs.parent-workflow-conclusion }}" == "failure" ]]; then + # AER comment does not exist, create a new comment + PR_MESSAGE="**Below is an analysis created by an LLM ($OPENAI_MODEL). Be mindful of hallucinations and verify accuracy.** + + $PR_MESSAGE" + fi fi fi + +echo "$PR_MESSAGE" > pr_message.md +echo "comment_id=$comment_id" >> "$GITHUB_OUTPUT"