Dynamic GitHub profile README with Github Actions and PHP
Last updated: 2021-01-11 :: Published: 13/08/2020 :: [ history ]You can also subscribe to the RSS or Atom feed, or follow me on Twitter.
A few weeks ago, GitHub quietly released a feature that was quickly noticed by the community – profile READMEs. A profile README is a global README
file for your GitHub profile, which you can set up by creating a public repository whose name is identical to your GitHub username. For instance, as my username is osteel
, I created the osteel/osteel
repository.
A little box like this one should appear while you add your own:
Once the repository is created, add a README
file with a short description explaining how great you are, and your GitHub profile page will display its content by default:
Neat and simple.
As I was browsing examples for some inspiration, I stumbled upon Simon Willison's version, which features some dynamic content like recent work and blog publications. He explained how he used a combination of GitHub Actions and Python to achieve this in a blog post, and I decided to do something similar with PHP.
The placeholder
The first thing to do is to create a placeholder in the README
file where the dynamic content will go. Since I wanted to automatically insert the latest publications of my blog, I used the following tags:
<!-- posts --><!-- /posts -->
You might recognise this format; since Markdown files also support HTML, I used some HTML comment tags to make sure they wouldn't show up on my profile page.
The PHP script
I can't remember the last time I wrote some PHP without a framework; as a result, I had to do a quick search just to get started with a basic PHP script and some Composer dependencies.
Turn out it's quite simple! The first step is to initialise the project with the following command:
$ composer init
From there, I installed a lightweight library to parse my blog's RSS feed:
$ composer require dg/rss-php
I then added a posts.php
file at the root of the project, with the following content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php
// Load Composer's autoload
require_once __DIR__ . '/vendor/autoload.php';
// Load the RSS feed
$feed = Feed::loadRss('https://tech.osteel.me/feeds/rss.xml')->toArray();
// Generate the list of blog posts
$posts = '';
foreach (array_slice($feed['item'], 0, 5) as $post) {
$date = date('d/m/Y', strtotime($post['pubDate']));
$posts .= sprintf("\n* **[%s]** [%s](%s \"%s\")", $date, $post['title'], $post['link'], $post['title']);
}
// Generate the new content
$content = preg_replace(
'#<!-- posts -->.*<!-- /posts -->#s',
sprintf('<!-- posts -->%s<!-- /posts -->', $posts),
file_get_contents('README.md')
);
// Overwrite the file
file_put_contents('README.md', $content);
|
Nothing too complicated here – Composer's autoload is required at the top, allowing me to load the RSS parser to generate a list of blog posts as a string, in Markdown format.
The existing content of the README
file is then loaded into the $content
variable, and the Markdown string is inserted between its <!-- posts -->
and <!-- /posts -->
tags with preg_replace
.
Finally, the file's entire content is replaced with the new one, using the file_put_contents
function.
The GitHub action
GitHub Actions are a fairly recent addition to GitHub, allowing developers to automate various CI/CD tasks, like running test suites or deploying web services.
They must be defined using YAML format in a .github/workflows
folder at the root of the project, and contain a list of steps that they are to execute.
Here's mine, which I named posts.yml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | name: Update blog posts
on:
push:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v2
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
- name: Install Composer dependencies
run: composer install
- name: Insert blog posts
run: php posts.php
- name: Push changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Updated latest blog posts
|
Again, nothing too complicated. We first give the action a name, and then define a list of events that should trigger it – pushing some code to the repository, a manual trigger from the interface (workflow_dispatch
), or periodically like a cron job (here, every day at midnight).
We then indicate that the action should run on an Ubuntu image, where it will:
- clone the repository;
- instal PHP 7.4;
- instal the Composer dependencies;
- run the PHP script;
- commit and push the changes, if any.
That's it! My GitHub profile is now automatically updated every time I publish a new article.
Conclusion
This was a quick experiment aiming at exploring GitHub Actions, which I expect to use more and more in the future. It was also fun to use PHP as a simple scripting language again, in a procedural way.
I've voluntarily left out a few things in order to keep this article short and simple – please refer to the repository for implementation details.
Resources
- Managing your profile README
- GitHub Actions
- This article’s repository
- GitHub Action: Checkout V2
- GitHub Action: Setup PHP
- GitHub Action: Git Auto Commit
You can also subscribe to the RSS or Atom feed, or follow me on Twitter.