”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 通过 GitHub Actions 按计划更新网站内容

通过 GitHub Actions 按计划更新网站内容

发布于2024-11-06
浏览:998

我想分享我构建一个自我可持续的内容管理系统的旅程,该系统不需要传统意义上的内容数据库。

问题

该网站的内容(博客文章和书签)存储在 Notion 数据库中:

Updating website content on schedule via GitHub Actions

带书签的数据库 –  Notion UI

我试图解决的问题是不必在添加每个书签后手动部署网站。最重要的是 - 保持托管尽可能便宜,因为对我来说,我添加到我的 Notion 数据库的书签最终在线的速度有多快并不重要。

因此,经过一番研究,我提出了以下设置:

Updating website content on schedule via GitHub Actions

内容交付机制的高级概述

该系统由几个组件组成:

  • 部署更改的“Push to Main”操作
  • “更新内容”操作,从 Notion API 下载内容并提交更改
  • “按计划更新内容”操作偶尔运行一次并触发“更新内容”操作

让我们从内到外详细研究每一个。

“推送到主”工作流程

这里没什么可说的,非常标准的设置, – 当推送到主分支时,此工作流程会构建应用程序并使用 Wrangler CLI 将其部署到 Cloudflare Pages:

name: Push to Main
on:
  push:
    branches: [main]
  workflow_dispatch: {}
jobs:
  deploy-cloudflare-pages:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup pnpm
        uses: pnpm/action-setup@v4
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version
          cache: pnpm
      - name: Install node modules
        run: |
          pnpm --version
          pnpm install --frozen-lockfile
      - name: Build the App
        run: |
          pnpm build
      - name: Publish Cloudflare Pages
        env:
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
        run: |
          pnpm wrangler pages deploy ./out --project-name ${{ secrets.CLOUDFLARE_PROJECT_NAME }}

“更新内容”工作流程

此工作流程只能“手动”触发……但也可以自动触发,因为您可以使用 GitHub 个人访问令牌(又名 PAT)触发它。我最初编写它是因为我想从我的手机部署更改。它使用 Notion API 下载帖子和书签,然后 - 如果代码库有任何更改 - 创建提交并推送它。为了正常运行,必须为该工作流程提供具有存储库“读取和写入代码访问权限”的 PAT:

name: Update Content
on:
  workflow_dispatch: {}
jobs:
  download-content:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          # A Github Personal Access Token with access to the repository 
          # that has the follwing permissions:
          # ✅ Read and Write access to code
          token: ${{ secrets.GITHUB_PAT_CONTENT }}
      - name: Setup pnpm
        uses: pnpm/action-setup@v4
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version
          cache: pnpm
      - name: Install node modules
        run: |
          pnpm --version
          pnpm install --frozen-lockfile
      - name: Download articles content from Notion
        env:
          NOTION_KEY: "${{ secrets.NOTION_KEY }}"
          NOTION_ARTICLES_DATABASE_ID: "${{ secrets.NOTION_ARTICLES_DATABASE_ID }}"
        run: |
          pnpm download-articles
      - name: Download bookmarks content from Notion
        env:
          NOTION_KEY: ${{ secrets.NOTION_KEY }}
          NOTION_BOOKMARKS_DATABASE_ID: ${{ secrets.NOTION_BOOKMARKS_DATABASE_ID }}
        run: |
          pnpm download-bookmarks
      - name: Configure Git
        run: |
          git config --global user.email "${{ secrets.GIT_USER_EMAIL }}"
          git config --global user.name "${{ secrets.GIT_USER_NAME }}"
      - name: Check if anything changed
        id: check-changes
        run: |
          if [ -n "$(git status --porcelain)" ]; then
            echo "There are changes"
            echo "HAS_CHANGED=true" >> $GITHUB_OUTPUT
          else
            echo "There are no changes"
            echo "HAS_CHANGED=false" >> $GITHUB_OUTPUT
          fi
      - name: Commit changes
        if: steps.check-changes.outputs.HAS_CHANGED == 'true'
        run: |
          git add ./src/content
          git add ./public
          git commit -m "Automatic content update commit"
          git push

“按计划更新内容”工作流程

这个非常简单:它只是每隔一段时间运行一次并触发上面的工作流程。为了正常运行,此工作流程必须提供一个 GitHub PAT,该 PAT 具有存储库的“对 actions 的读写访问权限”。就我而言,这是一个不同的 PAT:

name: Update Content on Schedule
on:
  schedule:
    - cron: "13 0,12 * * *"
  workflow_dispatch: {}
jobs:
  trigger-update-content:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Dispatch the Update Content workflow
        env:
          # A Github Personal Access Token with access to the repository 
          # that has the follwing permissions:
          # ✅ Read and Write access to actions
          GH_TOKEN: ${{ secrets.GITHUB_PAT_ACTIONS }}
        run: |
          gh workflow run "Update Content" --ref main

结论

对我来说,这个设置已被证明非常好且灵活。由于模块化结构,“更新内容”操作可以手动触发 - 例如旅行时从我的手机上。对我来说,这是逐步增强工作流程的又一宝贵经验。

希望您觉得这有帮助吗?

