Show Latest Posts on Github Profile

4 minute read Published

How not to show latest posts on a GitHub profile. An adventure in debugging JavaScript libraries and GitHub actions when happy path is not the case.

I like to blog using the blogging tool I created called After Dark. After some time away from GitHub I began self-hosting my source code with {{ external “https://gitea.io/" “Gitea” />}}. Since the Microsoft acquisition there are some cool features in GitHub which have brought me back, at least to play around a little with what’s there.

One feature is the ability to showcase latest blog posts on a GitHub profile. I learned about this trick a couple of days ago while doing Kubernetes research for a project I’m working on during my semi-permanent remote placement in Bali.

In this post we’re going to take a look at the feature and see if it’ll be useful in helping showcase my writing for others when they visit my GitHub profile.

So I went ahead and started by creating my self-named repository and low and behold some secret sauce magic occurred as promised:

I then connected that to a new local folder with a template to show posts:

mkdir ~/Developer/vhs-gh-repo && cd "$_" && \
cat > README.md << EOF
# Recent Blog Posts
<!-- BLOG-POST-LIST:START -->
<!-- BLOG-POST-LIST:END -->
EOF
git init && git add -A && \
git commit -m "chore: add post template" && \
git branch -M main && \
git remote add origin git@github.com:vhs/vhs.git && \
git push -u origin main

Created a GH action to update the template every 3 minutes:

mkdir -p .github/workflows && \
cat > .github/workflows/recent_posts.yml << EOF
name: Recent posts workflow
on:
 schedule:
   - cron: '*/3 * * * *' 
 workflow_dispatch: 
jobs:
 update-readme-with-blog:
   name: Update repo README with recent blog posts
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v2
     - uses: gautamkrishnar/blog-post-workflow@master
       with:
         feed_list: https://example.com/post/index.xml
         max_post_count: 10
         template: "- `$date` | [$title]($url)  $newline"
         date_format: yyyy-mm-dd
         tag_post_pre_newline: true
EOF
git add -A && \
git commit -m "feat: add recent posts" && \
git push origin main

Three minutes later no recent posts were showing up:

So opened the repo and triggered the action manually. It bombed:

The error output by the GH action:

Error: Non-whitespace before first tag. Line: 0 Column: 1 Char: 

So I took a look at which RSS parser was being used by the action:

www.npmjs.com/package/rss-parser

And found the same issue reported almost two years ago closed:

github.com/rbren/rss-parser/issues/95

Digging deeper I noticed the underlying XML parser had seen the same issue reported 4 years ago and the author of that library said:

This should work out of the box, since xml2js has now code to remove the byte order mark before parsing.

Leonidas-from-XIV commented on Dec 6, 2016

So I decided to find out if what they said was true by pulling down my web feed and running it in a reduced test case:

curl -O https://example.com/post/index.xml
npm i -g xml2js@0.4.23

Where xml2js@0.4.23 is the latest version the RSS parsing library and the version which would’ve been installed by the GH action today based on the RSS library’s package manifest and based on tracing deps of the GH action library.

In the xml2js issue I mentioned a woman was kind enough to provide a script required to reproduce the error which I saved to a parse.js file:

const fs = require('fs');
const util = require('util')
const parseString = require('xml2js').parseString;
const fileToParse = ('./index.xml')
const outputFilename=('output.json')

fs.readFile(fileToParse, function (err, data) {
    parseString(data, function (err, result) {
        console.dir(result);
        if (err) {
            console.log(err)
        }
       // do something with the JS object called result, or see below to save as JSON
        fs.writeFile('output.json', JSON.stringify(result), (writeErr) => {
            if (writeErr) throw writeErr;
            console.log('The file has been saved to ' + outputFilename);
        });
    });
});

After running it with node parse.js with Node.js v12.14.1 I saw:

undefined
Error: Non-whitespace before first tag.
Line: 0
Column: 1
Char: 
    at error (/Users/jos/Developer/node_modules/sax/lib/sax.js:651:10)
    at strictFail (/Users/jos/Developer/node_modules/sax/lib/sax.js:677:7)
    at beginWhiteSpace (/Users/jos/Developer/node_modules/sax/lib/sax.js:951:7)
    at SAXParser.write (/Users/jos/Developer/node_modules/sax/lib/sax.js:1006:11)
    at Parser.exports.Parser.Parser.parseString (/Users/jos/Developer/node_modules/xml2js/lib/parser.js:323
:31)
    at Parser.parseString (/Users/jos/Developer/node_modules/xml2js/lib/parser.js:5:59)
    at exports.parseString (/Users/jos/Developer/node_modules/xml2js/lib/parser.js:369:19)
    at /Users/jos/Developer/vhs-gh-repo/parse.js:8:5
    at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:61:3)
The file has been saved to output.json

The exact same error reported by the GitHub action:

Error: Non-whitespace before first tag. Line: 0 Column: 1 Char: 

We now know the issue is somewhere in the XML parser. We also know that when someone says “should work out of the box” it’s not the same as saying “does work out of the box”. But we still don’t know exactly what the issue is.

So I opened a new issue against the parsing library. And perhaps one day I’ll be able to add recent posts to my GH profile too. But probably not today.