oinume journal

Scratchpad of what I learned

ghコマンドでよく使ってるヤツ

このポストがなぜかやたらバズっていたので、調子に乗って自分がよく使っているghコマンドのサブコマンドを書いてみる。

gh pr view -w

Usage

gh pr view [<number> | <url> | <branch>] [flags]

該当のpull requestをブラウザで開くために使っている。自分は何かとブラウザ上で作業することが多いのでかなり多用してる。

  • -w を省略するとターミナル上でPRの内容が表示される。
  • 引数の<number>などを省略するとカレントブランチのpull requestになる

gh pr checks --watch

Usage

 gh pr checks [<number> | <url> | <branch>] [flags]

カレントブランチのpull requestのchecks(CI)の状況を確認するのに使ってる。

  • gh pr checks --watch -i 3 のように-iでリフレッシュする間隔を秒数で指定できる。デフォルトは10秒
  • gh pr checks --json=name,state のように指定すると以下のようにJSON形式で出力できる
[
  {
    "name": "triage",
    "state": "SUCCESS"
  },
  {
    "name": "lint",
    "state": "SUCCESS"
  },
  {
    "name": "test",
    "state": "SUCCESS"
  }
]

gh pr checkout

Usage

gh pr checkout [<number> | <url> | <branch>] [flags]

主に他の人のpull requestのコードを自分のPC上でcheckoutしたい時に使う。

gh pr create

Usage

gh pr create [flags]

カレントブランチにコミットがある場合、gh pr create -w を実行するとコミットをpushしてpull request をopenする画面をブラウザで開いてくれる。(コメントで教えてもらってから重宝してます)

fzf との組み合わせ

fzfと組み合わせて以下のようなfunctionを定義している。

# fghpr - list pull requests with search query, then open selected pull-request with browser
# Use like `fghpr -A '@me' -s closed`
fghpr() {
    gh pr list "$@" --json number,title -q '.[] | "\(.number) \(.title)"' \
    | fzf --delimiter=' ' --with-nth=2.. \
    | awk '{print $1}' \
    | xargs -I {} gh pr view -w {}
}

例えば fghpr -A '@me' -s closed で自分が過去にマージ or クローズしたPRをターミナル上に一覧表示して、Fuzzy検索しつつ選択したものをブラウザで開くことができる。

Claude Code

あとはClaude Codeと共に使うと色々便利らしいです。

複数のプロダクトのリポジトリをMonorepoに移行する

表題の通り、技術スタックがほぼ同じプロダクト群のリポジトリを1つのMonorepoにまとめてみたという雑な記録。

元々は以下のようなPolyrepo構造になっていた。

  • product-a (repository)
    • backend
    • web
  • product-b (repository)
    • backend
    • native
    • web

これを以下のような構成に移行した。

  • products (repository)
    • apps
      • product-a
        • backend
        • web
      • product-b
        • backend
        • native
        • web

大まかには以下のような流れで移行する。

  1. 移行元のリポジトリで移行用ブランチを作成する
  2. 移行先のリポジトリで移行用ブランチを作成し、1.の移行用ブランチをmergeする

では実際に移行してみよう。product-aのリポジトリで以下のコマンドを実行する。

mkdir -p apps/product-a
git checkout -b monorepo
git mv -k * apps/product-a/  # -k is used to ignore the error that it can't move the projects directory
git mv -k .* apps/product-a/  # .* to move .gitignore and other dot files

次に移行先のproductsリポジトリで以下のコマンドを実行する。

git remote add -f product-a https://github.com/<owner>/product-a.git
git checkout -b import-product-a
git merge product-a/monorepo --allow-unrelated-histories

これで products リポジトリの import-product-aというブランチにproduct-aリポジトリのファイルが追加されているので、pull-requestを作るなどしてこのブランチをmainブランチにマージすればOK

# on main branch
git merge import-product-a

これを移行したいプロダクトの数だけ繰り返せばOKである。なお、.github/workflows などリポジトリ直下にないといけないディレクトリはMonorepoに取り込んだ後に手動でファイルを移動する必要があるので気をつけること。

というわけで私はこれで素敵なMonorepo lifeを送れるようになりました。おしまい。

RaycastのScript Commandsを試してみた

