Total Pageviews

Sunday, 9 November 2025

用GitHub Actions 实现自动部署静态博客程序vuepress

 一开始的部署方式是使用sh部署脚本

(opens new window)把代码提交到这两个平台的仓库分支,虽然已经很方便了,但是我还想把博客未打包的源码提交到Github主分支上。这就需要我操作两次命令,我就想能不能只需要一次操作就可以同时把源码、部署代码一次性提交到两个平台呢?

实现

在了解GitHub Actions最近(2019.12)刚正式发布了之后,尝试使用它发现能够满足我的需求。GitHub Actions 入门教程

(opens new window)

首先,需要获取token,后面会用到。获取方法:github获取token官方文档

(opens new window)、coding获取token官方文档

(opens new window)

然后,将这两个token同时储存到github仓库的Settings/Secrets里面。变量名可以随便取,但是注意要和后面的ci.yml文件内的变量名一致,这里取的是ACCESS_TOKENCODING_TOKEN

GitHub Actions 的配置文件叫做 workflow 文件,存放在代码仓库的.github/workflows目录。

workflow 文件采用 YAML 格式

(opens new window),文件名可以任意取,但是后缀名统一为.yml,比如ci.yml。一个库可以有多个 workflow 文件。GitHub 只要发现.github/workflows目录里面有.yml文件,就会自动运行该文件。

我的ci.yml文件:

name: CI

# 在master分支发生push事件时触发。
on:
  push:
    branches:
      - master
jobs: # 工作流
  build:
    runs-on: ubuntu-latest #运行在虚拟机环境ubuntu-latest

    strategy:
      matrix:
        node-version: [10.x]

    steps:
      - name: Checkout # 步骤1
        uses: actions/checkout@v1 # 使用的动作。格式:userName/repoName。作用:检出仓库,获取源码。 官方actions库:https://github.com/actions
      - name: Use Node.js ${{ matrix.node-version }} # 步骤2
        uses: actions/setup-node@v1 # 作用:安装nodejs
        with:
          node-version: ${{ matrix.node-version }} # 版本
      - name: run deploy.sh # 步骤3 (同时部署到github和coding)
        env: # 设置环境变量
          GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} # toKen私密变量
          CODING_TOKEN: ${{ secrets.CODING_TOKEN }} # 腾讯云开发者平台(coding)私密token
        run: npm install && npm run deploy # 执行的命令
        # package.json 中添加 "deploy": "bash deploy.sh"

这个配置文件会在我push提交代码到主分支时触发工作,运行环境是ubuntu-latest,工作步骤:

  • 一,获取仓库源码

  • 二,安装nodejs,打包项目有用到nodejs

  • 三,把token设置到环境变量,安装项目依赖,并运行deploy.sh文件,

ACCESS_TOKE 和 CODING_TOKEN 都是保存在github仓库的Settings/Secrets位置的私密变量,仓库代码中可以通过<secrets.变量名>来获取,保证了token的私密性。

再来看看将要被运行的deploy.sh部署代码:

#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
npm run build # 生成静态文件
cd docs/.vuepress/dist # 进入生成的文件夹

# deploy to github
echo 'blog.xugaoyi.com' > CNAME
if [ -z "$GITHUB_TOKEN" ]; then
  msg='deploy'
  githubUrl=git@github.com:xugaoyi/blog.git
else
  msg='来自github action的自动部署'
  githubUrl=https://xugaoyi:${GITHUB_TOKEN}@github.com/xugaoyi/blog.git
  git config --global user.name "xugaoyi"
  git config --global user.email "894072666@qq.com"
fi
git init
git add -A
git commit -m "${msg}"
git push -f $githubUrl master:gh-pages # 推送到github

# deploy to coding
echo 'www.xugaoyi.com\nxugaoyi.com' > CNAME  # 自定义域名
if [ -z "$CODING_TOKEN" ]; then  # -z 字符串 长度为0则为true;$CODING_TOKEN来自于github仓库`Settings/Secrets`设置的私密环境变量
  codingUrl=git@git.dev.tencent.com:xugaoyi/xugaoyi.git
else
  codingUrl=https://xugaoyi:${CODING_TOKEN}@git.dev.tencent.com/xugaoyi/xugaoyi.git
fi
git add -A
git commit -m "${msg}"
git push -f $codingUrl master # 推送到coding

cd -
rm -rf docs/.vuepress/dist
这个文件使用Shell命令

