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:
- Get my Dev.to articles
- Parse my README
- 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
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();
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.
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)
That's awesome!
Yh it's really awesome