Github Action:让静态网站实现定时发布

简介: 本文探讨了静态网站实现定时发布的解决方案,针对静态博客缺乏原生定时发布功能的问题,作者基于Zola工具构建的静态网站,最终选择通过GitHub Action实现定时发布。文章对比了几种实现方式,包括人力、自建服务及平台原生功能等,指出最理想的是利用平台能力但多数平台缺乏该功能。文中详细介绍了GitHub Action方案的原理、部署过程和使用流程,并分享了高级配置如推送通知。同时分析了方案的局限性,如时间颗粒度粗、设置繁琐等,并提出改进建议。总结中展望了未来优化方向,旨在提升静态网站维护体验。

定时发布:静态网站的遗憾

定时发布顾名思义就是在特定时间发布文章或内容,是CMS系统的基础功能。目前,几乎所有动态博客框架都能实现,例如Ghost、WordPress等,然而,对于静态类型的博客来说,由于缺乏能够后台定时的服务端,使得无法将定时发布变为原生功能,需要站长各凭本事实现,较为繁琐。

为什么研究这个问题?因为本博客就是一个用 Zola SSG 工具构建的静态网站,从开始移植主题建站到现在,我已经构思并调研了好几种方案,最终决定基于 GitHub Action 来实现定时发布。

几种实现方式对比

这里我先把可以实现静态网站定时发布的几种方式列举出来,并对比关键指标。

方法 描述 心智负担 可靠性 运维难度 费用
自己干 通过手机闹钟、手机日历提醒自己该发布啦 中,节假日不保证
别人干 安排一个工具人帮我发布 中,取决于报酬,节假日不可用
自建发布服务 预先构建网站,然后在本地或云端自建定时服务部署网站 取决于是否使用付费云资源
自建CI触发服务 在本地或云端自建定时服务触发CI接口构建网站,然后自动发布 取决于是否使用付费云资源
使用平台原生功能 依托平台能力定时触发CI实现定时发布 取决于是否使用付费云资源

通过对比我们可以发现:

  • 靠人力(自己干、别人干)实现定时发布在可靠性上难以保证,因为定时发布的一个重要使用场景就是在节日等重要节点发布信息,其稳定性至关重要。

  • 依托外部服务(自建发布服务、自建 CI 触发服务)是符合直觉的,但是会引入额外的复杂度,同事可能产生一定的费用。

  • 最理想的情况是使用的工具或平台自带定时发布的功能(使用平台原生功能),但是遗憾的是,大部分平台并不具备这类功能。

为了实现最好的效果,我决定尽可能通过平台自身实现定时发布的功能。

通过 GitHub Action 实现定时发布

本博客使用 GitHub 私有仓库存储代码和文章,也就是 Git-Based 静态博客,那么接下来的工作势必要围绕 GitHub 生态进行。

在此之前,我已经通过 GitHub Action (GitHub 的持续集成 CI 服务) 实现了主分支的自动部署,若在此之上添加定时发布,必然是围绕分支合并和 CI 流水线做文章。

比较典型的方案是用新分支存放内容 + 定时合并 PR。将要发布的内容存在新分支中,到达特定时间后,自动合并,然后自动触发发布流水线,以此实现定时发布。

沿着该技术路线,我搜集到一些能够定时合并 PR 的 GitHub 扩展工具,然而,这类工具基本都需要使用付费高级版。比如有一款工具的免费版额度是每月 4 次定时合并,我想这很难满足博主的需求,毕竟定时发布除了用于发文章,也可用于发版。

最终,我找到了 Merge Schedule,可以完全基于 GitHub Action 实现定时合并 PR 进而实现自动发布。

前提条件

本方案需要具备以下条件,我想大部分静态网站应该都能轻易达成。

  • 网站存放在 GitHub,并且是 Git-Based 静态博客。

  • 代码仓库主分支已经实现自动构建、部署的流水线,能做到更新代码后自动部署到生产环境。

  • 重要更新(如文章发布、重大改版等)采用分支 + PR 的工作流,能做到通过合并 PR 即可完成所有发布内容的更新工作。

基本原理

经过深入研究,现将技术原理梳理了大概:

  1. 设置专门用于定时合并 PR 的 GitHub Action 流水线,并设置定时执行,如每小时cron: '0 * * * *'

  2. 在计划定时合并的 PR 描述中添加定时器指令,如/schedule 2022-06-08T09:00:00.000Z

  3. 每次运行定时合并流水线时,检查所有打开的 PR,如果时间匹配,则调用 API 完成 PR 合并。

