VPN完全に理解したテンションで書くメモ
VPNとは
テック系のYoutuberの広告案件でよく見るSurfsharkとかが提供しているサービスで使われている仕組みです。 主な用途としては以下のようなものがあります
- 通信を暗号化してフリーWifiなどの安全性が担保されていないものからでも安全にインターネットに接続する
- サービスへのアクセス元をわかりにくくする
- 会社などのローカルネットワークに外部から安全にアクセスする
VPNを使った通信のイメージ
- 自分の端末からアクセスしたいURLを指定する
- VPNクライアントがそのアクセスしたいURLや送信内容を暗号化する
- VPNクライアントが暗号化した内容を、VPNサーバーのIPアドレス宛のパケットとして包み直し、物理NIC経由で送信する
- パケットが公共Wi-Fiなどのネットワークを経由してVPNサーバーに届く
- VPNサーバー上で暗号化された内容を復号する
- VPNサーバーからもともとアクセスしたかったURLへリクエストを送る
- VPNサーバーが対象のサービスからレスポンスを受け取り内容を暗号化する
- 暗号化した内容をレスポンスとして返す
- もともとリクエストを送った通信網を経由して自分の端末がレスポンスを受け取る
- VPNクライアントが暗号化されたレスポンスを復号して、自分の端末で内容を見る
自宅にVPNサーバーを設置したときのイメージ

