Đăng ngày

Cách Tạo Nhắc Nhở Cho Bài Đăng Blog Sử Dụng GitHub Actions

Tác giả

Là một nhà văn, tôi hiểu tầm quan trọng của sự nhất quán khi xuất bản nội dung mới. Tuy nhiên, có những lúc cuộc sống chen ngang và có thể khó nhớ viết bài đăng blog mới. Để giúp tôi theo kịp lịch trình chia sẻ, tôi đã tạo một lời nhắc đơn giản bằng cách sử dụng GitHub Actions. Trong bài viết này, tôi sẽ chia sẻ cách tôi đã tạo ra luồng công việc này.

GitHub Action là gì?

GitHub Actions là một công cụ mạnh mẽ cho phép bạn tự động hóa luồng công việc của mình. Bạn có thể sử dụng nó để xây dựng, kiểm tra và triển khai mã của mình. Bạn cũng có thể sử dụng nó để thực hiện nhiều tác vụ khác, chẳng hạn như gửi thông báo hoặc lên lịch lời nhắc.

Cách tôi tạo lời nhắc viết bài đăng blog

Để tạo lời nhắc viết bài đăng blog, tôi đang sử dụng kho lưu trữ đặc biệt của GitHub README.md và đã thêm một tệp có tên .github/workflows/blog-posts.yml. Trong tệp này, tôi đã định nghĩa luồng công việc mà GitHub Actions sẽ thực thi. Dưới đây là nội dung ban đầu của tệp:

name: Blog Posts

on:
  schedule:
    - cron: '0 0 * * 0' # Chạy lúc 00:00 mỗi Chủ nhật
  workflow_dispatch:

jobs:
  update-posts:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Cập nhật danh sách bài đăng
        run: |
          sleep 1m
          curl -LO https://blog.imam.dev/feed.xml
          node src/list-posts.js
          rm feed.xml
      - name: Commit thay đổi
        run: |
          git config --local user.email "github-actions[bot]@users.noreply.github.com"
          git config --local user.name "github-actions[bot]"
          git add -A
          git diff-index --quiet HEAD || git commit -m "Cập nhật bài đăng blog"
      - name: Pull thay đổi
        run: git pull -r
      - name: Push thay đổi
        uses: ad-m/github-push-action@0fafdd62b84042d49ec0cb92d9cac7f7ce4ec79e
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

Luồng công việc này được kích hoạt mỗi Chủ nhật lúc 00:00. Sau đó, nó chạy một kịch bản cập nhật danh sách bài đăng blog. Kịch bản được viết bằng JavaScript và phân tích cú pháp nguồn cấp dữ liệu RSS của blog của tôi. Sau đó, nó tạo ra một danh sách bài đăng blog và cập nhật tệp README.md. Cuối cùng, nó xác nhận các thay đổi và đẩy chúng lên GitHub. Tôi đang sử dụng kho lưu trữ của ouuan làm tài liệu tham khảo cho luồng công việc này.

Lời nhắc đến từ đâu? Thực ra nó nằm trong tệp list-posts.js. Tôi đã thêm một lời nhắc vào danh sách bài đăng blog. Dưới đây là nội dung của tệp:

const { readFileSync, writeFileSync } = require('fs')

/**
 * Chuyển đổi chuỗi XML sang JSON
 * @param {string} xmlString
 * @returns {object} json
 */
const xmlToJson = (xmlString) => {
  const regex = /<(\w+)([^>]*)>([\s\S]*?)<\/\1>/gm
  const matches = xmlString.matchAll(regex)
  const json = {}

  for (const match of matches) {
    const [, key, attributes, value] = match
    const subMatches = value.matchAll(regex)
    const subJson = {}

    for (const subMatch of subMatches) {
      const [, subKey, subAttributes, subValue] = subMatch

      if (subValue.match(regex)) {
        if (Array.isArray(subJson[subKey])) {
          subJson[subKey].push(
            xmlToJson(`<${subKey}${subAttributes}>${subValue}</${subKey}>`)[subKey]
          )
        } else if (subJson[subKey]) {
          subJson[subKey] = [
            subJson[subKey],
            xmlToJson(`<${subKey}${subAttributes}>${subValue}</${subKey}>`)[subKey],
          ]
        } else {
          subJson[subKey] = xmlToJson(`<${subKey}${subAttributes}>${subValue}</${subKey}>`)[subKey]
        }
      } else if (Array.isArray(subJson[subKey])) {
        subJson[subKey].push(subValue)
      } else if (subJson[subKey]) {
        subJson[subKey] = [subJson[subKey], subValue]
      } else {
        subJson[subKey] = subValue
      }
    }

    if (json[key]) {
      if (Array.isArray(json[key])) {
        json[key].push(subJson)
      } else {
        json[key] = [json[key], subJson]
      }
    } else {
      json[key] = subJson
    }
  }

  return json
}

/**
 * Sắp xếp JSON theo pubDate
 * @param {object} json
 * @returns {object} sortedJson
 */
const sortJson = (json) => {
  json.sort((a, b) => new Date(b.pubDate) - new Date(a.pubDate))
  return json
}