这种方式巧妙的利用了 GitHub Action 的定时触发机制,实现了原生的定时合并 PR,进而做到定时发布。

部署过程

这个方案的部署十分简单,只需新增一个 GitHub Action 定义文件即可。

在代码库新建文件.GitHub/workflows/merge-schedule.yml,用于存放流水线定义。

在文件中粘贴以下内容,这里设置了时区为国内Asia/Shanghai,合并方式为merge,可以根据需要自行修改。

name: MergeSchedule

# see https://GitHub.com/gr2m/merge-schedule-action

on:
pull_request:
    types:
      -opened
      -edited
      -synchronize
schedule:
    # https://crontab.guru/every-hour
    -cron:'0 * * * *'

jobs:
merge_schedule:
    runs-on:ubuntu-latest
    steps:
      -id:merge-schedule
        uses:gr2m/merge-schedule-action@v2
        with:
          # Merge method to use. Possible values are merge, squash or
          # rebase. Default is merge.
          merge_method:merge
          # Time zone to use. Default is UTC.
          time_zone:'Asia/Shanghai'
          # Require all pull request statuses to be successful before
          # merging. Default is `false`.
          require_statuses_success:'true'
          # Label to apply to the pull request if the merge fails. Default is
          # `automerge-fail`.
          automerge_fail_label:'merge-schedule-failed'
        env:
          GitHub_TOKEN:${
  {secrets.GitHub_TOKEN }}
AI 代码解读

可以在官方文档中找到更高级的用法,例如如何绕过存储库安全规则等。

最后,将代码提交并推送到 GitHub 的主分支就大功告成了。

下面分享一种更高级的流水线配置,可以在定时发布之后推送通知。

这里我以 Bark 推送服务为例,需要提前配置好 GitHub Action 的 Secret 变量Bark_KEY,将推送服务的 API KEY 放进去。

name: MergeSchedule

# see https://GitHub.com/gr2m/merge-schedule-action

on:
pull_request:
    types:
      -opened
      -edited
      -synchronize
schedule:
    # https://crontab.guru/every-hour
    -cron:'0 * * * *'

jobs:
merge_schedule:
    runs-on:ubuntu-latest
    steps:
      -id:merge-schedule
        uses:gr2m/merge-schedule-action@v2
        with:
          # Merge method to use. Possible values are merge, squash or
          # rebase. Default is merge.
          merge_method:merge
          # Time zone to use. Default is UTC.
          time_zone:'Asia/Shanghai'
          # Require all pull request statuses to be successful before
          # merging. Default is `false`.
          require_statuses_success:'true'
          # Label to apply to the pull request if the merge fails. Default is
          # `automerge-fail`.
          automerge_fail_label:'merge-schedule-failed'
        env:
          GitHub_TOKEN:${
  {secrets.GitHub_TOKEN}}

        # run if there is any merged pull request
      -name:notification
        uses:shink/bark-action@v2
        if:${
  {fromJson(steps.merge-schedule.outputs.merged_pull_requests)[0]!=null}}
        with:
          key:${
  {secrets.Bark_KEY}}
          title:GitHubPR已自动合并
          body:稍后请检查部署结果
          sound:alarm
          isArchive:0
          automaticallyCopy: 0
AI 代码解读

这个流水线会在成功合并 PR 后,给用户推送通知,这样用户可以等待自动部署完成,然后访问网站看看结果。

使用流程

至此,我们可以按照直观的逻辑步骤来完成定时发布。

  1. 基于主分支创建用于定时发布的子分支,一般是文章分支。

  2. 完成内容更新,并推送到 GitHub。

  3. 在 GitHub 创建 PR 以合并到主分支,并在 PR 的描述内容最末尾,添加指明时间的以下内容

    • 特定日期,如/schedule 2022-06-08

    • 特定日期的整点时间,如/schedule 2022-06-08T09:00:00.000Z代表2022年6月8日的上午9点,时间格式遵循ISO 8601规范

    • 下一次整点时间/schedule

  4. 等待自动发布~

  5. 如果需要修改或者取消,直接删除或编辑 PR 的描述内容即可,你甚至可以简单粗暴地删除 PR ~

方案的局限性与解决措施