(opens new window)写的,它会先运行打包命令,进入打包好的文件,创建一个自定义域名的CNAME文件(如果你没有自定义域名可去掉这个命令),判断是否有token环境变量,如果没有说明是在本地自己的电脑上运行的部署,使用ssh代码仓库地址,如果有token环境变量,说明是GitHub Actions自动触发的部署,此时使用的是可以通过toKen来获取代码提交权限的提交地址。最后通过git命令提交到各自的仓库,完成部署。

提示:

  • Shell 可以获取到环境变量。

  • 我想给两个平台上部署的博客不一样的自定义域名,因此做了分开创建CNAME文件,分开提交。

至此,我前面提到的需求就实现啦,只需要把源码push到github仓库这一个步骤,后面的博客打包、部署到github和coding等工作都由GitHub Actions来自动完成。

如下你想查看部署日志,你可以到github仓库的Actions这里查看。

from https://xugaoyi.com/pages/6b9d359ec5aa5019/

( https://learnku.com/articles/45612)

-----

vuepress-theme-reco + Github Actions 搭建静态博客,自动构建部署到第三方服务器

 

先下载主题模板,再根据自己的需要进行相应的修改,再根据自己的服务器配置 Github Actions 文件,最后上传到 Github,触发 Github Actions 自动构建部署到服务器

# 相关

  • vuepress-theme-reco:

    一款简洁而优雅的 vuepress 博客 & 文档 主题。

  • Github Actions:

    GitHub 操作 帮助您在您存储代码的同一位置自动执行软件开发工作流程,并协作处理拉取请求和议题。 您可以写入个别任务,称为操作,并结合它们创建一个自定义的工作流程。 工作流程是您可以在仓库中创建的自定义自动化流程,用于在 GitHub 上构建、测试、封装、发行或部署任何代码项目。

    通过 GitHub 操作 可直接在仓库中构建端到端持续集成 (CI) 和持续部署 (CD) 功能。

  • SamKirkland / FTP-Deploy-Action:

    Automate deploying websites and more with this GitHub action

    通过 GitHub action 自动部署网页等操作

# 博客主题配置

# 快速开始

# 使用模板

# 初始化
sudo yarn global add @vuepress-reco/theme-cli
theme-cli init my-blog

# 安装
cd my-blog
sudo yarn install

# 更改最新依赖

{
  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  },
  "dependencies": {
    "@vuepress/plugin-nprogress": "1.9.8",
    "vuepress": "1.9.8",
    "vuepress-plugin-code-copy": "1.0.6",
    "vuepress-plugin-flowchart": "1.5.0",
    "vuepress-plugin-reading-progress": "1.0.10",
    "vuepress-theme-reco": "1.6.16"
  }
}

然后,安装依赖运行

npm install
npm run docs:build 

# 目录结构


.
├── .git-ftp-include  // 用于最后指定需要部署的文件或文件夹
├── .gitattributes  // 用于统一文件内编码的换行符
├── .github
│   └── workflows
│       └── nodejs.yml  // Github Actions的配置文件
├── .gitignore  // 忽略上传到Github的文件或目录
├── LICENSE // 许可证文件
├── README.md // Github项目展示文件
├── docs  // VuePress项目根目录
│   ├── .vuepress // 存放配置文件的文件夹
│   │   ├── config.js // 整个工程的配置文件
│   │   ├── dist  // 最后生成的文件目录
│   │   ├── public  // 媒体文件夹(主要是图片)
│   │   └── styles  // 网页样式文件夹(里面空的,没有用)
│   ├── README.md // 网页首页文件
│   └── views // 存放markdown文件的文件夹(可以不要直接把markdown文件放在docs里面)
│       └── frontEnd  // 分类目录(也可以不要分类目录直接放在views里面)
├── package.json  // 指定依赖,项目脚本,Node.js项目描述文件
├── yarn-error.log  // 记录构建失败的日志文件
└── yarn.lock // 变更依赖时自动生成和更新

# 添加博客配置

然后根据需要更改一些内容和设置,参考官方的文档,可自行取舍相应内容

(opens new window)

VuePress

// docs/.vuepress/config.js

