ブログをGitHub Actionsを使ったビルドに切り替えたときの手順

このブログはまだCI/CDも分からない頃に始めたのもあって、GitHub Actionsを使っていないビルドをしていた。いちいちビルドしてリポジトリにpushするのも面倒だし、Chanomic Sketchを昨年開設したときにGitHub Actionによるビルドを学んだので、重い腰を上げて切り替えようと思った。そのときのメモ。 色々調べていたら、Chanomic Sketchで上げたときとは違って、gh-pagesのようなブランチを作らなくても良い方法が作られていたので、その方法でやっていく。 基本的な手順はHugoの公式に書かれているが、一応現時点でのやり方をメモっておく。 (参考)現状のデプロイ方法と今後のデプロイ方法の比較 現状は、 hugo new posts/.../index.mdで記事を作成 記事を書いてhugo serverで確認 書き終わったらindex.mdのdraft: tureを外してcommit hugoコマンドを単体で実行してページのビルドをする → docs/下にHTMLが展開されるので、それをcommit pushする と手順を踏んでいたが、今回の変更によって、 hugo new posts/.../index.mdで記事を作成 記事を書いてhugo serverで確認 書き終わったらindex.mdのdraft: tureを外してcommit pushする と手順が1個減る。また、docs/ディレクトリがなくなるためコミットログがすっきりすることも期待される。 ブログの修正 まず、config.tomlのpublishDirにてdocs/下にHTMLを展開するようにしてあったが、この記述はいらないので消す。 1 publishDir="docs" また、docs/ディレクトリは git rm -rfで消す。 GitHub Pagesの設定 Pagesの設定に移動して、Build and deploymentの項目のSourceを、「Deploy from a branch」から「GitHub Actions」に変更。 workflowの記述 次に、.github/workflows/<適当な名前>.yaml を作成し、そこに以下の記述をする。 注)これは現時点でのHugoの公式をそのまま借りてきている。最新版は公式を参照すること。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 name: Deploy Hugo site to Pages on: push: branches: - master workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false defaults: run: shell: bash jobs: build: runs-on: ubuntu-latest env: HUGO_VERSION: 0....

2024-01-14 · (updated 2024-01-14) · 2 min · 297 words

NixOSをWSL2上で構築したときのメモ

年末からお正月の間帰省したときにWindowsのラップトップを持っていった。しかしWSL2にはUbuntuしか入っておらず、最近デスクトップで使っているNixOSが入っていなかった。そこで試しに構築してみたときのメモ。最低限コーディングができる環境が整った。 (IT系あるあるだけれど)NixOS-WSLの開発はまあまあ早いため、ここに書いてある内容もすぐ陳腐化してしまいそう。 インストール RepositoryのReleasesからnixos-wsl.tar.gzをDLしてくる コマンドプロンプト or PowerShell で以下のコマンドを実行 1 2 3 wsl --import NixOS .\NixOS\ nixos-wsl.tar.gz --version 2 wsl -d NixOS nix-channel --update Flake化による初回セットアップ 今回はなるべくnix-channelを使わず、flake.nixからなるべく必要なファイルを入れるようにしたい。そのほうが、今後再セットアップするときにそのflakeファイルを指定するだけで環境が構築できることを期待しているため。 とはいえ、現状のNixOSにはVimもGitも入っておらず限界があるので、それはChannelから入手する。まず現時点での最新版のnixosのChannelを登録する。 1 2 sudo nix-channel --add https://nixos.org/channels/nixos-23.11 nixos sudo nix-channel --update 次にVimとGitを入れる。Vimはテキスト編集のため、Gitはnix-flakeの動作のために必要。 1 nix-shell -p vim git NixOSで最強のLinuxデスクトップを作ろうやUsing nix flakes with NixOSに書かれている内容を参考に進めていく。 まずホームディレクトリに移動し、適当なディレクトリnixos-configを作り、そこにNixOSの設定ファイル(configuration.nix)を持ってくる。 1 2 3 4 cd ~ mkdir nixos-config cd nixos-config cp /etc/nixos/* . flake.nixを作成し以下のようにする。 inputsにnixosのリポジトリと、NixOS-WSLのリポジトリを指定する inputsの書き方はattribute setとurl-likeな書き方の2種類がある。url-likeな書き方だとtag指定の方法がわからなかったので、NixOS-WSLのinputに関してはattribute setで書いている nixosSystemの引数としてspecialArgsが指定でき、これでconfiguration.nixに引数を渡せる 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { inputs = { nixos....

