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 }}

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

最后,将代码提交并推送到 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

这个流水线会在成功合并 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 的静态网站定时发布方法,目标是为了让静态网站能享受到动态网站的功能与便利。接下来,我会继续研究如何提升静态网站的维护者体验,敬请期待!

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