module.exports = {
  //   host: "0.0.0.0", // 生成网页地址(本地调试使用)
  //   port: "22333", // 生成网页端口(本地调试使用)
  title: "Tsanfer's Blog", // 显示在左上角的网页名称以及首页在浏览器标签显示的title名称
  description: "现居住于猎户臂上的一个碳基生命", // meta 中的描述文字,用于SEO
  head: [
    ["link", { rel: "icon", href: "/favicon.svg" }], //浏览器的标签栏的网页图标,基地址/docs/.vuepress/public
    [
      "meta",
      {
        name: "viewport",
        content: "width=device-width,initial-scale=1,user-scalable=no",
      },
    ], //在移动端,搜索框在获得焦点时会放大
  ],
  theme: "reco", //选择主题‘reco’
  themeConfig: {
    type: "blog", //选择类型博客
    fullscreen: true,
    blogConfig: {
      category: {
        location: 2, // 在导航栏菜单中所占的位置,默认2
        text: "分类", // 默认 “分类”
      },
      tag: {
        location: 3, // 在导航栏菜单中所占的位置,默认3
        text: "标签", // 默认 “标签”
      },
      socialLinks: [
        { icon: "reco-github", link: "https://github.com/Tsanfer" },
        { icon: "reco-bilibili", link: "https://space.bilibili.com/12167681" },
        { icon: "reco-qq", link: "tencent://message/?uin=1124851454" },
        { icon: "reco-twitter", link: "https://twitter.com/a1124851454" },
        { icon: "reco-mail", link: "mailto:a1124851454@gmail.com" },
      ],
    },
    nav: [
      //导航栏设置
      { text: "主页", link: "/", icon: "reco-home" },
      {
        text: "工具",
        icon: "reco-api",
        items: [
          {
            text: "个人网盘",
            link: "http://clouddisk.tsanfer.com:8080",
            icon: "fa-hdd",
          },
          {
            text: "订阅转换器",
            link: "http://clouddisk.tsanfer.com:58080",
            icon: "fa-exchange-alt",
          },
          {
            text: "目标检测",
            link: "http://hpc.tsanfer.com:8000",
            icon: "fa-object-ungroup",
          },
        ],
      },
      {
        text: "联系",
        icon: "reco-message",
        items: [
          {
            text: "GitHub",
            link: "https://github.com/Tsanfer",
            icon: "reco-github",
          },
          {
            text: "CSDN",
            link: "https://blog.csdn.net/qq_27961843/",
            icon: "reco-csdn",
          },
          {
            text: "BiliBili",
            link: "https://space.bilibili.com/12167681",
            icon: "reco-bilibili",
          },
          {
            text: "QQ",
            link: "tencent://message/?uin=1124851454",
            icon: "reco-qq",
          },
          {
            text: "Twitter",
            link: "https://twitter.com/a1124851454",
            icon: "reco-twitter",
          },
          {
            text: "Gmail",
            link: "mailto:a1124851454@gmail.com",
            icon: "reco-mail",
          },
        ],
      },
    ],
    sidebar: {
      "/views/frontEnd/": [
        {
          title: "前端", // 必要的
          sidebarDepth: 2, // 可选的, 默认值是 1
          children: [
            "vuepress_theme_reco-Github_Actions",
            "VuePress_GithubPages_TravisCI",
            "Sphinx_GitHub_ReadtheDocs",
          ],
        },
      ],
      "/views/MCU/": [
        {
          title: "MCU", // 必要的
          sidebarDepth: 2, // 可选的, 默认值是 1
          children: [
            "Linux_board_NFS",
            "First_Prepare_for_Lanqiao_Cup_MCU_Competition",
          ],
        },
      ],
      "/views/Computer/": [
        {
          title: "计算机", // 必要的
          sidebarDepth: 2, // 可选的, 默认值是 1
          children: [
            "Storage_hardware",
            "Windows_WSL_terminal_WebDAV_PartitionBackup",
          ],
        },
      ],
      "/views/Tool/": [
        {
          title: "工具", // 必要的
          sidebarDepth: 2, // 可选的, 默认值是 1
          children: ["Frp_Docker_SSH_RDP"],
        },
      ],
      "/views/Hack/": [
        {
          text: "Hack",
          sidebarDepth: 2,
          children: ["Cheat_engine-Kingdom_rush"],
        },
      ],
    },
    // displayAllHeaders: true, // 默认值:false
    subSidebar: "auto",

    record: "蜀ICP备20005033号-2",
    recordLink: "https://beian.miit.gov.cn/",
    cyberSecurityRecord: "川公网安备 51110202000301号",
    cyberSecurityLink: "http://www.beian.gov.cn/",
    startYear: "2020", // 项目开始时间,只填写年份
    lastUpdated: "最后更新时间", // string | boolean
    author: "Tsanfer",
    authorAvatar: "/avatar.svg", //作者头像
    mode: "light", //默认显示白天模式
    codeTheme: "okaidia", // default 'tomorrow'
    smooth: "true", //平滑滚动
    // 评论设置
    valineConfig: {
      appId: process.env.LEANCLOUD_APP_ID,
      appKey: process.env.LEANCLOUD_APP_KEY,
    },
  },
  markdown: {
    lineNumbers: true, //代码显示行号
  }, // 搜索设置
  search: true,
  searchMaxSuggestions: 10, // 插件
  plugins: [
    ["flowchart"], // 支持流程图
    ["@vuepress/nprogress"], // 加载进度条
    ["reading-progress"], // 阅读进度条
    ["vuepress-plugin-code-copy", true], //一键复制代码插件
  ],
};