2024-01-13 · (updated 2024-01-14) · 3 min · 610 words

FastAPIとOAuth2でユーザログイン機能(備忘録)

何をするか 以下の3つの機能を実装する。 ユーザを作成する。 ユーザを認証してトークンを生成し返す。 ユーザがログインしていないと401を返す:ここでは「ユーザ情報を返すAPI」を作成。 ユーザがログインしているかどうかで異なるレスポンスを返す:ここでは「ログインしているかどうかを真偽値で返すAPI」を作成。 方針 使う技術・フレームワーク、ライブラリなど PythonとMySQLはDocker Composeで動かす。 PythonのパッケージはPoetryで管理する。 APIサーバーはFastAPI + uvicornで動かす。 認可の方式としてOAuth2.0を用いる。認可グラントのタイプはシンプルなROPC。 なぜこれを選んだのかというと、単純にFastAPIのドキュメントに書かれていたのがこれだったため。いつかほかのタイプも実装してみたい。 DBのマイグレーションはalbemicを使用してみる。今回はユーザ情報しか作らないので、alembicの使用は間違いなくオーバーなのだが、勉強のため使ってみる。 プロジェクト構成 プロジェクトディレクトリは次のようにする。 DBに関するCRUDs処理はcrudsモジュールに書く。 DBと対応するモデルはmodelモジュールに書く。 APIのリクエストボディ、レスポンスボディの形式はschemas.pyに書く。 DBのセッションの作成はdb.pyに書く。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 . ├── api │ ├── cruds │ │ ├── __init__.py │ │ └── user.py │ ├── models │ │ ├── __init__.py │ │ └── user.py │ ├── routers │ │ ├── __init__....

2023-06-29 · (updated 2023-06-30) · 7 min · 1388 words

Alembicを使ったDBマイグレーション(備忘録)

経緯 Alembicというライブラリを知ったので、試しに触ってみたメモ。 そもそもAlembicとは Alembicとは、DBマイグレーションライブラリの1つ。SQLAlchemyと一緒に用いる。 今回やってみること 今回行うマイグレーションは、以下の3つ。 空 User(email, password)を作成 User(email, password, name)に変更 使い方 Alembicの初期化 使うDBとの紐づけ エンティティ作成 マイグレーションファイルを作成 マイグレーション 想定する状況と準備 FastAPI上でWeb APIを提供し、その中でDBを操作することを想定する。ただし、メインテーマがマイグレーションのため、この記事でFastAPIの話は一切出ない。プロジェクト作成について、詳しくはFastAPI入門を参照するとよい。この記事では、ディレクトリ構成を大きく参考にしている。 パッケージ管理にはpoetryを使う。 DBにはMySQLを使う。 マイグレーションは同期処理で行うため、入れるのはPyMySQLだけでよい。しかしFastAPIでDBを処理するときに非同期での操作を行うことを見越し、aiomysqlを入れる。この時点でPyMySQLも入る。 1 poetry add sqlalchemy alembic aiomysql alembicの初期化 次のコマンドを実行する。 1 poetry run alembic init alembic プロジェクト配下にalembic/というディレクトリが生成される。 使うDBとの紐づけ alembic.iniを編集する。sqlalchemy.urlの記述を見つけたら以下のようにする。 1 sqlalchemy.url = mysql+pymysql://<url>/<name>?charset=utf8 <url>と<name>にはそれぞれ、mysqlのサーバーのURLとそのDBの名前を指定する。例えばmysqlがdbというDocker Composeのサービスとして稼働しており、3306ポートで受け付けており、そのDBの名前がappdbだった場合、次のようになる。 1 sqlalchemy.url = mysql+pymysql://root@db:3306/appdb?charset=utf8 api/db.pyにDBエンティティのベースを作っておく。 1 2 3 from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() alembic/env.pyのtarget_metadataを以下のようにする。 1 2 3 from api.db import Base target_metadata = Base....

