Skip to content

Commit

Permalink
Merge pull request #3173 from esl/mu-publish-github-comment-from-circ…
Browse files Browse the repository at this point in the history
…le-ci

Publish a comment from CircleCI to Github
  • Loading branch information
NelsonVides authored Jul 5, 2021
2 parents 6a1899b + cd8c707 commit 5624bf9
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ orbs:
command: |
tools/circleci-prepare-log-dir.sh
if [ -n "${AWS_SECRET_ACCESS_KEY}" ]; then tools/circleci-upload-to-s3.sh; fi
- run:
name: Publish a comment to GitHub
when: always
command: |
tools/circle-publish-github-comment.sh
package:
parallelism: 1
Expand Down Expand Up @@ -265,6 +270,11 @@ orbs:
command: |
tools/circleci-prepare-log-dir.sh
if [ -n "${AWS_SECRET_ACCESS_KEY}" ]; then tools/circleci-upload-to-s3.sh; fi
- run:
name: Publish a comment to GitHub
when: always
command: |
tools/circle-publish-github-comment.sh
docker_image:
parallelism: 1
Expand Down
228 changes: 228 additions & 0 deletions tools/circle-publish-github-comment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
#!/usr/bin/env bash

source tools/circleci-helpers.sh

set -e

if [ -z "$CIRCLE_BRANCH" ]; then
echo "\$CIRCLE_BRANCH is empty. Do nothing"
exit 0
fi

if [ -z "$CIRCLE_PULL_REQUEST" ]; then
echo "\$CIRCLE_PULL_REQUEST is empty. Do nothing"
exit 0
fi

if [ "$CIRCLE_PULL_REQUEST" = "false" ]; then
echo "Not a pull request. Do nothing"
exit 0
fi

if [ -z "$COMMENTER_GITHUB_TOKEN" ]; then
echo "\$COMMENTER_GITHUB_TOKEN is empty. Do nothing"
exit 0
fi


# COMMENTER_GITHUB_USER is nickname of a special github user.
# COMMENTER_GITHUB_TOKEN is token with scope public repo.
# Token can be obtained here https://github.com/settings/tokens/new
# Don't use ANY REAL user as a commenter, because GitHub access scopes are too wide.
echo "Used vars (you can use them to debug locally):"
echo "export COMMENTER_GITHUB_TOKEN=fillme"
echo "export COMMENTER_GITHUB_USER=$COMMENTER_GITHUB_USER"
echo "export PRESET=$PRESET"
echo "export CIRCLE_SHA1=$CIRCLE_SHA1"
echo "export CIRCLE_BUILD_URL=$CIRCLE_BUILD_URL"
echo "export CIRCLE_JOB=$CIRCLE_JOB"
echo "export CIRCLE_PROJECT_USERNAME=$CIRCLE_PROJECT_USERNAME"
echo "export CIRCLE_PROJECT_REPONAME=$CIRCLE_PROJECT_REPONAME"
echo "export CIRCLE_PULL_REQUEST=$CIRCLE_PULL_REQUEST"

PR_NUM="${CIRCLE_PULL_REQUEST##*/}"

REPO_SLUG="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME"

# IF we only run small tests, the file is missing
touch /tmp/ct_markdown

PRESET="${PRESET:-default}"

function remove_ct_log_links
{
mv /tmp/ct_markdown /tmp/ct_markdown_original
# grep fails if nothing matches
{ grep -v "Report log" /tmp/ct_markdown_original || echo ""; } > /tmp/ct_markdown
}

# https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
function replace_string {
sed -i "s/$( \
echo "$1" | sed -e 's/\([[\/.*]\|\]\)/\\&/g' \
| sed -e 's:\t:\\t:g' \
)/$( \
echo "$2" | sed -e 's/[\/&]/\\&/g' \
| sed -e 's:\t:\\t:g' \
)/g" "$3"
}

function rewrite_log_links_to_s3
{
local CT_REPORT=big_tests/ct_report
local CT_REPORT_ABS=$(./tools/abs_dirpath.sh "$CT_REPORT")
local CT_REPORTS=$(ct_reports_dir)
local BIG_TESTS_URL="$(direct_s3_url ${CT_REPORTS})/big"
cp /tmp/ct_markdown /tmp/ct_markdown_original
replace_string "$CT_REPORT_ABS" "$BIG_TESTS_URL" /tmp/ct_markdown
# URL escape for s3_reports.html script
replace_string "ct_run.test@" "ct_run.test%40" /tmp/ct_markdown
}

function last_ct_run_name
{
ls -1 -t big_tests/ct_report/ | grep ct_run | head -n1
}


function small_suite_path
{
if [ -d _build/test/logs ]; then
cd _build/test/logs
ls -t -1 ct_run.mongooseim@localhost.*/lib.mongooseim.logs/run.*/suite.log.html
cd ../../..
fi
}

function ct_run_url
{
local CT_REPORTS=$(ct_reports_dir)
local BIG_TESTS_URL="$(direct_s3_url ${CT_REPORTS})/big"
local RUN_PART=$(echo "$(last_ct_run_name)" | sed "s/@/%40/g")
echo "$BIG_TESTS_URL/$RUN_PART/index.html"
}

function ct_small_url
{
local CT_REPORTS=$(ct_reports_dir)
local SMALL_TESTS_URL="$(direct_s3_url ${CT_REPORTS})/small"
local SUFFIX=$(small_suite_path)
echo "$SMALL_TESTS_URL/$SUFFIX"
}

function reports_url
{
local CT_REPORTS=$(ct_reports_dir)
# Something like that:
# http://esl.github.io/circleci-mim-results/s3_reports.html?prefix=PR/3173/60934/pgsql_mnesia.23.0.3-1
s3_url "${CT_REPORTS}"
}