RaycastにはScript Commandsという機能があり、ずっとずっと気になっていたのでGW中に重い腰を上げて試してみた。最近会社の人にRaycastをオススメすることが多くなってきたのだけれども、「Raycast歴1年以上経つのにScript Commandsも使ったことないの?」みたいに後ろ指差されないようにするためにも...

Script Commandsとは?

簡単にいうとCUIのコマンドをRaycastから呼び出せるというただそれだけのものっぽい。「っぽい」というのは単純に自分がちゃんと調べてないだけです。はいテキトーですいません。

なにを作るか?

Hello Worldを出力するだけのScript Commandsを作っても仕方がないので、よく自分でやっている単純作業を自動化するスクリプトを考えてみた。結果として生まれたのは、以下のような beforeの文字列をafterに整形するだけのスクリプトである。なんでこんなものが必要かというと、スプレッドシートからIDなどのリストをコピーしてSQLのWHERE句のINに指定する、ということをよくやっているから。

before

aaa
bbb
ccc

after

'aaa',
'bbb',
'ccc',

Script Commandsの登録方法

めちゃくちゃ簡単なのでこのページを見てもらうのが良いと思う。テキストで手順を書くと以下の4ステップしかない。

  1. Raycastを起動する
  2. Create Script Commandと入力する
  3. 必要な情報を入力する
  4. スクリプトにコマンドを記述する

ちなみに上で書いたScript Commandのスクリプトは以下のような感じである。

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title single-quote-with-trailing-comma
# @raycast.mode fullOutput

# Optional parameters:
# @raycast.icon 🤖
# @raycast.needsConfirmation true

# Documentation:
# @raycast.description single-quote-with-trailing-comma
# @raycast.author oinume
# @raycast.authorURL https://github.com/oinume

pbpaste | perl -pe "s/.*/'\$&',/"

作成したScript Commandを呼び出す

あとはRaycastから作成したsingle-quote-with-trailing-commaを呼び出すだけである。以下の動画ではsingle-quote-with-trailing-commaによって生成された出力をクリップボードにコピーしている。

最後に一言

というわけで駆け足でScript Commandsについて説明した。Apple Scriptを使って特定のSlack Channelを開くということもできるらしいので夢は広がりそうである。Raycast、本当によくできていてこれがあるおかげでmacOSから離れられない。次はExtensionの作成にチャレンジしてみたい。

GraphQL Codegenで自動生成されたファイルでNamed export 'gql' not foundのビルドエラーを回避する

Vite + Apollo Client + GraphQL Codegenの組み合わせでgraphql-codegenを実行すると、gql関数を以下のようにimportするためにエラーが出る。

import { gql } from '@apollo/client';
[vite] Named export 'gql' not found. The requested module '@apollo/client' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@apollo/client';
const {gql} = pkg;

解決方法としては graphql-codegenの設定ファイルにgqlImportの設定を追加して再度コード生成する。

const config: CodegenConfig = {
  ...
  generates: {
  ...
    ".": {
      config: {
        gqlImport: "@apollo/client/core#gql",
      },
    },
  },

そうすると import { gql } from '@apollo/client/core'; が生成されるのでビルドエラーが回避できた 🎉

PostgreSQL + HasuraでUUID v7を生成できるようにする

2024年にRFC 9562としてUUID v7が標準化された。今までは主キーにUUID v4を使っていたけど、時間軸でソートできるUUID v7を使いたいと思ったのでメモ。

簡単に書くとPostgreSQLでUUID v7形式のUUIDを生成するには以下を行えば実現できる。

  • PostgreSQLにはUUID型が標準装備されているのでこれを使用する
  • postgres-uuid-generate-v7にあるUUID v7を生成するFUNCTIONを定義する
  • カラムを "id" uuid NOT NULL DEFAULT uuid_generate_v7() のように定義する

上記を踏まえてHasura consoleでUUID v7のFUNCTIONを定義して使えるようにするには、

  1. consoleからであればDATAタブのSQLを選択
  2. エディター部分にpostgres-uuid-generate-v7リポジトリのuuid_generate_v7.sqlの中身をそのままコピペ
  3. This is a migration にチェックを入れてMigration nameに適当な名前をつける

をやれば良い(以下スクショ参照)