# Github Actions 配置

# 修改 Github Actions 配置文件

在 Github 网页上添加 Github Actions 配置文件,参考官方的文档,可自行取舍相应内容,其中需要保密的部分需要添加 Github Secrets 环境变量

# .github/workflows/nodejs.yml

on: push # 触发此文件运行的条件
name: CI/CD # 此工作流程(workflow)的名字
jobs:
  FTP-Deploy-Action:
    name: CI&CD # 此任务(job)的名字
    runs-on: ubuntu-22.04 # 运行环境
    steps:
      - uses: actions/checkout@v3 # 切换分支
        with:
          fetch-depth: 2

      - name: Use Node.js 16
        uses: actions/setup-node@v3 # 使用node环境
        with:
          node-version: 16 # 版本16

      - name: Cache node modules
        id: cache # 缓存id
        uses: actions/cache@v3
        env:
          cache-name: cache-node-modules # 缓存名字
        with:
          path: node_modules # 缓存路径
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package.json') }} # 缓存标识

      - name: Install Dependencies
        if: steps.cache.outputs.cache-hit != 'true' # 如果没有缓存的话
        run: npm install # 安装依赖

      - name: Build project
        run: npm run docs:build # 构建项目和生成代码覆盖率报告
        env:
          LEANCLOUD_APP_ID: ${{ secrets.LEANCLOUD_APP_ID }} # 评 论系统的ID
          LEANCLOUD_APP_KEY: ${{ secrets.LEANCLOUD_APP_KEY }} # 评论系统的KEY

      # 如果FTP-Deploy-Action出现,Dirty repository: Having uncommitted changes. 问题时,使用以下注释步骤解决问题
      - name: reset git
        run: git reset --hard

      - name: 📂 Sync files
        uses: SamKirkland/FTP-Deploy-Action@4.3.3
        with:
          server: ${{ secrets.FTP_IP }}
          username: ${{ secrets.FTP_USERNAME }}
          password: ${{ secrets.FTP_PASSWORD }}
          local-dir: docs/.vuepress/dist/ # 选择哪些文件要部署到服务器,这个选项在这里选了之后,要在.git-ftp-include中添加相应的路径
          server-dir: /

#           ftp-server: sftp://${{ secrets.FTP_IP }}/home/www/htdocs # 服务器地址和端口(可以填域名,不过我服务器做了全站加速会导向加速结点的IP,所以只能用服务器的IP)
#           ftp-username: ${{ secrets.FTP_USERNAME }} # FTP用户名
#           ftp-password: ${{ secrets.FTP_PASSWORD }} # FTP密码
#           git-ftp-args: --insecure # (如果是FTP连接的话--insecure不用加)
#           local-dir: docs/.vuepress/dist/ # 选择哪些文件要部署到服务器,这个选项在这里选了之后,要在.git-ftp-include中添加相应的路径

      - name: upload-artifact
        uses: actions/upload-artifact@v3 #共享或保存action过程中产生的文件
        with:
          name: static_web_file
          path: ./docs/.vuepress/dist/ # or path/to/artifact
// .git-ftp-include

!docs/.vuepress/dist/

# 添加 Github Token

为了保密,把重要信息用变量表示,在 Github Secrets 中添加相应的值

仓库的 Settings --> Secrets --> Add a new secret

比如

  • Name: FTP_USERNAME
  • Value: admin

最后再把代码上传到 Github 便可自动触发构建,部署到第三方服务器.

WTFPL License