図に出てくる物理NICや仮想NICについて
ネットワークと接続するためにはNICという物理機器が必要となります。 物理NICは、PCやスマホに実際に搭載されているWi-Fiチップやイーサネットポートのことで、仮想NICは、ソフトウェアで作られた「存在しないけどOSからは本物に見えるネットワークカード」です。 VPNクライアントが仮想NICを作って通信を暗号化したうえで物理NICに通信を流してくれることによって、安全な通信が行えるようになります。
自宅でVPN構築をするイメージ
※VPNを作成したわけではないので作り方はこの記事では記載しません。
自宅でVPNを構築するためには以下のようなものが必要となります。
- インターネットプロバイダーとの契約
- 自分で設定をいじれるルーター
- VPNサーバー用に常時起動できるPC
- VPNサーバー用のソフトウェア
- VPNクライアント用のソフトウェア
実際にVPNを作成するためには以下のような対応が必要となります。
- VPNサーバー用に常時起動できるPCに固定IPを設定します
- 自宅のグローバルIPに特定のプロトコルかつ特定のポートでリクエストが来たときにルーターから対象のPCへ通信をつなげるためのポートフォワーディングを設定する
- VPNサーバー用に常時起動できるPCへVPNサーバー用のソフトウェアをインストールし、公開鍵ペアの生成と、接続を許可するクライアントの公開鍵の登録を行います
- VPNクライアント用のソフトウェアをスマホなどに導入します
- VPNクライアントを導入した端末からリクエストを送ります
おわり
VPNの仕組みについて完全に理解したので自分用にまとめておきました。
Rails 8 のパスワードリセットトークンの仕組みメモ
Rails 8 では、パスワードリセットなどの機能で使うトークンは、専用のカラムに保存されるのではなく、動的に生成・検証される仕組みが採用されています。具体的には、ActiveModel の has_secure_password と ActiveRecord の TokenFor 機能を利用して、トークン生成時に署名付きの文字列として生成されます。
トークンの生成とペイロード
Rails8では下記のコードを実行するとパスワードリセット用の値がセットされます。
token = user.password_reset_token
しかし、テーブルにはパスワードリセット時に使用するトークンを保存するカラムは存在しません
ActiveRecord::Schema[8.0].define(version: 2025_04_05_082450) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" create_table "sessions", force: :cascade do |t| t.bigint "user_id", null: false t.string "ip_address" t.string "user_agent" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["user_id"], name: "index_sessions_on_user_id" end create_table "users", force: :cascade do |t| t.string "email_address", null: false t.string "password_digest", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["email_address"], name: "index_users_on_email_address", unique: true end add_foreign_key "sessions", "users" end
これはhas_secure_password の実装で、パスワードのリセットトークンをユーザーのsaltの一部を使って生成しているためDBに保存しなくても一意の値として扱うことが出来、ユーザーの認証に使えるためです。
例えば、以下のようなコードがモデルに含まれているとします。
# app/models/user.rb class User < ApplicationRecord has_secure_password end
内部では、パスワードリセットのために以下のコードが実行されます。
if reset_token && respond_to?(:generates_token_for) generates_token_for :"#{attribute}_reset", expires_in: 15.minutes do public_send(:"#{attribute}_salt")&.last(10) end class_eval <<-RUBY, __FILE__, __LINE__ + 1 silence_redefinition_of_method :find_by_#{attribute}_reset_token def self.find_by_#{attribute}_reset_token(token) find_by_token_for(:#{attribute}_reset, token) end silence_redefinition_of_method :find_by_#{attribute}_reset_token! def self.find_by_#{attribute}_reset_token!(token) find_by_token_for!(:#{attribute}_reset, token) end RUBY end
このコードでは、generates_token_for によってトークンの「目的(purpose)」が :"password_reset" として定義され、
ブロック内の処理
public_send(:"#{attribute}_salt")&.last(10)
が、トークン生成時に評価されます。
つまり、トークンのペイロードは以下のように構成されます。
def payload_for(model) block ? [model.id, model.instance_eval(&block).as_json] : [model.id] end
ここで、User モデルのインスタンスに対して payload_for を呼び出すと、たとえば [1, "Rskh7hOSW."] のような配列となります。
この配列には、モデルの ID と、ブロック内で評価された(例:パスワードソルトの最後10文字)値が含まれます。
myapp(dev)> user.class.token_definitions.fetch(:password_reset) => #<struct ActiveRecord::TokenFor::TokenDefinition defining_class=User(id: integer, email_address: string, password_digest: string, created_at: datetime, updated_at: datetime), purpose=:password_reset, expires_in=15 minutes, block=#<Proc:0x00007faffcad69d0 /usr/local/bundle/gems/activemodel-8.0.2/lib/active_model/secure_password.rb:163>> myapp(dev)> struct.payload_for(user) => [1, "Rskh7hOSW."] myapp(dev)> user.password_salt&.last(10) => "Rskh7hOSW."
password_saltはpassword_digestに含まれており3つ目の$から22文字がソルト、それ以降がパスワードのハッシュ値になっています。$2a$はbcryptのバージョン、12はコストらしいです。
myapp(dev)> user.password_digest => "$2a$12$l7RnzuO88dMKRskh7hOSW.m8d0tcoajdLnCIbB2n/GBvIOHMwRyu." myapp(dev)> user.password_salt => "$2a$12$l7RnzuO88dMKRskh7hOSW."
トークンはカラムに保存されない
重要な点は、生成されたトークンは ActiveSupport の MessageVerifier を利用して、ペイロードと有効期限情報(例えば expires_in: 15.minutes で渡される情報)を元に署名された文字列となることです。
def generate_token(model) message_verifier.generate(payload_for(model), expires_in: expires_in, purpose: full_purpose) end
この処理により、トークン自体に以下の情報が埋め込まれます。
モデルの ID
追加のブロック評価結果(ここではパスワードソルトの一部)
有効期限(生成時の現在時刻から15分後の絶対時刻)
目的情報(
defining_class.name、purpose、expires_inを連結した文字列)
トークンは、署名(HMAC によるダイジェスト)とペイロード部分を Base64 エンコードした文字列として返され、例としては以下のような形になります。
eyJfcmFpbHMiOnsiZGF0YSI6WzEsIlJza2g3aE9TVy4iXSwiZXhwIjoiMjAyNS0wNC0wNVQxMDoyMzowOC42MjRaIiwicHVyIjoiVXNlclxucGFzc3dvcmRfcmVzZXRcbjkwMCJ9fQ==--76d7cbf8d76d1bbdb4596475e4a5285cce65e86f
このトークンは、サーバー側で再度検証する際に、内部に埋め込まれたペイロードと署名情報を用いて改ざんチェックや有効期限の判定が行われます。
つまり、データベースに password_reset_token のようなカラムが存在しなくても、トークン自体に必要な情報が含まれているため、ユーザー認証が可能となります。
有効期限の計算の仕組み
有効期限は expires_in オプションで指定されますが、実際の計算は ActiveSupport の MessageVerifier 内部で行われています。
具体的には、シリアライズ処理でメタデータとして埋め込む際に、pick_expiry メソッドが使用されます。
def pick_expiry(expires_at, expires_in) expiry = if expires_at expires_at.utc elsif expires_in Time.now.utc.advance(seconds: expires_in) end unless Metadata::TIMESTAMP_SERIALIZERS.include?(serializer) expiry = expiry&.iso8601(3) end expiry end
この処理で、expires_in によって現在時刻から15分後の絶対時刻が算出され、メタデータ(キー "exp")としてメッセージに埋め込まれます。検証時にはこの値と現在時刻が比較され、有効期限が切れていればトークンは無効とされます。
まとめ
トークンはデータベースに保存されない
トークンは生成時に、モデルの ID と追加情報(例:パスワードソルトの一部)、有効期限、目的が埋め込まれた署名付き文字列として返される。署名とペイロードによる検証
ActiveSupport::MessageVerifier により、トークンには改ざん検出のための HMAC 署名が付与され、検証時にペイロード内容と有効期限がチェックされる。動的なブロック評価
generates_token_forに渡されたブロックが評価され、その結果がトークンのペイロードに含まれるため、たとえば[1, "Rskh7hOSW."]のような値となる。
この仕組みにより、パスワードリセット時のトークンはデータベースのカラムを必要とせず、トークン自体に必要な情報がすべて含まれているため、ユーザー認証が実現されています。
CDK&AWS Lambda お手軽API作成
こんなもの作れます
https://cgo3wctz6upknfwfyltvlrhsea0mpiyy.lambda-url.ap-northeast-1.on.aws/?text=konkoncha
ここにアクセスするとクエリに渡されたtextの文字をヒエログリフに変換して返してくれます
AWS CLIでアクセスキーなどを設定する
AWS CLIのインストール
brew install awscli
キーの設定
aws configure
アクセスキーなどを入力すると~/.awd/config/に登録されます
CDKのセットアップ
CDKのインストール
npm install -g aws-cdk
CDK用の作業ディレクトリ作成
mkdir ~/適当なディレクトリ/CDK用のディレクトリ && cd ~/適当なディレクトリ/CDK用のディレクトリ
※空のディレクトリじゃないとCDKの初期化コマンドが失敗します
初期化
cdk init app --langage typescript
CDKのデプロイに必要なディレクトリが作られます
. ├── README.md ├── bin ├── cdk.json ├── jest.config.js ├── lib ├── node_modules ├── package-lock.json ├── package.json ├── test └── tsconfig.json
lambda用の処理を記述
import { Stack, StackProps } from "aws-cdk-lib"; import { Construct } from 'constructs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import { FunctionUrlAuthType, HttpMethod } from "aws-cdk-lib/aws-lambda"; export class HieroRubyStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const url = new lambda.Function(this, 'MyFunction', { runtime: lambda.Runtime.RUBY_2_7, handler: 'main.lambda_handler', code: lambda.Code.fromAsset('./app'), }); url.addFunctionUrl({ authType: lambda.FunctionUrlAuthType.NONE, }); } }
appディレクトリを作ってrubyの処理を記述
require 'json' def lambda_handler(event:, context:) hash = { A: ["1313F"], B: ["130C0"] , C: ["133A1"], D: ["130A7"], E: ["131CB"], F: ["13191"], G: ["133BC"], H: ["1339B"], I: ["131CB"], J: ["13193"], K: ["133A1"], L: ["130ED"], M: ["13153"], N: ["13216"], O: ["1336F"], P: ["133E4"], Q: ["133D8"], R: ["1308B"], S: ["132F4"], T: ["133CF"], U: ["13171"], V: ["13191"],W: ["13171"], X: ["133A1", "132F4"], Y: ["131CB"], Z: ["13283"] } text = get_text(event) result = text && text.upcase.split("").map{ |string| hash[string.to_sym] ? hash[string.to_sym].map{ |s| s.hex.chr(Encoding::UTF_8)} : string }.join { statusCode: 200, body: result } end def get_text(event) if event["requestContext"]["http"]["method"] == "POST" JSON.parse(event["body"])["text"].to_s elsif event["requestContext"]["http"]["method"] == "GET" event["rawQueryString"].split("&").map{ |string| string.split("=") }.to_h["text"] end end
クエリの受けとり方
event["rawQueryString"]で受け取れる
bodyの受け取り方
event["body"]で受け取れる
デプロイ
cdk deploy
meishi2のキーマップをQMK Firmwareを使って書き換えるメモ
環境
- MacBook Pro (13-inch, M1, 2020)
QMK Firmwareをインストール(brew経由でいけたっぽいからそっち使えばよかった)
git clone https://github.com/qmk/qmk_firmware.git #下記コマンドでbrewのupgradeが入りました(長かった) ./util/qmk_install.sh
キーマップを書き換えるために設定をコピー
qmk new-keymap #keymapの名前を入力するように言われます今回はcustom_keymapにしました
キーマップを編集
keyboards/biacco42/meishi2/keymaps/custom_keymap/keymap.cファイルを編集します
今回はデフォルトのやつ(コピペとか)からただの文字を出力するように変えてみます
/* Copyright 2019 Biacco42 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include QMK_KEYBOARD_H const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = LAYOUT( /* Base */ KC_Z, KC_X, KC_C, KC_V ) };
コンパイル
下記コマンドを打ってコンパイル
qmk compile -kb biacco42/meishi2 -km custom_keymap
エラーが出た
Ψ Compiling keymap with gmake --jobs=1 biacco42/meishi2:custom_keymap QMK Firmware 0.17.9 WARNING: Some git submodules are out of date or modified. Please consider running make git-submodule. Making biacco42/meishi2 with keymap custom_keymap tmk_core/protocol/lufa.mk:13: lib/lufa/LUFA/makefile: No such file or directory gmake[1]: *** No rule to make target 'lib/lufa/LUFA/makefile'. Stop. gmake: *** [Makefile:413: biacco42/meishi2:custom_keymap] Error 1 Make finished with errors
指示通りに下記コマンドを打つ
make git-submodule
実行結果
❯❯❯make git-submodule [master] QMK Firmware 0.17.9 Submodule 'lib/chibios' (https://github.com/qmk/ChibiOS) registered for path 'lib/chibios' Submodule 'lib/chibios-contrib' (https://github.com/qmk/ChibiOS-Contrib) registered for path 'lib/chibios-contrib' Submodule 'lib/googletest' (https://github.com/qmk/googletest) registered for path 'lib/googletest' Submodule 'lib/lufa' (https://github.com/qmk/lufa) registered for path 'lib/lufa' Submodule 'lib/printf' (https://github.com/qmk/printf) registered for path 'lib/printf' Submodule 'lib/vusb' (https://github.com/qmk/v-usb) registered for path 'lib/vusb' Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/chibios'... remote: Enumerating objects: 241811, done. remote: Counting objects: 100% (555/555), done. remote: Compressing objects: 100% (259/259), done. remote: Total 241811 (delta 374), reused 394 (delta 294), pack-reused 241256 Receiving objects: 100% (241811/241811), 157.10 MiB | 24.06 MiB/s, done. Resolving deltas: 100% (184417/184417), done. Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/chibios-contrib'... remote: Enumerating objects: 22528, done. remote: Counting objects: 100% (2835/2835), done. remote: Compressing objects: 100% (787/787), done. remote: Total 22528 (delta 2205), reused 2455 (delta 2007), pack-reused 19693 Receiving objects: 100% (22528/22528), 9.11 MiB | 19.03 MiB/s, done. Resolving deltas: 100% (14528/14528), done. Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/googletest'... remote: Enumerating objects: 22998, done. remote: Total 22998 (delta 0), reused 0 (delta 0), pack-reused 22998 Receiving objects: 100% (22998/22998), 9.01 MiB | 18.95 MiB/s, done. Resolving deltas: 100% (16989/16989), done. Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/lufa'... remote: Enumerating objects: 76739, done. remote: Counting objects: 100% (3089/3089), done. remote: Compressing objects: 100% (73/73), done. remote: Total 76739 (delta 3041), reused 3020 (delta 3016), pack-reused 73650 Receiving objects: 100% (76739/76739), 18.93 MiB | 14.62 MiB/s, done. Resolving deltas: 100% (61662/61662), done. Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/printf'... remote: Enumerating objects: 1578, done. remote: Counting objects: 100% (627/627), done. remote: Compressing objects: 100% (94/94), done. remote: Total 1578 (delta 566), reused 552 (delta 528), pack-reused 951 Receiving objects: 100% (1578/1578), 794.81 KiB | 6.16 MiB/s, done. Resolving deltas: 100% (977/977), done. Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/vusb'... remote: Enumerating objects: 1372, done. remote: Counting objects: 100% (73/73), done. remote: Compressing objects: 100% (50/50), done. remote: Total 1372 (delta 32), reused 46 (delta 18), pack-reused 1299 Receiving objects: 100% (1372/1372), 476.46 KiB | 15.37 MiB/s, done. Resolving deltas: 100% (832/832), done. Submodule path 'lib/chibios': checked out '257302333c31f1f710800c2b97acf3550de043e1' Submodule path 'lib/chibios-contrib': checked out '2a6b73ff51baf89083a220b6692a04ca2cae8750' Submodule 'ext/mcux-sdk' (https://github.com/NXPmicro/mcux-sdk) registered for path 'lib/chibios-contrib/ext/mcux-sdk' Cloning into '/Users/kenchaso/workspace/qmk_firmware/lib/chibios-contrib/ext/mcux-sdk'... remote: Enumerating objects: 38269, done. remote: Counting objects: 100% (3140/3140), done. remote: Compressing objects: 100% (1337/1337), done. remote: Total 38269 (delta 1836), reused 3046 (delta 1796), pack-reused 35129 Receiving objects: 100% (38269/38269), 73.83 MiB | 18.72 MiB/s, done. Resolving deltas: 100% (26262/26262), done. Submodule path 'lib/chibios-contrib/ext/mcux-sdk': checked out '102c27d7cc2aaac87c133702e7829a105e0cb433' Submodule path 'lib/googletest': checked out 'e2239ee6043f73722e7aa812a459f54a28552929' Submodule path 'lib/lufa': checked out '19a5d533f02a7b46eeadca99cc9699659cef7a60' Submodule path 'lib/printf': checked out 'd3b984684bb8a8bdc48cc7a1abecb93ce59bbe3e' Submodule path 'lib/vusb': checked out 'bdb53e4c043d089279d9891b68bea77614cb97ee'
その後再度コンパイルコマンドを打つ
qmk compile -kb biacco42/meishi2 -km custom_keymap
書き込み
avrdudeが大事らしい
make biacco42/meishi2:custom_keymap:avrdude
途中でreset押してって言われるのでmeishi2のリセットボタンを押す
Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)..........
実行結果
❯❯❯make biacco42/meishi2:custom_keymap:avrdude
QMK Firmware 0.17.9
Making biacco42/meishi2 with keymap custom_keymap and target avrdude
avr-gcc (Homebrew AVR GCC 8.5.0) 8.5.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Size before:
text data bss dec hex filename
0 20726 0 20726 50f6 biacco42_meishi2_custom_keymap.hex
Compiling: quantum/command.c [OK]
Linking: .build/biacco42_meishi2_custom_keymap.elf [OK]
Creating load file for flashing: .build/biacco42_meishi2_custom_keymap.hex [OK]
Copying biacco42_meishi2_custom_keymap.hex to qmk_firmware folder [OK]
Checking file size of biacco42_meishi2_custom_keymap.hex [OK]
* The firmware size is fine - 20726/28672 (72%, 7946 bytes free)
Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)........................................................................................
Device /dev/tty.usbmodem11201 has appeared; assuming it is the controller.
Waiting for /dev/tty.usbmodem11201 to become writable.
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.
Programmer supports the following devices:
Device code: 0x44
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file ".build/biacco42_meishi2_custom_keymap.hex"
avrdude: input file .build/biacco42_meishi2_custom_keymap.hex auto detected as Intel Hex
avrdude: writing flash (20726 bytes):
Writing | ################################################## | 100% 1.53s
avrdude: 20726 bytes of flash written
avrdude: verifying flash memory against .build/biacco42_meishi2_custom_keymap.hex:
avrdude: input file .build/biacco42_meishi2_custom_keymap.hex auto detected as Intel Hex
Reading | ################################################## | 100% 0.15s
avrdude: 20726 bytes of flash verified
avrdude done. Thank you.
avrdude
- :avrdude: Checks every 5 seconds until a Caterina device is available (by detecting a new COM port), and then flashes the firmware.
参考
GCPのCloud Natural LanguageのanalyzeSentimentの分析結果をhttp通信で取得するメモ
GCPのCloud Natural Languageの分析結果をVSCodeからHTTP通信で取得してみたのでそのメモ
POST https://language.googleapis.com/v1beta2/documents:analyzeSentiment?key=自分で発行したAPIキー HTTP/1.1
content-type: application/json
{
"document": {
"content": "text",
"type": "PLAIN_TEXT"
}
}
GCPのコンソールからプロジェクトを作成後APIキーを発行しクエリのkeyに入れる リクエストの中身は上記の通りdocumentの中にcontentとtypeを持たせる感じで多分もっとオプションある gcloud ml language analyze-sentiment | Cloud SDK Documentation 詳しくはこの辺を参考に
今回は通信できるかに焦点を当てて分析結果全く気にしてなかったのでtextとかいう適当な文字列持たせてるけどcontentにちゃんとした文字列持たせたらちゃんと分析できるはず
レスポンスは以下の感じ
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Vary: Origin, X-Origin, Referer
Content-Encoding: gzip
Date: Fri, 01 Oct 2021 01:00:45 GMT
Server: ESF
Cache-Control: private
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Connection: close
Transfer-Encoding: chunked
{
"documentSentiment": {
"magnitude": 0,
"score": 0
},
"language": "en",
"sentences": [
{
"text": {
"content": "text",
"beginOffset": -1
},
"sentiment": {
"magnitude": 0,
"score": 0
}
}
]
}
ちゃんと通信できた
■
Star Ship導入手順メモ
ターミナルの見た目を変えるStarship: Cross-Shell Promptを導入したのでそのメモです
zshのみについて書いてます
環境
- OS
macOS Big Sur(11.2.3)
- シェル
zsh(echo $SHELLで確認できます)
- ターミナル
iTerm2, VSCode
Nerd Fontsから好きなフォントをインストールする
Nerd Fontsで良さげなフォントをダウンロードして自分の普段使うターミナルに設定してください
brewを使う時は下記コマンドの感じでいけます(Fira Codeの例)
brew tap homebrew/cask-fontsこれやんないとフォント見つからなかった
brew install font-fira-code-nerd-font --cask
brew install font-hack-nerd-font --caskVSCode用
フォントをターミナルに設定する
Iterm2はここから設定できます

