7

Make Your Github Profile Dynamic - Ravi Rupareliya

 2 years ago
source link: https://www.ravirupareliya.com/blog/make-your-github-profile-dynamic/?amp%3Butm_medium=rss&%3Butm_campaign=make-your-github-profile-dynamic
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Home Github Make Your Github Profile Dynamic

Make Your Github Profile Dynamic

banner_github.png?fit=750%2C375&ssl=1

Yes, You read it right. You don’t have to do anything and your profile will be updated with dynamic contents.

Let me first give you an overview of Github hidden repository. Earlier we used to create github pages to create own portfolio but recently github has revealed a secret where you can create a repo of your username and it will be shown as home page whenever someone visits your profile.

Bit complicated? Look at the below image

Github profile dynamic

If you remember, there was just a section of pinned repo and contributions, but now with this change people can see your portfolio as well.

For every github user, there is hidden repo, you just have to create a repository and name it same as your github username. That’s it, there you have your own portfolio repo. Now add as many content you want in readme.md file and it will be shown to home page of your github profile.

What kind of things you can include?

  • You can include your own words which describe yourself.
  • Social media profiles.
  • Blogposts.
  • Youtube videos.
  • Projects you have worked.
  • Contributions you are doing on various platform.
  • Applications/websites that you have built.

If you are confused on what to include in readme file, here are some repos which has list of various readme files.

Interesting?

But now problem arise, imagine you are writing blogs on daily or weekly basis, or posting videos on youtube or other platform. Will you be able to update readme file on regular basis? Will you be able to keep it updated whenever you post blog/article/video?

Well, you can, but it’s bit difficult and you have to keep this in your bucket list whenever you post something.

Here comes the actual thing that I want to share.

What if we will make our github profile dynamic?

What if it will just read your blog feed or video feed and update readme file on regular basis by its own? Yes, we can do it by writing few piece of code.

Before going through further I will assume you are having basic knowledge of Github Action and Node.js, because this is what we are going to use further.

Let’s do some code now

First step will be to create .yml file in your repository inside .github/workflow

For this tutorial, I will name it as instagram-post-workflow.yml

name: Instagram post
  workflow_dispatch:
  schedule:
    - cron:  '0 13 * * *'
jobs:
  build:
    runs-on: macOS-latest
    strategy:
        matrix:
          node-version: [12.x]
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - name: Install dependencies
      run: |
        npm ci
    - name: Update README
      run: |-
        npm start
        cat README.md
    - name: Commit and push if changed
      run: |-
        git add .
        git diff
        git config --global user.email "[email protected]"
        git config --global user.name "Ravi Rupareliya"
        git commit -m "Instagram feed updated." -a || echo "No changes to commit"
        git push

This is basically a cron job, which will run at 1PM UTC time. You can look into document for more detail about how you can set different schedule time

Once you are done with .yml file creation, you need to create package.json file and index.js on root of your repository.

