DevContainerからgit pushできるようにした話。

# 初めに
DevContainerでローカル環境を簡単に起動できるようになり作業していると、こう思ったことはありませんか?
コンテナ内からgit push 出来たらいいのにな～と。
でも.sshディレクトリのSSHキーはセキュリティ上マウントしたくないし...
というそんな方向けの記事です。
# なぜpushできないのか
①作成済みのSSHキーをマウントするか都度keygenして登録する必要がある。
②LinuxとWindowsで改行コードが異なるためCRLFで保存していると、大量の差分が出る。
③git config safe directroyコマンドで登録が必要
④git configコマンドを使うのに.gitconfigファイル必要だが、単純にマウントしてもコマンドが通らない。※試した感じだとWindowsで使用中判定なのが原因っぽいのですが解決できなかったので諦めました。

# なぜDevContainer内からpushしたいのか
以下のモチベーションがあると考えています。
①エディタ内でgit pushまで完結するので作業効率が上がる
②commit時に言語のテストコマンドを実行するといったgitフックが使用できる。また、PC内に言語をインストールしなくても済むので汚染せずに済みます。

特に②の恩恵は大きく、commit前にテストコマンドを実行してね！みたいな案件は結構あると思うのですが、手動だと忘れることもありますし、やり忘れによるしょうもない人間関係のストレスは避けたいところです。



# ディレクトリ構成
DevContainerの場合このような構成になることが多いと思います。
今回はGoを例にしていますが、必要な要素は列挙していくのでそこだけ抑えていただけたらと思います。
```
business
├── .devcontainer
│   ├── infra
│   │   ├── go
│   │   │   └── Dockerfile
│   │   └── mysql
│   │       └── 1_ddl.sql
│   ├── .env
│   ├── devcontainer.json
│   └── docker-compose.yml
├── .air.toml
├── go.mod
├── go.sum
├── Taskfile.yml
└── main.go
```

# どうやってやるの?
今回使用するのはkeychainです。
参考記事
https://esc.sh/blog/ssh-agent-windows10-wsl2/
# 実装方法
## WSL側の対応
### 以下のターミナルでコマンド実行
```
sudo sudo apt install keychain
sudo sudo apt install socat
```
### WSL2の.bashrcに追加
```
# すでにソケットがなければ起動
if ! [ -S "$SSH_AUTH_SOCK" ]; then
  eval $(ssh-agent -s) > /dev/null
  ssh-add $HOME/.ssh/id_rsa
  socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"ssh-agent -a $SSH_AUTH_SOCK",pty,stderr,setsid,sigint,sane &
fi

# keychain（オプション）
/usr/bin/keychain -q --nogui $HOME/.ssh/id_rsa
source $HOME/.keychain/$(hostname)-sh
```
## ファイル修正
下記のファイルを修正してください。
Dockerfile
```Dockerfile
FROM golang:1.22.0-bookworm

～～中略～～

# 以下を追加
# Task Runner のインストール
RUN curl -sL "https://github.com/go-task/task/releases/download/v3.9.0/task_linux_amd64.deb" -o task.deb && dpkg -i task.deb && rm task.deb

# keychainでgitのSSHキーを扱えるようにする。
RUN apt-get update && apt-get install -y keychain

CMD task setup
```

docker-compose.yml
```docker
volumes:
- ~/.gitconfig:${APP_ROOT}/.gitconfig
```

Taskfile.yml
```
tasks:
  setup:
    desc: "ローカル環境のセットアップを行う。(gitコマンドが使用できるようにする)"
    cmds:
      - cp {{.APP_ROOT}}/.gitconfig /root/.gitconfig
      - git config --global core.autocrlf input
      - git config --global --add safe.directory {{.APP_ROOT}}
```

.devcontainer.json
```json
"postCreateCommand": "task setup"
```


これでpushまでできます。

でも、このままだとブランチ名が表示されないので、ちょっと作業し辛いですよね。

## ブランチ名を表示させる
プロジェクトルートに`.bashrc`を作成して、このようにします。
```.bashrc
# Git ブランチ名をプロンプトに追加
parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}

export PS1="\u@\h:\w\[\033[34m\]\$(parse_git_branch)\[\033[00m\] $ "

```


表示されました！👏👏👏
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3753262/5efa9032-6397-da7f-499b-8a03deec1b70.png)

## 動作確認

```bash
git checkout -b feature/test
git commit --allow-empty -m "first commit"
git push origin feature/test
```

このように表示されれば動作確認完了です!

```bash
To github.com:hogehoge/fugafuga.git
 * [new branch]      feature/test -> feature/test
root@6edadf4e2f75:/data (feature/test) $ 
```

## 日本語のコミットメッセージが書けないんだけど！
bashの場合日本語に対応していないため、別途ライブラリをインストールしたりENVの設定が必要になります。
Dockerfileに以下を追加します。

```Dockerfile
# 環境変数を設定して、日本語UTF-8ロケールを使用
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
# 必要なパッケージのインストールとロケールの設定
RUN apt-get update && \
    apt-get install -y locales && \
    localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
```
これで日本語が扱えるようになります。
# 最後に
ググっても出てこなかったので苦戦しつつ導入しました。
後発者の方々の参考になれば幸いです。