2023-06-20 · (updated 2023-06-25) · 3 min · 588 words

ReactとD3.jsを使ったWordCloudの作成(備忘録)

注意 筆者はReact歴1週間なので、筋の良い書き方でなかったり、間違った書き方であったりするかもしれない。 前半は車輪の再発明をしてしまっている。書いている途中にreact-d3-cloudライブラリの存在に気づいたので、記事の最後にサンプルコードを記載している。 プロジェクト準備 このあたりは人によりけりだが、ここでは次のようにする。 Reactのビルド環境はDockerないしDocker Composeで構築。 Reactのプロジェクトはcreate-react-appで構築。 それではまずDocker・Docker Composeの構築から。 プロジェクトディレクトリを適当に作成し、そこにdocker-compose.yamlを書く。 1 2 3 4 5 6 7 8 9 10 version: "3.0" services: app: image: node:20-slim volumes: - ./app:/src ports: - 3000:3000 command: npm start working_dir: /src 続いて次のコマンドを実行してcreate-react-appを導入し、実行する。 1 $ docker-compose run --rm app sh -c "npm install -g create-react-app && create-react-app ." これによりappディレクトリが作成され、中にReactのプロジェクトが生成される。 このタイミングでD3.jsとd3-cloudも入れておく。 1 docker-compose run --rm app npm install d3 d3-cloud これでサーバーを起動してみると、localhost:3000にアクセスできることがわかるだろう。 1 $ docker-compouse up ちなみに現状ではapp下のディレクトリがコンテナ内のrootで作成されたため、権限の問題で中のソースコードを編集できない。 VSCodeとかだとRemote Containerという拡張を入れることで解決できるらしいが、Vimユーザの自分にとっての正しい解決策はまだ未調査。 今回は、その場しのぎでsudo chownを使うことで、権限を変更しておく。...

2023-06-11 · (updated 2023-06-11) · 4 min · 777 words

ニューラルネットワーク ノート - 誤差逆伝播の計算

誤差逆伝播法の数式の説明なんて世の中にたくさんあると思うが、理解のために自分でもまとめる。 特に添字などのミスがあると思うので、見つけ次第修正する。 誤差逆伝播の計算 (1) 問題設定 入力を第 $0$ 層、出力を第 $L$ 層とする。ニューラルネットワークはよく次のようなグラフで描かれる。 円がノードを表す。ノードに入っていく矢印が入力、出ていく矢印が出力を表す。 第 $l$ 層 $j$ 番目のノードの出力を $y_j^l$ とおく (注意: この記事では $y_j^{l}$ の $l$ は添字を表すものとする。累乗ではない。これから現れる変数についても同様)。これはある関数 $f_l$ を用いて以下の式で表される。$f_l$ は活性化関数と呼ばれる。 ただし、$u_j^{l}$ は前の層の出力を用いて計算される線形和で、以下のように定義される。 このような、線形和を取って $f$ を適用するという流れは次のようなグラフで描かれる。 この $\sum | f$ のノードがたくさん集まって第 $l$ 層を形成している。 損失関数 $E$ は、重み$w_{ij}^{l}$ についての関数である。これは出力値 $y_i^{L}$ と教師データ $\tilde{y}_i$ との違いを測る尺度であるから、$y_i^{L}$ の関数でもある。 例えば、以下の二乗誤差は損失関数の一種である。 定義中に $w_{ij}^{l}$ が含まれていないじゃないか、と思うかもしれないが、$y_i^{L}$ の定義中に $w_{ij}^{L}$ が含まれている。さらにその中の $y_i^{L-1}$ 中に $w_{ij}^{L-1}$ が含まれている。以下同様にして $w_{ij}^l$ は $E$ の中に含まれている。 いま、$E$ を最小化するような $w_{ij}^{l}$ を求めたい。これには確率的勾配法が利用できるが、そのために偏微分 $\displaystyle \frac{\partial E}{\partial w_{ij}^{l}}$ を計算する必要がある。以降、これをどう計算するかという話を展開していく。...