package.json

  "name": "ravirupareliya",
  "version": "0.0.1",
  "description": "Instagram feed generate",
  "main": "feed.js",
  "scripts": {
    "start": "node index.js"
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ravirupareliya/ravirupareliya.git"
  "author": "Ravi Rupareliya",
  "license": "GPL-3.0",
  "bugs": {
    "url": "https://github.com/ravirupareliya/ravirupareliya/issues"
  "homepage": "https://github.com/ravirupareliya/ravirupareliya#readme",
  "dependencies": {
    "@actions/core": "^1.2.4",
    "process": "latest",
    "axios": "^0.19.2"
  "devDependencies": {
    "jshint": "^2.11.1",
    "mocha": "^8.1.1",
    "parcel-bundler": "^1.12.4"

index.js

const process = require('process');
const axios = require('axios');
const core = require('@actions/core');
const fs = require('fs');
const exec = require('./exec');
const buildReadme = (previousContent, newContent) => {
  const tagToLookFor = `<!-- insta-feed:`;
  const closingTag = '-->';
  const startOfOpeningTagIndex = previousContent.indexOf(
    `${tagToLookFor}START`,
  const endOfOpeningTagIndex = previousContent.indexOf(
    closingTag,
    startOfOpeningTagIndex,
  const startOfClosingTagIndex = previousContent.indexOf(
    `${tagToLookFor}END`,
    endOfOpeningTagIndex,
    startOfOpeningTagIndex === -1 ||
    endOfOpeningTagIndex === -1 ||
    startOfClosingTagIndex === -1
    // Exit with error if comment is not found on the readme
    core.error(
      `Cannot find the comment tag on the readme:\n<!-- ${tagToLookFor}:START -->\n<!-- ${tagToLookFor}:END -->`
    process.exit(1);
  return [
    previousContent.slice(0, endOfOpeningTagIndex + closingTag.length),
    '\n',
    newContent,
    '\n',
    previousContent.slice(startOfClosingTagIndex),
  ].join('');
* Code to do git commit
* @return {Promise<void>}
const commitReadme = async () => {
  // Getting config
  const committerUsername = 'Ravi Rupareliya';
  const committerEmail = '[email protected]';
  const commitMessage = 'Instagram feed updated.';
  // Doing commit and push
  await exec('git', [
    'config',
    '--global',
    'user.email',
    committerEmail,
  await exec('git', ['config', '--global', 'user.name', committerUsername]);
  await exec('git', ['add', README_FILE_PATH]);
  await exec('git', ['commit', '-m', commitMessage]);
  await exec('git', ['push']);
  core.info("Readme updated successfully.");
  // Making job fail if one of the source fails
  process.exit(jobFailFlag ? 1 : 0);
// Total no of posts to display on readme, all sources combined, default: 5
const TOTAL_POST_COUNT = 12;
// Readme path, default: ./README.md
const README_FILE_PATH = './README.md';
let postsArray = []; // Array to store posts
let jobFailFlag = false; // Job status flag
let siteUrl = 'https://www.instagram.com/ravi.rupareliya/?__a=1';
axios.get(siteUrl)
  .then(response => {
    const responsePosts = response.data.graphql.user.edge_owner_to_timeline_media.edges;
    postsArray = responsePosts
      .map((item) => {
        return {
          url: item.node.thumbnail_resources[0].src
    postsArray = postsArray.slice(0, TOTAL_POST_COUNT);
    if (postsArray.length > 0) {
        const readmeData = fs.readFileSync(README_FILE_PATH, "utf8");
        const postListMarkdown = postsArray.reduce((acc, cur, index) => {
          // Default template: - [$title]($url)
          let startTag = '', endTag = ''
          if (index === 0 || index === 3 || index === 6 || index === 9) {
            startTag = '<p align=\"center\">\n'
          if (index === 2 || index === 5 || index === 8 || index === 11) {
            endTag = '</p>\n'
          return acc + startTag + `<img align="center" src=${cur.url} />\n` + endTag;
        }, '');
        const newReadme = buildReadme(readmeData, postListMarkdown);
        // if there's change in readme file update it
        if (newReadme !== readmeData) {
          core.info('Writing to ' + README_FILE_PATH);
          fs.writeFileSync(README_FILE_PATH, newReadme);
          if (!process.env.TEST_MODE) {
            // noinspection JSIgnoredPromiseFromCall
            commitReadme();
        } else {
          core.info('No change detected, skipping');
          process.exit(0);
      } catch (e) {
        core.error(e);
        process.exit(1);
    } else {
      core.info("0 blog posts fetched");
      process.exit(jobFailFlag ? 1 : 0);
  .catch(error => {
    core.error(' runner failed, please verify the configuration. Error:');
    core.error(error);

You will also need exec.js file,

const {spawn} = require('child_process');
const exec = (cmd, args = [], options = {}) => new Promise((resolve, reject) => {
  console.log(`Started: ${cmd} ${args.join(' ')}`);
  const optionsToCLI = {
    ...options
  if (!optionsToCLI.stdio) {
    Object.assign(optionsToCLI, {stdio: ['inherit', 'inherit', 'inherit']});
  const app = spawn(cmd, args, optionsToCLI);
  app.on('close', (code) => {
    if (code !== 0) {
      const err = new Error(`Invalid status code: ${code}`);
      err.code = code;
      return reject(err);
    return resolve(code);
  app.on('error', reject);
module.exports = exec;

This is not must need file, you can have this logic inside index.js also. This is for safe side we are creating separate file and validating commands.

Once you have above code, you are almost done with the things. Only part that needs to be done now is, adding tag in readme.md file. If you have observed index.js file, you might have seen we are looking for some tags in readme file to add content inside it.

Just add below tag in readme.md file

<!-- insta-feed:START-->
<!-- insta-feed:END-->

and you are done, all dynamic instagram feed will be added within this tag.

Github profile dynamic

For detail code, you can look into my github repo Ravi Rupareliya

Reference links:

Do share your readme file in comment section, let’s see how creative you are and what have you done with readme file to portrait your profile.

Ravi Rupareliya

He loves to explore new technologies and have worked on Android, React Native, Action on Google and Flutter.

Ravi Rupareliya August 25, 2020


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK