<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Hexo - 她和她的猫</title>
    <link>https://her-cat.com/tags/hexo/</link>
    <description>Hexo的文章列表 - 她和她的猫</description>
    <image>
      <title>她和她的猫</title>
      <url>https://her-cat.com/assets/favorite.jpeg</url>
      <link>https://her-cat.com/assets/favorite.jpeg</link>
    </image>
    <generator>Hugo -- 0.148.1</generator>
    <language>zh</language>
    <lastBuildDate>Tue, 30 Mar 2021 16:02:45 +0800</lastBuildDate>
    <atom:link href="https://her-cat.com/tags/hexo/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>使用 GitHub Actions 自动部署 Hexo</title>
      <link>https://her-cat.com/posts/2021/03/30/github-action-deploy-hexo/</link>
      <pubDate>Tue, 30 Mar 2021 16:02:45 +0800</pubDate>
      <guid>https://her-cat.com/posts/2021/03/30/github-action-deploy-hexo/</guid>
      <description>目前部署 Hexo 的操作比较麻烦，先在本地执行 hexo clean &amp;amp;&amp;amp; hexo d 生成博客静态文件并发布到 GitHub 上，然后通过 XShell 登录</description>
      <content:encoded><![CDATA[<p>目前部署 Hexo 的操作比较麻烦，先在本地执行 <strong>hexo clean &amp;&amp; hexo d</strong> 生成博客静态文件并发布到 GitHub 上，然后通过 XShell 登录到服务器，切换到博客站点目录下 git pull 拉取最新的代码，最近网络也不太不稳定，拉取代码也经常超时，更新的时候还得看运气。</p>
<p>有两种方案可以自动更新：GitHub WebHook 和 GitHub Actions。</p>
<p>WebHook 是一种比较简单且常见的方式，在仓库配置一个回调地址并指定需要回调的事件类型即可。</p>
<p>比如指定了 push 事件，往该仓库 push 代码时，GitHub 就会请求配置的回调地址并携带一些信息，通过这些信息就可以检查请求是否合法、是哪个仓库的谁提交了代码，从而决定是否需要更新服务器端的代码。</p>
<p>详情可以看官方的文档：<a href="https://docs.github.com/cn/developers/webhooks-and-events/about-webhooks">https://docs.github.com/cn/developers/webhooks-and-events/about-webhooks</a></p>
<p>Actions 是 GitHub 新推出来（快两年，也不算新了）的一种持续集成的方案，将上面这些操作变成一个个的任务（Job）组成工作流，当发生指定事件后触发该工作流，也可以用别人写好的工作流。</p>
<p>更详细的内容可以看 <a href="https://docs.github.com/cn/actions">官方文档</a> 和阮老师的 <a href="http://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html">GitHub Actions 入门教程</a>。</p>
<p>话不多说，直接贴 GitHub Actions 的配置。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 工作流的名称</span>
</span></span><span class="line"><span class="cl"><span class="n">name</span><span class="p">:</span> <span class="n">Hexo</span> <span class="n">Blog</span> <span class="n">CI</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 指定触发的条件，这里是打标签才触发该工作流，你也可以改成 on: push，只要提交代码就触发</span>
</span></span><span class="line"><span class="cl"><span class="n">on</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">push</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">tags</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="s1">&#39;v*&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">jobs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">build</span><span class="p">:</span> 
</span></span><span class="line"><span class="cl">    <span class="n">runs</span><span class="o">-</span><span class="n">on</span><span class="p">:</span> <span class="n">ubuntu</span><span class="o">-</span><span class="n">latest</span> 
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="n">steps</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 检查工作流是否可以访问 actions</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Checkout</span> <span class="n">Repository</span> <span class="n">master</span> <span class="n">branch</span>
</span></span><span class="line"><span class="cl">      <span class="n">uses</span><span class="p">:</span> <span class="n">actions</span><span class="o">/</span><span class="n">checkout</span><span class="err">@</span><span class="n">master</span> 
</span></span><span class="line"><span class="cl">      
</span></span><span class="line"><span class="cl">    <span class="c1"># 安装 NodeJs</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Setup</span> <span class="ne">Node</span><span class="o">.</span><span class="n">js</span> <span class="mf">12.</span><span class="n">x</span> 
</span></span><span class="line"><span class="cl">      <span class="n">uses</span><span class="p">:</span> <span class="n">actions</span><span class="o">/</span><span class="n">setup</span><span class="o">-</span><span class="n">node</span><span class="err">@</span><span class="n">master</span>
</span></span><span class="line"><span class="cl">      <span class="n">with</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">node</span><span class="o">-</span><span class="n">version</span><span class="p">:</span> <span class="s2">&#34;12.x&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 安装 Hexo 的依赖库</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Setup</span> <span class="n">Hexo</span> <span class="n">Dependencies</span>
</span></span><span class="line"><span class="cl">      <span class="n">run</span><span class="p">:</span> <span class="o">|</span>
</span></span><span class="line"><span class="cl">        <span class="n">npm</span> <span class="n">install</span> <span class="n">hexo</span><span class="o">-</span><span class="n">cli</span> <span class="o">-</span><span class="n">g</span>
</span></span><span class="line"><span class="cl">        <span class="n">npm</span> <span class="n">install</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 设置 Hexo 部署的私钥</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Setup</span> <span class="n">Deploy</span> <span class="n">Private</span> <span class="n">Key</span>
</span></span><span class="line"><span class="cl">      <span class="n">env</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">HEXO_DEPLOY_PRIVATE_KEY</span><span class="p">:</span> <span class="o">$</span><span class="p">{{</span> <span class="n">secrets</span><span class="o">.</span><span class="n">HEXO_DEPLOY_PRIVATE_KEY</span> <span class="p">}}</span>
</span></span><span class="line"><span class="cl">      <span class="n">run</span><span class="p">:</span> <span class="o">|</span>
</span></span><span class="line"><span class="cl">        <span class="n">mkdir</span> <span class="o">-</span><span class="n">p</span> <span class="o">~/.</span><span class="n">ssh</span><span class="o">/</span>
</span></span><span class="line"><span class="cl">        <span class="n">echo</span> <span class="s2">&#34;$HEXO_DEPLOY_PRIVATE_KEY&#34;</span> <span class="o">&gt;</span> <span class="o">~/.</span><span class="n">ssh</span><span class="o">/</span><span class="n">id_rsa</span> 
</span></span><span class="line"><span class="cl">        <span class="n">chmod</span> <span class="mi">600</span> <span class="o">~/.</span><span class="n">ssh</span><span class="o">/</span><span class="n">id_rsa</span>
</span></span><span class="line"><span class="cl">        <span class="n">ssh</span><span class="o">-</span><span class="n">keyscan</span> <span class="n">github</span><span class="o">.</span><span class="n">com</span> <span class="o">&gt;&gt;</span> <span class="o">~/.</span><span class="n">ssh</span><span class="o">/</span><span class="n">known_hosts</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 设置 Git 信息</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Setup</span> <span class="n">Git</span> <span class="n">Infomation</span>
</span></span><span class="line"><span class="cl">      <span class="n">run</span><span class="p">:</span> <span class="o">|</span> 
</span></span><span class="line"><span class="cl">        <span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">user</span><span class="o">.</span><span class="n">name</span> <span class="s2">&#34;Git 用户名&#34;</span> 
</span></span><span class="line"><span class="cl">        <span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">user</span><span class="o">.</span><span class="n">email</span> <span class="s2">&#34;Git 邮箱&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 部署 Hexo 静态文件到博客所在的分支</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Deploy</span> <span class="n">Hexo</span> 
</span></span><span class="line"><span class="cl">      <span class="n">run</span><span class="p">:</span> <span class="o">|</span>
</span></span><span class="line"><span class="cl">        <span class="n">hexo</span> <span class="n">clean</span>
</span></span><span class="line"><span class="cl">        <span class="n">hexo</span> <span class="n">generate</span> 
</span></span><span class="line"><span class="cl">        <span class="n">hexo</span> <span class="n">deploy</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 部署到服务器</span>
</span></span><span class="line"><span class="cl">    <span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="n">Deploy</span> <span class="n">Server</span>
</span></span><span class="line"><span class="cl">      <span class="n">uses</span><span class="p">:</span> <span class="n">appleboy</span><span class="o">/</span><span class="n">ssh</span><span class="o">-</span><span class="n">action</span><span class="err">@</span><span class="n">master</span>
</span></span><span class="line"><span class="cl">      <span class="n">env</span><span class="p">:</span> 
</span></span><span class="line"><span class="cl">        <span class="n">SITE_DIR</span><span class="p">:</span> <span class="err">站点目录（如：</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="n">www</span><span class="o">/</span><span class="n">blog</span><span class="err">）</span>
</span></span><span class="line"><span class="cl">      <span class="n">with</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">host</span><span class="p">:</span> <span class="o">$</span><span class="p">{{</span> <span class="n">secrets</span><span class="o">.</span><span class="n">SERVER_IP</span> <span class="p">}}</span>
</span></span><span class="line"><span class="cl">        <span class="n">port</span><span class="p">:</span> <span class="o">$</span><span class="p">{{</span> <span class="n">secrets</span><span class="o">.</span><span class="n">SERVER_PORT</span> <span class="p">}}</span>
</span></span><span class="line"><span class="cl">        <span class="n">username</span><span class="p">:</span> <span class="o">$</span><span class="p">{{</span> <span class="n">secrets</span><span class="o">.</span><span class="n">SERVER_USERNAME</span> <span class="p">}}</span>
</span></span><span class="line"><span class="cl">        <span class="n">key</span><span class="p">:</span> <span class="o">$</span><span class="p">{{</span> <span class="n">secrets</span><span class="o">.</span><span class="n">SERVER_PRIVATE_KEY</span> <span class="p">}}</span>
</span></span><span class="line"><span class="cl">        <span class="n">envs</span><span class="p">:</span> <span class="n">SITE_DIR</span>
</span></span><span class="line"><span class="cl">        <span class="n">script</span><span class="p">:</span> <span class="o">|</span>
</span></span><span class="line"><span class="cl">          <span class="n">cd</span> <span class="o">$</span><span class="n">SITE_DIR</span>
</span></span><span class="line"><span class="cl">          <span class="n">sudo</span> <span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="n">global</span> <span class="n">pull</span><span class="o">.</span><span class="n">rebase</span> <span class="bp">true</span>
</span></span><span class="line"><span class="cl">          <span class="n">sudo</span> <span class="n">git</span> <span class="n">pull</span> <span class="n">origin</span> <span class="n">master</span> <span class="o">--</span><span class="n">allow</span><span class="o">-</span><span class="n">unrelated</span><span class="o">-</span><span class="n">histories</span>
</span></span></code></pre></div><p>其中 <strong>Git 用户名</strong>、<strong>Git 邮箱</strong>、<strong>站点目录</strong> 都要替换成你自己的。</p>
<p>首先打开 <a href="https://github.com/">https://github.com/</a>用户名/仓库名/settings/secrets/actions 新增几个 Action secret，在上面的执行工作流的时候会用到。</p>
<p>需要新增以下几项：</p>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Value</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SERVER_IP</td>
          <td>服务器 IP</td>
      </tr>
      <tr>
          <td>SERVER_PORT</td>
          <td>服务器端口号</td>
      </tr>
      <tr>
          <td>SERVER_USERNAME</td>
          <td>用户名</td>
      </tr>
      <tr>
          <td>SERVER_PRIVATE_KEY</td>
          <td>服务器私钥（服务器的 ~/.ssh/id_rsa）</td>
      </tr>
      <tr>
          <td>HEXO_DEPLOY_PRIVATE_KEY</td>
          <td>部署私钥（本地的 ~/.ssh/id_rsa）</td>
      </tr>
  </tbody>
</table>
<p>前三项就不多说，主要讲下后面两项怎么设置。</p>
<blockquote>
<p>HEXO_DEPLOY_PRIVATE_KEY 是为了在工作流中能够提交代码到 GitHub，SERVER_PRIVATE_KEY 是为了能在工作流中登录到服务器上执行命令。</p></blockquote>
<p>工作流被触发后，先生成博客的静态文件，并通过 hexo deploy 提交到博客所在的分支（由 Hexo 配置文件中的 deploy.branch 指定），这里涉及到提交代码，所以要配置 SSH Key。</p>
<p>查看电脑上是否已经生成了密钥对。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ ll ~/.ssh
</span></span><span class="line"><span class="cl"># 输出： id_rsa  id_rsa.pub  known_hosts
</span></span></code></pre></div><p>如果为空则执行以下命令，一路回车就可以了：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ ssh-keygen -t rsa -C &#34;你的邮箱&#34;
</span></span></code></pre></div><p>这时候电脑上就会有两个文件：~/.ssh/id_rsa、~/.ssh/id_rsa.pub，分别是是私钥和公钥。</p>
<p>id_rsa 文件的内容就是 HEXO_DEPLOY_PRIVATE_KEY 的 Value。</p>
<p>然后打开 <a href="https://github.com/settings/ssh/new">https://github.com/settings/ssh/new</a>，将 id_rsa.pub 的内容填到 Key 里面，Title 可以随便去，然后保存。</p>
<p>接下来就是 SERVER_PRIVATE_KEY，登录到服务器拿到密钥对，步骤跟上面差不多，没有的话就生成。</p>
<p>服务器中 ~/.ssh/id_rsa 文件的内容就是 SERVER_PRIVATE_KEY 的 Value，然后将 ~/.ssh/id_rsa.pub 的内容追加到 ~/.ssh/authorized_keys 文件中。</p>
<p>需要注意：</p>
<ul>
<li>服务器中必须已经存在 SITE_DIR 目录，且已经将仓库 clone 下来了。</li>
<li>在服务器上可以免密执行 git pull。</li>
</ul>
<p>更新博客时只需要打标签，然后将标签推送到云端就会触发工作流。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">$ git tag v1.0.0
</span></span><span class="line"><span class="cl">$ git push origin v1.0.0
</span></span></code></pre></div><p><img alt="GitHub Actions Log" decoding="async" height="869" loading="lazy" sizes="(max-width: 768px) 100vw, (max-width: 1024px) 768px, 1024px" src="/posts/2021/03/30/github-action-deploy-hexo/github-actions-log.png" srcset="/posts/2021/03/30/github-action-deploy-hexo/github-actions-log_hu_37b79eb5e295c66d.png 384w, /posts/2021/03/30/github-action-deploy-hexo/github-actions-log_hu_4630f40328e043eb.png 768w, /posts/2021/03/30/github-action-deploy-hexo/github-actions-log_hu_b0ff64478b3ef28e.png 1024w, /posts/2021/03/30/github-action-deploy-hexo/github-actions-log_hu_7ff4ce1cd4b71578.png 1536w, /posts/2021/03/30/github-action-deploy-hexo/github-actions-log.png 1897w" style="max-width: 100%; height: auto; aspect-ratio: 2.1830;" width="1897"></p>
]]></content:encoded>
    </item><follow_challenge>
      <feedId>58021783493571598</feedId>
      <userId>56882619875632128</userId>
    </follow_challenge>
  </channel>
</rss>