2022-01-15 · (updated 2022-11-24) · 3 min · 516 words

PureScriptでパーサーコンビネータを触る (2) テキストファイル

前回の記事 と合わせて1つの記事にする予定だったが、前回があまりに長くなってしまったので分割した。 ある書式に従ったテキストファイルをパースすることを考える。パースしたデータを整形し、HTML文書として出力するところまでやる。 前回インポートした関数で今回使うものは、(漏れが無ければ)以下の通り。 1 2 3 4 import Control.Alt ((<|>)) import Control.Lazy (defer) import Text.Parsing.Parser (Parser, fail) import Text.Parsing.Parser.String (char) テキストの仕様 テキストファイルは、複数のentryで構成される。 1つのentryはタイトルtitleと中身bodyで構成される。 titleは[と]でくくられる。 titleとbodyの間、bodyと次のentryのtitleの間には、1つの改行と、0個以上の空行があり得る。それらはbodyには含まない。 空行とは、0個以上のスペースだけから構成される行のことである。 BNF風に書くと次のようになるだろう。 1 2 3 4 5 6 <entries> = (0個以上の<entry>) <entry> = <title> "\n" <empty lines> <body> "\n" <empty lines> <title> = "[" (文字列) "]" <body> = (先頭、末尾が<empty lines>でないような文字列) <empty lines> = (0個以上の<empty line>) <empty line> = (0個以上のスペース) "\n" 例えば、以下のファイルがあったとする。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [Title1] line1 line2 line3 line4 [Title2] line1 line2 [Title3] line1 line2 line3 これは次のようにパースされる。...

2021-12-31 · (updated 2021-12-31) · 9 min · 1750 words

PureScriptでパーサーコンビネータを触る (1) 四則演算のパース

PureScriptのパーサーコンビネータにpurescript-parsingがある。これはHaskellのParsecが基になっているので、使い方はParsecとほとんど同じだと思われる(とはいえ、Parsecを使ったことはあまりない)。これを用いて四則演算のパーサーを実装してみたが、うまく動かず詰まる点がいくつかあった。その備忘録。 パーサーコンビネータの準備 % spago install parsing 後々使うので以下のパッケージもインストール。 % spago install either integers maybe strings arrays lists src/Main.pursに以下の記述を追加。 1 2 3 4 import Text.Parsing.Parser (Parser) parser :: Parser String String parser = pure "Hello" REPLを起動して、動くか確認する。どんな文字列を食わせても"Hello"としか結果を返さないパーサーの完成。 > import Main > import Text.Parsing.Parser (runParser) > runParser "hoge" parser (Right "Hello") REPLでMain.pursをリロードする場合は:rをREPLで実行する。 数字のパース 1文字取得 1文字の数字を読み取りたいなら、Text.Parsing.Parser.Tokenにdigitがあるのでそれを使う。 1 2 3 4 5 import Text.Parsing.Parser.Token (digit) parser :: Parser String Char parser = digit > runParser "12345" parser (Right '1') 1文字以上取得 1文字以上を取得したいなら、Data....

2021-12-30 · (updated 2021-12-30) · 11 min · 2146 words

モンテカルロ法による積分

