منتشر شده در

ایجاد اعلان انتشار پست‌های وبلاگ با استفاده از GitHub Actions

نویسندگان

به عنوان یک نویسنده، اهمیت حفظ انسجام در انتشار محتوا را درک می‌کنم. با این حال، گاهی اوقات زندگی به راه خودش ادامه می‌دهد و یادآوری نوشتن یک پست وبلاگ جدید می‌تواند دشوار باشد. برای کمک به خودم در حفظ برنامه انتشار محتوا، از GitHub Actions برای ایجاد یک یادآور ساده استفاده کردم. در این پست، نحوه ایجاد این گردش کار را به اشتراک خواهم گذاشت.

GitHub Action چیست؟

GitHub Actions ابزاری قدرتمند است که به شما امکان می‌دهد گردش کار خود را خودکار کنید. می‌توانید از آن برای ساخت، آزمایش و استقرار کد خود استفاده کنید. همچنین می‌توانید از آن برای انجام طیف وسیعی از وظایف دیگر مانند ارسال اعلان یا زمان‌بندی یادآورها استفاده کنید.

نحوه ایجاد یک یادآور برای نوشتن یک پست وبلاگ

برای ایجاد یک یادآور برای نوشتن یک پست وبلاگ، از انبار ویژه GitHub README.md استفاده می‌کنم و یک فایل به نام .github/workflows/blog-posts.yml اضافه کردم. در این فایل، گردش کاری که GitHub Actions اجرا می‌کند را تعریف کردم. محتوای اولیه این فایل به شرح زیر است:

name: Blog Posts

on:
  schedule:
    - cron: '0 0 * * 0' # هر یکشنبه در ساعت 00:00 اجرا می‌شود
  workflow_dispatch:

jobs:
  update-posts:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Update post list
        run: |
          sleep 1m
          curl -LO https://blog.imam.dev/feed.xml
          node src/list-posts.js
          rm feed.xml
      - name: Commit changes
        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 "Update blog posts"
      - name: Pull changes
        run: git pull -r
      - name: Push changes
        uses: ad-m/github-push-action@0fafdd62b84042d49ec0cb92d9cac7f7ce4ec79e
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

این گردش کار هر یکشنبه در ساعت 00:00 اجرا می‌شود. سپس یک اسکریپت اجرا می‌کند که لیست پست‌های وبلاگ را به روز می‌کند. اسکریپت با جاوا اسکریپت نوشته شده است و خوراک RSS وبلاگ من را تجزیه می‌کند. سپس لیست پست‌های وبلاگ را ایجاد کرده و فایل README.md را به روز می‌کند. در نهایت، تغییرات را ثبت کرده و آنها را به GitHub ارسال می‌کند. من از مخزن ouuan به عنوان مرجع برای این گردش کار استفاده می‌کنم.

یادآور از کجا می‌آید؟ در واقع در فایل list-posts.js است. یک یادآور به لیست پست‌های وبلاگ اضافه کردم. محتوای این فایل به شرح زیر است:

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

/**
 * تبدیل رشته XML به 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
}

/**
 * مرتب سازی JSON بر اساس pubDate
 * @param {object} json
 * @returns {object} sortedJson
 */
const sortJson = (json) => {
  json.sort((a, b) => new Date(b.pubDate) - new Date(a.pubDate))
  return json
}

// خواندن فایل XML و تبدیل آن به JSON
const xmlString = readFileSync('feed.xml', 'utf8')
const feeds = sortJson(xmlToJson(xmlString).rss.channel.item)

// ایجاد لیست Markdown از پست‌ها
const posts = feeds
  .slice(0, 5)
  .map(
    (item) =>
      `- ${new Date(item.pubDate).toISOString().split('T')[0]} [${item.title}](${
        item.link
      }?utm_source=GitHubProfile)`
  )

// به روزرسانی README.md اگر پست‌ها تغییر کرده‌اند،
// در غیر این صورت خطایی برای یادآوری من برای نوشتن یک پست وبلاگ ایجاد می‌شود
const readme = readFileSync('README.md', 'utf8')
if (readme.includes(posts.join('\n'))) {
  throw new Error('No new blog posts')
} 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('Updated README.md')
}

