DEV Community

Cover image for Self-updating GitHub Profile README with JavaScript
Dan Curtis
Dan Curtis

Posted on

Self-updating GitHub Profile README with JavaScript

GitHub recently released a feature that allows users to add markdown to their profile. People have done some pretty cool things, which inspired me to create a README that dynamically updates with my Dev.to posts. Here's the link to my GitHub repo, which has a live example!

GitHub Actions and NodeJS make this easy. I created a script to:

  1. Get my Dev.to articles
  2. Parse my README
  3. Update the README with my latest articles

GitHub Actions make it possible to schedule automatic runs of a program at timed intervals, known as a cron job.

I currently have my GitHub Action Workflow configured to run the script three times a week. I thought this would push me to publish articles three times a week, but that hasn't happened yet...

You'll need 3 files: .github/workflows/build.yaml, updateReadme.js, and README.md. Without further ado, here's the code:

.github/workflows/build.yaml

# Name of workflow
name: Build README

# Run workflow at 12:01 on Sunday, Wednesday, and Friday
on:
  schedule:
    - cron: '1 12 * * 0,3,5'
  # Run workflow on pushes to main branch
  push:
    branches:
      - main

# Steps to carry out
jobs:
  build:
    # Create a ubuntu virtual machine
    runs-on: ubuntu-latest

    # Checkout repo code
    steps:
    - name: Checkout repo
      uses: actions/checkout@v2

    # Install node
    - name: Use Node.js
      uses: actions/setup-node@v1
      with:
        node-version: 10.16
    - run: npm install
    - run: npm run build --if-present
    - run: npm test
      env:
        CI: true

    # Run script "updateReadme.js" 
    - name: Update README
      run: |-
        node updateReadme.js
        cat README.md

    # Commit changes
    - name: Commit and push if changed
      run: |-
        git diff
        git config --global user.email "readme-bot@example.com"
        git config --global user.name "README-bot"
        git add -A
        git commit -m "Updated articles" || exit 0
        git push
Enter fullscreen mode Exit fullscreen mode

updateReadme.js

// Include node fs (file stream) and https modules
const fs = require('fs');
const https = require('https');

// API endpoint
const url = 'https://dev.to/api/articles?username=<YOUR DEV USERNAME>';

function readWriteAsync() {
  // Get articles using HTTPS
  https.get(url, (res) => {
    res.setEncoding('utf8');

    // Set variable body to response data from API
    let body = '';
    res.on('data', (data) => body += data);

    res.on('end', () => {
      // Parse the JSON response
      body = JSON.parse(body);

      // Shorten array to latest 3 articles
      body = body.slice(0, 3);

      // Create string of markdown to be inserted
      const articles = `\n - [${body[0].title}](${body[0].url})\n - [${body[1].title}](${body[1].url})\n - [${body[2].title}](${body[2].url})\n \n`;

      // Update README using FS
      fs.readFile('README.md', 'utf-8', (err, data) => {
        if (err) {
          throw err;
        }

        // Replace text using regex: "I'm writing: ...replace... ![Build"
        // Regex101.com is a lifesaver!
        const updatedMd = data.replace(
          /(?<=I'm writing:\n)[\s\S]*(?=\!\[Build)/gim,
          articles
        );

        // Write the new README
        fs.writeFile('README.md', updatedMd, 'utf-8', (err) => {
          if (err) { 
            throw err;
          }

          console.log('README update complete.');
        });
      });
    });
  });
}

// Call the function
readWriteAsync();
Enter fullscreen mode Exit fullscreen mode

README.md

# Self-updating README

This text won't be change.

The text below will be, though!

What I'm writing:

- This will be replaced
- This too!
- This three!

![Build README](https://github.com/<YOUR GITHUB USERNAME>/<YOUR GITHUB USERNAME>/workflows/Build%20README/badge.svg)

This won't be impacted either. The text above is a GitHub build badge.
Enter fullscreen mode Exit fullscreen mode

I tried to explain what the code is doing with comments, which makes the code look longer/more daunting than it is. GitHub Action's documentation and this README cheatsheet are excellent if you're just getting started with either. Here's another link to my GitHub repo, to see it live!

What are your README tips for this new feature? 👀

Top comments (2)

Collapse
 
matoval profile image
matoval

That's awesome!

Collapse
 
asiedu13 profile image
Asiedu13

Yh it's really awesome