GitpodでAWS CDKにContributeするためのdotfilesを作る


## はじめに

NTTテクノクロス株式会社の渡邉洋平です。

https://qiita.com/watany/items/324e1af8fcd195523213

以前の記事で、dotfiles機能を用いることでGitpodsやGithub Codespacesの初期化ノウハウをお話ししました。

書いているうちに、もう少し実用的なdotfilesを作ってみたくなったため、私が日ごろ行っている「AWS CDKへのContributeの効率化」をテーマにdotfilesを作ってみました。

## dotfilesで実施したいこと

1. GitHub Mailアドレスの隠蔽
    - `git config user.email`のマスキング
2. AWS CLIコマンドのインストール
    - AWS CDKのContribute時には、実際のAWSリソースを用いたテストがあるので、AWS CLI v2コマンドを導入する。 
    - AWS CLI v2のコマンド補完を有効にする。
3. 機密情報の漏洩対策
    - git-secretsなどのコマンドもありますが、今回は[Gitleaks](https://github.com/gitleaks/gitleaks)を使います。
    - precommitフックは、Gitleaksの公式にも案内がある[pre-commit](https://pre-commit.com/)を使います。

### 準備
まずここからひな形をフォークし、以降紹介するスクリプトは`scripts/`配下に配置するものとします。

https://github.com/gitpod-samples/demo-dotfiles-with-gitpod


### 1. GitHub Mailアドレスの隠蔽

このブログで書いた`/scripts/mask_email.sh`にて実施できます。

https://qiita.com/watany/items/324e1af8fcd195523213


### 2. AWS CLI v2のインストール

スクリプトでは、以下を実施しています。
- 導入されていない、あるいはAWS CLI v1が入っていれば、AWS CLI v2をインストールする。
- Bash補完を有効にする。

```bash:scripts/install_aws_cli.sh
#!/bin/bash

# Check AWS CLI version
if ! command -v aws &> /dev/null || aws --version 2>&1 | grep -q 'aws-cli/1.'; then
    echo "Installing AWS CLI v2..."

    # Install AWS CLI v2
    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    unzip awscliv2.zip
    sudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update

    echo "AWS CLI v2 installed."
else
    echo "AWS CLI v2 is already installed."
fi

# AWS CLI bash-completion
echo "Setting up AWS CLI bash completion..."
if [ -f /usr/local/bin/aws_completer ]; then
    echo "complete -C '/usr/local/bin/aws_completer' aws" >> ~/.bashrc
    source ~/.bashrc
    echo "AWS CLI bash completion configured."
else
    echo "Unable to find AWS CLI completer script. Bash completion not configured."
fi
```

### 3. 機密情報の漏洩対策


#### 課題

いろいろ試した結果として、Gitleaksの導入には課題があることがわかった。 

gitleaksの導入法は以下の３通りなのだが、それぞれ一癖ある。

1. HomeBrew
    - コマンドで導入するのは少し面倒
2. Docker
    - Pre-commit hook が煩雑？
3. Build(Go)
    - 普段なら良さそう。
    - Gitpod Dotfilesでの制約として、実行時間が120秒制約があり、ボトルネックになる可能性が高い。
        -  > Note: Your installation script will be terminated if it exceeds 120 seconds.
    
https://www.gitpod.io/docs/configure/user-settings/dotfiles#custom-installation-script


悩んだ結果、今回は3.＋事前ビルド案を取ることとした。1がスムーズにいくなら乗り換えた方が良いとは思う。

#### Github Actions

ChatGPTにも相談しつつ、以下のようなワークフローでGitleaksのバイナリを事前ビルドすることができました。

Go環境によるビルドを週一実行し、差分があったらリポジトリの`bin/`にPushします。うーん力業。


```yaml:.github/workflows/build.yml
name: Build Gitleaks

on:
  schedule:
    - cron: '0 9 * * 1'
    # for debug
#     - cron: '*/5 * * * *'
  workflow_dispatch:
jobs:
  build:
    permissions:
      contents: write
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: 1.19

    - name: Prep dir
      run: mkdir -p bin

    - name: Build Gitleaks
      run: |
        git clone https://github.com/gitleaks/gitleaks.git
        cd gitleaks
        make build
        cp gitleaks ../bin/  
        
    - name: Commit and push if changed
      run: |
        git config core.filemode false
        git config --local user.email "github-actions[bot]@users.noreply.github.com"
        git config --local user.name "github-actions[bot]"
        
        # Stash changes before rebasing
        git stash
        git pull --rebase
        
        # Apply stashed changes after rebasing
        git stash pop        
        git add -f bin/gitleaks
        git diff-index --quiet HEAD || git commit -m "Add built gitleaks binary"
        git push https://${{github.actor}}:${{secrets.GITHUB_TOKEN}}@github.com/${{github.repository}}.git HEAD:${{github.ref}}
```

#### スクリプト

スクリプトでは、以下を実施しています。
- 作業ディレクトリの調整
- homebrewがあれば`brew install gitleaks`を行い、コマンドが無い、あるいは失敗していたらビルド済みのgitleaksバイナリを配置。
- 公式に従った、pre-commitフック設定。

https://github.com/gitleaks/gitleaks#pre-commit


```bash:scripts/hook_gitleaks.sh
#!/bin/bash

# move work dirctory
TARGET_DIR='/workspace'
subdir=$(find "$TARGET_DIR" -maxdepth 1 -mindepth 1 -type d ! -name ".*" | head -n 1)
if [ -d "$subdir" ]; then
    cd "$subdir"
    echo "Moved to: $(pwd)"
else
    echo "No subdirectory found in $TARGET_DIR"
fi

# Install gitleaks
copy_prepared_gitleaks_binary() {
    echo "Copying the prepared gitleaks binary to a location in the PATH..."
    sudo cp /home/gitpod/.dotfiles/bin/gitleaks /usr/local/bin/gitleaks
    sudo chmod +x /usr/local/bin/gitleaks
    echo "Gitleaks binary copied to /usr/local/bin/gitleaks"
}

if command -v brew &> /dev/null; then
    echo "Installing gitleaks using Homebrew..."
    if ! brew install gitleaks; then
        copy_prepared_gitleaks_binary
    fi
else
    copy_prepared_gitleaks_binary
fi

# Setting pre-commit
pip install --upgrade pip
pip install pre-commit
echo 'repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.17.0
    hooks:
      - id: gitleaks' > .pre-commit-config.yaml
pre-commit autoupdate
pre-commit install
```

## まとめ

ということでGitpodを実践的に使えるTipsを紹介しました。これをベースにAWS CLIの部分を抜いたり、bashをzshにしたりするのも面白いですね。

Github Actionsの勉強としては良かったのですが、gitleaksの導入は多分ここまで頑張らなくていいと思えるので、ノウハウは別途探してみます。