版本声明 本文转载于:https://dev.to/prudkohliad/updating-website-content-on-schedule-via-github-actions-39o7?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-07-03
  • 为什么在我的Linux服务器上安装Archive_Zip后,我找不到“ class \” class \'ziparchive \'错误?
    为什么在我的Linux服务器上安装Archive_Zip后,我找不到“ class \” class \'ziparchive \'错误?
    Class 'ZipArchive' Not Found Error While Installing Archive_Zip on Linux ServerSymptom:When attempting to run a script that utilizes the ZipAr...
    编程 发布于2025-07-03
  • Go web应用何时关闭数据库连接?
    Go web应用何时关闭数据库连接?
    在GO Web Applications中管理数据库连接很少,考虑以下简化的web应用程序代码:出现的问题:何时应在DB连接上调用Close()方法?,该特定方案将自动关闭程序时,该程序将在EXITS EXITS EXITS出现时自动关闭。但是,其他考虑因素可能保证手动处理。选项1:隐式关闭终止数...
    编程 发布于2025-07-03
  • Android如何向PHP服务器发送POST数据?
    Android如何向PHP服务器发送POST数据?
    在android apache httpclient(已弃用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    编程 发布于2025-07-03
  • 如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    Red: How to Redirect Multiple User Types to Respective ActivitiesUnderstanding the ProblemIn a Firebase-based voting app with three distinct user type...
    编程 发布于2025-07-03
  • 如何在鼠标单击时编程选择DIV中的所有文本?
    如何在鼠标单击时编程选择DIV中的所有文本?
    在鼠标上选择div文本单击带有文本内容,用户如何使用单个鼠标单击单击div中的整个文本?这允许用户轻松拖放所选的文本或直接复制它。 在单个鼠标上单击的div元素中选择文本,您可以使用以下Javascript函数: function selecttext(canduterid){ if(do...
    编程 发布于2025-07-03
  • 如何在GO编译器中自定义编译优化?
    如何在GO编译器中自定义编译优化?
    在GO编译器中自定义编译优化 GO中的默认编译过程遵循特定的优化策略。 However, users may need to adjust these optimizations for specific requirements.Optimization Control in Go Compi...
    编程 发布于2025-07-03
  • 为什么我的CSS背景图像出现?
    为什么我的CSS背景图像出现?
    故障排除:CSS背景图像未出现 ,您的背景图像尽管遵循教程说明,但您的背景图像仍未加载。图像和样式表位于相同的目录中,但背景仍然是空白的白色帆布。而不是不弃用的,您已经使用了CSS样式: bockent {背景:封闭图像文件名:背景图:url(nickcage.jpg); 如果您的html,css...
    编程 发布于2025-07-03
  • 为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    查询模式实现缺失:解决“无法找到”错误在Silverlight应用程序中,尝试使用LINQ建立LINQ连接以错误而实现的数据库”,无法找到查询模式的实现。”当省略LINQ名称空间或查询类型缺少IEnumerable 实现时,通常会发生此错误。 解决问题来验证该类型的质量是至关重要的。在此特定实例中...
    编程 发布于2025-07-03
  • 如何有效地选择熊猫数据框中的列?
    如何有效地选择熊猫数据框中的列?
    在处理数据操作任务时,在Pandas DataFrames 中选择列时,选择特定列的必要条件是必要的。在Pandas中,选择列的各种选项。选项1:使用列名 如果已知列索引,请使用ILOC函数选择它们。请注意,python索引基于零。 df1 = df.iloc [:,0:2]#使用索引0和1 c...
    编程 发布于2025-07-03
  • 左连接为何在右表WHERE子句过滤时像内连接?
    左连接为何在右表WHERE子句过滤时像内连接?
    左JOIN CONUNDRUM:WITCHING小时在数据库Wizard的领域中变成内在的加入很有趣,当将c.foobar条件放置在上面的Where子句中时,据说左联接似乎会转换为内部连接。仅当满足A.Foo和C.Foobar标准时,才会返回结果。为什么要变形?关键在于其中的子句。当左联接的右侧值...
    编程 发布于2025-07-03
  • 将图片浮动到底部右侧并环绕文字的技巧
    将图片浮动到底部右侧并环绕文字的技巧
    在Web设计中围绕在Web设计中,有时可以将图像浮动到页面右下角,从而使文本围绕它缠绕。这可以在有效地展示图像的同时创建一个吸引人的视觉效果。 css位置在右下角,使用css float and clear properties: img { 浮点:对; ...
    编程 发布于2025-07-03
  • 如何简化PHP中的JSON解析以获取多维阵列?
    如何简化PHP中的JSON解析以获取多维阵列?
    php 试图在PHP中解析JSON数据的JSON可能具有挑战性,尤其是在处理多维数组时。 To simplify the process, it's recommended to parse the JSON as an array rather than an object.To do...
    编程 发布于2025-07-03
  • 在C#中如何高效重复字符串字符用于缩进?
    在C#中如何高效重复字符串字符用于缩进?
    在基于项目的深度下固定字符串时,重复一个字符串以进行凹痕,很方便有效地有一种有效的方法来返回字符串重复指定的次数的字符串。使用指定的次数。 constructor 这将返回字符串“ -----”。 字符串凹痕= new String(' - ',depth); console.Wr...
    编程 发布于2025-07-03
  • 如何高效地在一个事务中插入数据到多个MySQL表?
    如何高效地在一个事务中插入数据到多个MySQL表?
    mySQL插入到多个表中,该数据可能会产生意外的结果。虽然似乎有多个查询可以解决问题,但将从用户表的自动信息ID与配置文件表的手动用户ID相关联提出了挑战。使用Transactions和last_insert_id() 插入用户(用户名,密码)值('test','test...
    编程 发布于2025-07-03

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3