今年の7月くらいに書き始め、存在をすっかり忘れていた記事をUP。 モンテカルロ法でどうやって積分計算をするのか、重点サンプリングとはどのようなものなのかついて勉強したので、そのメモ。 一般論 $$ \begin{aligned} \int_{\Omega_0} f(x) dx &= \int_{\Omega_0} \frac{f(x)}{p(x)}p(x)dx\\ &= \mathbb{E}\left[\frac{f(x)}{p(x)}\right] \end{aligned} $$ ここで、$p$ は確率密度関数。上の $\mathbb{E}$ が期待値であるためには、 $$ \int_{\Omega_0} p(x) dx = 1 $$ である必要がある。 大数の法則より、確率分布 $p$ に従う 標本 $x_n\ (n = 1, 2, \ldots, N)$ に対して、$N$ が十分大きければ、 $$ \mathbb{E}\left[\frac{f(x)}{p(x)}\right] \simeq \frac{1}{N} \sum_{n=1}^{N} \frac{f(x_n)}{p(x_n)} $$ となるから、結局、 $$ \begin{aligned} \int_{\Omega} f(x) dx \simeq \frac{1}{N} \sum_{n=1}^{N} \frac{f(x_n)}{p(x_n)} \end{aligned} $$ と近似できる。 ちなみに、$p(x_n) = 0$ なる $x_n$ が選ばれることは絶対に無い(確率0だから)。よって分母が0になることを心配する必要はない。 定義域を広げる $p$ の定義域をもう少し広げられる。$\Omega \supset \Omega_0$ であれば、集合$A$に関する指示関数を $\bm{1}_A$ と書くことにして、...

2021-12-28 · (updated 2021-12-28) · 2 min · 409 words

Neovimのプラグインを初めて作る - REPLの操作

動機 研究で使っているソフトウェアのREPLが少し使いづらい。というのも、制御文字がそのまま表示されてしまうため、十字キーのカーソル移動やCmd + Aの行先頭移動、Cmd + Kの行削除など効かないからだ。 rlwrap を使えばこの問題を解決できるのだが、別の解決案としてNeovimのREPL支援プラグインを作ってみようと思い立った。 Neovim のターミナル機能を使ってREPLを起動し、別バッファー上で入力した文字列をREPLに送るようなプラグインを作りたい。 GitHubで検索してみると同様の機能を実現するプラグインはいくつもあるようだが(例えば、vim-slime)、プラグインを作る勉強として、自分で作ってみる。 提供する機能 使用感をvlimeと似たものにしたい。キーマップは次のようにする。 <LocalLeader>ss カーソル下の行をREPLに送る。 <LocalLeader>s 選択範囲内行の文字列をREPLに送る。 <LocalLeader>i 1行入力用のバッファを表示し、そこで書いた文字列をREPLに送る。 <LocalLeader>cd Ctrl + DをREPLに送る。 <LocalLeader>cc Ctrl + CをREPLに送る。 その他、以下のコマンドを定義する。 ReplOpen [cmd]: REPLを起動する。例えばReplOpen pythonならpythonのREPLが起動する。 [cmd]には任意のコマンドが入れられるため、REPL支援というよりターミナル支援プラグインという感じがするが、気にしないことにする。 ReplSend [string]: 文字列[string]をREPLに送る。 補足 vlimeとキーマップが被るため、vlimeを入れている人はどうするんだという事になる。 その場合、キーマップが被らないようにしたり、ftplugin下にスクリプトを書くなど色々と方法が考えられる。 ここでは一番無難そうな、「ReplOpenが呼び出された時にキーマップを登録する」という方法を採用する。 注意 普段使っているのがVimではなくNeovimなので、Neovimを使ってプラグインを書く。Vimには無い関数/機能を使うので注意。 あとVim scriptをほとんど書いたこと無いため、今回載せるコードには色々改善点があるだろう。 準備 適切なディレクトリにプラグインのディレクトリを作成。自分の環境では、packpathの1つに~/.config/nvimがあったので、 ~/.config/nvim/pack/plugins/start/に置く。プラグインのディレクトリは愚直にrepl.nvimとする そこにautoload、plugin、ftpluginディレクトリを作成する。 1 2 3 4 5 6 7 8 9 repl.nvim | +-- autoload/ | | | +-- repl.vim | +-- plugin/ | +-- repl....

2021-12-25 · (updated 2022-01-01) · 4 min · 655 words