블로그 게시물을 dev.to에 게시하기 위한 GitHub 작업

21815 단어
원본 기사: https://aralroca.com/blog/ghaction-devto

저는 2017년에 가입했을 때 글을 쓰기 시작했고 커뮤니티에 가입하는 것이 저에게 동기를 부여했습니다.

몇 가지 기사를 읽은 후 나만의 개인용blog을 만들기로 결정했습니다. 하지만 저는 항상 dev.to에 계속 기여하고 싶었습니다. 그래서 개인 블로그에 기사를 게시한 다음 dev.to에서 정식으로 공유합니다. 나는 그것이 표준 관행이고 당신 중 한 명 이상이 그것을하고 있다고 생각합니다.

내 삶을 조금 더 쉽게 만들기 위해 최근에 내 블로그에서 새 기사를 감지하면 dev.to에 직접 게시하는 GitHub 작업을 만들었습니다.

새 게시물을 감지하는 방법



문서가 새 문서이고 게시해야 하는지 확인하려면 마크다운 메타데이터를 사용하여 알아낼 수 있습니다. 제 경우에는 게시 날짜를 메타데이터로 유지합니다(마스터에 병합되더라도 다른 날짜에 게시하려는 경우).

그런 다음 GitHub 작업으로 dev.to에 게시되면 다른 메타데이터를 생성하여 게시됨으로 태그를 지정합니다.

왜요? GitHub 작업이 실행되기 때문에:
  • 무언가가 마스터로 푸시될 때마다.

  • 매일 17:00 UTC.

  • 이렇게 하면 게시물을 이미 게시된 것으로 표시하여 16:00에 기사를 마스터로 푸시하는 경우 게시물을 두 번 게시하지 않습니다.

    dev.to에 게시할 GH 동작 다이어그램


    작동 중인 GitHub 작업



    name: Publishing post
    
    on:
      push:
        branches: [master]
      schedule:
        - cron: '0 17 */1 * *'
    
    jobs:
      build:
        runs-on: ubuntu-latest
    
        strategy:
          matrix:
            node-version: [14.x]
    
        steps:
          - uses: actions/checkout@v2
    
          - name: Publishing post
            uses: actions/setup-node@v1
            with:
              node-version: ${{ matrix.node-version }}
          - run: yarn install --pure-lockfile
          - run: DEV_TO=${{secrets.DEV_TO}} yarn run publish:post
          - run: |
              git config user.name aralroca
              git config user.email [email protected]
              git add -A
              git diff --quiet && git diff --staged --quiet || git commit -m "[bot] Published to dev.to"
              git push origin master
    

    무엇을 하는가?
  • cron을 사용하여 매일 17:00 UTC에 마스터로 푸시할 때 작업을 프로그래밍합니다.
  • yarn install --pure-lockfile와 함께 종속성을 설치합니다.
  • GitHub secrets을 사용하여 환경 변수DEV_TO를 설정합니다. 이것은 스크립트에 필요합니다.
  • 스크립트를 실행하여 dev.to에 게시합니다
  • .
  • 변경 사항이 있는 경우에만 커밋하고 마스터에 푸시합니다.

  • dev.to에 게시할 스크립트


    package.json 파일에서 스크립트가 노드 파일을 실행함을 나타내야 합니다.

    {
      "scripts": {
        "publish:post": "node ./publish/index.js"
      }
    }
    

    다음은 dev.to에 기사를 게시하는 스크립트의 내용입니다.

    async function deploy() {
      const post = getNewPost()
    
      if (!post) {
        console.log('No new post detected to publish.')
        process.exit()
      }
    
      await deployToDevTo(post)
    }
    
    console.log('Start publishing')
    deploy()
      .then(() => {
        console.log('Published!')
        process.exit()
      })
      .catch((e) => {
        console.log('ERROR publishing:', e)
        process.exit()
      })
    
    getNewPost 함수는 새 게시물이 없는 경우 dev.to가 필요로 하는 방식으로 이미 형식이 지정된 게시물을 반환합니다null.

    const fs = require('fs')
    const path = require('path')
    const matter = require('gray-matter')
    
    const deployToDevTo = require('./dev-to')
    
    function getNewPost() {
      const today = new Date()
    
      return (
        fs
          .readdirSync('posts')
          .map((slug) => {
            const post = matter(fs.readFileSync(path.join('posts', slug)))
            return { ...post, slug }
          })
          .filter((p) => {
            const created = new Date(p.data.created)
    
            return (
              !p.data.published_devto &&
              created.getDate() === today.getDate() &&
              created.getMonth() === today.getMonth() &&
              created.getFullYear() === today.getFullYear()
            )
          })
          .map(({ slug, data, content }) => {
            const id = slug.replace('.md', '')
            const canonical = `https://aralroca.com/blog/${id}`
            const body = `***Original article: ${canonical}***\n${content}`
    
            return {
              body_markdown: body,
              canonical_url: canonical,
              created: data.created,
              description: data.description,
              main_image: data.cover_image,
              published: true,
              series: data.series,
              slug,
              tags: data.tags,
              title: data.title,
            }
          })[0] || null
      )
    }
    

    저는 gray-matter 라이브러리를 사용하여 마크다운 메타데이터와 해당 콘텐츠를 검색합니다.

    스크립트에 사용된 deployToDevTo 함수는 다음과 같습니다.

    const fetch = require('isomorphic-unfetch')
    const path = require('path')
    const fs = require('fs')
    
    function createPost(article) {
      return fetch('https://dev.to/api/articles', {
        method: 'POST',
        headers: {
          'api-key': process.env.DEV_TO,
          'content-type': 'application/json',
        },
        body: JSON.stringify({ article }),
      })
        .then((r) => r.json())
        .then((res) => {
          console.log('dev.to -> OK', `https://dev.to/aralroca/${res.slug}`)
          return res.slug
        })
        .catch((e) => {
          console.log('dev.to -> KO', e)
        })
    }
    
    async function deployToDevTo(article) {
      const devToId = await createPost(article)
    
      if (!devToId) return
    
      const postPath = path.join('posts', article.slug)
      const post = fs.readFileSync(postPath).toString()
      let occurrences = 0
    
      // Write 'published_devto' metadata before the second occourrence of ---
      fs.writeFileSync(
        postPath,
        post.replace(/---/g, (m) => {
          occurrences += 1
          if (occurrences === 2) return `published_devto: true\n${m}`
          return m
        })
      )
    }
    

    에 기사를 업로드한 다음 마크다운 파일을 수정하여 published_devto: true 메타데이터를 추가하도록 요청합니다. 이렇게 하면 GitHub 작업이 마스터에 업로드할 변경 사항이 있음을 감지합니다.

    결론



    이 짧은 기사에서 개인 블로그의 새 기사를 에 자동으로 게시하는 GitHub 작업을 만드는 방법을 살펴보았습니다. 유용하게 사용하시길 바랍니다.

    좋은 웹페이지 즐겨찾기