CI/CD

  • Github 链接

    from https://tsanfer.com/views/frontEnd/vuepress_theme_reco-Github_Actions.html 

  • ------------------------------------------------- 

    Vuepress + GitHub Actions 实现博客自动部署!

     

    本文已同步至:https://cunyu1943.github.io,欢迎关注后续更新!

    前言

    正常我们利用 Vuepress 搭建一个文档博客之后,往往都是通过如下步骤来部署一篇博客:

    1. 首先写文章;
    2. 写完文章之后生成静态文件,这里一般使用的是 npm run build 命令,但也有使用 yarn build 的;
    3. 将我们生成的静态文件推送到 Github Pages;
    4. 访问我们对应的网址,查看我们的推送是否成功。

    上述步骤看似简单,但一旦文档过多时,生成静态文件就十分耗费时间。这时候我们就想了,有不有一种方法,能够帮我们自动构建静态文件然后部署到 Github Pages 上呢。刚好,Github 官方提供了这个一个工具:Github Actions。利用它,我们就能够将重心转移到创作之后,每次创作之后推送到远程之后它就会自动后续工作,接下来我们就来看看如何利用 Github Action 实现自动部署我们的博客。

    生成 Token

    要部署 Actions,那么它就需要有能够操作我们仓库的权限,因此需要提前设置个人访问令牌(Github personal access)。设置方法如下:进入 Github 后,点击我们的头像,然后依次进入 Settings -> Developer settings -> Personal access tokens,对应地址就是 Token 生成[1]。然后点击右上方的 Generate new token,接着输入 token 的名字,这个名字可以随意,不过还是推荐根据它的用途来命名。然后选 Expiration,也就是这个 Token 的有效期,如果我们要长期用,建议选为 No expiration,意思就是无期限。最后就是选权限,一般来讲这里选 repo 就够了,但是如果你不确定,那就全都选上也行。然后点击 Generate Token,会生成一个令牌,注意这里它只会出现一次,一旦刷新该网页就不见了,所以最好把它复制到你的备忘录备份一下,而且我们待会也是需要用到这个 Token 的。


    设置 Secrets

    进入你存放你博客源码的项目,然后依次点击 Settings -> Secrets,接着点击右上角的 New repository secret,新建一个 Secret。这里的名字要命名为 ACCESS_TOKEN,然后 Value 就是我们上一步中所生成的 Token。


    编写 Action

    进入项目的的 Actions 选项,然后新建一个 workflow(我是因为已经建立过了,所以才是下面的界面),默认新建的 workflow 名字是 main.yml 这个可以自己自定义,根据你自己喜好来就行了。

    生成后的 main.yml 位于项目的 .github/workflows 目录下。

    接下来是在 main.yml 中填入如下信息即可,具体实例的可以参考我的博客实例:

    https://github.com/cunyu1943/cunyu1943.github.io/

    代码语言:javascript
    AI代码解释
    # name 可以自定义
    name: Deploy GitHub Pages
    
    # 触发条件:在 push 到 main/master 分支后,新的 Github 项目 应该都是 main,而之前的项目一般都是 master
    on:
      push:
        branches:
          - main
    
    # 任务
    jobs:
      build-and-deploy:
        # 服务器环境:最新版 Ubuntu
        runs-on: ubuntu-latest
        steps:
          # 拉取代码
          - name: Checkout
            uses: actions/checkout@v2
            with:
              persist-credentials: false
    
          # 生成静态文件
          - name: Build
            run: npm install && npm run docs:build
    
          # 部署到 GitHub Pages
          - name: Deploy
            uses: JamesIves/github-pages-deploy-action@releases/v3
            with:
              ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} # 也就是我们刚才生成的 secret
              BRANCH: gh-pages # 部署到 gh-pages 分支,因为 main 分支存放的一般是源码,而 gh-pages 分支则用来存放生成的静态文件
              FOLDER: docs/.vuepress/dist # vuepress 生成的静态文件存放的地方
    

    验证

    经过上面的的步骤配置好之后,就可以点击仓库的 Actions 来查看部署情况了。

    如果是绿色的,说明自动部署成功了,如果是红色,那就说明部署失败。这个时候我们可以点进去看看部署失败的日志信息。

    以我部署失败的一个实例来讲,可以看到主要是在部署步骤出了问题,我们就可以根据给出的错误日志来找出问题所在,然后找方法解决它了。

    我这里错误的大体意思就是说我 Vuepress 项目下的的 dist 目录不存在,而解决方法则是在 Vuepress 的配置文件中的 dist 设置为 docs/.vuepress/dist 即可。


    总结

    以上就是关于 Vuepress + Github Actions 实现自动部署的所有内容了,如果对你有所帮助,那就帮忙点赞关注吧!

    最后,贴出我的博客地址,可以去看看效果!

    • 项目文件:https://github.com/cunyu1943/cunyu1943.github.io
    • 预览地址:https://cunyu1943.github.io/

    参考资料

    [1] Token 生成: https://github.com/settings/tokens

    from https://cloud.tencent.com/developer/article/1956413 

    (https://juejin.cn/post/7239536753971724344,

     https://www.cnblogs.com/robindevnotes/p/18577680)

     --------------------

    相关帖子:

     https://briteming.blogspot.com/2017/02/githubnodejsvue-ghpages-blog.html

    No comments:

    Post a Comment