// Đọc tệp XML và chuyển đổi sang JSON
const xmlString = readFileSync('feed.xml', 'utf8')
const feeds = sortJson(xmlToJson(xmlString).rss.channel.item)

// Tạo danh sách bài đăng Markdown
const posts = feeds
  .slice(0, 5)
  .map(
    (item) =>
      `- ${new Date(item.pubDate).toISOString().split('T')[0]} [${item.title}](${
        item.link
      }?utm_source=GitHubProfile)`
  )

// Cập nhật README.md nếu bài đăng đã thay đổi,
// Nếu không, ném lỗi để nhắc tôi viết bài đăng blog
const readme = readFileSync('README.md', 'utf8')
if (readme.includes(posts.join('\n'))) {
  throw new Error('Không có bài đăng blog mới')
} else {
  const updatedReadme = readFileSync('README.md', 'utf8').replace(
    /(?<=<!--START_SECTION:blog-posts-->\n)[\s\S]*(?=\n<!--END_SECTION:blog-posts-->)/,
    posts.join('\n')
  )
  writeFileSync('README.md', updatedReadme)

  console.log('Đã cập nhật README.md')
}

Kịch bản này đọc nguồn cấp dữ liệu RSS của blog của tôi và tạo ra một danh sách bài đăng blog. Sau đó, nó cập nhật tệp README.md với danh sách bài đăng blog. Nếu không có bài đăng blog mới, nó sẽ ném lỗi để nhắc tôi viết bài đăng blog.

Đó chỉ là một lỗi sẽ được ném ra khi kịch bản được thực thi trong khi bài đăng vẫn giữ nguyên và nó không phải là lời nhắc sẽ được gửi đến email của tôi hoặc điều gì đó rõ ràng hơn với tôi. Vì vậy, tôi đã quyết định bật thông báo cho mọi lần chạy luồng công việc thất bại. Dưới đây là cách thực hiện:

  1. Nhấp vào góc trên bên phải của trang và chọn Cài đặt.

  2. Chọn Thông báo trên thanh bên trái.

  3. Nhấp vào Hành động.

  4. Chọn Gửi thông báo cho các luồng công việc thất bại.

Bây giờ, tôi sẽ nhận được thông báo khi kịch bản được thực thi và không có bài đăng blog mới. Tôi cũng có thể xem thông báo trên trang web GitHub.

Một cách khác mà tôi đã khám phá

Luồng công việc trước đó mà tôi nói với bạn là một phiên bản được sửa đổi để README.md của tôi luôn được cập nhật. Tôi cũng đã khám phá một cách khác để tạo lời nhắc viết bài đăng blog. Nhưng, nó chỉ là một lời nhắc thuần túy mà không có cơ chế cập nhật README.md nào, chỉ là một lời nhắc.

Để tạo lời nhắc viết bài đăng blog, tôi đã tạo một kho lưu trữ GitHub mới và thêm một tệp có tên .github/workflows/remind.yml. Trong tệp này, tôi đã định nghĩa luồng công việc mà GitHub Actions sẽ thực thi. Dưới đây là nội dung của tệp:

name: Lời nhắc viết bài đăng blog

on:
  schedule:
    - cron: '0 10 * * 1-5'

jobs:
  remind:
    runs-on: ubuntu-latest
    steps:
      - name: Gửi lời nhắc
        uses: dawidd6/action-send-mail@v3.1.0
        with:
          server_address: smtp.gmail.com
          server_port: 465
          username: ${{ secrets.EMAIL_USERNAME }}
          password: ${{ secrets.EMAIL_PASSWORD }}
          subject: 'Lời nhắc viết bài đăng blog mới'
          body: "Đừng quên viết bài đăng blog mới hôm nay!"
          to: my-email@example.com

Luồng công việc này gửi cho tôi một email nhắc nhở mỗi ngày trong tuần lúc 10:00 sáng, nhắc tôi viết bài đăng blog mới. Tôi đã sử dụng một hành động của bên thứ ba, dawidd6/action-send-mail, để gửi email. Tôi đã cung cấp thông tin xác thực email của mình dưới dạng bí mật GitHub, vì vậy chúng không hiển thị trong tệp luồng công việc.

Kết luận

Tôi đã khám phá hai cách để tạo lời nhắc viết bài đăng blog. Cách đầu tiên là cập nhật tệp README.md của hồ sơ GitHub của tôi. Cách thứ hai là gửi email nhắc nhở. Hiện tại tôi đang sử dụng cách đầu tiên vì nó rõ ràng hơn cách thứ hai. Tôi có thể thấy lời nhắc mỗi khi tôi truy cập hồ sơ GitHub của mình.

Tạo lời nhắc viết bài đăng blog bằng GitHub Actions là một cách đơn giản và hiệu quả để theo kịp lịch trình viết blog của bạn. Với luồng công việc này được cài đặt, bạn sẽ không bao giờ quên viết bài đăng mới nữa. Nếu bạn quan tâm đến việc tạo luồng công việc nhắc nhở của riêng mình, hãy chắc chắn kiểm tra tài liệu GitHub Actions để tìm hiểu thêm. Chúc bạn viết blog vui vẻ!