nabeo がピーしているブログ (仮)

どーも、nabeop です

(Emacs さんの) 気分によってフォントを変える

今日はこどもの日なので、童心に返って Emacs の設定を見直していた。

で、最後にフォントを変えてみようかと思って最近の等幅フォント事情をググってみたら、いくつか気になるフォントを見つけた。どれも良さそうだったので、決められないなーと思っていたら、元同僚の id:aerealArray#sample で毎日変えているという話題を思い出した。

ということで、Emacs でも同じようなことは簡単にできるなーと思ったので、こんな感じで Emacs を起動するごとにフォントを変えてみた。

(setq my/fontfamilies
      '("HackGen Console NF"
        "Moralerspace Neon HWNF"
        "Moralerspace Argon HWNF"
        "Moralerspace Xenon HWNF"
        "Moralerspace Radon HWNF"
        "Moralerspace Krypton HWNF"))
(set-face-attribute 'default nil :family (elt my/fontfamilies (- (random (length my/fontfamilies)) 1)) :height 140)

最近の emacs さんには restart-emacs コマンドで気軽に再起動することができるので、これで再起動の楽しみを1つ追加できた。

Node.js の grpc パッケージのインストール時に python で gyp が見つからなくてエラーになる時の対処

手元環境の python を 3.12 系に更新したあとに Node.js で grpc パッケージを入れようとすると

│ Traceback (most recent call last):
│   File "/Users/nabeo/.cache/node/corepack/pnpm/8.15.3/dist/node_modules/node-gyp/gyp/gyp_main.…
│     import gyp  # noqa: E402
│     ^^^^^^^^^^
│   File "/Users/nabeo/.cache/node/corepack/pnpm/8.15.3/dist/node_modules/node-gyp/gyp/pylib/gyp…
│     import gyp.input
│   File "/Users/nabeo/.cache/node/corepack/pnpm/8.15.3/dist/node_modules/node-gyp/gyp/pylib/gyp…
│     from distutils.version import StrictVersion
│ ModuleNotFoundError: No module named 'distutils'

こういうエラーで失敗してしまう。エラーメッセージでググるpython 3.12 から distutils は削除されたので、python の packaging を入れなさいという issue が nodejs/node-gyp であった。

もしくは npm_config_python 環境変数python 3.11 のパスを設定すると回避もできるらしい。とりあえずの対処としては npm_config_python 環境変数で逃げるでもよいけど、これからのことを考えるといつまでも python 3.11 に依存したくないので、python 3.12 でちゃんと使えるようにしたい。

homebrew では python の packaging は python-packaging として提供されていて、このエラーが発生時している時点でちゃんと入っていた。

% brew info python-packaging
==> python-packaging: stable 24.0 (bottled)
Core utilities for Python packages
https://packaging.pypa.io/
/opt/homebrew/Cellar/python-packaging/24.0 (53 files, 372KB) *
  Poured from bottle using the formulae.brew.sh API on 2024-03-25 at 10:36:03
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/p/python-packaging.rb
License: Apache-2.0 or BSD-2-Clause
==> Dependencies
Build: python-flit-core ✘, python@3.11 ✔, python@3.12 ✔
==> Analytics
install: 19,387 (30 days), 63,842 (90 days), 205,027 (365 days)
install-on-request: 821 (30 days), 1,497 (90 days), 3,796 (365 days)
build-error: 24 (30 days)
% brew list python-packaging
/opt/homebrew/Cellar/python-packaging/24.0/lib/python3.11/ (23 files)
/opt/homebrew/Cellar/python-packaging/24.0/lib/python3.12/ (23 files)
%

実は python の setuptools も必要というオチだったので、brew install python-setuptools で setuptools も入れて、python 3.12 の環境でも Node.js の grpc パッケージのインストールができるようになった。

git の alias の紹介、あるいは、init.defaultBranch を設定しておくと生活が豊かになる話

git の操作は基本的に Emacs から Magit を使っているけど、ちょっとした操作とかはターミナルから git コマンドを直接実行することもある。で、よく使うコマンドは git alias でいい感じにしておくとタイプ数が少なくなったり、シュッと使えて体験がよくなる。

というわけで、僕の ~/.gitconfigalias セクションにはこんな感じで設定している

[alias]
  aliases = config --get-regexp alias
  log-graph = log --graph --date=short --pretty=format:'%Cgreen%h %cd %Cblue%cn %Creset%s'
  log-all = log --graph --all --color --pretty='%x09%h %cn%x09%s %Cred%d%Creset'
  log-pr = !git log --stat --no-merges $( git merge-base origin/$( git config --get init.defaultBranch ) HEAD )...HEAD
  diff-pr = !git diff $( git merge-base origin/$( git config --get init.defaultBranch ) HEAD )...HEAD
  remotes = remote -v
  f = fetch origin --prune
  r = rebase
  s = status
  c = switch
  cd = !git switch $( git config --get init.defaultBranch )
  co = checkout
  sui = submodule update --init
  pf = push --force-with-lease --force-if-includes
  wc = whatchanged
  ls = log --stat --no-merges
  lp = log -p

git config --get init.defaultBranch というコマンドは git のデフォルトブランチを取得しているんだけど、現代ではリポジトリごとになることが普通だと思う。とくに新しく作業ブランチを作成する時にリポジトリごとに異なるデフォルトブランチを気にする必要なく、git cd しておけば良いので、事故を防ぐことができて便利に使っている。

で、肝心のデフォルトブランチの設定は GitHubリポジトリだったら、gh コマンドからリポジトリに設定されているデフォルトブランチを gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' で取得できるので、以下のような関数を .zshrc に登録している。

set-default-branch () {
        git rev-parse 2> /dev/null || return 0
        defaultBranch=$( gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' )
        [ -z ${defaultBranch} ] && return 0
        git config --local init.defaultBranch ${defaultBranch}
        echo "set init.defaultBranch : ${defaultBranch}"
}

Github Actions と blogsync を使ってはてなブログの記事を管理する

前々からこのブログを Github で管理したいなーと思っていたけど、なかなか手をつける気になっていなかった。なぜかこの連休中に機運が高まったのでえいやで Github Actions と blogsync を使った仕組みを導入した。

大筋では

  • 新しいエントリを追加する P-R を作る
  • 作業ブランチでの作業中は下書き状態にしておく
  • P-R をメインブランチにマージするときに公開する

といった運用を想定している。

特に P-R ベースでの作業フローはブログの執筆者のほかに公開前に投稿内容をチェックするような体制を想定している。

仕組み

Github Actions のワークフローは以下の3つを実装している。

  • 下書き状態で新しい記事をはてなブログに投稿するワークフロー : blogsync-post.yaml
    • blogsync post --draft を実行している
    • P-R の最初に動くことを想定している
    • blogsync post を実行した後は blogsync/created ラベルを P-R につける
  • はてなブログに投稿している記事を更新するワークフロー : blogsync-push.yaml
    • blogsync push を実行している
    • P-R 中に記事のコミットがつまれたときに
  • 下書き状態の記事を公開状態にするワークフロー : blogsync-publish.yaml
    • 記事のメタデータDraft の値を変更して blogsync push を実行している
    • P-R がマージされたときに実行される

blogsync がはてなブログAtom Pub API を使うときの認証情報は設定ファイルか環境変数で扱うことができる。リポジトリに秘密情報は含めたくないので環境変数を使うことになるんだけど、複数の執筆者が想定される環境では、Github の世界とはてなの世界でユーザのマッピングが必要になる。今回は json ファイルで Github の login 名とはてな ID (とその API Key を保存しているシークレットの名前) を定義して、ワークフロー中で取得している。ワークフロー中での取得している様子は以下のとおり。

- name: hatenaid
  id: hatena_id
  env:
    PR_AUTHOR: ${{ github.event.pull_request.user.login }}
  run: |
    echo hatena_id=$(jq --arg github_login ${PR_AUTHOR} '.[$github_login].hatena_id' map.json) | tr -d '"' >> $GITHUB_OUTPUT
    echo password_secret_name=$(jq --arg github_login ${PR_AUTHOR} '.[$github_login].password_secret_name' map.json) | tr -d '"' >> $GITHUB_OUTPUT

ひとまず、今の状態でしばらく使ってみていまいちなところとかはチマチマ直していくかという気分になっている。今のところ blogsync pull に相当するワークフローを作っていないのではてなブログの管理画面などで変更した内容を取り込むときには個別で頑張る必要があるはず。

追記

この記事を公開するための準備ではじめて使ったら P-R にラベルを付与するところで、

GraphQL: Resource not accessible by integration (addLabelsToLabelable)

というエラーが出て失敗してしまった。これは Github token のデフォルトの権限が参照しか付与されていないからだった。リポジトリの Settings から Workflow permissions が「Read repository contents and packages permissions」になっているので「Read and write permissions」に変更するか、ワークフローの定義で個別に指定すればよいはず。面倒なのでデフォルトの権限を「Read and write permissions」にしちゃったけど、本来は contents: writepull-requests: writeissues: write の権限があれば十分なはず。

ある github organization のリポジトリを手元に持ってくる時に使っているアレ

github apigh api で呼び出していい感じに

  • 手元になければ ghq get して、デフォルトブランチを設定する
  • アーカイブ済みのリポジトリは消していいかを聞いてから消す

ということをしてくれる。

#!/usr/bin/env zsh

for repo in $( gh api --paginate --jq '.[] | select( .archived != true ) | .full_name' "/orgs/${org_name}/repos" ); do
  repodir=$( ghq list -p -e "${repo}" )
  if [ "x${repodir}" == "x" ]; then
    ghq get "git@github.com:${repo}.git"
    pushd "${repodir}"
    git config --local init.defaultBranch $( gh api "/repos/${repo}" --jq '.default_branch' )
    popd
  fi
done

for repo in $( gh api --paginate --jq '.[] | select( .archived == true ) | .full_name' "/orgs/${org_name}/repos" ); do
  repodir=$( ghq list -p -e "${repo}" )
  if [ "x${repodir}" != "x" ]; then
    echo "remove ${repo}? (y/N): "; read -q && rm -rf "${repodir}"
  fi
done

${org_name} は目的の Organization を入れる。

cdktf 再入門

どうも、型にハマらない人生を歩みたいけど、コードを書く時は型が欲しい id:nabeop です。

1年くらい前に cdktf に入門したあとは changelog は追っていたけど、使う機会がなかった。 ちょうど AWS アカウント単位で検証環境を複数作ることになったので、cdktf に再入門してみた。

最初に触ったときは v0.0.18 で現時点では v0.9.0 だった。

続きを読む

AWS Certified Security - Specialty に合格しました

会社の資格取得補助を利用して、AWS Certified Security - Specialty の資格を取得できた。

一昨年は AWS Certified Solutions Architect – Associate に合格したけど、去年は AWS Certified Advanced Networking - Specialty に落ちちゃったので、今年こそは絶対に取るぞと気合を入れていたのでなんとか取得できて嬉しい。

AWS Certified Security - Specialty は AWS が認定している資格の1つで公式の説明では以下のようになっています。

この資格は、組織がクラウドイニシアチブを実装するための重要なスキルを持つ人材を特定して育成するのに役立ちます。AWS Certified Security – Specialty を取得することで、AWS クラウドにおけるデータやワークロードのセキュリティ確保に関する専門知識が認定されます。 https://aws.amazon.com/jp/certification/certified-security-specialty/?ch=sec&sec=rmg&d=1

詳しくは公式の説明を読んでもらうとわかると思うけど、要するに AWS のサービスのうちセキュリティ分野に特化した専門知識を持っているかを試される、という感じです。最近は AWS アカウント周りの整備をやっていてセキュリティ周りもスコープに入っていたので仕事でやっていることの再確認も兼ねてちょうど良い感じだった。

AWS Certified Security - Specialty の取得を考えている人の参考になるかもしれないので、資格取得のためにやった準備とかをまとめておこうと思う。

会社で資格取得補助をやっているという関係で毎年この時期に資格取得のための勉強会が立ち上がるので、その流れにのって週一回に1時間ほど同じに用に資格取得を目指す同僚とオンラインで黙々と勉強をしていました。このエントリも勉強会の時間に書いています。

すでに AWS については3年程の実務経験があって、直近では AWS アカウントのセキュリティやガバナンス強化の設計をしていたので、ある程度の専門知識はありそう(むしろ無いと困る)という感じだったので、初手で模試を受けてみました。Solutions Architect の Associate に合格していたので、クーポンが使えるのでお得だったんだけど、僕がうけた模試は結果がわかるけど、具体的にどの問題が不正解だったのかがわからないタイプだった。一緒に勉強会に参加していた id:wtatsuru さんは AWS Skill Builder の模試を受けていて、こっちは解答と解説がでていたそうなので、失敗したなーと思っています。

wtatsuru.hatenadiary.com

最初に受けた模試の結果では総合スコアが 75% で合格ラインには達していそうだったけど、スコアが低い分野があったので、スコアが低かった分野を中心に勉強をするという方針を立てた。

勉強の教材は AWS Certified Security - Specialty に特化した参考書が会社に転がっていたので、一通り目を通してみて、スコアが低かった分野は Blackbelt で知識を保管するという作戦です。

会社に転がっていた参考書はこれ

試験はリモートでの試験も選択可能だったけど、会社の近くに試験会場があったし、リモート受験して苦労している同僚もみていたので、試験会場で直接受けた。試験の内容は模試と同じような雰囲気だったのでどこかの時点で模試は受けておいた方が良いと思う。あと、AWS におけるセキュリティといえば IAM や KMS 、GuardDuty や Security Hub とかが思い浮かぶけど、試験ではそのようなセキュリティサービスに加えて、CloudFront などのサービスでセキュリティを担保するため構成が問われるような問題も出ていた。

来年も勉強会は開催されると思うので、次回は DevOps Engineer Professional か Solutions Architect - Professional あたりに挑戦するかと思っている。