虽然我们实现了不出 GitHub 就能定时发布,但是仍存在一些局限性:

  1. 可选时间颗粒度较粗,默认只能按照整点时间进行配置,如8点、9点等。虽然可以满足大部分应用场景了,但存在用户希望半点发布,如8点30分,可以通过自行调整流水线定时触发频率来结婚,如每半小时。目前另外尚未测试是否存在时间的模糊匹配或近似匹配,

  2. 定时器的设置仍然较为繁琐,在 PR 中需要输入较长的指令,缺少正确性校验,可能导致失败。针对该问题,可以通过接下来在定时合并流水线中添加新增通知来解决。

  3. 缺少发布结果的预览,用户对最终效果缺少掌控。针对该问题,需要进一步定制 CI 流水线,增加子分支的自动部署,预览最终效果,还可以为项目增加预生产分支,确保合并后没有 Bug,不过这些实现起来就比较繁琐了。

总结与展望

这个方案本质是持续集成流水线的高级应用,依托 GitHub Action 的定时功能实现定时发布。围绕流水线可以添加许多有意思且实用的功能,例如构建预览环境、提前的错误检查等,这就需要发挥大家的想象力了。

其实,我最初的构想是基于免费的函数服务(如 Cloudflare Worker)实现定时触发功能,但是函数服务的冷启动问题可能会影响定时触发的稳定性,所以这个方案暂时搁置了,如果大家有解决方案欢迎在评论区分分享~

这篇文章提供了一种基于 GitHub Action 的静态网站定时发布方法,目标是为了让静态网站能享受到动态网站的功能与便利。接下来,我会继续研究如何提升静态网站的维护者体验,敬请期待!

目录
打赏
0
0
0
0
0
分享
相关文章
使用VitePress静态网站生成器创建组件库文档网站并部署到GitHub
本文介绍了如何使用 Vue3、TypeScript 和 Vite 开发组件库并将其发布到 npm。文章详细描述了安装依赖、配置项目、创建文档网站以及编写组件文档的步骤。通过使用 VitePress,可以轻松搭建组件库的文档站点,并实现 Algolia 搜索功能。此外,还提供了自动化脚本用于部署静态网站至 GitHub 以及发布组件库到 npm。最后,展示了完整的目录结构和网站效果。
254 1
使用VitePress静态网站生成器创建组件库文档网站并部署到GitHub
【Azure Developer】在Github Action中使用Azure/functions-container-action@v1配置Function App并成功部署Function Image
【Azure Developer】在Github Action中使用Azure/functions-container-action@v1配置Function App并成功部署Function Image
【Azure Developer】Github Action使用Azure/login@v1插件登录遇见错误的替代方案
【Azure Developer】Github Action使用Azure/login@v1插件登录遇见错误的替代方案
|
7月前
|
【Azure Developer】Github Action部署资源(ARM模板)到Azure中国区时,遇见登录问题的解决办法
【Azure Developer】Github Action部署资源(ARM模板)到Azure中国区时,遇见登录问题的解决办法
国内docker公开镜像站的关闭!别急,docker_image_pusher 使用Github Action将国外的Docker镜像转存到阿里云私有仓库
通过使用 docker_image_pusher 这样的开源项目,我们能够轻松地解决国内访问 Docker 镜像拉取速度慢及拉去失败的问题,同时保证了镜像的稳定性和安全性。利用 Github Action 的自动化功能,使得这一过程更加简单和高效。
2243 2
【完美解决】Github action报错remote: Write access to repository not granted.
【完美解决】Github action报错remote: Write access to repository not granted.
干货分享!基于 Github Action 的 taosX CI 搭建
去年随着 3.1.1.0 版本的发布,TDengine 数据接入工具 taosX 正式推出。该工具具备强大的数据抓取、清洗、转换及加载(ETL)功能。它不仅能无缝对接物联网中的 MQTT 协议,更重要的是能够连接到工业数据源如 OPC-UA、OPC-DA、PI System 等。借助这一模块,工业场景中常用的 SCADA、DCS 等系统无需编写任何代码,仅需通过简单配置即可实现数据的实时、持续导入至 TDengine。
86 1
保姆级教程:从零构建GitHub Pages静态网站(下)
保姆级教程:从零构建GitHub Pages静态网站(下)
425 0
保姆级教程:从零构建GitHub Pages静态网站(上)
保姆级教程:从零构建GitHub Pages静态网站
5578 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等