اسکریپت خوراک RSS وبلاگ من را می‌خواند و لیست پست‌های وبلاگ را ایجاد می‌کند. سپس فایل README.md را با لیست پست‌های وبلاگ به روز می‌کند. اگر پست وبلاگ جدیدی وجود نداشته باشد، خطایی را برای یادآوری من برای نوشتن یک پست وبلاگ ایجاد می‌کند.

این فقط یک خطایی است که هنگام اجرای اسکریپت، در حالی که پست‌ها هنوز یکسان هستند، ایجاد می‌شود و یادآوری نیست که به ایمیل من ارسال شود یا چیزی که برای من قابل مشاهده‌تر باشد. بنابراین، تصمیم گرفتم اعلان را برای هر اجرای گردش کاری که با شکست مواجه می‌شود فعال کنم. نحوه انجام آن به شرح زیر است:

  1. روی گوشه سمت راست بالای صفحه کلیک کنید و تنظیمات را انتخاب کنید.

  2. اعلان‌ها را در نوار کناری سمت چپ انتخاب کنید.

  3. روی Actions کلیک کنید.

  4. ارسال اعلان فقط برای گردش کارهای ناموفق را انتخاب کنید.

حالا هر بار که اسکریپت اجرا می‌شود و پست وبلاگ جدیدی وجود ندارد، اعلانی دریافت می‌کنم. همچنین می‌توانم این اعلان را در وب سایت GitHub ببینم.

راه دیگری که بررسی کردم

گردش کار قبلی که به شما گفتم، یک نسخه اصلاح شده است تا README.md من همیشه به روز باشد. همچنین یک راه دیگر برای ایجاد یک یادآور برای نوشتن یک پست وبلاگ را بررسی کردم. اما فقط یک یادآور ساده بدون هیچ مکانیسم به‌روزرسانی README.md است، فقط یک یادآور.

برای ایجاد یک یادآور برای نوشتن یک پست وبلاگ، یک مخزن جدید GitHub ایجاد کردم و یک فایل به نام .github/workflows/remind.yml اضافه کردم. در این فایل، گردش کاری که GitHub Actions اجرا می‌کند را تعریف کردم. محتوای این فایل به شرح زیر است:

name: Reminder to write a blog post

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

jobs:
  remind:
    runs-on: ubuntu-latest
    steps:
      - name: Send a reminder
        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: 'Reminder to write a new blog post'
          body: "Don't forget to write a new blog post today!"
          to: my-email@example.com

این گردش کار، هر روز هفته در ساعت 10:00 صبح یک یادآور ایمیل برای من ارسال می‌کند و به من یادآوری می‌کند که یک پست وبلاگ جدید بنویسم. من از یک اکشن شخص ثالث، dawidd6/action-send-mail، برای ارسال ایمیل استفاده کردم. اعتبارنامه ایمیل خود را به عنوان اسرار GitHub ارائه دادم، بنابراین در فایل گردش کار قابل مشاهده نیستند.

نتیجه

دو راه مختلف برای ایجاد یک یادآور برای نوشتن یک پست وبلاگ را بررسی کردم. راه اول به‌روزرسانی فایل README.md نمایه GitHub من است. راه دوم ارسال یک یادآور ایمیل است. من در حال حاضر از راه اول استفاده می‌کنم، زیرا نسبت به راه دوم قابل مشاهده‌تر است. هر بار که از نمایه GitHub خود بازدید می‌کنم، یادآور را می‌بینم.

ایجاد یک یادآور برای نوشتن یک پست وبلاگ با استفاده از GitHub Actions، روشی ساده و موثر برای حفظ برنامه وبلاگ نویسی شما است. با استفاده از این گردش کار، دیگر هرگز نوشتن یک پست جدید را فراموش نخواهید کرد. اگر به ایجاد گردش کار یادآور خود علاقه‌مند هستید، حتما برای یادگیری بیشتر، مستندات GitHub Actions را بررسی کنید. وبلاگ نویسی خوبی داشته باشید!