tag:crieit.net,2005:https://crieit.net/tags/GitHubActions/feed
「GitHubActions」の記事 - Crieit
Crieitでタグ「GitHubActions」に投稿された最近の記事
2022-02-21T21:08:44+09:00
https://crieit.net/tags/GitHubActions/feed
tag:crieit.net,2005:PublicArticle/18120
2022-02-21T21:08:44+09:00
2022-02-21T21:08:44+09:00
https://crieit.net/posts/GitHub-Actions-EACCES-permission-denied
GitHub ActionsでEACCES: permission deniedが出るとき
<p>GitHub Actionsでnpx prisma generateを実行するとEACCES: permission deniedというエラーが出て全然うまくいかない。</p>
<p>ためしに yarn prisma generate とすると動いた。npxだとユーザーかなにかが違う…?</p>
だら@Crieit開発者
tag:crieit.net,2005:PublicArticle/17627
2021-08-30T17:14:25+09:00
2021-08-30T17:14:25+09:00
https://crieit.net/posts/GitHub-Actions-Jest
GitHub ActionsでJestを叩くときのタイムゾーンと言語を設定する
<p>GitHub リポジトリにプッシュした時、GitHub Actions のワークフローで自動的に Jest を走らせるようにしています。GitHub 上で自動的に走る Jest と、手動で直接叩く Jest との違いはタイムゾーンとロケールです。ここでは、GitHub 上で Jest を動かすときに環境変数としてタイムゾーンとロケールを指定する方法について説明します。</p>
<h2 id="1. package.json にグローバル設定ファイルを指定する"><a href="#1.+package.json+%E3%81%AB%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B">1. package.json にグローバル設定ファイルを指定する</a></h2>
<p>以下のように設定を追記します。<code>jest-global-setup.js</code>に設定を記載すれば、環境変数から読み込まれた値を上書きできます。</p>
<pre><code class="javascript"> "jest": {
"globalSetup": "./jest-global-setup.js"
},
</code></pre>
<h2 id="2. jest-global-setup.js の中身を記載する"><a href="#2.+jest-global-setup.js+%E3%81%AE%E4%B8%AD%E8%BA%AB%E3%82%92%E8%A8%98%E8%BC%89%E3%81%99%E3%82%8B">2. jest-global-setup.js の中身を記載する</a></h2>
<p>タイムゾーンと言語を指定します。</p>
<pre><code class="javascript">module.exports = async () => {
process.env.TZ = "Asia/Tokyo";
process.env.LANG = "en_US.UTF-8";
};
</code></pre>
<h2 id="3. 動作結果を確認する"><a href="#3.+%E5%8B%95%E4%BD%9C%E7%B5%90%E6%9E%9C%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B">3. 動作結果を確認する</a></h2>
<p>Jest のテストで出力される日時の文字列を確認したところ、言語が日本語から英語になっていることが確認できました。</p>
<pre><code class="text"> - "date": "Wed Apr 01 2020 09:00:00 GMT+0900 (日本標準時)",
+ "date": "Wed Apr 01 2020 09:00:00 GMT+0900 (Japan Standard Time)",
</code></pre>
kabueye
tag:crieit.net,2005:PublicArticle/17425
2021-06-21T22:22:57+09:00
2021-06-21T22:22:57+09:00
https://crieit.net/posts/Node-js-GitHub-Actions
📝 Node.js パッケージを公開するための GitHub Actions を構築する
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/react-emoji-textarea">react-emoji-textarea</a> の開発を行った際、<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/github/administering-a-repository/releasing-projects-on-github/managing-releases-in-a-repository">リリース</a>を作成したら自動的に Node.js パッケージにライブラリが公開される仕組みがほしいと考え、GitHub Actions でそれを実現することにしました。</p>
<p>その際、公式サイトに <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/en/actions/guides/publishing-nodejs-packages#publishing-packages-using-yarn">公開されている内容</a> を参考に GitHub Actions を作成したのですが、そのまま利用すると私の環境では下記のエラーが発生してしまいました。</p>
<pre><code class="bash">error Couldn't publish package: "https://registry.yarnpkg.com/@nikaera/react-emoji-textarea: You do not have permission to publish \"react-emoji-textarea\". Are you logged in as the correct user?"
</code></pre>
<p>上記のエラーについて調査しながら改修したところ、最終的に下記の GitHub Actions で Node.js パッケージを公開できるようになりました。<code>secrets.NPM_TOKEN</code> には <a target="_blank" rel="nofollow noopener" href="https://docs.npmjs.com/creating-and-viewing-access-tokens">NPM Token</a> を登録します。</p>
<pre><code class="yml"># package.yml
name: Node.js Package
on:
# workflow_dispatch を追加して手動でも実行できるよう改修
workflow_dispatch:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14.x"
registry-url: "https://registry.npmjs.org"
# registry.npmjs.org へアクセスする際は必ず認証を試みるオプションを追加
always-auth: true
# scope には自分のユーザ名を指定
scope: "@nikaera"
# .npmrc に https://registry.npmjs.org アクセス時に利用する認証情報を記載する
- run: echo "//registry.npmjs.org/:_authToken=$<span>{</span><span>{</span> secrets.NPM_TOKEN <span>}</span><span>}</span>" > ~/.npmrc
- name: Build react-emoji-textarea 😆💖
run: |
yarn install --frozen-lockfile
yarn format
yarn build
- run: yarn publish --access public
env:
NODE_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NPM_TOKEN <span>}</span><span>}</span>
</code></pre>
nikaera
tag:crieit.net,2005:PublicArticle/17282
2021-05-26T22:30:30+09:00
2021-05-26T22:30:30+09:00
https://crieit.net/posts/unity-gameci-github-actions
GameCI で Unity の CI 環境を GitHub Actions で構築する
<h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1>
<p>先日同僚が Unity の CI 環境を構築するためのライブラリである <a target="_blank" rel="nofollow noopener" href="https://game.ci/">GameCI</a> について教えてくれました。早速 GameCI の GitHub Actions を利用して、サンプルプロジェクトで色々動作検証してみたところ、Unity の CI 環境を楽に構築できることが分かりました。</p>
<p>もちろん、<a target="_blank" rel="nofollow noopener" href="https://unity3d.com/jp/unity/features/cloud-build">Unity Cloud Build</a> を利用すれば CI 環境の構築は以前から楽にできました。しかし、選択肢の 1 つとして GameCI を持っておくことで、<strong>サクッと GitHub Actions に統合する形で Unity の CI 環境を導入できるのは他には無いメリットを感じました。</strong></p>
<p>本記事で紹介しているソースコード、及び検証時に利用したプロジェクトは GitHub にアップ済みですので、手っ取り早く内容を把握されたい方は下記をご参照くださいませ。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/Unity-GameCI-Sample">https://github.com/nikaera/Unity-GameCI-Sample</a></p>
<p>業務でも利用できそうなので、GameCI を利用して CI 環境を構築する手順を記事でまとめました。</p>
<h1 id="GameCI に備わっている機能紹介"><a href="#GameCI+%E3%81%AB%E5%82%99%E3%82%8F%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E6%A9%9F%E8%83%BD%E7%B4%B9%E4%BB%8B">GameCI に備わっている機能紹介</a></h1>
<p>GameCI には現状下記の GitHub Actions が用意されているようです。</p>
<div class="table-responsive"><table>
<thead>
<tr>
<th>機能</th>
<th>概要</th>
</tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/activation">Activation</a></td>
<td>Unity ライセンスを任意の Unity バージョンで発行する</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/test-runner">Test runner</a></td>
<td>Unity の PlayMode 及び EditMode のテストを実行する (テスト結果の出力にも対応)</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/builder">Builder</a></td>
<td>任意の Platform ビルドを実行する (<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/guides/storing-workflow-data-as-artifacts">アーティファクト</a> 利用でダウンロードも可能)</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/returning-a-license">Returning a license</a></td>
<td>Unity ライセンスの返却ができる (Professional License のみ対応)</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/remote-builder">Remote builder</a></td>
<td>GitHub Actions のスペックでは満足のいくビルドができない際に AWS 環境でハイスペックなマシンを用意してビルドできる。ビルドのためのインフラ構築には <a target="_blank" rel="nofollow noopener" href="https://aws.amazon.com/jp/cloudformation/">AWS CloudFormation</a> を使用している (現在は AWS のみ対応。今後 GCP, Azure にも対応予定とのこと)</td>
</tr>
<tr>
<td><a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/deployment/android">Deployment</a></td>
<td>Unity ビルドを各種 Platform 向けにデプロイする (iOS 及び Android のみ記載あり。厳密に言うと <code>Builder</code> でビルド出力した内容を <a target="_blank" rel="nofollow noopener" href="https://fastlane.tools/"><code>fastlane</code></a> を用いてデプロイするためのワークフロー紹介になっている)</td>
</tr>
</tbody>
</table></div>
<p>上記を見ると既に <strong>GameCI には開発者として Unity CI に欲しい機能は最低限揃っているように見受けられました。</strong> また本記事では、今後機会があれば試してみたいと考えていますが <strong>Remote builder 及び Deployment</strong> については言及していません。</p>
<p>今回は実例を交えながら <strong>Activation 及び Test runner、Builder、Returning a license</strong> の使用方法について紹介していきます。</p>
<h2 id="Activation: GameCI で必要となる Unity License のアクティベーションを行う"><a href="#Activation%3A+GameCI+%E3%81%A7%E5%BF%85%E8%A6%81%E3%81%A8%E3%81%AA%E3%82%8B+Unity+License+%E3%81%AE%E3%82%A2%E3%82%AF%E3%83%86%E3%82%A3%E3%83%99%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%A1%8C%E3%81%86">Activation: GameCI で必要となる Unity License のアクティベーションを行う</a></h2>
<p>GameCI で Unity ライセンスをアクティベートするには <a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/activation">Activation</a> を利用します。早速ドキュメントの手順に沿って作業を進めていきます。</p>
<p>まず CI を導入したい GitHub 上の Unity プロジェクトの <code>.github/workflows</code> 内に Unity ライセンスアクティベート用のワークフローファイルを作成します。</p>
<pre><code class="yml"># .github/workflows/activation.yml
name: Acquire activation file
on:
workflow_dispatch: {}
jobs:
activation:
name: Request manual activation file 🔑
runs-on: ubuntu-latest
steps:
# GameCI の Activation を利用して alf ファイルを発行する
- name: Request manual activation file
id: getManualLicenseFile
uses: game-ci/unity-request-activation-file@v2
with:
# Unity プロジェクトのバージョンを指定する
# ProjectSettings/ProjectVersion.txt に記載されているバージョンを入力すれば OK
unityVersion: 2020.3.5f1
# Upload artifact (Unity_v20XX.X.XXXX.alf)
- name: Expose as artifact
uses: actions/upload-artifact@v2
with:
name: $<span>{</span><span>{</span> steps.getManualLicenseFile.outputs.filePath <span>}</span><span>}</span>
path: $<span>{</span><span>{</span> steps.getManualLicenseFile.outputs.filePath <span>}</span><span>}</span>
</code></pre>
<p>その後、<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/github/setting-up-and-managing-your-github-user-account/managing-user-account-settings/managing-the-default-branch-name-for-your-repositories#about-management-of-the-default-branch-name">デフォルトブランチ</a> にプッシュして GitHub Actions で実行可能にしたら、下記手順に従い Unity ライセンスファイルのアクティベート及びダウンロードを行います。</p>
<p><img src="https://i.gyazo.com/bd276ca6dcf6a2c12ce9ff9569e08ce3.png" alt="1. ブラウザから GitHub リポジトリにアクセスして、Unity ライセンスアクティベート用のワークフローを実行して <code>alf</code> ファイルを生成する" /><br />
<strong>1. ブラウザから GitHub リポジトリにアクセスして、Unity ライセンスアクティベート用のワークフローを実行して <code>alf</code> ファイルを生成する</strong></p>
<p><img src="https://i.gyazo.com/2271b3cb35efc7f1c9d51702662cdac9.png" alt="2. ワークフローの実行に成功したら、該当項目をクリックして詳細画面に遷移する" /><br />
<strong>2. ワークフローの実行に成功したら、該当項目をクリックして詳細画面に遷移する</strong></p>
<p><img src="https://i.gyazo.com/71b9dff8266c9bc990e1b709a5191535.png" alt="3. <code>Artifacts</code> の項目から <code>alf</code> ファイルをダウンロードする" /><br />
<strong>3. <code>Artifacts</code> の項目から <code>alf</code> ファイルをダウンロードする</strong></p>
<p><img src="https://i.gyazo.com/cfec48fc58f2a17560ea2e7d0f71cc41.png" alt="4. [Unity license manual activation webpage](https://license.unity3d.com) からログインして <code>alf</code> ファイルをアップロードする" /><br />
<strong>4. <a target="_blank" rel="nofollow noopener" href="https://license.unity3d.com">Unity license manual activation webpage</a> からログインして <code>alf</code> ファイルをアップロードする</strong></p>
<p><img src="https://i.gyazo.com/72239a40ef5b2474f34c814a68f8c61d.png" alt="5. Unity ライセンスの用途に応じて適切な選択肢を入力する (本記事では Personal ライセンスを選択)" /><br />
<strong>5. Unity ライセンスの利用用途に応じて適切な選択肢を入力する (本記事では Personal ライセンスを選択)</strong></p>
<p><img src="https://i.gyazo.com/9ddc63dc321a68986bfedfb8a97c8f00.png" alt="6. <code>Download license</code> ボタンをクリックして <code>ulf</code> ファイルをダウンロードする" /><br />
<strong>6. <code>Download license</code> ボタンをクリックして <code>ulf</code> ファイルをダウンロードする</strong></p>
<p>これで Unity ライセンスファイルのアクティベートは完了です。<strong>次にアクティベートしたライセンスファイルを GitHub リポジトリの <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/reference/encrypted-secrets">Secrets</a> に登録して、GameCI で PlayMode 及び EditMode のテストが実行できるようにしていきます。</strong></p>
<p><em><code>alf</code> 拡張子のファイルがライセンスリクエストファイルを指していて、Unity ライセンスの発行に必要となるファイルです。<code>ulf</code> 拡張子のファイルが Unity ライセンスのファイルです。<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></em></p>
<h2 id="Test runner: PlayMode 及び EditMode テストを実行して結果を参照する"><a href="#Test+runner%3A+PlayMode+%E5%8F%8A%E3%81%B3+EditMode+%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6%E7%B5%90%E6%9E%9C%E3%82%92%E5%8F%82%E7%85%A7%E3%81%99%E3%82%8B">Test runner: PlayMode 及び EditMode テストを実行して結果を参照する</a></h2>
<p>GitHub Actions 上でテストを実行するために、<strong>先ほどアクティベートした Unity ライセンスの情報を ワークフロー上で扱えるようにする必要があります。そのため、まずは Secrets に <code>ulf</code> ファイルの内容を登録することから始めます。</strong></p>
<p><img src="https://i.gyazo.com/e126ae5e2fe9339d56047b8497808100.png" alt="1. Unity ライセンスの情報登録のため、Github リポジトリの <code>Secrets</code> 登録画面に遷移する" /><br />
<strong>1. Unity ライセンスの情報登録のため、Github リポジトリの <code>Secrets</code> 登録画面に遷移する</strong></p>
<p><img src="https://i.gyazo.com/f52356a229caa4e31e3ae8268d53a4e6.png" alt="2. GameCI はライセンス情報参照のため <code>Secrets</code> の <code>UNITY_LICENSE</code> を参照する。そのため、<code>Name</code> を <code>UNITY_LICENSE</code> で <code>Value</code> に <code>ulf</code> ファイルの中身をコピー & ペーストしておく" /><br />
<strong>2. GameCI はライセンス情報参照のため、デフォルト設定では <code>Secrets</code> の <code>UNITY_LICENSE</code> を参照する。そのため、<code>Name</code> が <code>UNITY_LICENSE</code>、<code>Value</code> には <code>ulf</code> ファイルの中身を登録する<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></strong></p>
<p>上記作業で GameCI でテストやビルド実行を行える環境が整ったので、動作検証のためテスト実行用のワークフローファイルを作成します。</p>
<pre><code class="yml"># .github/workflows/test.yml
name: Run EditMode and PlayMode Test
on:
workflow_dispatch: {}
jobs:
test:
name: Run EditMode and PlayMode Test
runs-on: ubuntu-latest
steps:
# actions/checkout@v2 を利用して作業ディレクトリに
# Unity プロジェクトの中身をダウンロードしてくる
- name: Check out my unity project.
uses: actions/checkout@v2
# GameCI の Test runner を利用して
# EditMode 及び PlayMode のテストを実行する
- name: Run EditMode and PlayMode Test
uses: game-ci/unity-test-runner@v2
env:
# 2. の手順で Secrets に登録した Unity ライセンスの情報を指定する
UNITY_LICENSE: $<span>{</span><span>{</span> secrets.UNITY_LICENSE <span>}</span><span>}</span>
# もし Professional license を使いたい場合は、
# メールアドレス、パスワード、シリアルナンバーを入力する必要がある
# ref: https://game.ci/docs/github/test-runner#professional-license
# UNITY_EMAIL: $<span>{</span><span>{</span> secrets.UNITY_EMAIL <span>}</span><span>}</span>
# UNITY_PASSWORD: $<span>{</span><span>{</span> secrets.UNITY_PASSWORD <span>}</span><span>}</span>
# UNITY_SERIAL: $<span>{</span><span>{</span> secrets.UNITY_SERIAL <span>}</span><span>}</span>
with:
projectPath: .
# テストの実行結果もみたい場合は githubToken を指定する
# secrets.GITHUB_TOKEN は Secrets 未登録でも利用可能
githubToken: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span>
# Unity プロジェクトのバージョンを指定する
# ProjectSettings/ProjectVersion.txt に記載されているバージョンを入力すれば OK
unityVersion: 2020.3.5f1
# 実行したいテストの種類を指定できる
# 指定可能な値は All, PlayMode, EditMode
# testMode: All
# テスト実行時に利用したい Docker イメージを明示的に指定できる
# customImage: 'unityci/editor:2020.1.14f1-base-0'
# テストの実行結果をアーティファクトにアップロードしてダウンロードして参照できるようにする
- uses: actions/upload-artifact@v2
if: always()
with:
name: Test results
path: artifacts
</code></pre>
<p>上記のワークフローファイルを GitHub Actions 上で動作検証する際の手順は下記になります。</p>
<p><img src="https://i.gyazo.com/9bace70734f1e99955f5b9aa068b31de.png" alt="1. Unity のテストを実行するためのワークフローを選択して実行する" /><br />
<strong>1. Unity のテストを実行するためのワークフローを選択して実行する</strong></p>
<p><img src="https://i.gyazo.com/ffc31b5919431fedb516f1932a13ce62.png" alt="2. ワークフローの実行が成功したら、詳細画面に遷移した後、<code>Test Results</code> の項目からテストの実行結果を確認する" /><br />
<strong>2. ワークフローの実行が成功したら、詳細画面に遷移した後、<code>Test Results</code> の項目からテストの実行結果を確認する</strong></p>
<p>テスト実行用のワークフローファイルでは <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/reference/events-that-trigger-workflows#manual-events"><code>workflow_dispatch</code></a> で実行可能にしていますが、<code>pull_request</code> を利用すればプルリク時にテストを実行させることが可能になります。</p>
<h2 id="Builder: プロジェクトのビルドを実行して出力結果を確認する"><a href="#Builder%3A+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6%E5%87%BA%E5%8A%9B%E7%B5%90%E6%9E%9C%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B">Builder: プロジェクトのビルドを実行して出力結果を確認する</a></h2>
<p>GameCI にはプロジェクトのビルドを行うための GitHub Actions も用意されています。<strong>実際に GameCI で WebGL ビルドを行いその内容を GitHub Pages で確認できるようにして動作検証していきます。</strong></p>
<p>早速 WebGL ビルドを行うためのワークフローファイルを作成していきます。</p>
<pre><code class="yml"># .github/workflows/webgl_build.yml
name: Run the WebGL build
on:
workflow_dispatch: {}
jobs:
build:
name: Run the WebGL build
runs-on: ubuntu-latest
steps:
# actions/checkout@v2 を利用して作業ディレクトリに
# Unity プロジェクトの中身をダウンロードしてくる
- name: Check out my unity project.
uses: actions/checkout@v2
# GameCI の Builder を利用して、
# Unity プロジェクトのビルドを実行する
- name: Run the WebGL build
uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: $<span>{</span><span>{</span> secrets.UNITY_LICENSE <span>}</span><span>}</span>
with:
# 今回は WebGL ビルドを行いたいため WebGL を指定する
# WebGL 以外の指定可能な値は下記に記載の値が利用可能
# ref: https://docs.unity3d.com/ScriptReference/BuildTarget.html
targetPlatform: WebGL
unityVersion: 2020.3.5f1
# Builder で出力した WebGL ビルドを GitHub Pages にデプロイする
- name: Deploy to GitHub Pages
uses: JamesIves/[email protected]
with:
# GitHub Pages デプロイ用の Orphan ブランチ名を指定する
branch: gh-pages
# デプロイ用ビルドフォルダパスを指定する
# GameCI の Builder はデフォルトでは build フォルダにビルド内容を出力する
folder: build
# Builder で出力した WebGL ビルドをアーティファクトでダウンロード可能にする
- name: Upload the WebGL Build
uses: actions/upload-artifact@v2
with:
name: Build
path: build
</code></pre>
<p>上記のワークフローファイルを GitHub Actions 上で動作検証する際の手順は下記になります。</p>
<p><img src="https://i.gyazo.com/b8f43baef2e2edbf8d5510ce8f58172d.png" alt="1. Unity の WebGL ビルドを実行するためのワークフローを実行する" /><br />
<strong>1. Unity の WebGL ビルドを実行するためのワークフローを実行する</strong></p>
<p><img src="https://i.gyazo.com/a102d1f5cb4d0581746770d1d9cad965.png" alt="2. ワークフローの実行が成功したら、詳細画面に遷移した後、ビルド内容が正常か確認する" /><br />
<strong>2. ワークフローの実行が成功したら、詳細画面に遷移した後、ビルド内容が正常そうか確認する</strong></p>
<p><img src="https://i.gyazo.com/7d39c035b52ba3862d5dad18213a2041.png" alt="3. ビルド内容を確認するための GitHub Pages の設定を Settings から行う" /><br />
<strong>3. ビルド内容を確認するための GitHub Pages の設定を Settings から行う</strong></p>
<p><img src="https://i.gyazo.com/b2e1bd86ca9d3b3f207a5ddbb1de3ba7.png" alt="4. GitHub Pages でブラウザから WebGL ビルドの動作確認をする" /><br />
<strong>4. GitHub Pages でブラウザから WebGL ビルドの動作確認をする</strong></p>
<p><strong>上記のように Builder を利用することで WebGL ビルドの成否及び、最新のビルド内容を常に GitHub Pages で見られるようにできます。</strong> すると WebGL ビルドが正常かどうかの確認が常に GitHub Pages を見れば把握できるようになるため、<a target="_blank" rel="nofollow noopener" href="https://unityroom.com/unity1weeks">Unity1 週間ゲームジャム</a> などに参加する際で便利に活用できそうです。</p>
<p><em>WebGL ビルドを行う際、Unity バージョンやアセットの対応状況によっては正しくブラウザ上で動作しないビルドが出力されます。<strong>ただし、ブラウザで発生するエラー内容によっては WebGL のビルド設定を見直すだけで解決できる場合があります。</strong> 例えば <code>unityframework is not defined</code> というエラーが発生した際は、<a target="_blank" rel="nofollow noopener" href="https://qiita.com/aguroshou0413/items/1451a6779a92acb96b78">この記事</a> のように WebGL の <code>Build Settings</code> を見直すことで解決できる場合があります。</em></p>
<p><em>私の環境では <a target="_blank" rel="nofollow noopener" href="https://github.com/JamesIves/github-pages-deploy-action"><code>JamesIves/github-pages-deploy-action</code></a> で GitHub Pages へのデプロイを行った際、<strong>デフォルトでは <code>/WebGL/WebGL</code> フォルダにビルド内容が出力されました。そのため、ブラウザから WebGL ビルドにアクセスする際、<code><GitHub Pages の URL>/WebGL/WebGL</code> のような URL にアクセスする必要がありました。</strong></em></p>
<h2 id="Returning a license: GameCI で利用している Unity License を返却する"><a href="#Returning+a+license%3A+GameCI+%E3%81%A7%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B+Unity+License+%E3%82%92%E8%BF%94%E5%8D%B4%E3%81%99%E3%82%8B">Returning a license: GameCI で利用している Unity License を返却する</a></h2>
<p><strong>通常利用することは無いと<a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/github/returning-a-license">公式サイト</a>にも書かれていますが、Professional License の返却も GameCI で行うことが可能です。</strong> 今回は Personal License を利用したため使用しませんでしたが、下記をワークフローのステップに組み込むことで Professional License を返却できるようです。</p>
<pre><code class="yml"># ...
# どこかのタイミングでライセンスのアクティベートを行う
- name: Activate Unity
uses: game-ci/unity-activate@v1
env:
UNITY_LICENSE: $<span>{</span><span>{</span> secrets.UNITY_LICENSE <span>}</span><span>}</span>
#...
# ステップの最後などに game-ci/unity-return-license@v1 を呼び出して
# アクティベート済みのライセンスを返却する
- name: Return license
uses: game-ci/unity-return-license@v1
if: always()
#...
</code></pre>
<h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1>
<p>以前 Unity コマンドを駆使して自分で CI 環境を構築した経験があるのですが、<br />
GameCI を利用した方が全然楽に Unity CI 環境構築を GitHub Actions 上で行えました。</p>
<p>ちなみに <a target="_blank" rel="nofollow noopener" href="https://game.ci/docs/docker/docker-images">GameCI で利用されている Docker イメージ</a> は以前からよく使われていた <a target="_blank" rel="nofollow noopener" href="https://hub.docker.com/r/gableroux/unity3d/">gableroux/unity3d</a> が元になっているようでした。ってか <a target="_blank" rel="nofollow noopener" href="https://gableroux.com/about/">GabLeRoux さんのホームページ</a> を見たら、GameCI の開発を始めた方のようでした。すごい。</p>
<p>本記事が GitHub Actions で Unity CI 環境構築を始めようとしている方の助けになれれば幸いです。</p>
<h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://game.ci/">GameCI - The fastest and easiest way to automatically test and build your game projects</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://unity3d.com/jp/unity/features/cloud-build">Services - Cloud Build - Unity</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://aws.amazon.com/jp/cloudformation/">AWS CloudFormation(テンプレートを使ったリソースのモデル化と管理)| AWS</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://fastlane.tools/">fastlane - App automation done right</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/github/setting-up-and-managing-your-github-user-account/managing-user-account-settings/managing-the-default-branch-name-for-your-repositories#about-management-of-the-default-branch-name">リポジトリのデフォルトブランチ名を管理する - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://blog.yucchiy.com/2019/01/08/how-to-get-unity-free-license/">Unity でパーソナルライセンスのシリアルナンバーを発行する | Yucchiy's Note</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://license.unity3d.com">Unity license manual activation webpage</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/reference/encrypted-secrets">暗号化されたシークレット - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.unity3d.com/ScriptReference/BuildTarget.html">Unity - Scripting API: BuildTarget</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://unityroom.com/unity1weeks">Unity 1 週間ゲームジャム | フリーゲーム投稿サイト unityroom</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/aguroshou0413/items/1451a6779a92acb96b78">Unity2020 WebGL 9 割まで読み込めるがアプリが起動しない不具合の解決方法 - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/deploy-to-github-pages">Deploy to GitHub Pages · Actions · GitHub Marketplace</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn:1" role="doc-endnote">
<p><code>alf</code> ファイル及び <code>ulf</code> ファイルの実態は XML ファイルです。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>適当なテキストエディタで <code>ulf</code> ファイルを開き全文をコピー & ペーストします。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
nikaera
tag:crieit.net,2005:PublicArticle/16763
2021-03-22T13:21:27+09:00
2021-03-22T13:21:27+09:00
https://crieit.net/posts/sync-zenn-with-dev-action
Zenn の記事を DEV に自動的に同期させる GitHub Action 作ってみた
<h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1>
<p>去年 <a target="_blank" rel="nofollow noopener" href="https://dev.to/">DEV</a> のアカウントを作成したものの、今まで全く有効活用出来ていませんでした。</p>
<p>DEV には <a target="_blank" rel="nofollow noopener" href="https://dev.to/michaelburrows/comment/125j0">カノニカル URL</a> を設定出来るので、常々 Zenn の記事を投稿する際にクロスポストしたいなと考えておりました。そこで、<strong>Zenn に記事を投稿したら、自動的に DEV にも記事を投稿 & 同期する GitHub Action を作ってみました。</strong><br />
<a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/sync-zenn-with-dev-action">sync-zenn-with-dev-action</a></p>
<p>今回初めて GitHub Action を自作したのですが、その中で得た知見を残す形で記事を書くことにしました。また、GitHub Action は TypeScript で作成しました。</p>
<h1 id="開発した GitHub Action の概要"><a href="#%E9%96%8B%E7%99%BA%E3%81%97%E3%81%9F+GitHub+Action+%E3%81%AE%E6%A6%82%E8%A6%81">開発した GitHub Action の概要</a></h1>
<p>まずはザッとどのような GitHub Action を作成したのか、概要について説明いたします。</p>
<p><strong>GitHub リポジトリで管理している Zenn の記事を DEV に同期して投稿する GitHub Action を作成しました。</strong> その際に DEV へ投稿する記事には Zenn の該当記事へのカノニカル URL も自動で設定できます。これにより DEV と Zenn へ記事をシームレスにクロスポストすることが可能となります。</p>
<p>今回作成した GitHub Action を利用するワークフローファイルの一例は下記となります。</p>
<pre><code class="yml">name: "Sync all Zenn articles to DEV"
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout my project
uses: actions/checkout@v2
- name: dev.to action step
uses: nikaera/sync-zenn-with-dev-action@v1
# id を設定することで、後のジョブで Output で指定した値が参照可能になる
id: dev-to
with:
# DEV の API キーを指定する
api_key: $<span>{</span><span>{</span> secrets.api_key <span>}</span><span>}</span>
# (オプション) DEV に記事を投稿した際に Zenn のカノニカル URL を設定したい場合に指定する
# username: nikaera
# (オプション) 改行区切りで指定した articles フォルダ内のファイルパスを記載した txt ファイルを指定することで、記載された記事のみを同期するようになる。
# 他プラグインと組み合わせることで差分のみを txt ファイルに載せることが可能。詳細については後述の Outputs の項目に記載。
# added_modified_filepath: ./added_modified.txt
# (オプション) Zenn の articles 以下全ての記事を常に DEV に同期するか指定する
# update_all が true のときは added_modified_filepath は無視される。
# update_all: false
# 上記アクション実行時に DEV に新規で同期する記事に関しては Zenn のマークダウンヘッダに
# 該当する DEV の記事の ID が dev_article_id として記載されるようになる。
# 今後はその ID を元に同期するようになるため、該当する Zenn の記事をコミットする。
# 新規で同期する記事が無ければ、このジョブは実行しない。
- name: write article id of DEV to articles of Zenn.
run: |
git config user.name github-actions
git config user.email [email protected]
git add $<span>{</span><span>{</span> steps.dev-to.outputs.newly-sync-articles <span>}</span><span>}</span>
git commit -m "sync: Zenn with DEV [skip ci]"
git push
if: steps.dev-to.outputs.newly-sync-articles
# Outputs には DEV の記事情報 (title, url) が含まれるようになるため、
# 最後に出力して実行結果の内容を確認することもできる
- name: Get the output articles.
# dev-to という id が紐付いたジョブの Outputs を取得して echo で内容を出力する
run: echo "$<span>{</span><span>{</span> steps.dev-to.outputs.articles <span>}</span><span>}</span>"
</code></pre>
<p>簡単に <code>nikaera/sync-zenn-with-dev-action@v1</code> というジョブの内部処理について説明いたします。</p>
<ol>
<li>Inputs の <code>update_all</code> 及び <code>added_modified_filepath</code> で受け取った情報を元に、<br />
どの記事を DEV に同期させるか判定する</li>
<li>DEV に同期する記事のファイルパス一覧を取得して、<br />
それぞれの記事のヘッダに <code>dev_article_id</code> の記載があるか判定する</li>
<li>Inputs の <code>api_key</code> を利用して、Zenn の記事に <code>dev_article_id</code> が含まれていれば、<br />
該当する DEV の記事を更新する。含まれていなければ DEV に新規で記事を作成する</li>
<li>Inputs の <code>username</code> を利用して、<br />
DEV の記事に該当する Zenn 記事のカノニカル URL を設定する</li>
<li>DEV に新規で記事を作成した場合は、<br />
Zenn の該当記事のヘッダに <code>dev_article_id</code> を書き込む</li>
<li>DEV に記事を投稿する際、Zenn は対応しているが、<br />
DEV では対応していない記述は削除する (<code>:::</code> 記法や一部のコード記法)</li>
<li>記事の公開ステータス及びタグなどについても DEV の記事に反映する<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li>
<li>新規で DEV に記事を同期した Zenn 記事のファイルパスを、<br />
Outputs の <code>newly-sync-articles</code> に設定する<br />
(後のジョブで <code>dev_article_id</code> の含まれた記事をコミットしたいため)</li>
<li>ワークフローで同期された記事情報は Outouts の <code>articles</code> に設定する</li>
</ol>
<p>Inputs と Outputs の内容一覧については下記になります。</p>
<p><strong>Inputs</strong></p>
<div class="table-responsive"><table>
<thead>
<tr>
<th align="left">キー</th>
<th align="left">説明</th>
<th align="center">必須</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">api_key</td>
<td align="left">DEV の <a target="_blank" rel="nofollow noopener" href="https://docs.forem.com/api/#section/Authentication">API Key</a> を設定する</td>
<td align="center">o</td>
</tr>
<tr>
<td align="left">username</td>
<td align="left">Zenn の <strong>自分のアカウント名</strong> を設定する (DEV に同期する記事に Zenn のカノニカル URL を設定したい場合のみ)</td>
<td align="center">x</td>
</tr>
<tr>
<td align="left">added_modified_filepath</td>
<td align="left">改行区切りで指定した articles フォルダ内のファイルパスを記載した txt ファイルを指定することで、記載された記事のみを同期するようになる。<strong>PR やコミット差分のファイルのみを取得するための GitHub Action <a target="_blank" rel="nofollow noopener" href="https://github.com/jitterbit/get-changed-files">jitterbit/get-changed-files@v1</a> と組み合わせることで、更新差分のあった記事のみを随時同期することも可能。<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></strong> 更新差分のあった記事のみを随時同期するための<a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/zenn.dev/blob/main/.github/workflows/sync-zenn-with-dev.yml">実際のワークフローファイルはこちら</a></td>
<td align="center">x</td>
</tr>
<tr>
<td align="left">update_all</td>
<td align="left">Zenn の全ての記事をどうきするかどうかを設定する。GitHub Action 初回実行時のみ true にする使い方を想定している。デフォルトは true。<strong><code>added_modified_filepath</code> よりも <code>update_all</code> が優先されるため <code>added_modified_filepath</code> を設定する場合は false を設定する必要あり`</strong></td>
<td align="center">x</td>
</tr>
</tbody>
</table></div>
<p><strong>Outputs</strong></p>
<div class="table-responsive"><table>
<thead>
<tr>
<th align="left">キー</th>
<th align="left">説明</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">articles</td>
<td align="left">同期された DEV の記事のタイトル及び URL が格納された配列</td>
</tr>
<tr>
<td align="left">newly-sync-articles</td>
<td align="left">DEV で新たに新規作成された Zenn 記事のファイルパスが格納された配列。<strong><a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/sync-zenn-with-dev-action/blob/main/.github/workflows/test.yml#L31-L38">実際のワークフローファイルの該当する記述</a>のように、必ずコミットに含めるようにする必要がある (理由は後述)</strong></td>
</tr>
</tbody>
</table></div>
<p>Inputs 及び Outputs については<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#">公式サイトの説明</a>をご参照ください。</p>
<h2 id="Zenn の記事を DEV に同期するための仕組み"><a href="#Zenn+%E3%81%AE%E8%A8%98%E4%BA%8B%E3%82%92+DEV+%E3%81%AB%E5%90%8C%E6%9C%9F%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF">Zenn の記事を DEV に同期するための仕組み</a></h2>
<p>Zenn の記事を新規で DEV に同期する際は、DEV に記事を新規作成する必要があります。<strong>その際に Zenn の記事と DEV の記事を紐付けるための何らかの仕組みが必要となります。そうしないと、今後 Zenn の記事内容を更新した際に、DEV のどの記事に内容を同期させればよいかが不明なためです。</strong></p>
<p>そこで、記事を同期するための仕組みとして、<strong><code>dev_article_id</code> というフィールドを Zenn のマークダウンヘッダに追記することで DEV の同期すべき記事との紐付けを行うことにしました。</strong><code>dev_article_id</code> には <a target="_blank" rel="nofollow noopener" href="https://docs.forem.com/api/#operation/createArticle">DEV の記事作成 API</a> 実行時の返り値である <code>id</code> を設定します。</p>
<p>一度 <code>id</code> を <code>dev_article_id</code> として Zenn の記事に紐付けてしまえば、次回以降に記事の同期を行う際は <a target="_blank" rel="nofollow noopener" href="https://docs.forem.com/api/#operation/updateArticle">DEV の記事更新 API</a> を利用できます。</p>
<p>また、<strong>Outputs の <code>newly-sync-articles</code> には新規で作成された DEV 記事の <code>id</code> である <code>dev_article_id</code> が追記された Zenn 記事のファイルパスが格納されています。そのため、<code>nikaera/sync-zenn-with-dev-action@v1</code> 実行後は、下記のように <code>steps.dev-to.outputs.newly-sync-articles</code> 内に格納されたファイル群をコミットに反映させる必要があります。</strong></p>
<pre><code class="yml"># `nikaera/sync-zenn-with-dev-action@v1` 実行後に必ず定義すべきジョブ
# DEV に新規に作成した記事がなければ実行しない (if: steps.dev-to.outputs.newly-sync-articles)
- name: write article id of DEV to articles of Zenn.
run: |
git config user.name github-actions
git config user.email [email protected]
git add $<span>{</span><span>{</span> steps.dev-to.outputs.newly-sync-articles <span>}</span><span>}</span>
git commit -m "sync: Zenn with DEV [skip ci]"
git push
if: steps.dev-to.outputs.newly-sync-articles
</code></pre>
<p>上記のジョブで <code>newly-sync-articles</code> に格納された <code>dev_article_id</code> が追記された Zenn 記事は随時コミットに反映しないと、<strong>Zenn の全ての記事が同期毎 DEV に新規作成され続けるという不具合を引き起こしてしまうので、ご注意ください</strong></p>
<h1 id="GitHub Action を開発する手順"><a href="#GitHub+Action+%E3%82%92%E9%96%8B%E7%99%BA%E3%81%99%E3%82%8B%E6%89%8B%E9%A0%86">GitHub Action を開発する手順</a></h1>
<p>サクッと開発に取り組みたかったため、<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/creating-a-docker-container-action">Docker コンテナを利用する方法</a> ではなく、<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/creating-a-javascript-action">JavaScript を利用する方法</a> で開発を進めていくことにしました。</p>
<h2 id="TypeScript で GitHub Action を作る"><a href="#TypeScript+%E3%81%A7+GitHub+Action+%E3%82%92%E4%BD%9C%E3%82%8B">TypeScript で GitHub Action を作る</a></h2>
<p>GitHub 公式が TypeScript で GitHub Action を作るための <a target="_blank" rel="nofollow noopener" href="https://github.com/actions/typescript-action">テンプレートプロジェクト</a> を用意してくれています。今回はこのテンプレートプロジェクトを利用する形でプロジェクトを作成しました。</p>
<p><em>(余談) GitHub Action では <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/creating-a-docker-container-action">Docker コンテナ</a> を用いてワークフローを実行可能です。<strong>そのため、実行環境は自由に設定出来ます。(Go, Python, Ruby, etc.)</strong></em></p>
<p>早速 TypeScript のテンプレートプロジェクトを元に自分の GitHub Action プロジェクトを作成します。</p>
<p><img src="https://i.gyazo.com/359f6f795bab9807c9f480c0f922973a.png" alt="スクリーンショット 2021-03-21 13.25.54.png" /><br />
<strong>1. テンプレートプロジェクトを元に GitHub Action の TypeScript プロジェクトを作成する</strong></p>
<p><img src="https://i.gyazo.com/76aecd3d63db95d34c086774ded122d4.png" alt="スクリーンショット 2021-03-21 13.29.43.png" /><br />
<strong>2. プロジェクトの作成後 <code>git clone</code> してきて開発する準備を整える</strong></p>
<h2 id="GitHub Action プロジェクトの開発を進めるための準備を行う"><a href="#GitHub+Action+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E9%96%8B%E7%99%BA%E3%82%92%E9%80%B2%E3%82%81%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E6%BA%96%E5%82%99%E3%82%92%E8%A1%8C%E3%81%86">GitHub Action プロジェクトの開発を進めるための準備を行う</a></h2>
<p>テンプレートプロジェクトを <code>git clone</code> したら、まずは <code>action.yml</code> の内容を変更します。<br />
今回作成した GitHub Action の <code>action.yml</code> は下記となっております。</p>
<pre><code class="yml"># action.yml
# GitHub Action のプロジェクト名
name: 'Sync Zenn articles to DEV'
# GitHub Action のプロジェクト説明文
description: 'Just sync Zenn articles to DEV.'
# GitHub Action の作者
author: 'nikaera'
# GitHub Action に渡せる引数の値定義
inputs:
api_key:
# フィールドの指定が必須であれば true、必須でなければ false を設定する
# DEV の API キーは同期を行う際に必須なため、true を設定している
required: true
# フィールドの説明文
description: 'The api_key required to use the DEV API (https://docs.forem.com/api/#section/Authentication)'
username:
required: false
description: "Zenn user's account name. (Fields to be filled in if canonical url is set.)"
articles:
required: false
description: "The directory where Zenn articles are stored."
# フィールドにはデフォルト値を指定することも可能
# Zenn の記事がデフォで格納されているフォルダ名を指定している
default: articles
update_all:
require: false
description: "Whether to synchronize all articles."
default: true
added_modified_filepath:
required: false
description: |
Synchronize only the articles in the file path divided by line breaks.
You can use jitterbit/get-changed-files@v1 to get only the file paths of articles that have changed in the correct format.
(https://github.com/jitterbit/get-changed-files)
# GitHub Action 実行後に参照可能になる値定義
outputs:
articles:
description: 'A list of URLs of dev.to articles that have been created or updated'
newly-sync-articles:
description: 'File path list of newly synchronized articles.'
# GitHub Action の実行環境
runs:
using: 'node12'
# テンプレートプロジェクトでは コンパイル先が dist になるため `dist/index.js` を指定している
main: 'dist/index.js'
</code></pre>
<p>TypeScript のテンプレートプロジェクトでは、バンドルツールとして <a target="_blank" rel="nofollow noopener" href="https://github.com/vercel/ncc"><code>ncc</code></a> が採用されています。<strong>GitHub Action 実行時に使用されるのは ncc によりコンパイルされた単一の JavaScript ファイル (<code>dist/index.js</code>) になります。</strong></p>
<p>あとは <code>src</code> フォルダ内でプログラムを書いて、<code>npm run all && node dist/index.js</code> のようにコマンド実行しながら開発を進めていくだけです。</p>
<p><em>(余談) GitHub Action の開発ツールとして Docker を利用した <a target="_blank" rel="nofollow noopener" href="https://github.com/nektos/act"><code>act</code></a> というものが存在するようです。ローカル環境で検証する際は <a target="_blank" rel="nofollow noopener" href="https://github.com/nektos/act#known-issues">既知の問題</a> に対応する必要がありそうですが、GitHub Action の開発で非常に有効活用できそうで気になっております。</em></p>
<p>今回の開発では利用しなかったのですが、今後開発を進めていく中で利用する機会も出てきそうなので、その際は本記事内容を更新する形で知見を追記したいと考えております。</p>
<p>:::</p>
<h2 id="GitHub Action を実装する際に利用した機能"><a href="#GitHub+Action+%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AB%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E6%A9%9F%E8%83%BD">GitHub Action を実装する際に利用した機能</a></h2>
<p>GitHub Action を実装する際に利用した機能を、実際のコード内容を抜粋して簡単に説明していきます。下記で紹介する内容は <a target="_blank" rel="nofollow noopener" href="https://github.com/actions/toolkit">GitHub Actions Toolkit</a> の機能です。</p>
<pre><code class="typescript">/**
下記の yml の with で指定した値は core.getInput で受け取ることが可能。
- name: dev.to action step
uses: nikaera/sync-zenn-with-dev-action@v1
id: dev-to
with:
# DEV の API キーを指定する
api_key: $<span>{</span><span>{</span> secrets.api_key <span>}</span><span>}</span>
*/
core.getInput("api_key", { required: true });
core.getInput("update_all", { required: false });
/**
下記の yml の steps.<ジョブで指定した id>.outputs で参照可能な値をセットすることが可能。
セットする内容は文字列である必要がある。
- name: dev.to action step
uses: nikaera/sync-zenn-with-dev-action@v1
id: dev-to
- name: Get the output articles.
run: echo "$<span>{</span><span>{</span> steps.dev-to.outputs.articles <span>}</span><span>}</span>"
*/
core.setOutput("articles", JSON.stringify(devtoArticles, undefined, 2));
core.setOutput("newly-sync-articles", newlySyncedArticles.join(" "));
/**
GitHub Action 実行時に出力されるログをレベルごとに出力することが可能
core.debug はローカル実行時のみに出力内容を確認することができる
*/
core.debug("debug");
core.info(`update_all: ${updateAll}`);
core.error(JSON.stringify(error));
</code></pre>
<p>上記だけ把握してれば GitHub Action の開発は問題なく行うことができました。</p>
<h1 id="作成した GitHub Action を実際に GitHub 上で実行可能にする"><a href="#%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F+GitHub+Action+%E3%82%92%E5%AE%9F%E9%9A%9B%E3%81%AB+GitHub+%E4%B8%8A%E3%81%A7%E5%AE%9F%E8%A1%8C%E5%8F%AF%E8%83%BD%E3%81%AB%E3%81%99%E3%82%8B">作成した GitHub Action を実際に GitHub 上で実行可能にする</a></h1>
<p>ローカル環境で一通り開発が完了したら、GitHub リポジトリに push した後タグ付けを行います。<strong>GitHub Action はタグを設定しないと実行できないため必要な作業となります。</strong> 今回タグ付けは GitHub 上で行いました。</p>
<p><img src="https://i.gyazo.com/252514cca20470154475db75b133e9b3.png" alt="スクリーンショット 2021-03-22 8.11.58.png" /><br />
<strong>1. タグの項目をクリックする</strong></p>
<p><img src="https://i.gyazo.com/a8c145f8d6ae7b1f6253eb4866bcbb51.png" alt="スクリーンショット 2021-03-22 8.14.47.png" /><br />
<strong>2. <code>Create a new release</code> ボタンをクリックしてタグ作成画面に遷移する</strong></p>
<p><img src="https://i.gyazo.com/25e019e42227ad7e0b0b634e68bb1873.png" alt="スクリーンショット 2021-03-22 8.20.00.png" /><br />
<strong>3. <code>Publish release</code> ボタンをクリックしてタグの作成を完了する</strong></p>
<p><strong>上記の例では <code>v1</code> というタグを作成したので <code>nikaera/sync-zenn-with-dev-action@v1</code> のような記述で GitHub Action を利用可能になりました。</strong> 私は Zenn の記事を <a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/zenn.dev/"><code>zenn.dev</code></a> というリポジトリで管理しているため、早速このリポジトリに GitHub Action を導入してみます。</p>
<h2 id="Zenn の全ての記事を DEV に同期するためのワークフロー"><a href="#Zenn+%E3%81%AE%E5%85%A8%E3%81%A6%E3%81%AE%E8%A8%98%E4%BA%8B%E3%82%92+DEV+%E3%81%AB%E5%90%8C%E6%9C%9F%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC">Zenn の全ての記事を DEV に同期するためのワークフロー</a></h2>
<p>本記事の GitHub Action では DEV の API キーを使用するため、<strong>事前にシークレットへ <code>API_KEY</code> という名称で値を登録しておきます。</strong><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository">公式サイトの手順</a> に従い シークレットの登録が完了したら、該当リポジトリに <code>.github/workflows/sync-zenn-with-dev-all.yml</code> というワークフローファイルを作成します。</p>
<pre><code class="yml"># .github/workflows/sync-zenn-with-dev-all.yml
name: "Sync-All Zenn with DEV"
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
if: contains(github.event.head_commit.message, '[skip ci]') == false
steps:
- name: setup node project
uses: actions/checkout@v2
- name: dev.to action step
uses: nikaera/sync-zenn-with-dev-action@v1
id: dev-to
with:
api_key: $<span>{</span><span>{</span> secrets.api_key <span>}</span><span>}</span>
# Zenn の自分のアカウント名を指定すると
# DEV 記事のカノニカル URL に Zenn 記事の URL を指定できる
# username: nikaera
update_all: true
- name: write article id of DEV to articles of Zenn.
run: |
git config user.name github-actions
git config user.email [email protected]
git add $<span>{</span><span>{</span> steps.dev-to.outputs.newly-sync-articles <span>}</span><span>}</span>
git commit -m "sync: Zenn with DEV [skip ci]"
git push
if: steps.dev-to.outputs.newly-sync-articles
- name: Get the output articles.
run: echo "$<span>{</span><span>{</span> steps.dev-to.outputs.articles <span>}</span><span>}</span>"
</code></pre>
<p>上記は手動実行が可能な Zenn の記事を全て DEV に同期するためのワークフローファイルになります。作成が完了したらワークフローファイルを実行して、記事が正常に同期できているか確認してみます。</p>
<p><img src="https://i.gyazo.com/e0740fe369752db67514e0ab50e88772.png" alt="スクリーンショット 2021-03-22 8.35.38.png" /><br />
<strong>1. <code>Actions</code> タブをクリックする</strong></p>
<p><img src="https://i.gyazo.com/2aeadddccf08c0dddc54dddab464edee.png" alt="スクリーンショット 2021-03-22 8.37.24.png" /><br />
<strong>2. 作成した <code>Sync-All Zenn with DEV</code> ワークフローファイルを選択する</strong></p>
<p><img src="https://i.gyazo.com/d9e138de1f6e0baac8b0c3bc6742f4f2.png" alt="スクリーンショット 2021-03-22 8.40.11.png" /><br />
<strong>3. <code>Run workflow</code> ボタンを実行して、ワークフローを実行する</strong></p>
<p><img src="https://i.gyazo.com/e67df0f6e33d1f57a46000d20ef2c824.png" alt="スクリーンショット 2021-03-22 8.45.23.png" /><br />
<strong>4. ワークフローの実行が正常に完了していれば、ログに DEV の記事情報が出力される</strong></p>
<p><img src="https://i.gyazo.com/4acc0b0de3acd6731918a9347e7baea8.png" alt="スクリーンショット 2021-03-22 8.50.37.png" /><br />
<strong>5. <code>dev.to</code> にアクセスして Zenn の記事情報が正常に同期されていることを確認する</strong></p>
<p>正常に Zenn の全ての記事が DEV に同期されていることが確認できたら、次は Zenn の記事が新規作成されたり、更新されたときのみに DEV に同期するためのワークフローファイルを作成します。</p>
<h2 id="更新差分のあった Zenn 記事のみを DEV に同期するためのワークフロー"><a href="#%E6%9B%B4%E6%96%B0%E5%B7%AE%E5%88%86%E3%81%AE%E3%81%82%E3%81%A3%E3%81%9F+Zenn+%E8%A8%98%E4%BA%8B%E3%81%AE%E3%81%BF%E3%82%92+DEV+%E3%81%AB%E5%90%8C%E6%9C%9F%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC">更新差分のあった Zenn 記事のみを DEV に同期するためのワークフロー</a></h2>
<p><code>main</code> ブランチが更新されたときのみ更新された記事のみを DEV に同期するためのワークフローファイルを作成します。該当リポジトリに <code>.github/workflows/sync-zenn-with-dev.yml</code> というワークフローファイルを作成します。</p>
<pre><code class="yml"># .github/workflows/sync-zenn-with-dev.yml
name: "Sync Zenn with DEV"
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
if: contains(github.event.head_commit.message, '[skip ci]') == false
steps:
- name: setup node project
uses: actions/checkout@v2
- name: get modified files
id: files
uses: jitterbit/get-changed-files@v1
- name: output modified files to text
run: |
for changed_file in $<span>{</span><span>{</span> steps.files.outputs.added_modified <span>}</span><span>}</span>; do
echo "${changed_file}" >> added_modified.txt
done
- name: dev.to action step
uses: nikaera/sync-zenn-with-dev-action@v1
id: dev-to
with:
api_key: $<span>{</span><span>{</span> secrets.api_key <span>}</span><span>}</span>
# Zenn の自分のアカウント名を指定すると
# DEV 記事のカノニカル URL に Zenn 記事の URL を指定できる
# username: nikaera
added_modified_filepath: ./added_modified.txt
update_all: false
- name: write article id of DEV to articles of Zenn.
run: |
git config user.name github-actions
git config user.email [email protected]
git add $<span>{</span><span>{</span> steps.dev-to.outputs.newly-sync-articles <span>}</span><span>}</span>
git commit -m "sync: Zenn with DEV [skip ci]"
git push
if: steps.dev-to.outputs.newly-sync-articles
- name: Get the output articles.
run: echo "$<span>{</span><span>{</span> steps.dev-to.outputs.articles <span>}</span><span>}</span>"
</code></pre>
<p>上記ワークフローファイルの作成が完了したら、早速動作確認のために、<strong>まさに今執筆中の本記事内容をリポジトリに push してみます。</strong></p>
<p><img src="https://i.gyazo.com/36512e7874b49edc1e48f0ef88af5d89.png" alt="スクリーンショット 2021-03-22 9.07.55.png" /><br />
<strong>1. <code>git push</code> 後に該当するワークフローの実行結果を確認する</strong></p>
<p><img src="https://i.gyazo.com/cbb0a1cf7b94605680e39630dded0096.png" alt="Image from Gyazo" /><br />
<strong>2. <code>dev.to</code> に執筆途中の内容で記事が同期されていることを確認する</strong></p>
<p>これまで説明してきた 2 つのワークフローを利用することで、大抵のユースケースはカバーできるはずです。</p>
<h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1>
<p>GitHub Action の勉強のために取り組んだプロジェクトですが、思いの外楽しくて他にも色々な機能のアイデアがあるので随時実装していきたいと考えています。(英訳, タイトルフォーマット変更, etc.)</p>
<p>DEV に Zenn の記事をクロスポストする GitHub Action を公開することで、いつもお世話になっている Zenn というプラットフォームを海外の方に認知していただける機会を創出できたのかもと考えたらテンションが上がってきました。</p>
<p>それはさておき、Zenn の記事を他でも有効活用するための GitHub Action を開発する際には、恐らく本記事で紹介した GitHub Action のコードが参考になるはずです。</p>
<p>また、<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/publishing-actions-in-github-marketplace">GitHub Action の Marketplace</a> というものが用意されているようなので、開発がある程度完了次第、こちらに申請するのも試してみたいと考えております。</p>
<p>ところで、<em>Crieit さんにも記事投稿 API ができたらクロスポストできるようにしたいな...という個人的願望がありますw</em></p>
<h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://dev.to/">DEV Community 👩💻👨💻</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://dev.to/michaelburrows/comment/125j0">dev.to supports canonical URLs so you can share content without impacting SEO... - DEV Community</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/sync-zenn-with-dev-action">nikaera/sync-zenn-with-dev-action: Just sync Zenn articles to DEV.</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.forem.com/api/#section/Authentication">DEV API (beta)</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/jitterbit/get-changed-files">jitterbit/get-changed-files: Get all of the files changed/modified in a pull request or push's commits.</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/creating-a-docker-container-action">Docker コンテナのアクションを作成する - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/creating-actions/creating-a-javascript-action">JavaScript アクションを作成する - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/actions/typescript-action">actions/typescript-action: Create a TypeScript Action with tests, linting, workflow, publishing, and versioning</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/vercel/ncc">vercel/ncc: Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/nektos/act">nektos/act: Run your GitHub Actions locally 🚀</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/actions/toolkit">actions/toolkit: The GitHub ToolKit for developing GitHub Actions.</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository">暗号化されたシークレット - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.deepl.com/ja/pro#developer">DeepL Pro:テキストの他、Word などの文書をセキュアに翻訳</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/">Qiita</a></li>
<li><a href="https://crieit.net/advent-calendars/2020/crieit">Crieit - プログラマー、クリエイターが何でも気軽に書けるコミュニティ</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn:1" role="doc-endnote">
<p>DEV (Forem) の仕様上、<a target="_blank" rel="nofollow noopener" href="https://dev.to/p/editor_guide#front-matter">タグは最大でも 4 つまで</a>しか設定できないため、Zenn で設定したタグの先頭 4 つまで DEV の記事には設定しています <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>当然といえば当然ですが <a target="_blank" rel="nofollow noopener" href="https://github.com/jitterbit/get-changed-files">jitterbit/get-changed-files@v1</a> は <code>workflow_dispatch</code> でワークフローを手動実行した際や、<code>force push</code> 等でファイル差分を正確に特定できない操作には対応しておりませんので、その場合はエラーが発生します <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
nikaera
tag:crieit.net,2005:PublicArticle/16694
2021-02-20T15:13:23+09:00
2021-02-20T15:13:43+09:00
https://crieit.net/posts/Netlify-GitHub-Actions-0
Netlifyのビルド時間をGitHub Actionsで0時間にして月末のヒヤヒヤから解放されよう!
<h1 id="Netlifyのビルド時間をGitHub Actionsで0時間にして月末のヒヤヒヤから解放されよう!"><a href="#Netlify%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E6%99%82%E9%96%93%E3%82%92GitHub+Actions%E3%81%A70%E6%99%82%E9%96%93%E3%81%AB%E3%81%97%E3%81%A6%E6%9C%88%E6%9C%AB%E3%81%AE%E3%83%92%E3%83%A4%E3%83%92%E3%83%A4%E3%81%8B%E3%82%89%E8%A7%A3%E6%94%BE%E3%81%95%E3%82%8C%E3%82%88%E3%81%86%EF%BC%81">Netlifyのビルド時間をGitHub Actionsで0時間にして月末のヒヤヒヤから解放されよう!</a></h1>
<h2 id="Netlify"><a href="#Netlify">Netlify</a></h2>
<p>みなさんもご存じ超便利ありがたサービスNetlifyですが、<strong>無料で使ってる貧民</strong>には毎月とある悩みがでてきます。</p>
<p><em>今月のビルド時間は残り○○分</em></p>
<p><img src="https://i.imgur.com/TSm24w0.png" alt="img" /></p>
<p>NetlifyはGitHubのレポジトリと連携して、フロントのビルドを実行した上で、デプロイするという超便利機能があるのですが、このビルドを回すのに時間の制約があり、</p>
<p>無料民だと月300分となっております。(それ以上はPro版月19ドル課金すれば問題なく使えます。課金も経験済み)</p>
<p>300分あれば大丈夫そう、とそう思う気もしなくなくもないですが、</p>
<p>複数レポジトリにわたってNetlifyを使っていたり、Gatsby.jsで画像をたくさん使っていて<strong>Sharp</strong>の画像リサイズに時間がかかったり、<strong>Dependabot</strong>で定期的にPRが出てPreview deployが発生したりすると<br />
案外ぎりぎりだったりします。</p>
<p><img src="https://i.imgur.com/y7ixbEG.png" alt="img" /></p>
<p>なので、私のような貧民は月末になると、Netlifyのビルド時間が気になって<strong>このブログの記事を書かなくなったり</strong>、<strong>サイトリファクターのペースが落ちて</strong>しまいます。</p>
<p>特にブログ更新は顕著で、例えば今書いている記事も通勤の電車の中でスマホから書いているわけなので、細かくコミットを打って保存したいのですが、コミットを打ってプッシュしてしまうと、ビルドが走ることになるので、WIPでのコミットが億劫になり、結果的に家のようなまとめてプッシュできるような作業スペースがある場所でないと、<br />
ブログを書かなくなってしまいました。</p>
<p>せっかく<a target="_blank" rel="nofollow noopener" href="https://blog.tubone-project24.xyz/2019-09-01-netlify-and-gatsby#cms%E3%81%AE%E7%AE%A1%E7%90%86%E7%94%BB%E9%9D%A2%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B">Netlify CMS化</a>した意味がないですね。</p>
<h2 id="この悩みGitHub Actionsにお任せください"><a href="#%E3%81%93%E3%81%AE%E6%82%A9%E3%81%BFGitHub+Actions%E3%81%AB%E3%81%8A%E4%BB%BB%E3%81%9B%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84">この悩みGitHub Actionsにお任せください</a></h2>
<p>ということでこの悩み、GitHub Actionsで解決してみたいと思います。</p>
<p>なんか工務店のCMみたいな表現になってしまいました。</p>
<p><img src="https://i.imgur.com/JlvUJ4zl.png" alt="ojisan" /></p>
<h2 id="Netlifyのビルド時やっていることを洗い出して自前でやってみる"><a href="#Netlify%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E6%99%82%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8%E3%82%92%E6%B4%97%E3%81%84%E5%87%BA%E3%81%97%E3%81%A6%E8%87%AA%E5%89%8D%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">Netlifyのビルド時やっていることを洗い出して自前でやってみる</a></h2>
<p>基本的にNetlifyがビルド時やってることは、例えばGatsby.jsであれば、gatsby buildコマンドを実行し、特定のディレクトリー(大概は./public)に配置されたビルド済みJSをデプロイする動きなので、<br />
それをそっくりGitHub Actionsに移行すればいいのですが、Netlifyがビルド済みJSに対して後処理(PostProcess)を実行してるパターンもあります。</p>
<p>私の場合、JSやイメージを最適化してくれる<strong>Asset optimization</strong>とFormタグに属性をつければ勝手にFormを作ってくれる<strong>Form detection</strong>の二つが設定されていましたのでそれぞれまず無効化します。</p>
<p>Form detectionの解説は<a target="_blank" rel="nofollow noopener" href="https://blog.tubone-project24.xyz/2019/09/30/netlify-form">こちら</a>を参照ください。</p>
<p><img src="https://i.imgur.com/ytjbJQA.png" alt="img" /></p>
<p><img src="https://i.imgur.com/LfL70Br.png" alt="img" /></p>
<p>こちら、Netlifyで実施してくれなくなりますので、こちらで実装し直す必要があります。</p>
<h2 id="gatsby-plugin-minify"><a href="#gatsby-plugin-minify">gatsby-plugin-minify</a></h2>
<p>Asset optimizationのうち、JSやCSSのminiferは<a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/plugins/gatsby-plugin-minify/">gatsby-plugin-minify</a>を使うことでhtmlやJS、CSSをminifyできます。</p>
<p>インストールはいつも通りNPM(yarn)から</p>
<pre><code>npm install gatsby-plugin-minify
</code></pre>
<p>使い方はgatsby-config.jsのpluginsに次のように設定すればできます。</p>
<pre><code> {
resolve: 'gatsby-plugin-minify',
options: {
caseSensitive: false,
collapseBooleanAttributes: true,
useShortDoctype: false,
removeEmptyElements: false,
removeComments: true,
removeAttributeQuotes: false,
minifyCSS: true,
minifyJS: true,
},
},
</code></pre>
<p>minifyCSSとminifyJSをtrueにすることにより、CSSについては<a target="_blank" rel="nofollow noopener" href="https://github.com/jakubpawlowicz/clean-css">clean-css</a>、JSについては<a target="_blank" rel="nofollow noopener" href="https://github.com/mishoo/UglifyJS">UglifyJS</a>を使って一緒にminifyされます。また、gatsby-plugin-minifyの裏側は<a target="_blank" rel="nofollow noopener" href="https://github.com/kangax/html-minifier">html-minifier</a>をgatsby-node.jsでpostbuildで全掛けしているだけなので、細かいオプションは<a target="_blank" rel="nofollow noopener" href="https://github.com/kangax/html-minifier#options-quick-reference">html-minifier</a>で設定できる感じです。</p>
<p>ちなみに、気を付けないといけないのが<strong>removeAttributeQuotes</strong>のオプションをfalseにすること。</p>
<p>これをtrueにすると、HTMLタグ内のアトリビュートにダブルクオートが入らなくなりちょっとファイルが軽くなるのですが、<a target="_blank" rel="nofollow noopener" href="https://berss.com/feed/Find.aspx">berss.com</a>のようにサイトのRSSリンクを取得するようなシステムでうまく読み込めなくなってしまい、サイト更新が最悪通知できなくなってしまう現象が発生しました。</p>
<p>これで1日使ってしまった...。</p>
<p>RSSのリンクをページのLinkとして仕込んでいる人は要注意です。</p>
<h2 id="imgurを使うことで、画像ホスティングとリサイズを同時にやっちゃう"><a href="#imgur%E3%82%92%E4%BD%BF%E3%81%86%E3%81%93%E3%81%A8%E3%81%A7%E3%80%81%E7%94%BB%E5%83%8F%E3%83%9B%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%A8%E3%83%AA%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%92%E5%90%8C%E6%99%82%E3%81%AB%E3%82%84%E3%81%A3%E3%81%A1%E3%82%83%E3%81%86">imgurを使うことで、画像ホスティングとリサイズを同時にやっちゃう</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://imgur.com/">imgur</a>というサービスがあります。</p>
<p>主にRedditとかGifをあげるための画像ホスティングサービスとして有名なのですが、こちらを使うことで簡単に画像のリサイズとホスティングを実現できるため、このブログではimgurを使ってます。</p>
<p>画像URLの後ろに画像サイズに合わせたキーワードを入れることで実現できます。</p>
<p>例えばこちらのURLの画像を</p>
<pre><code>[https://i.imgur.com/Wfz9G0B.png](https://i.imgur.com/Wfz9G0B.png)
</code></pre>
<p>160x160にリサイズするには後ろに<strong>b</strong>をくっつけます。</p>
<pre><code>[https://i.imgur.com/Wfz9G0Bb.png](https://i.imgur.com/Wfz9G0Bb.png)
</code></pre>
<p>これで、画像最適化も完了です。</p>
<h2 id="getform.io"><a href="#getform.io">getform.io</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://getform.io/">Getform.io</a>はフォームのバックエンドを提供するすばらしいサービスです。</p>
<p>便利なインテグレーションを使うには有料版が必要ですが、フォームに投稿されたら指定したメールアドレスに通知メール飛ばす、くらいのことであれば無料でできます。</p>
<p>これで、NetlifyのForm detectionを置き換えていきます。</p>
<p>まず、新しいフォームを作ると、FormのAction先URLが発行できます。</p>
<p>Formの作り方は下記のブログにわかりやすく纏めてあったので参照いただければと思います。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://blog.nakamu.life/posts/getform-io">https://blog.nakamu.life/posts/getform-io</a></p>
<p>さて、Formができたらチュートリアルに沿ってそのまま、FormタグのactionにこちらのURLを設定してもいいのですが、GetFormは無料版だと、<strong>Form投稿後のThanksページが設定</strong>できません。</p>
<pre><code class="html"><!--
* Add your getform endpoint into "action" attribute
* Set a unique "name" field
* Start accepting submissions
-->
<form action="{getform-endpoint}" method="POST">
<input type="text" name="name">
<input type="email" name="email">
<button type="submit">Send</button>
</form>
</code></pre>
<p><img src="https://i.imgur.com/sT5vhFE.png" alt="img" /></p>
<p>まぁこれでも十分なのですが、せっかく<strong>React</strong>を使ってるので、裏側でgetform.ioのURLをPOST fetchしながら、actionsで定義した自分のThanks URLに飛ばすように指定しましょう。</p>
<p>まずは、Formに<strong>onSubmit</strong>を設定します。</p>
<p>```typescript{numberLines: 1}{5}<br />
<form
name="contact"
method="post"
action="/thanks/"
onSubmit={this.handleSubmit}
><br />
<label><br />
<span className="icon-user" /> Your name<br /><br />
<input
type="text"
name="name"
className="form-control"
maxLength="30"
minLength="2"
required
placeholder="Enter your name"
onChange={this.handleChange}
/><br />
</label><br />
</p></p>
<pre><code><br />そして、別途にonSubmitで発火する関数を定義します。
```typescript
handleSubmit(e) {
e.preventDefault();
const form = e.target;
fetch('https://getform.io/f/xxxxxxxxxxxxxxxxxxxxxxxxx', {
method: 'POST',
body: Contact.encode({
'form-name': form.getAttribute('name'),
...this.state,
}),
})
}
</code></pre>
<p>Formの送信なので、fetchでは<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/FormData">FormData</a>に要素をappendしたものを送信しないといけません。</p>
<pre><code> static encode(data) {
const formData = new FormData();
// eslint-disable-next-line no-restricted-syntax
for (const key of Object.keys(data)) {
formData.append(key, data[key]);
}
return formData;
}
</code></pre>
<p>繰り返しになりますがReactではFormで、actionのほか、onSubmitを関数としてすることができます。</p>
<p>ただし、onSubmitが押されたタイミングで、Formの入力項目をPOST Fetchで渡さないといけないので、Formの入力で発生するchangeEventごとに、Formの値をstateとして保存しておくようにします。</p>
<p>```typescript{numberLines: 1}{1-7,21}<br />
handleChange(e) {<br />
this.setState({ [e.target.name]: e.target.value });<br />
}</p>
<p>handleAttachment(e) {<br />
this.setState({ [e.target.name]: e.target.files[0] });<br />
}</p>
<p>(中略)</p>
<pre><code> <label>
<span className="icon-user" /> Your name<br />
<input
type="text"
name="name"
className="form-control"
maxLength="30"
minLength="2"
required
placeholder="Enter your name"
onChange={this.handleChange}
/>
</label>
</p>
</code></pre>
<pre><code><br />また、onSubmitを使ってしまうと、Form規定のactionでは飛ばなくなるので自前でGatsbyのnavigateを使ってPost処理が終わったらThanksページに飛ぶようにします。
```typescript{numberLines: 1}{11-12}
handleSubmit(e) {
e.preventDefault();
const form = e.target;
fetch('https://getform.io/f/897f187e-876d-42a7-b300-7c235af72e6d', {
method: 'POST',
body: Contact.encode({
'form-name': form.getAttribute('name'),
...this.state,
}),
})
.then(() => navigateTo(form.getAttribute('action')))
.catch((error) => alert(error));
}
</code></pre>
<p>これでGetForm無料版でも自前のThanksページを作ることができます。</p>
<p><img src="https://i.imgur.com/gumRkbF.png" alt="img" /></p>
<h2 id="GitHub Actionsでビルドとデプロイ"><a href="#GitHub+Actions%E3%81%A7%E3%83%93%E3%83%AB%E3%83%89%E3%81%A8%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4">GitHub Actionsでビルドとデプロイ</a></h2>
<p>ここまで来たらあとはGitHub Actionsでビルドとデプロイを行うだけです。</p>
<p>masterブランチへのPRでPreviewデプロイ、masterへのコミットで本番デプロイをするように2つactionsを作ります。</p>
<p>まずはPreviewデプロイ</p>
<pre><code class="yaml">name: DeployToNetlifyPreview
on:
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Cache node_modules
uses: actions/cache@v1
with:
path: node_modules
key: $<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-$<span>{</span><span>{</span> hashFiles('**/package-lock.json') <span>}</span><span>}</span>
restore-keys: |
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: npm install and build
env:
GATSBY_GITHUB_CLIENT_SECRET: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_SECRET<span>}</span><span>}</span>
GATSBY_GITHUB_CLIENT_ID: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_SEARCH_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_SEARCH_API_KEY<span>}</span><span>}</span>
GATSBY_ALGOLIA_INDEX_NAME: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_INDEX_NAME<span>}</span><span>}</span>
GATSBY_ALGOLIA_APP_ID: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_APP_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_ADMIN_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_ADMIN_API_KEY<span>}</span><span>}</span>
FAUNADB_SERVER_SECRET: $<span>{</span><span>{</span>secrets.FAUNADB_SERVER_SECRET<span>}</span><span>}</span>
run: |
npm install
npm run build
- name: Deploy to netlify
run: npx netlify-cli deploy --dir=./public > cli.txt
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
- name: Cat cli.txt
run: |
cat cli.txt
sed -i -z 's/\n/\\n/g' cli.txt
- name: Post Netlify CLI Comment
env:
GITHUB_TOKEN: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span>
URL: $<span>{</span><span>{</span> github.event.pull_request.comments_url <span>}</span><span>}</span>
run: |
curl -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-d "{\"body\": \"$(cat cli.txt)\"}" \
${URL}
</code></pre>
<p>node setupやnpm install, buildはいつも通りです。</p>
<p>GitHub ActionsではSecretを指定することができますので、Algolia searchやFaunaDBのAPIキーはシークレットとしてビルド時の環境変数で渡してます。</p>
<p>ちなみに、環境変数で<strong>GATSBY_XXXX</strong>としておくと、ビルドされたJSにも環境変数が入る形になります。(JSから環境変数を使う場合はこれを忘れないこと。)これ結構詰まるポイント。</p>
<p>デプロイには<a target="_blank" rel="nofollow noopener" href="https://docs.netlify.com/cli/get-started/">netlify-cli</a>を使います。</p>
<p>必要な環境変数はサイトIDとAUTH TOKENです。</p>
<p>ちょっと特徴として、netlify-cliでデプロイが成功すると、<strong>デプロイURLが標準出力</strong>に出ますので、それをいったん適当なtextファイルに書き出し、</p>
<p>PRコメントにもURLを送るようにしています。</p>
<p>GitHub Actionsの素晴らしいところは、GITHUB TOKENについては、特に設定しなくてもsecrets.GITHUB_TOKENで取り出すことができますので簡単にPRコメントに送信できます。</p>
<pre><code class="yaml"> - name: Deploy to netlify
run: npx netlify-cli deploy --dir=./public > cli.txt
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
- name: Cat cli.txt
run: |
cat cli.txt
sed -i -z 's/\n/\\n/g' cli.txt
- name: Post Netlify CLI Comment
env:
GITHUB_TOKEN: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span>
URL: $<span>{</span><span>{</span> github.event.pull_request.comments_url <span>}</span><span>}</span>
run: |
curl -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-d "{\"body\": \"$(cat cli.txt)\"}" \
${URL}
</code></pre>
<p>次に本番へのデプロイです。</p>
<pre><code class="yaml">name: DeployToNetlifyPRD
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Cache node_modules
uses: actions/cache@v1
with:
path: node_modules
key: $<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-$<span>{</span><span>{</span> hashFiles('**/package-lock.json') <span>}</span><span>}</span>
restore-keys: |
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: npm install and build
env:
GATSBY_GITHUB_CLIENT_SECRET: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_SECRET<span>}</span><span>}</span>
GATSBY_GITHUB_CLIENT_ID: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_SEARCH_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_SEARCH_API_KEY<span>}</span><span>}</span>
GATSBY_ALGOLIA_INDEX_NAME: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_INDEX_NAME<span>}</span><span>}</span>
GATSBY_ALGOLIA_APP_ID: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_APP_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_ADMIN_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_ADMIN_API_KEY<span>}</span><span>}</span>
FAUNADB_SERVER_SECRET: $<span>{</span><span>{</span>secrets.FAUNADB_SERVER_SECRET<span>}</span><span>}</span>
run: |
npm install
npm run build
- name: Deploy to netlify
run: npx netlify-cli deploy --prod --dir=./public
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
</code></pre>
<p>ほとんど同じですが、netlify-cliでdeployコマンドに --prodオプションを入れることで、本番環境へデプロイされます。</p>
<pre><code class="yaml"> - name: Deploy to netlify
run: npx netlify-cli deploy --prod --dir=./public
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
</code></pre>
<h2 id="結論"><a href="#%E7%B5%90%E8%AB%96">結論</a></h2>
<p>これで、Netlifyのビルド時間は0になり、精神的に安心できるようになりました。</p>
<p><img src="https://i.imgur.com/ugdUr9l.png" alt="img" /></p>
<p>リファクタや記事の執筆もはかどっていいですね!!</p>
tubone24
tag:crieit.net,2005:PublicArticle/16550
2021-01-06T23:45:20+09:00
2021-01-06T23:55:33+09:00
https://crieit.net/posts/badge-of-github-actions-with-chrome-extension-20210106
Github Actions のバッジを付ける (+バッジに Github Actions ページへのリンクを付与するChrome拡張機能を作成)
<p><a href="https://crieit.net/posts/run-phpunit-on-github-actions-20210105">前回記事</a>の続き。 Github Actions で PHPUnit が走ることが確認できたところで、今度は「そういえば Github Actions のバッジはあるのだろうか?」と気になって調べてみました。</p>
<h2 id="バッジの所在"><a href="#%E3%83%90%E3%83%83%E3%82%B8%E3%81%AE%E6%89%80%E5%9C%A8">バッジの所在</a></h2>
<p>バッジについては Github Actions のページにありました。</p>
<ol>
<li>リポジトリの対象アクション ( <code>https://github.com/<user>/<repo>/actions?<workflow></code> ) に遷移</li>
<li>上のハンバーガー( <code>…</code> ) からメニューを開く</li>
<li><code>Create status badge</code> をクリック</li>
</ol>
<p>以上の手順で発行できます。</p>
<p><a href="https://crieit.now.sh/upload_images/30fd56cee47ae62946d6c90ff72122da5ff5cbafc5560.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/30fd56cee47ae62946d6c90ff72122da5ff5cbafc5560.jpg?mw=700" alt="バッジ発行のメニューを展開した画面" /></a></p>
<p>メニュー展開時。</p>
<p><a href="https://crieit.now.sh/upload_images/8ae1b6cc9da667dd3e02d32105a009505ff5cbba9ec66.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8ae1b6cc9da667dd3e02d32105a009505ff5cbba9ec66.jpg?mw=700" alt="バッジの Markdownコード をコピペできるダイアログ" /></a></p>
<p>ダイアログ表示。</p>
<p><a href="https://crieit.now.sh/upload_images/141188e82ee2e92f15b7ec06bc7286ef5ff5cbc8c6e40.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/141188e82ee2e92f15b7ec06bc7286ef5ff5cbc8c6e40.jpg?mw=700" alt="バッジを readme.md に貼り付け" /></a></p>
<p>バッジを readme.md に貼り付けてみました。</p>
<h2 id="バッジのリンクを変更する Chrome拡張機能"><a href="#%E3%83%90%E3%83%83%E3%82%B8%E3%81%AE%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B+Chrome%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD">バッジのリンクを変更する Chrome拡張機能</a></h2>
<p>ところで、</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/akameco/items/e474691964703033e18d">GitHub Actionsのバッジをリンク付きでREADMEに追加する - Qiita</a></li>
</ul>
<p>こちらの記事で「デフォルトのバッジ画像の Markdownコード は画像のみとなっていて対象の Github Actions へのリンクにはなっていないのが不便」とありました。確かに……。</p>
<p>上記の記事では UserScript で該当の Markdownコード を書き換える方法を紹介していましたが、個人的には Chrome拡張機能 で充分な気がしたのでざっくり自前で作ってみました。</p>
<h3 id="リポジトリ"><a href="#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA">リポジトリ</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/chrome_extensions_cambadge">arm-band/chrome_extensions_cambadge</a></li>
</ul>
<h3 id="manifest.json"><a href="#manifest.json">manifest.json</a></h3>
<pre><code class="json">{
"manifest_version": 2,
"name": "cambadge",
"description": "Github Actions のバッジのURLを変更する拡張機能です。",
"version": "0.0.1",
"browser_action": {
"default_icon": {
"19": "icon_19.png",
"38": "icon_38.png"
},
"default_title": "cambadge"
},
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"content_scripts": [
{
"matches": [
"https://github.com/*"
],
"js": [
"main.js"
]
}
]
}
</code></pre>
<h3 id="main.js"><a href="#main.js">main.js</a></h3>
<pre><code class="javascript">/**
* cambadgeCampaign: rewrite markdown code in textarea
*
* @param {object} DOMBadgeMd
*/
const cambadgeCampaign = (DOMBadgeMd) => {
if (/^\!\[(.*)\]\((.*)\)$/gi.test(DOMBadgeMd.textContent)) {
DOMBadgeMd.textContent = `[${DOMBadgeMd.textContent}](${location.href})`;
}
};
window.addEventListener('load', (e) => {
// triggered load
if (/https:\/\/github\.com\/(.*)actions(.*)/gi.test(location.href)) {
// only github actions page
const clickItem = document.querySelector('summary[data-test-selector="badge-builder-button"]');
clickItem.addEventListener('click', (ev) => {
// triggered click of element:summary[data-test-selector="badge-builder-button"]
let setIntervalId;
let DOMBadgeMd;
function findTargetElement () {
// watch until find element:#badge-markdown
DOMBadgeMd = document.querySelector('#badge-markdown');
if (DOMBadgeMd !== null && DOMBadgeMd !== undefined) {
// found
clearInterval(setIntervalId);
// call function
cambadgeCampaign(DOMBadgeMd);
}
};
setIntervalId = setInterval(findTargetElement, 100);
});
}
});
</code></pre>
<p>ダイアログ中の <code>#badge-markdown</code> を含むバッジ生成の要素は <code>Create status badge</code> をクリックした際に生成されるようなので、 <code>Create status badge</code> をクリックした後、 <code>#badge-markdown</code> が見付かるまで書き換えの処理を待つようにしました。</p>
<p><a href="https://crieit.now.sh/upload_images/fdaadb5b62dc4f103757d48bb84e12645ff5ccc3a2263.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fdaadb5b62dc4f103757d48bb84e12645ff5ccc3a2263.jpg?mw=700" alt="バッジの Markdownコード (Chrome拡張機能 で書き換え実施後の表示)" /></a></p>
<p>Chrome拡張機能 で書き換えられたダイアログ。これで該当の Github Actions ページへのリンクに繋がるようになりました。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<h3 id="バッジ"><a href="#%E3%83%90%E3%83%83%E3%82%B8">バッジ</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/SnowCait/items/487d70b342ffbe2f33d8#fn1">GitHub Actions でステータスバッジを表示する - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/actions/managing-workflow-runs/adding-a-workflow-status-badge">ワークフローステータスバッジを追加する - GitHub Docs</a></li>
</ul>
<h3 id="バッジのリンクを変更する"><a href="#%E3%83%90%E3%83%83%E3%82%B8%E3%81%AE%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B">バッジのリンクを変更する</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/akameco/items/e474691964703033e18d">GitHub Actionsのバッジをリンク付きでREADMEに追加する - Qiita</a></li>
</ul>
<h3 id="UserScript"><a href="#UserScript">UserScript</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://kenchan0130.github.io/post/2018-05-21-1">UserScriptで業務改善</a></li>
</ul>
arm-band
tag:crieit.net,2005:PublicArticle/16539
2021-01-05T22:38:21+09:00
2021-01-05T22:40:17+09:00
https://crieit.net/posts/run-phpunit-on-github-actions-20210105
Github Actions で PHPUnit を走らせる
<p>Github Actions で ESLint や Stylelint 、あるいはデプロイのワークフローは走らせたことがありますが、 Jest も行けるはず……と思い至ったところで、ふとそういえば PHPUnit はどうでしょうか、と思い実験。</p>
<h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2>
<p>検索すると、</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/blue32a/items/0661d70216051ad6552d">GitHub ActionsでPHPUnitを実行する - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://techblog.istyle.co.jp/archives/4143">GitHubActionsでPHP7.4環境のPHPUnitを実行する - istyle Tech Blog</a></li>
</ul>
<p>これらの記事がヒットしました。そこで、この記事を参考に <code>.github/workflows/test.yml</code> として作成。</p>
<h3 id=".github/workflows/test.yml"><a href="#.github%2Fworkflows%2Ftest.yml">.github/workflows/test.yml</a></h3>
<pre><code class="yml">name: PHPUnit test
on: [push]
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['7.4']
steps:
- name: Setup PHP $<span>{</span><span>{</span> matrix.php-version <span>}</span><span>}</span>
uses: shivammathur/setup-php@v2
with:
php-version: $<span>{</span><span>{</span> matrix.php-version <span>}</span><span>}</span>
extension-csv: mbstring, xdebug, dom
- name: Add Plugin
run: sudo apt install -y php7.4-xml
- name: Checkout
uses: actions/checkout@v2
- name: Check PHP Version
run: php -v
- name: Check Composer Version
run: composer -V
- name: Check PHP Extensions
run: php -m
- name: Validate composer.json and composer.lock
run: composer validate
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run test suite
run: composer run-script test
</code></pre>
<p>試しに Github に push してみます。</p>
<p><a href="https://crieit.now.sh/upload_images/5e7f8b136f405d78a18e5bea06bfba145ff4680848495.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5e7f8b136f405d78a18e5bea06bfba145ff4680848495.jpg?mw=700" alt="Github Actions で PHPUnit が走った結果の様子" /></a></p>
<p>走りました。</p>
<p>先人の知恵があればこそですが、 workflows の <code>yml</code> ファイルがあれば PHPUnit のテストも可能ということが分かりました。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<h3 id="Github Actions で PHPUnit"><a href="#Github+Actions+%E3%81%A7+PHPUnit">Github Actions で PHPUnit</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/blue32a/items/0661d70216051ad6552d">GitHub ActionsでPHPUnitを実行する - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://techblog.istyle.co.jp/archives/4143">GitHubActionsでPHP7.4環境のPHPUnitを実行する - istyle Tech Blog</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/nanasess/items/09b0798eb878328b195f">GitHub Actions で PHP の CI/CD をする - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.pnkts.net/2020/03/22/github-actions-phpunit">【Github Actions】プッシュ時にgithubに自動でテストを実行してもらおう! - ポンコツエンジニアのごじゃっぺ開発日記。</a></li>
</ul>
<h3 id="composer"><a href="#composer">composer</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://getcomposer.org/doc/03-cli.md#install-i">Command-line interface / Commands - Composer</a></li>
<li><a target="_blank" rel="nofollow noopener" href="http://blog.tojiru.net/article/440339824.html">Composerの作者に会った (PHP勉強会 番外編レポート) #phpstudy #composerphp: Architect Note</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/tadsan/items/3a753f9eca83f2867a0a">composer.jsonのrequireを直接編集してはいけない - Qiita</a></li>
</ul>
arm-band
tag:crieit.net,2005:PublicArticle/16323
2020-12-10T00:55:08+09:00
2020-12-10T00:59:23+09:00
https://crieit.net/posts/hugo-github-actions-for-github-pages
Hugo + GitHub Pages + GitHub Actions で独自ドメインのウェブサイトを構築する
<h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1>
<p><img src="https://i.gyazo.com/ffe8fe276b9d008461880581002430ec.png" alt="Hugo のトップページ" /></p>
<p>Zenn や Qiita, note など様々なウェブサービスで記事を書くにつれて、ふと雑多な内容で自分の好き勝手に記事を書いて公開できる自分のブログが欲しくなりました。そこで、自分のブログを作ろうと思い調査したところ、SSG で作るのが手っ取り早そうだったのと、その中でも一番ラクにウェブサイトが構築できそうな <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/">Hugo</a> を採用しました。</p>
<p>また、デプロイは簡単に行いたかったので、デプロイ先として <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/about-github-pages">GitHub Pages</a> を採用しました。<br />
独自ドメインの割り当てから HTTPS 対応まで無料でできるかつ、使い慣れている GitHub をデプロイ先に使えることが決め手でした。</p>
<p>Hugo で自分のブログを構築して GitHub Pages で公開できるようになったのですが、ブログ内容を更新したり記事を書くたびにビルドしてデプロイをするのが、意外と面倒なことに気づきました。そこで、<a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a> を用いて、ビルドしてデプロイするという作業は自動化しました。</p>
<p>上記までの作業をすることで、自分のブログを書いたり更新することだけに集中できる環境を整えることができました。ウェブサイトを作りこむ以外は、簡単ないくつかの作業をするだけで Hugo で満足のいく自分のブログを書く環境が整えられたので、その手順についてまとめてみました。</p>
<p>ちなみに本記事の手順で実際に作成した私のブログは下記です。<br />
<a target="_blank" rel="nofollow noopener" href="https://nikaera.com/">https://nikaera.com/</a></p>
<h1 id="Hugo を PC にインストールする"><a href="#Hugo+%E3%82%92+PC+%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B">Hugo を PC にインストールする</a></h1>
<p>私は Windows には <a target="_blank" rel="nofollow noopener" href="https://chocolatey.org/">Chocolatey</a>、Mac では <a target="_blank" rel="nofollow noopener" href="https://brew.sh/index_ja">Homebrew</a> で Hugo をインストールしました。Chocolatey や Homebrew を利用したインストール方法については <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/installing/">公式サイトの手順</a> で公開されています。</p>
<pre><code class="bash"># Mac で Homebrew を使って Hugo をインストールする
brew install hugo
</code></pre>
<pre><code class="powershell"># Windows で Chocolatey を使って Hugo をインストールする
choco install hugo -confirm
# Sass/SCSS を用いてウェブサイトのデザイン改修を行いたい場合は
# 下記で Chocolatey を使って Hugo をインストールする
choco install hugo-extended -confirm
</code></pre>
<h1 id="Hugo で自分のウェブサイトを構築する"><a href="#Hugo+%E3%81%A7%E8%87%AA%E5%88%86%E3%81%AE%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E6%A7%8B%E7%AF%89%E3%81%99%E3%82%8B">Hugo で自分のウェブサイトを構築する</a></h1>
<h2 id="Hugo プロジェクトを作成する"><a href="#Hugo+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">Hugo プロジェクトを作成する</a></h2>
<p>下記コマンドで Hugo のプロジェクトフォルダを生成できます。</p>
<pre><code class="bash">hugo new site <プロジェクトフォルダのパス>
</code></pre>
<p>Hugo のコンフィグファイルのデフォルトフォーマットは <a target="_blank" rel="nofollow noopener" href="https://github.com/toml-lang/toml.io/blob/main/specs/ja/v1.0.0-rc.2.md">TOML</a> 形式なのですが、<code>hugo new site <プロジェクトフォルダへのパス> -f json</code> のように <code>-f</code> オプションを付与することで JSON フォーマットでもコンフィグファイルを生成可能です。</p>
<p>後述しますが、一部の Hugo のテーマはコンフィグファイルのサンプルが JSON ファイルで書かれています。その場合は、新規で設定するコンフィグファイルのフォーマットも JSON で統一しておくと各種設定項目の調整が楽になりそうです。</p>
<p>もしくは<a target="_blank" rel="nofollow noopener" href="https://github.com/sclevine/yj">こちら</a>のようなコンバーターを使用したり、<a target="_blank" rel="nofollow noopener" href="https://pseitz.github.io/toml-to-json-online-converter/">こちら</a>のようなウェブのコンバーターを使用して、設定ファイルを JSON から TOML フォーマットに変更しても良さそうです。</p>
<h2 id="ウェブサイトのテーマを探す"><a href="#%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%81%AE%E3%83%86%E3%83%BC%E3%83%9E%E3%82%92%E6%8E%A2%E3%81%99">ウェブサイトのテーマを探す</a></h2>
<p>テーマとは、ウェブサイトのデザインテンプレートのことです。テーマは <a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/">Hugo Themes</a> で公開されているので、この中から自分の好みを選びます。Hugo ではテーマの内容をカスタマイズしたり差し替えることもできるので、あとから一部デザインを自分好みに修正できます。</p>
<p><img src="https://i.gyazo.com/294b076125052fe8bd9574c5bd0d1f0b.png" alt="Hugo Themes にアクセスした時のページ" /><br />
<strong><a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/">Hugo Themes</a> にアクセスした時のページ</strong></p>
<p>お気に入りのテーマが見つかったら、<code>Download</code> ボタンをクリックしてテーマの GitHub URL を控えておきます。</p>
<p><img src="https://i.gyazo.com/36ce79358e416ff6c92e7ad405c2abfa.png" alt="Kiera というテーマのページ" /><br />
<strong><a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/hugo-kiera/">Kiera</a> というテーマのページ</strong></p>
<h2 id="Hugo プロジェクトにテーマを適用する"><a href="#Hugo+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E3%83%86%E3%83%BC%E3%83%9E%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B">Hugo プロジェクトにテーマを適用する</a></h2>
<p>テーマの適用方法については <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/quick-start/#step-3-add-a-theme">公式サイトの手順</a> で紹介されていますが、Hugo のプロジェクトフォルダのルートで下記コマンドを実行して、コンフィグファイルに <code>theme</code> を追記するだけです。</p>
<pre><code class="bash">git clone <テーマの GitHub URL> themes/<テーマ名> --depth=1
echo 'theme = "<テーマ名>"' >> config.toml
</code></pre>
<p>どのテーマも基本的に適用方法は同じで、例えば私が採用したテーマである <a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/hugo-papermod/">PaperMod</a> を適用する場合は下記コマンドを実行することになります。</p>
<pre><code class="bash">git clone https://github.com/adityatelange/hugo-PaperMod themes/hugo-PaperMod --depth=1
echo 'theme = "hugo-PaperMod"' >> config.toml
</code></pre>
<p>これで自分のウェブサイトを作り込んでいくための準備が整いました。</p>
<h2 id="ウェブサイトを作り込む"><a href="#%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E4%BD%9C%E3%82%8A%E8%BE%BC%E3%82%80">ウェブサイトを作り込む</a></h2>
<p><strong>各テーマには <code>exampleSite</code> というウェブサイト作成の参考になる Hugo のプロジェクトフォルダが存在します。</strong> 最初は <code>exampleSite</code> フォルダ内に存在する各種ファイルを自分のプロジェクトにコピー&ペーストして、改変しながらウェブサイトを作り込んでいくとスムーズに作業が進められます。</p>
<p><code>exampleSite</code> フォルダは大抵 GitHub プロジェクトのルートに存在しているのですが、<strong>GitHub のブランチで管理しているものもあります。</strong> 私の採用した PaperMod は GitHub の <code>exampleSite</code> ブランチで管理していました。</p>
<p>上記のような詳細は Hugo のテーマページに記載があるはずなので、事前に <code>exampleSite</code> フォルダが配置されている場所や設定可能な項目等をチェックしておくことをオススメします。実際のウェブサイトの見た目を確認するには、Hugo のプロジェクトフォルダのルートで下記コマンドを実行します。</p>
<pre><code class="bash">hugo server
</code></pre>
<p><code>hugo server</code> 実行中に、ウェブサイトの設定を変更したり記事を追加すると、自動的にビルドが実行されるので常に最新のウェブサイトの見た目を確認できます。また、その際にエラーもコンソールに出力されるので、適宜修正しながらウェブサイトの作成を進めていくことが可能です。</p>
<h1 id="GitHub にデプロイ環境を整える"><a href="#GitHub+%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E7%92%B0%E5%A2%83%E3%82%92%E6%95%B4%E3%81%88%E3%82%8B">GitHub にデプロイ環境を整える</a></h1>
<p>ウェブサイトの構築が出来ればあとはデプロイするだけです。今回は GitHub Actions でデプロイするため、残りの作業は GitHub 上で進めていきます。一応 GitHub Actions を使わずに手動でデプロイする手順については、Hugo の <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hosting-and-deployment/hosting-on-github/">公式サイトの手順</a> にて紹介されています。</p>
<p>GitHub Actions を用いてデプロイできるようにした際の利点としては下記があります。</p>
<ul>
<li>デプロイ時に毎回手動で複数コマンド実行する手間が省ける</li>
<li>自動化することでデプロイ時のコマンドミスを防ぐことが可能</li>
<li><strong>常に統一した Hugo のビルド環境が利用可能</strong></li>
</ul>
<p>最初のうちは私も公式サイトの手順通りに Mac で手動デプロイしていました。しかし、Windows 環境でデプロイ作業した際、本番環境デプロイ時に <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hugo-pipes/fingerprint/">SRI</a> 関連のエラーが発生してしまい、ウェブサイトに stylesheet が適用されないバグが発生してしまいました。</p>
<p>結局原因はよく分からなかったのですが、GitHub Actions 経由でデプロイするようにしたところ直りました。<strong>CI 経由でデプロイできるようになると、こういった実行環境の違いによる挙動も気にする必要が無くなります。</strong></p>
<p>一応 Windows 環境で発生した SRI 関連のバグは Hugo で該当するテンプレートファイルを <code>layouts</code> フォルダを利用して差し替えて、integrity の設定内容を空にすることで、本番環境でも stylesheet が適用できるようになったことは確認しました。<a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/a/65052963">詳細はこちら</a>。</p>
<h2 id="自分のウェブサイトをデプロイするためのリポジトリを作成する"><a href="#%E8%87%AA%E5%88%86%E3%81%AE%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">自分のウェブサイトをデプロイするためのリポジトリを作成する</a></h2>
<p>GitHub の <a target="_blank" rel="nofollow noopener" href="https://pages.github.com/">公式サイトの手順</a> に従って、自身のウェブサイトをデプロイするためのリポジトリを作成します。また本記事では、<strong>Hugo プロジェクトのリポジトリはデプロイ用リポジトリとは別で扱うため、Hugo プロジェクトのリポジトリも新たに作成します。</strong></p>
<p>本記事では Hugo プロジェクトのリポジトリ名は <code>hugo-blog</code> という名前に設定した前提で進めていきます。また作成したリモートリポジトリの情報は、下記コマンドで Hugo プロジェクトに登録しておきます。</p>
<pre><code class="bash"># Hugo プロジェクトフォルダのルートで Git リポジトリを作成する
git init
# Hugo プロジェクトのリポジトリ情報を登録しておく (hugo-blog の GitHub URL)
git remote add origin <Hugo プロジェクトのリポジトリの URL>
</code></pre>
<h2 id="GitHub Actions で Hugo のビルドからデプロイまでを自動化するための環境を整える"><a href="#GitHub+Actions+%E3%81%A7+Hugo+%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%81%8B%E3%82%89%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%BE%E3%81%A7%E3%82%92%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E7%92%B0%E5%A2%83%E3%82%92%E6%95%B4%E3%81%88%E3%82%8B">GitHub Actions で Hugo のビルドからデプロイまでを自動化するための環境を整える</a></h2>
<p>今回は <code>hugo-blog</code> という Hugo プロジェクトのリポジトリから、デプロイ用リポジトリへデプロイしたいため、まずはデプロイ用リポジトリでデプロイキーを登録します。<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/developers/overview/managing-deploy-keys#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%82%AD%E3%83%BC">公式サイトの手順</a> に従いデプロイキーを登録したら、秘密鍵を <code>hugo-blog</code> リポジトリのシークレットに登録します。</p>
<p>シークレットは <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/actions/reference/encrypted-secrets#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">公式サイトの手順</a> に従って登録します。今回は秘密鍵をシークレットに登録する際の名前に <code>ACTIONS_DEPLOY_KEY</code> を設定した前提で進めていきます。</p>
<p>次に <a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a> を導入して Hugo のビルドから公開までを自動化する環境をセットアップします。</p>
<p><code>hugo-blog</code> リポジトリに GitHub Pages action の <a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action#getting-started">Getting started</a> を参考にワークフローファイルを追加します。<code>- name: Deploy</code> の項目のみデプロイ用リポジトリへデプロイするために設定内容を変更します。</p>
<pre><code class="yaml"># .github/workflows/gh-pages.yml
name: github pages
on:
push:
branches:
- main # Set a branch name to trigger deployment
jobs:
deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.78.2'
- name: Build
run: hugo --minify
# - name: Deploy
# uses: peaceiris/actions-gh-pages@v3
# with:
# github_token: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span>
# publish_dir: ./public
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: $<span>{</span><span>{</span> secrets.ACTIONS_DEPLOY_KEY <span>}</span><span>}</span>
external_repository: nikaera/nikaera.github.io
publish_branch: main
cname: nikaera.com
</code></pre>
<p><code>- name: Deploy</code> の項目で設定した各種パラメータは下記になります。</p>
<div class="table-responsive"><table>
<thead>
<tr>
<th>キー</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>deploy_key</td>
<td>デプロイ時に使用する秘密鍵</td>
</tr>
<tr>
<td>external_repository</td>
<td>デプロイ先のリモートリポジトリ</td>
</tr>
<tr>
<td>publish_branch</td>
<td>デプロイ先のリモートリポジトリのブランチ</td>
</tr>
<tr>
<td>cname</td>
<td>設定するカスタムドメイン名</td>
</tr>
</tbody>
</table></div>
<p><code>deploy_key</code> にはシークレットに登録した秘密鍵を設定します。<code>external_repository</code> には Hugo をビルドした際のデプロイ先リポジトリを <code><ユーザ名>/<リポジトリ名></code> のフォーマットで指定します。<code>publish_branch</code> はデプロイ先として使用するブランチ名になります。<code>cname</code> には自分が設定したいドメイン名を指定します。<code>cname</code> の <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site">詳細</a> はこちらからご確認いただけます。</p>
<h2 id="カスタムドメインで設定した内容で DNS 設定を書き換える"><a href="#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%A7%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E5%86%85%E5%AE%B9%E3%81%A7+DNS+%E8%A8%AD%E5%AE%9A%E3%82%92%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B">カスタムドメインで設定した内容で DNS 設定を書き換える</a></h2>
<p>GitHub Pages にカスタムドメインを利用する際は、該当するドメインの DNS レコードの設定で CNAME レコードもしくは A レコードを設定する必要があります。<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site">公式サイトの手順</a> に従って設定します。</p>
<p>また、カスタムドメインの設定後は特別な理由がない限りは、デプロイ用リポジトリで <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/securing-your-github-pages-site-with-https">HTTPS 強制の設定</a> をしておくことオススメします。</p>
<p>ちなみに GitHub Pages で利用している証明書は <a target="_blank" rel="nofollow noopener" href="https://github.blog/2018-05-01-github-pages-custom-domains-https/">Let's Encrypt</a> のものになります。</p>
<p>設定作業はこれで完了です。あとは実際に Hugo プロジェクトを更新後、<code>hugo-blog</code> リポジトリに push することでビルドからデプロイまで GitHub Actions で行われるようになったかを確認していきます。</p>
<h2 id="Hugo プロジェクトの更新時に自動でデプロイが行われるか確認する"><a href="#Hugo+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E6%9B%B4%E6%96%B0%E6%99%82%E3%81%AB%E8%87%AA%E5%8B%95%E3%81%A7%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%8C%E8%A1%8C%E3%82%8F%E3%82%8C%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B">Hugo プロジェクトの更新時に自動でデプロイが行われるか確認する</a></h2>
<p>Hugo プロジェクトには既に <code>hugo-blog</code> リポジトリの GitHub URL が <code>origin</code> として設定されているはずなので、下記で実際に <code>hugo-blog</code> リポジトリへ push してみます。</p>
<pre><code class="bash"># Hugo プロジェクトを hugo-blog リポジトリに push する
git add -A
git commit -m "initial commit"
git push origin main
</code></pre>
<p>次は実際に GitHub リポジトリの <code>Actions</code> タブから、GitHub Pages action のワークフローが実行されているか確認します。</p>
<p><img src="https://i.gyazo.com/d4c3c5477c0f149ae84464fcc63c593b.png" alt="GitHub Pages actions の実行に成功した様子" /><br />
<strong>GitHub Pages actions の実行に成功した様子</strong></p>
<p>無事ワークフローの実行に成功したことを確認したら、デプロイ用リポジトリの様子を確認します。</p>
<p><img src="https://i.gyazo.com/3a0eb5ca58701a39bb922ea14477488c.png" alt="デプロイ用リポジトリに Hugo の最新ビルドが push されていることを確認する" /><br />
<strong>デプロイ用リポジトリに Hugo の最新ビルドが push されていることを確認する</strong></p>
<p>最新コミットのメッセージに <code>deploy: <ユーザ名>/hugo-blog@<コミットハッシュ></code> のコメントが表示されているはずです。コメントのリンクをクリックすると、<code>hugo-blog</code> リポジトリの最新コミットの確認画面に遷移するはずです。</p>
<p>ここまで確認できれば、あとはローカルで <code>hugo server</code> して確認していたウェブサイトと同じように、GitHub Pages 上でもウェブサイトが見えるか実際に確認してみます。</p>
<p>デプロイ用リポジトリ名が <code><ユーザ名>/<ユーザ名>.github.io</code> であった場合、<code>https://<ユーザ名>.github.io</code> でウェブサイトにアクセスできます。私の場合は <code>https://nikaera.github.io</code> になります。その際、カスタムドメインにリダイレクトすることも確認できれば、カスタムドメインの設定も正常に反映されています。</p>
<p><img src="https://i.gyazo.com/b3c061569dae33a1dd58f4741c6d77cc.png" alt="ページが正常に表示できカスタムドメインでもアクセスできている様子" /><br />
<strong>ページが正常に表示されていてカスタムドメインでアクセスできた様子</strong></p>
<p>アクセス時に意図したページが表示されていることが確認できれば大丈夫です。これで自分のウェブサイトを更新したら <code>hugo-blog</code> リポジトリに Hugo プロジェクトを push するだけで自分のウェブサイトを自動更新できるようになりました。</p>
<h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1>
<p>今回は Hugo を例にしましたが、本記事内で紹介した <a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a> は <a target="_blank" rel="nofollow noopener" href="https://jamstack.org/generators/">様々な SSG</a> に対応しています。そのため Hugo ではウェブサイトのカスタマイズに限界が来たなと感じたら <a target="_blank" rel="nofollow noopener" href="https://nextjs.org/">Next.js</a> や <a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/">Gatsby</a> に乗り換えるといったことも可能です。</p>
<p>また Hugo では何も考えずとも、マークダウンで記事が書けてビルドも高速なので、手っ取り早く自分のウェブサイトを構築してみたいという用途にはピッタリだと感じました。</p>
<p>関係ないですが、Hugo でウェブサイト構築する際の知見も記事に含めてしまったせいで、文章量が意図した倍近い量になってしまいました。。簡潔で分かりやすい文章が書けるようにならなきゃ。。</p>
<h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/">The world’s fastest framework for building websites | Hugo</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/">Complete List | Hugo Themes</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/about-github-pages">GitHub Pages について - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/installing/">Install Hugo | Hugo</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/quick-start/#step-3-add-a-theme">Quick Start | Hugo</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hosting-and-deployment/hosting-on-github/">Host on GitHub | Hugo</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://pages.github.com/">GitHub Pages | Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live.</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/developers/overview/managing-deploy-keys#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%82%AD%E3%83%BC">デプロイキーの管理 - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/actions/reference/encrypted-secrets#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">暗号化されたシークレット - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site">GitHub Pages サイトのカスタムドメインを管理する - GitHub Docs</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/securing-your-github-pages-site-with-https">HTTPS で GitHub Pages サイトを保護する - GitHub Docs</a></li>
</ul>
nikaera
tag:crieit.net,2005:PublicArticle/15810
2020-04-04T10:47:33+09:00
2020-04-04T15:57:22+09:00
https://crieit.net/posts/github-actions-build-lastmod
hugoをgithub-actions上でbuildした際、lastmodの更新がすべての記事に適用される問題を解決した
<h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://tech-wafter.net/2020/build-hugo-homepage-by-github-action/">hugoのジェネレートをGitHub-actionsを使って、pushするだけでデプロイできるようにした</a>のですが、全記事の最終更新日が更新されていたため原因調査をおこないました。</p>
<h2 id="TL;DR"><a href="#TL%3BDR">TL;DR</a></h2>
<ul>
<li>gitのcloneを行う際に最新コミットしか取得していなかった</li>
<li><code>actions/checkout</code>を利用する場合は以下の方法でfetchを行わせ、全履歴を取得しておく</li>
</ul>
<pre><code class="yaml">- uses: actions/checkout@v2
with:
fetch-depth: 0 # Fetch all history for .GitInfo and .
</code></pre>
<h2 id="試したこと"><a href="#%E8%A9%A6%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8">試したこと</a></h2>
<h3 id="GitHub-actions上とlocalの比較"><a href="#GitHub-actions%E4%B8%8A%E3%81%A8local%E3%81%AE%E6%AF%94%E8%BC%83">GitHub-actions上とlocalの比較</a></h3>
<div class="table-responsive"><table>
<thead>
<tr>
<th align="center">icon</th>
<th align="center">結果</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">✅</td>
<td align="center">更新対象記事のみlastmodが更新されていた</td>
</tr>
<tr>
<td align="center">❎</td>
<td align="center">すべての記事に対して更新が入っていた</td>
</tr>
</tbody>
</table></div>
<ul>
<li>ローカル
<ul>
<li>✅MacOSでのビルド</li>
<li>✅Vagrant内のUbuntu:18.04.4でのビルド</li>
</ul></li>
<li><p>CI環境</p>
<ul>
<li>❎Ubuntu:ubuntu-18.04でのビルド</li>
<li>❎MacOS:latestでのビルド</li>
<li>✅hugoのビルドを省いてデプロイ</li>
<li>❎オプションを外してビルド</li>
<li><p>❎既存のworkflowを使わずにコマンドでインストール(下記コマンドを実行)</p>
<pre><code class="bash">wget https://github.com/gohugoio/hugo/releases/download/v0.68.3/hugo_0.68.3_Linux-64bit.deb
sudo apt-get install -y ./hugo_0.68.3_Linux-64bit.deb
</code></pre></li>
</ul></li>
</ul>
<h3 id="git周りの確認"><a href="#git%E5%91%A8%E3%82%8A%E3%81%AE%E7%A2%BA%E8%AA%8D">git周りの確認</a></h3>
<ul>
<li>参照先のcommitIDが対象コミットのcommitIDになっているか
<ul>
<li>対象のコミットIDでした</li>
</ul></li>
<li><code>git log</code>の結果が正常に表示されているか
<ul>
<li><strong>CI上のログでは、1件しか表示されていなかった</strong></li>
</ul></li>
</ul>
<h2 id="結果"><a href="#%E7%B5%90%E6%9E%9C">結果</a></h2>
<p><code>actions/checkout@v2</code>という公式のworkflowを利用してgitのcloneを行っていたのですが、デフォルトでは最新のコミットしか取ってこないようです。<br />
更新日時の参照先が見つけられなくなるため、すべての記事が最新のコミット更新日時を取得しに行ってしまったのだと思います。</p>
<blockquote>
<pre><code class="markdown"># Number of commits to fetch. 0 indicates all history.
# Default: 1
fetch-depth: ''
</code></pre>
<p>https://github.com/actions/checkout#usage</p>
</blockquote>
<p>すべての履歴をcloneしてくることで、解決しました。<br />
GitHub Actionsのymlファイルでは、以下のように記載するようです。</p>
<blockquote>
<pre><code class="yaml">- uses: actions/checkout@v2
with:
fetch-depth: 0 # Fetch all history for .GitInfo and .
</code></pre>
<p>https://github.com/peaceiris/actions-hugo#️-create-your-workflow</p>
</blockquote>
<h2 id="さいごに"><a href="#%E3%81%95%E3%81%84%E3%81%94%E3%81%AB">さいごに</a></h2>
<p>最初はhugoのセットアップに使っているworkflowが悪いのかを疑ってたせいで、結構解決までに時間がかかりました…</p>
<p>今回のような問題を早期発見するために、確認用のStepも入れたほうが良いのかなと思いました。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/actions/checkout">actions/checkout: Action for checking out a repo</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/peaceiris/actions-hugo">peaceiris/actions-hugo: GitHub Actions for Hugo ⚡️ Setup Hugo quickly and build your site fast. Hugo extended, Hugo Modules, Linux (Ubuntu), macOS, and Windows are supported.</a></li>
</ul>
matsu4ki
tag:crieit.net,2005:PublicArticle/15728
2020-02-20T18:48:36+09:00
2020-02-26T17:42:55+09:00
https://crieit.net/posts/GitHub-Actions-MySQL-Laravel
GitHub ActionsでMySQLを使ったLaravelのテストを実行する
<p>GitHub ActionsでMySQLを使ったLaravelのテストを実行してみたら出来たのでメモ。</p>
<p>アクションを作成する時にLaravelの雛形が選べるようなので、とりあえずそちらを使って作成する。雛形を下記のように置き換えた。</p>
<pre><code class="yaml">name: Laravel
on: [push]
jobs:
laravel-tests:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:5.7
ports:
- 3306
options: --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: laravel
steps:
- uses: actions/checkout@v2
- name: Copy .env
run: php -r "file_exists('.env') || file_put_contents('.env', str_replace('DB_PORT=3306', 'DB_PORT=$<span>{</span><span>{</span> job.services.mysql.ports['3306'] <span>}</span><span>}</span>', file_get_contents('.env.example')));"
- name: Cache vendor
id: cache-vendor
uses: actions/cache@v1
with:
path: vendor
key: $<span>{</span><span>{</span> runner.os <span>}</span><span>}</span>-vendor-$<span>{</span><span>{</span> hashFiles('**/composer.lock') <span>}</span><span>}</span>
- name: Install Dependencies
if: steps.cache-vendor.outputs.cache-hit != 'true'
run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
run: vendor/bin/phpunit
</code></pre>
<h2 id="やったこと"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">やったこと</a></h2>
<p>下記が追加で編集したもの。</p>
<h3 id="MySQLの設定"><a href="#MySQL%E3%81%AE%E8%A8%AD%E5%AE%9A">MySQLの設定</a></h3>
<p>もともとはSQLiteでテストが行われる設定になっていたが、ちゃんとMySQLで実行したいのでその設定。まずはservicesにMySQLのサービスを追加。optionsはよくわからないがコンテナが落ちてしまうらしいので追加している。そのうち不要になるのでは。</p>
<p>接続の設定は <code>.env.example</code> をコピーして使う。そのため、その設定に合わせてこのサービスのenvを設定する。具体的な設定はDockerHubのmysqlイメージのところに書いてある。</p>
<p>ポートは <code>$<span>{</span><span>{</span> job.services.mysql.ports['3306'] <span>}</span><span>}</span></code> という感じでサービスのポートを参照できる。ホストはローカル。ただしlocalhostでなく127.0.0.1としないとつながらないっぽい。</p>
<h4 id="phpunit.xmlの編集"><a href="#phpunit.xml%E3%81%AE%E7%B7%A8%E9%9B%86">phpunit.xmlの編集</a></h4>
<p>phpunit.xmlにSQLiteを使う設定が書かれているので、そちらを削除する。</p>
<h3 id="キャッシュの設定"><a href="#%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%AE%E8%A8%AD%E5%AE%9A">キャッシュの設定</a></h3>
<p>vendorフォルダをキャッシュする。Cache vendorとInstall Dependenciesのところ。これでキャッシュされて次回から0秒になっているので多分大丈夫っぽい。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e4e55ac0e03c.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e4e55ac0e03c.png?mw=700" alt="image.png" /></a></p>
<p>ちなみに下記がキャッシュ前。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e4e55d2a2859.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e4e55d2a2859.png?mw=700" alt="image.png" /></a></p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>雛形もあるし非常に簡単だった。</p>
だら@Crieit開発者