Remix+CloudflareでWebサイトを作る 7(GitHub Action・PRでStaging環境に自動デプロイ・環境毎にD1の参照先を変更・Markdownパーサーの作り方調査)
【2024-02-17】GithubActionsで設定できる環境変数周りについてざっくり知る
Secretsは機密情報を保存して後から見れなくなり、Github Actionsのログではマスクされる。
Variablesも機密情報扱いだけど、後から確認できるしGithub Actionsのログに値が出力される。
Github Actionsのログに値が出力されることはやばいとはわかるけど、実際どのくらいのヤバさなのかがわかってない。具体的にどういうケースのときにログの値が見られてやばくなるんだろうか。
そういえばBasic認証の情報をCloudflareの環境変数として管理するようにした時 に環境変数がデフォルトでは設定後に確認できて、「暗号化」ボタンを押すと「この値は一度保存すると表示されなくなります。」と表示されてたけどこれはデフォルトだとGithubでいうVariablesだけど、「暗号化」ボタンを押すとSecretsになるということかな?
軽くまとめ
「Repository secrets, Repository variables」「Environments secrets, Environments variables」の4種類がある。
- Repository
- レポジトリ全体で使うやつを指定する
- Environments
- 環境ごとで分けたい時にそれぞれの環境を作成して、その中に環境変数を作成する
- secrets
- 見られちゃだめな秘匿情報で後から内容は確認できない
- variables
- 機密情報だが後から確認できてログにも出力される
例(あってるのかわからない)
- Repository secrets
- SlackのToken
- Repository variables
- (思い浮かばなかった...)
- Environments secrets
- 環境ごとのAPIトークンやAWSのアカウントID
- Environments variables
- 環境ごとのAPIのルートURL(
https://app/api/stg
,https://app/api/prd
)
- 環境ごとのAPIのルートURL(
【2024-02-17】GithubActionsでProduction/Staging環境ごとにデプロイする
現状
Repository secretsにCLOUDFLARE_ACCOUNT_ID
と CLOUDFLARE_API_TOKEN
を設定している。
環境ごとに分けるためにEnvironment secretsにこの値を書き写して、GithubActionsのYAMLファイルを修正する。
手を動かしながら気付いてしまった
GithubActionsのYAMLを修正してpushしてを繰り返しながら気付いたけどCloudflareはデプロイする環境によってAPIトークンとか変わらないから、わざわざ課金してEnvironments使えるようにして環境別に設定できるようにする意味なかったことに気付いた。
4ドルで済んで良かったと思おう...。
今回やること整理
Production
- As is
- mainブランチにpushされた時に、Repository secretsの値を使ってProduction環境にデプロイする
- To be
- 現状 + 手動でもProduction環境にデプロイできるようにする
Staging
- As is
- GithubActionsによるデプロイができない
- To be
- PRが作成された時に、Repository secretsの値を使ってStaging環境にデプロイする
- 手動でもStaging環境にデプロイできるようにする
できた
PRでStaging環境にデプロイされてる
ファイルの分け方考えるのに時間食った
最初は1つのYAMLファイルで場合分けをしてStagingとProductionにデプロイしようとしていたけど、Production環境はmainにpushされた時に発火すれば良くて、それを明示的にしたかったので環境ごとにファイルは分けた。要するにon:
を見た時にどのタイミングでどこにデプロイされるのか把握したいが、その下で色々場合分けが生じると可読性が低くなるし、今後バグの原因にもなるのでは?と思いやめた。
重複しているコードは多いけど一旦これで良しとする。
もっと良い書き方はあるんだろうな。
そして1つのファイルで場合分けをしようとしていたのでこの中の場合分けの方法とかググってて時間食った。
成果物
Production環境にデプロイするGithubActions
name: Production Deploy
# ここを見た時にmainにpushされたときだけ発火するというのがわかるのが嬉しい
on:
push:
branches:
- main
workflow_dispatch: # 手動でも実行できるようにしておいた
jobs:
publish:
runs-on: ubuntu-20.04
permissions:
contents: read
deployments: write
statuses: write
steps:
- name: 🔀 Checkout
uses: actions/checkout@v3
- name: ⏬ Install
run: npm install
working-directory: ./
- name: 🔨 Build
run: npm run build
working-directory: ./
- name: 🚀 Deploy
id: cloudflare-wrangler
uses: cloudflare/wrangler-action@v3
with:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy ./public --project-name=YOUR_PROJECT_NAME
- name: 🔗 Add publish URL as commit status
uses: actions/github-script@v6
with:
script: |
const sha = context.payload.pull_request?.head.sha ?? context.sha;
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
context: "Cloudflare Pages", # ここでも絵文字使いたかったけどエラーで落ちる。無理っぽい
description: "Access Cloudflare Pages deployment",
state: "success",
sha,
target_url: "${{ steps.cloudflare-wrangler.outputs.deployment-url }}",
});
Staging環境にデプロイするGithubActions
name: Staging Deploy
on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
jobs:
setup:
runs-on: ubuntu-latest
outputs:
BRANCH: ${{ env.BRANCH }}
steps:
- name: ⏳ Setup
run: echo "BRANCH=${{ github.ref }}" >> "$GITHUB_ENV" # Cloudflareにデプロイする際に必要となる
publish: # ここからは下はほぼ一緒
needs: setup
runs-on: ubuntu-20.04
permissions:
contents: read
deployments: write
statuses: write
steps:
- name: 🔀 Checkout
uses: actions/checkout@v3
with:
ref: ${{ needs.setup.outputs.BRANCH }}
- name: ⏬ Install
run: npm install
working-directory: ./
- name: 🔨 Build
run: npm run build
working-directory: ./
- name: 🚀 Deploy
id: cloudflare-wrangler
uses: cloudflare/wrangler-action@v3
with:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# デプロイコマンドに --branch があるところだけが差分
# Cloudflareでは初期設定だと--branch=main以外の場合はプレビュー環境にデプロイされる
command: pages deploy ./public --project-name=YOUR_PROJECT_NAME --branch=${{ needs.setup.outputs.BRANCH }}
- name: 🔗 Add publish URL as commit status
uses: actions/github-script@v6
with:
script: |
const sha = context.payload.pull_request?.head.sha ?? context.sha;
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
context: "Cloudflare Pages",
description: "Access Cloudflare Pages deployment",
state: "success",
sha,
target_url: "${{ steps.cloudflare-wrangler.outputs.deployment-url }}",
});
参考になったサイト
GithubActionsの書き方例
- GitHub Actionsを使用して環境別のCDを構築する #GitHub - Qiita
- GitHub Actionsのワークフローをブランチ名を元に環境定義を切り替える方法 #GitHubActions - Qiita
-
GitHub Actions の Workflow 実行内で Ref(ブランチ名)を取得する方法 | DevelopersIO
-
github.ref
github.ref_name
github.head_ref
の違いがわかったの良かった
-
こんな使い方もあるよ
今はやらないけど今後色々いじっていきたい
【2024-02-17】環境ごとにDBを分ける
背景
一番最初にここを見ながらDBの設定を行っていたけど、Staging/Production環境でバインディング先を同じにしてしまった。
Staging環境はDBを別にする。
やってみる Part1
1. DBの作成とバインディング
Staging環境用のデータベースを作成し、「Worker &Pages > [任意のアプリ] > 設定 > Functions」からバインディングを変更。
wrangler.toml
を更新
2.
公式に従い以下のように書く。
[env.staging]
d1_databases = [
{ binding = "DB_STAGING", database_name = "YOUR_PROJECT_NAME-staging", database_id = "<UUID1>" },
]
# This is a production environment
[env.production]
d1_databases = [
{ binding = "DB", database_name = "YOUR_PROJECT_NAME", database_id = "<UUID2>" },
]
3. Staging環境にマイグレーションファイルを適用
ローカルから実行してDBにテーブルを作成する
$ npx wrangler d1 migrations apply YOUR_PROJECT_NAME-staging
4. PRを作成してStaging環境のページにアクセスしてみる
StagingのDBに適当なデータを入れてトップページのloaderにそれを取得するコードを書いておいた。
PRを作成するとCloudflare Pagesにデプロイされるのでそのページに適当に入れたデータが表示されたら無事に動いているということになる。
ちーん。
多分env.DB
でアクセスすることができていなくて、env.DB_STAGING
とする必要があるから値が取得できないのでは。とは言っても対応方法がわからない。
調べてみる
公式含めここらへんをみる限り、wrangler
コマンドの引数に--env
を指定すると wrangler.toml
でそこにアクセスできるようになるっぽい。
以下のようにしてみて、開発環境で試してみるがどうにも動かない。
"build": "remix build",
"dev": "remix dev --manual -c \"npm run start\"",
"start": "wrangler pages dev --compatibility-date=2023-06-21 ./public --env development",
[env.development]
d1_databases = [
{ binding = "DB", database_name = "YOUR_PROJECT_NAME", database_id = <YOUR_DB_ID> },
]
なおった
色々いじってなんやかんやでやり方はわかった。
5時間くらいかかった。
その他
wrangler.toml
は .gitignore
に入れるべきなのか
そういやアプリケーション作成した時に.dev.vars
はgitignoreされてて、wrangler.toml
はされてなかったけど database_id
とかはシークレットな情報ではないのかな?
なんかそのうちセキュアな情報は入りそうだけど一旦トークンとかは入っていないから大丈夫?
この記事ではignoreしてるな。
今回はもうpushしちゃってるしAPIキーとかはGithubのEnvironmentsで管理してるし大丈夫、ということにして一旦進んだ。
因みに、Honoだとデフォルトでignoreされているらしい。
Staging環境へデプロイしたときのURLについて
毎回変わるけどURL固定にしたいかもな〜と少し思った。
【2024-02-18】Markdownパーサーを作りたいので調べてみよう
背景
Remixで単に管理画面を作って記事を投稿できるだけでは面白みがないので今までやったことないリッチなことをしてみたい。
ということでこのZennの様に独自の記法を使えるMarkdownパーサーを作ってみたい。
ということで一旦調べてみた。
調べる
ZennのPublic Rrepository
こういうやつを作りたい。
構文解析器
構文解析器とかの世界に足を踏み入れることになる。
このブログで作ったコードのPlaygroundを見てみると良さげな感じがする。オリジナルのも作れそう。
作った方のポートフォリオ発見。すごそう。
ブログで紹介されているのはこの方が趣味で開発したminuteというMarkdownパーサーということで、リポジトリが公開されていた。
minuteの方は21Commitしかないし全部読んでみる。
やりたいことをやっている人を発見
全部同じ方の記事で特に番号はふられていないけど以下の順で見ていくっぽい。
- 1 unified を使う前準備
- 基礎知識解説(ASTとかparserとか)
- 2 unified におけるプラグインまとめ
- テキストと構文木やASTを変換するためのJavaScript 製フレームワークであるunifiedの使い方解説
- 3 unified を使って Markdown を拡張する
- 実際にZennの
:::message :::
記法を作ってみている
- 実際にZennの
- 4 unified を使ってオレオレ Markdown を ReactElement に変換する
- まとめ+α
同じくunified エコシステム周りの記事
ここでも使ってた
typescriptbookはよく参照しているけど、ここでもMarkdownパーサーを拡張している。
Repositoryは公開されているので除きにいってもみても良いかも。
感想
minuteのPlayground を見る限り、これにStyleを適用すれば自分のやりたいことできるなら21Commit全部読んでゼロから実装していくのが勉強になるし面白そうだと思った。
その一方でまだ知らない部分、実は今後必要になる機能が色々あり、そこの開発が自分ではどうにもできないレベルになってくるなら unified を導入したい。
調べてみるとunifiedも2024-02-18現在で401Commitだから読もうとすれば全部読めそうな気はする。
Next Actionはminuteのコードを読みながら構文解析器の勉強をする、になるかな。
その他
調べながらWYSIWYG(ウィジウィグ)って言葉に出会った。
What You See Is What You Get の略で「見たままを得られる」という意味らしい。