DEV Community

Rob Bos
Rob Bos

Posted on

Automatically cross-publish posts from my blog to dev.to

What?

I use my RSS feed to cross publish my blogposts from devopsjournal.io to https://dev.to, but I have to wait until the background job at dev.to picks up the changes. It seems to run every couple of hours or so. After the job has ran, I need to log in to dev.to and publish any new posts that have been found.

The main reason for this way of working is of course that you need to verify if all your markup comes through correctly. Fortunately my blog comes in perfectly so far, so I wanted to automate this step.

Implementing this in a workflow is a perfect fit for me, since my blog is running on GitHub Pages, so I push my changes into a GitHub repo anyway, and can kick off a workflow!

Submission Category:

  • Maintainer Must-Haves
  • DIY Deployments

Yaml File or Link to Code

The workflow can be found here and thus is actively in use for my own blog!

on:
  workflow_dispatch:

  schedule:
    - cron: "0 3 * * *"

jobs:
  sync:
    runs-on: ubuntu-latest
    concurrency: once
    steps:
      - uses: actions/checkout@v2
      - run: npm install axios
      - name: Sync to dev-to
        uses: actions/github-script@v5
        with:
          script: |
             const devtoToken = "${{ secrets.DEVTO_API_TOKEN }}"
             const script = require('.github/workflows/dev-to-script.js')
             const axios = require('axios');
             script({devtoToken, axios})
Enter fullscreen mode Exit fullscreen mode

You can see that we pull in a Javascript file that has all the code for talking to the dev.to API's and then follow these steps:

  1. Get all unpublished posts from dev.to
  2. Filter down to a keyword, in this case 'GitHub'
  3. Publish the post by updating the published: false in the frontmatter of the body.

Javascript code:

module.exports = ({devtoToken, axios}) => {
  console.log(`devtoToken: ${devtoToken}`);

  const instance = axios.create({
    baseURL: 'https://dev.to/api',
    timeout: 10000,
    headers: {'api-key': `${devtoToken}`},
  });

  instance.get('/articles/me/unpublished')
  .then(function (response) {    
    handleUnpublished(response.data);    
  })

  function handleUnpublished(data) {
      console.log(`Unpublished articles: ${data.length}`);
      let filtered = data.filter(article => {
        if (article.title.toLowerCase().indexOf('github') > -1) {
          return true;
        }
        return false;
      })

      console.log(`Filtered articles: ${filtered.length}`);
      filtered.forEach(element => {
          console.log(`Publishing article: [${element.title}]`)
          // replace the `published: false` to `true`
          let updated_markdown = element.body_markdown.replace(/published: false/, "published: true");          

          // update the article to published
          instance.put(`/articles/${element.id}`, {
              article: 
                {                     
                    body_markdown: `${updated_markdown}`
                }
        })
      });
  }
}
Enter fullscreen mode Exit fullscreen mode

Additional Resources / Info

This workflow makes use of the awesome github-script that makes working with API's a breeze!

Discussion (0)