Using the API to add Codacy Grade details to the Readme

Hélio Rocha
3 min readApr 13, 2021

Some context

Codacy has a badge mechanism that can be included in your Readme file. It gives you an idea of the grade of your repository, from A to F, but sometimes that’s just not enough.

Fortunately, the new Codacy V3 API gives us a lot of new endpoints with useful information.

In order to learn more about API consumption on pipelines, I’ve purposed myself to find a way to put these metrics on the Readme file of a sample repository with an handicap: will not use pre-commit.

Prerequisites — A Placeholder

Since the grade details tendentially changes in each commit, it’s wise to have a placeholder inside the README.md file that we can fill with a sed script. Something like:

# An amazing repository with code<!-- codacy-status --> 
<!-- /codacy-status -->

Hands on

My first idea was to use a GitHub Action on the main branch, call the API and update the readme file. It failed 🤬! My main branch is protected and Actions force commits into protected branches are not allowed. Yes, I know I can turn that off but it would defeat the purpose.

So the path is to trigger the action from the feature branches using the following GHA example:

name: Update Readmeon:
push:
branches-ignore:
- master
jobs:
update-readme:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
- name: update README.md with codacy status
run: |
RETRIES=0
ANALYZED=$(curl -X GET https://app.codacy.com/api/v3/analysis/organizations/gh/codacy-acme/repositories/nodeproject/commits/${GITHUB_SHA}/deltaStatistics -H 'api-token: ${{ secrets.API_TOKEN }}' | jq '.analyzed')
while [ $ANALYZED != "true" ]
do
sleep 10s
RETRIES=$((RETRIES+1))
if [ "$RETRIES" -gt "10" ]; then
echo "pipeline will exit due to max retries (10)"
exit 0
fi
ANALYZED=$(curl -X GET https://app.codacy.com/api/v3/analysis/organizations/gh/codacy-acme/repositories/nodeproject/commits/${GITHUB_SHA}/deltaStatistics -H 'api-token: ${{ secrets.API_TOKEN }}' | jq '.analyzed')
done
RESULT=$(curl https://app.codacy.com/api/v3/analysis/organizations/gh/codacy-acme/repositories/nodeproject | jq -r -j '["Grade: \(.data.grade) |", "Issues: \(.data.issuesPercentage)% |", "Complex Files: \(.data.complexFilesPercentage)% |", "Coverage: \(.data.coverage.coveragePercentage)%"]' | tr -d \" | tr -d \[ | tr -d \] | tr -d , | tr -d '\n')
sed -i ":a;N;\$!ba;s/\(<!-- codacy-status -->\).*\(<!-- \/codacy-status -->\)/\1 \n$RESULT\n \2/g" README.md
env:
CI: true
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "Update README.md with Project Grade"
file_pattern: README.md

In this snippet, we check if the commit is already analysed and, if it is, we’ll replace the content between the placeholder tags with the new metrics. There’s also a “max retries” mechanism in case PR doesn’t exist yet (other validation mechanisms can be considered here).

After the merge, README.md will have the current grade details

But there’s a…

Downside

Following this approach, there’s a huge limitation: the result will be the one before the merge. In order to avoid this, there’s a mandatory convention you should follow: do a rebase before merging.

Not perfect, I know but the purpose of this article is to demonstrate the power of the V3 API and how it can bring value outside the regular use cases. For instance, this endpoint can be used in a pipeline checkpoint.

Do you have any other “weird” use case? Let me know!

--

--