VSCodeはここから設定できます(Fira Codeは謎にできなかったのでHackを使ってます)

Starshipをインストールする
brewを使ってインストール
brew install starship
.zshrcに設定を追記する
Starshipがインストールできたら設定をzshに設定をします
~/.zshrcの一番最後にeval "$(starship init zsh)"を追記してください
ちゃんと設定ができていればsource ~/.zshrcを打つとターミナルの見た目が変わると思います

iTerm2
おしゃターミナルは気分が上がりますね
気が向いてカスタマイズしたら記事更新します
GitHubActionsメモ
# 好きな名前をつける
name: RUN Rspec
# どのタイミングで実行するかをここで決める pushとかpullreqestとかを指定するとそのタイミングで実行できる
on: [push]
jobs:
test:
# OSを選択するMacとかも選べる
runs-on: ubuntu-latest
services:
# みま神のarrangyのやつコピペしました
db:
image: postgres:latest
ports: ['5432:5432']
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
# masterkeyはcredential読むのにgithubに設定した
RAILS_ENV: test
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_HOST: 127.0.0.1
POSTGRES_PORT: 5432
steps:
- name: check out code
uses: actions/checkout@v2
# github actionsに用意されてるruby用の設定使っただけ
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7.2
# github actionsに用意されてるnode用の設定使っただけ
- name: setup node.js 15.4.0
uses: actions/setup-node@v1
with:
node-version: 15.4.0
# gemキャッシュしたい念を送ったけど行けてない感じがする
- name: chache Gemfile.lock
uses: actions/cache@v2
with:
path: vendor/bundle
key: bundle-${{ hashFiles('**/Gemfile.lock') }}
# yarnはなんでもいいから1回build通したらキャッシュ出来た
- name: chache yarn.lock
uses: actions/cache@v2
with:
path: node_modules
key: yarn-${{ hashFiles('**/yarn.lock') }}
- name: yarn install
run: yarn install
- name: Build
run: |
# postgres関連インストールしてる感ある
sudo apt-get -yqq install libpq-dev
# github actions用の設定ファイル作ってdatabase.ymlとして使ってる
cp config/database.yml.github-actions config/database.yml
# gemキャッシュできてる感ないから分けないといけないのかも
gem install bundler
bundle install --path vendor/bundle --jobs 4
bundle exec rails db:setup
- name: RSpec
run: bundle exec rails spec
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
config.before(:each) do |example|
if example.metadata[:type] == :system
driven_by :selenium_chrome_headless, screen_size: [1600, 1600]
end
end
end
test: adapter: postgresql encoding: unicode database: hieroglitter_test pool: 5 port: <%= ENV["POSTGRES_PORT"] %> username: <%= ENV["POSTGRES_USER"] %> password: <%= ENV["POSTGRES_PASSWORD"] %> host: <%= ENV["POSTGRES_HOST"] %>
環境変数はどこのやつを呼んでいるのじゃろうか envに設定したやつがPCに環境変数設定したのと同じ扱いになる感はある
- Google Chromeはデフォルトで入っているから入れる必要がなかった
- system specは
rails_helper.rbにdriven_byの設定を書かないとエラー起きる
RSpec.configure do |config|
config.before(:each) do |example|
if example.metadata[:type] == :system
driven_by :selenium_chrome_headless, screen_size: [1600, 1600]
end
end
end