How to Automate Your GitHub Profile README

Header image of an automated GitHub profile README

If you‘ve spent much time browsing GitHub profiles lately, you may have noticed more and more of them sporting a slick-looking profile-level README. GitHub recently added this feature to allow users to showcase their work, introduce themselves, and add some personality to their profile landing page.

Many developers are taking the opportunity to get creative with their profile READMEs – adding images, GIFs, fancy formatting, and more. But one of the coolest tricks is to make your README dynamic by automatically updating it with your latest projects, blog posts, tech tweets, or anything else you dream up.

In this guide, I‘ll walk you through how to automate your GitHub profile README from top to bottom. We‘ll cover:

  • Creating a template README with placeholders for dynamic content
  • Writing a Python script to populate the README with live data
  • Configuring a GitHub Action to update your README on a schedule

By the end, you‘ll have a self-updating README that stays fresh with your latest content. Let‘s dive in!

Step 1: Create Your README Template

The first step is to create a template for your README with space for the dynamic bits you want to include. You‘ll write this in regular GitHub Flavored Markdown, with a few placeholders sprinkled in.

For example, let‘s say you want to always feature your most recent blog post and your latest GitHub repository releases. Here‘s what a simple template might look like:

### Hi there 👋 I‘m [Your Name]

- 🔭 I‘m currently working on [Cool Project]
- 🌱 I‘m currently learning [New Skill]
- 👯 I‘m looking to collaborate on [Type of Project] 
- 💬 Ask me about [Area of Expertise]

### 📕 Latest Blog Posts

<!-- BLOG-POST-LIST:START -->
<!-- BLOG-POST-LIST:END -->

### 🔨 Latest Releases

<!-- RELEASES-LIST:START -->
<!-- RELEASES-LIST:END -->

The funky looking <!-- --> bits are HTML comments that will act as placeholders for our dynamic content. The Python script we write next will look for those placeholders and replace them with live data.

Step 2: Fetch Dynamic Data with Python

Now for the fun part – writing a Python script to pull in live data from around the web and update your template with it. For this example, we‘ll fetch your latest blog posts from an RSS feed and your recently released GitHub repositories using the GitHub API.

First, let‘s parse the README template and locate the placeholders using regular expressions:

import re

with open(‘template.md‘, ‘r‘) as file:
    template = file.read()

blog_pattern = r"<!-- BLOG-POST-LIST:START -->.*<!-- BLOG-POST-LIST:END -->"
releases_pattern = r"<!-- RELEASES-LIST:START -->.*<!-- RELEASES-LIST:END -->"

Next, let‘s fetch the blog posts from an RSS feed using the feedparser library:

import feedparser

blog_rss_url = "https://yoursite.com/rss"
feed = feedparser.parse(blog_rss_url)

latest_posts = []
for post in feed.entries[:5]:
    latest_posts.append(f"- [{post.title}]({post.link})")

blog_text = "\n".join(latest_posts)

This grabs your 5 most recent blog posts, formats them in Markdown, and joins them together into a single string.

Now let‘s use the GitHub API to fetch a list of your latest releases:

import requests

github_username = "yourusername" 
url = f"https://api.github.com/users/{github_username}/repos?sort=pushed&direction=desc"

response = requests.get(url)
repos = response.json()

latest_releases = []
for repo in repos[:5]:
    if repo["has_releases"]:
        release_url = f"https://api.github.com/repos/{github_username}/{repo[‘name‘]}/releases/latest"
        release_response = requests.get(release_url)
        release = release_response.json()
        latest_releases.append(f"- [{repo[‘name‘]} {release[‘tag_name‘]}]({release[‘html_url‘]})")

releases_text = "\n".join(latest_releases)

This code fetches your repositories, sorted by most recently pushed, and checks each one for a release. It grabs the most recent release from each of your top 5 repos and compiles them into a Markdown list.

Finally, we replace the placeholders in the template with our shiny new dynamic text:

template = re.sub(blog_pattern, f"<!-- BLOG-POST-LIST:START -->\n{blog_text}\n<!-- BLOG-POST-LIST:END -->", template)
template = re.sub(releases_pattern, f"<!-- RELEASES-LIST:START -->\n{releases_text}\n<!-- RELEASES-LIST:END -->", template)

with open(‘README.md‘, ‘w‘) as file:
    file.write(template)

Boom! Your template is now updated with your latest content. The last step is to automate this bad boy.

Step 3: Automate with GitHub Actions

To keep your README populated with fresh data, you‘ll want to run this Python script on a recurring basis. That‘s where GitHub Actions comes in handy.

Actions allow you to automate tasks based on triggers like pushing a commit, opening a PR, or on a set schedule. In our case, we‘ll run our README updater every day using the schedule event.

Here‘s what the workflow YAML configuration looks like:

name: Update README

on:
  schedule:
    - cron: ‘0 * * * *‘ # runs every hour
  workflow_dispatch: # lets you run workflow manually from Actions tab

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.8
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install feedparser requests
      - name: Update README
        run: python update_readme.py
      - name: Commit changes
        run: |
          git config --local user.email "[email protected]"
          git config --local user.name "GitHub Action"
          git add -A
          git commit -m "Updated README with latest info"
          git push

This configuration tells GitHub to:

  1. Check out your repository
  2. Set up a Python environment and install the necessary libraries
  3. Run your Python script to update the README
  4. Commit the changes and push them back to your repo

With this workflow in place, your README will be refreshed every single day, no manual effort required on your part. Pretty nifty, right?

Ideas for Dynamic GitHub README Content

The beauty of this technique is that it‘s super flexible – you can populate your README with just about anything you can pull data for using Python. Here are a few other ideas of what you could include:

  • Your latest tweets or Twitter metrics using the Twitter API
  • Stats from your GitHub profile like stars, forks, PRs, etc. using the GitHub API
  • A list of your most recent YouTube videos if you have a channel
  • New posts or followers from Instagram, TikTok, etc. via their respective APIs
  • Links to your latest DEV/Hashnode/Medium articles
  • Really any other data you want to expose via an API!

Mixing in a few of these auto-updating elements is an awesome way to keep your profile feeling fresh and showcase what you‘ve been working on lately.

Wrapping Up

Hopefully this guide has shown you how easy it is to take your GitHub profile README to the next level by automating parts of it with Python and GitHub Actions.

The specific APIs and data points you include are totally up to you – feel free to get creative and personalize things to your heart‘s content. You could even combine this with other fun profile README tricks like animated text, badges, and interactive widgets.

However you choose to spruce up your README, automating the content is an excellent way to keep it current without extra ongoing effort. So go forth and build an awesome auto-updating profile that shows off the latest and greatest of YOU!

For more GitHub Actions tips, Python automation ideas, and other coding tutorials, you can find me on Twitter @yourtwitterhandle. Happy coding!

Similar Posts