if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
REPORTS_URL_BODY="Reports are not uploaded"$'\n'
remove_ct_log_links
else
REPORTS_URL="$(reports_url)"
CT_RUN_URL="$(ct_run_url)"
SMALL_CT_URL="$(ct_small_url)"
REPORTS_BIG_URL_BODY=""
REPORTS_SMALL_URL_BODY=""
if [ -f big_tests/ct_report/index.html ]; then
rewrite_log_links_to_s3
REPORTS_BIG_URL_BODY="/ [big]($CT_RUN_URL)"
fi
if [ -d _build/test/logs ]; then
REPORTS_SMALL_URL_BODY=" / [small]($SMALL_CT_URL)"
fi
REPORTS_URL_BODY="Reports [root](${REPORTS_URL})${REPORTS_BIG_URL_BODY}${REPORTS_SMALL_URL_BODY}"$'\n'
fi

COUNTERS_FILE=/tmp/ct_stats_vars
COUNTERS_BODY=""
if [ -f "$COUNTERS_FILE" ]; then
. "$COUNTERS_FILE"
COUNTERS_BODY="**OK: $CT_COUNTER_OK** "
if [ "$CT_COUNTER_FAILED" != "0" ]; then
COUNTERS_BODY="$COUNTERS_BODY/ **Failed: $CT_COUNTER_FAILED** "
else
COUNTERS_BODY="$COUNTERS_BODY/ Failed: 0 "
fi
if [ "$CT_COUNTER_USER_SKIPPED" != "0" ]; then
COUNTERS_BODY="$COUNTERS_BODY/ **User-skipped: $CT_COUNTER_USER_SKIPPED** "
else
COUNTERS_BODY="$COUNTERS_BODY/ User-skipped: 0 "
fi
if [ "$CT_COUNTER_AUTO_SKIPPED" != "0" ]; then
COUNTERS_BODY="$COUNTERS_BODY/ **Auto-skipped: $CT_COUNTER_AUTO_SKIPPED** "
else
COUNTERS_BODY="$COUNTERS_BODY/ Auto-skipped: 0 "
fi
COUNTERS_BODY="$COUNTERS_BODY"$'\n'
fi

TRUNCATED_BODY=""
# Number of truncated failed tests if file exists
TRUNCATED_FILE="/tmp/ct_markdown_truncated"
if [ -f "$TRUNCATED_FILE" ]; then
TRUNCATED_COUNTER=$(cat "$TRUNCATED_FILE")
TRUNCATED_BODY=$'\n'$'\n'"$TRUNCATED_COUNTER errors were truncated"
fi

# Link to a CircleCI job
JOB_URL="$CIRCLE_BUILD_URL"
DESC_BODY="[$CIRCLE_JOB]($JOB_URL) / $PRESET / $CIRCLE_SHA1"$'\n'
# This file is created by ct_markdown_errors_hook
ERRORS_BODY="$(cat /tmp/ct_markdown || echo '/tmp/ct_markdown missing')"
BODY="${DESC_BODY}${REPORTS_URL_BODY}${COUNTERS_BODY}${ERRORS_BODY}${TRUNCATED_BODY}"

function post_new_comment
{
# Create a comment GitHub API doc
# https://developer.github.com/v3/issues/comments/#create-a-comment
echo "Posting a new comment"
POST_BODY=$(BODY_ENV="$BODY" jq -n '{body: env.BODY_ENV}')
curl -o /dev/null -i \
-H "Authorization: token $COMMENTER_GITHUB_TOKEN" \
-H "Content-Type: application/json" \
-X POST -d "$POST_BODY" \
https://api.github.com/repos/$REPO_SLUG/issues/$PR_NUM/comments
}

function append_comment
{
# Concat old comment text and some extra text
# Keep a line separator between them
# $'\n' is a new line in bash
#
# Edit commment GitHub API doc
# https://developer.github.com/v3/issues/comments/#edit-a-comment
COMMENT_ID="$1"
echo "Patch comment $COMMENT_ID"
BODY_FROM_GH="$(cat /tmp/gh_comment | jq -r .body)"
BODY="${BODY_FROM_GH}"$'\n'$'\n'"---"$'\n'$'\n'"${BODY}"
PATCH_BODY=$(BODY_ENV="${BODY}" jq -n '{body: env.BODY_ENV}')
curl -o /dev/null -i \
-H "Authorization: token $COMMENTER_GITHUB_TOKEN" \
-H "Content-Type: application/json" \
-X PATCH -d "$PATCH_BODY" \
https://api.github.com/repos/$REPO_SLUG/issues/comments/$COMMENT_ID
}

# List comments
# https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue
curl -s -S -o /tmp/gh_comments -L \
-H "Authorization: token $COMMENTER_GITHUB_TOKEN" \
-H "Content-Type: application/json" \
https://api.github.com/repos/$REPO_SLUG/issues/$PR_NUM/comments

# Filter out all comments for a particular user
# Then filter out all comments that have a git commit rev in the body text
# Then take first comment (we don't expect more comments anyway)
cat /tmp/gh_comments | jq "map(select(.user.login == \"$COMMENTER_GITHUB_USER\")) | map(select(.body | contains(\"$CIRCLE_SHA1\")))[0]" > /tmp/gh_comment
COMMENT_ID=$(cat /tmp/gh_comment | jq .id)

if [ "$COMMENT_ID" = "null" ]; then
post_new_comment
else
append_comment "$COMMENT_ID"
fi

0 comments on commit 5624bf9

Please sign in to comment.