Automatically cross-publish  posts from my blog to dev.to
Tags: actionshackathon21, actions, github
Published: 2021-12-07 19:44:57

## What?
I use my RSS feed to cross publish my blogposts from [devopsjournal.io](https://devopsjournal.io) to [https://dev.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](https://docs.github.com/en/pages/getting-started-with-github-pages/about-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](https://github.com/rajbos/rajbos.github.io/blob/main/.github/workflows/dev-to-sync.yml) and thus is actively in use for my own blog!

``` yaml
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})
```
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
1. Filter down to a keyword, in this case 'GitHub'
1. Publish the post by updating the `published: false` in the frontmatter of the body.

Javascript code:
``` javascript
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}`
                }
        })
      });
  }
}
```

### Additional Resources / Info
This workflow makes use of the awesome [github-script](https://github.com/actions/github-script) that makes working with API's a breeze!