使用Github Action自动部署到Vercel修复文章更新时间错误问题

Oxysc Lv1

问题在于哪里?

当你使用VercelGithub Actions自动化部署Hexo博客时会发现,每次git push都会导致文章更新时间变为此次提交修改时间,然而实际上文章并没有进行任何修改。

这个问题是由于git在推送更新时不会保存文件创建和修改时间等文件元数据。

Git SCM Wiki 中的解释

Modification time on files is a feature that affects build tools. Most build tools compare the timestamp of the source(s) with the timestamp of the derived file(s). If the source is newer, then a rebuild takes place, otherwise nothing happens. This speeds up the build process a lot.

Now consider what would happen if you check out another branch, and modification times were preserved. We assume you already have a fully-built project. If a source file on that other branch has a timestamp that is older than that of the corresponding derived file, the derived file will not be built even if it is different, because the build system only compares modification times. At best, you’ll get some kind of weird secondary error; but most likely everything will look fine at first, but you will not get the same result as you would have with a clean build. That situation is unhealthy since you really do not know what code you are executing and the source of the problem is hard to find. You will end up always having to make a clean build when switching branches to make sure you are using the correct source. (Git bisect is another Git procedure that checks out old and new revisions where you need a reliable rebuild.)

Git sets the current time as the timestamp on every file it modifies, but only those. The other files are left untouched, which means build tools will be able to depend on modification time and rebuild properly. If build rules change, that can cause a failure anyway, but that is a far less common problem than accidentally not rebuilding.

来自: Why isn’t Git preserving modification time on files?/为什么 Git 不保留文件的修改时间?

所以当你每次使用git clone上传或下载的项目的文件元数据都是当前系统时间,而不是项目的创建时间。

而在Hexo中,文章默认会使用文件的最后修改时间作为文章的更新时间,所以CI构建之后进入博客就会看到所有文章修改时间都会变为“刚刚”或者”X分钟以前“这种地狱绘图,因为git push上去的文件不会保存元数据。

如何修复

这里只提供一个很有效但稍有些麻烦的方法,同时也是本站正在使用的方法

效果

由于每次更新推送后Vercel都会自动构建部署,我们无法对构建流程进行修改,因此需要关闭Vercel的自动构建,转而使用Github Action来将Hexo自动化部署到Vercel

实现原理

在Next主题issue #893 @wylu 提到了这个问题,@sli1989 提出了以下解决方案

Hi, the updated time with CI deployment can be fixed using this. please check Continuous Integration configurations carefully.

1
2
# Restore last modified time
- "git ls-files -z | while read -d '' path; do touch -d \"$(git log -1 --format=\"@%ct\" \"$path\")\" \"$path\"; done"

该条命令会将文件的最后修改时间修改为 Git 仓库中文件的最后提交时间,即文章的更新时间。

同样使用 find 命令也可以实现这个功能:

1
find source/_posts -name '*.md' | while read file; do touch -d "$(git log -1 --format="@%ct" "$file")" "$file"; done

准备工作

首先,将 Vercel 项目Github 仓库 的绑定关系解除,因为我们将要在 Github Action 中手动部署HexoVercel

在 Github Action 中需要使用以下两个环境变量和一个秘钥:

  • VERCEL_ORG_ID
  • VERCEL_PROJECT_ID
  • VERCEL_TOKEN

步骤一: 获取Vercel Access Token

我们需要在 Vercel 中获取一段 Vercel Access Token 用于 Github Action 自动化部署。

点击直达Token创建页面

步骤二: 获取 VERCEL_ORG_ID 和 VERCEL_PROJECT_ID的值

前置条件:已安装Node.js(都用Hexo了肯定装了纯废话)

1
2
#使用npm安装
npm i -g vercel

或者使用yarn

1
2
3
4
5
#安装yarn包管理器
npm install --global yarn

#yarn安装Vercel CLI
yarn global add vercel

然后在博客根目录下执行

1
vercel link

来创建一个 Vercel 项目,此操作会在博客根目录下生成一个 .vercel 文件夹,在.vercel/project.json 里面包含了 VERCEL_ORG_IDVERCEL_PROJECT_ID

步骤三: 在 Github 仓库中添加 secrets

在你的博客所在的 Github 仓库中,点击 Settings -> Secrets and Variables -> Actions 中添加以下秘钥和环境变量:

  • VERCEL_TOKEN ——前面创建的Vercel Access Token
  • VERCEL_ORG_ID ——.vercel/project.json中的"orgId"字段
  • VERCEL_PROJECT_ID ——.vercel/project.json中的"projectId"字段

步骤四: 创建 Github Action

完成上面两条环境变量和一条密钥总共三条的创建后,接下来我们开始创建 Github Action

Github 仓库中创建一个名为 .github/workflows/deploy.yml 的文件,添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
name: Deploy Blog to Vercel Production Deployment
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
# 0 indicates all history for all branches and tags.
fetch-depth: 0
- name: Restore file modification time 🕒
run: find source/_posts -name '*.md' | while read file; do touch -d "$(git log -1 --format="@%ct" "$file")" "$file"; done
# run: "git ls-files -z | while read -d '' path; do touch -d \"$(git log -1 --format=\"@%ct\" \"$path\")\" \"$path\"; done"
- name: Install Vercel-cli🔧
run: npm install --global vercel@latest
- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}

注意

步骤图中的master为作者所在使用的仓库分支名称,请以实际为准(即原Vercel自动部署时的默认分支)

点击Commit changes后弹出的选项框通常情况下会是要求你填写Commit备注的对话框,按自己看得懂来即可。

完成

在本地仓库根目录执行git pull同步远程仓库更新

git push之后,你会发现所有文章的更新日期都被同步为了在远程仓库中最后一次修改提交的时间

即,假如文章创建时间为2024-04-05 17:45:43date: 同样也为2024-04-05 17:45:43,在2024-04-08 17:45:43修改2024-04-08 17:47:21被git push更新到远程仓库,则他人看到的最后修改时间为2024-04-08 17:47:21

参考链接

本文章在编写时使用了以下链接进行参考(不分先后)

Why isn’t Git preserving modification time on files?

hexo-theme-next issue # 893

How can I use GitHub Actions with Vercel? - Vercel Docs

examples/production.yaml at main - vercel/examples

修复 CI 构建博客造成的更新时间错误

  • 标题: 使用Github Action自动部署到Vercel修复文章更新时间错误问题
  • 作者: Oxysc
  • 创建于 : 2024-04-14 17:45:43
  • 更新于 : 2024-08-31 11:28:11
  • 链接: https://blog.oxysc.cc//works/ghaction-hexo/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论