Qiita CLI & DevContainersを使って記事を書くときの注意点


# はじめに

先日公開した記事を書いたときに、Qiita CLI と記事を Git 管理下にしました。
[その時の記事はこちら](https://qiita.com/genimura/items/6a934dbcf2a52264ef91)

## Qiita CLI とは

Qiita CLI は Qiita の記事をコマンドラインから操作できるツールです。
記事の作成、編集、削除、公開、非公開などができます。
また、記事のテンプレートを作成しておくこともできます。

[詳しくはこちら](https://github.com/increments/qiita-cli)

## DevContainer とは

VSCode の拡張機能で、開発環境をコンテナで構築することができます。
Dockerfile や docker-compose.yml を使って、環境を構築することができます。
また、devcontainers.json を使って、VSCode の拡張機能を使って、環境を構築することができます。

[詳しくはこちら](https://code.visualstudio.com/docs/devcontainers/containers)

## Qiita CLI と DevContainer を使って記事を書くときにストレスに感じたこと

最初はめちゃくちゃ快適だと思っていたのですが、いくつかストレスを感じたことがありました。

1. リビルドすると Qiita CLI のトークンが消える
2. リビルドすると GitHub の Personal Access Token が消える
3. 作成中の記事が意図せずに公開される
4. 公開した記事を編集反映をした次回の GitHub Actions 起動時にロールバックされる

それを解決するために、設定をしていきます。

## Qiita CLI の Token の設定

Qiita CLI を使うためには、Qiita のアクセストークンが必要です。
下記コマンドを実行するとトークンを発行してくださいと言われます。

```bash
npx qiita login

以下のURLにアクセスしてトークンを発行してください。（「read_qiita」と「write_qiita」にチェックを入れてください）
  https://qiita.com/settings/tokens/new?read_qiita=1&write_qiita=1&description=qiita-cli
```

こちらの URL にアクセスして、トークンを発行して、コマンドラインに貼り付けるとログインができるのですが、DevContainer を使っていると、リビルドするたびにトークンを発行しないといけないです。

そこで、ホストからトークンをコンテナに渡すように設定します。

### .gitignoreにcredentials.jsonを追加

まずは `.gitignore` に `credentials.json` を追加しましょう。

```.gitignore
~~~~
++ credentials.json
```

### devcontainer.json でcredentials.jsonをマウントする設定を追加

次にログインを一度してしまえば、
`/home/node/.config/qiita-cli/credentials.json` にトークンが保存されます。
こちらのファイルをまずはコピーして、ホストに保存します。

次に、`devcontainer.json` に以下の設定を`features`の下に追加します。
これは、コンテナを起動するときに、ホストの`credentials.json`をコンテナにマウントする設定です。

Qiita CLI のトークンを保存するために、`credentials.json`をマウントします。
`localWorkspaceFolder`は、VSCode のワークスペースのルートディレクトリを指します。

```.devcontainer/devcontainer.json
  "mounts": [
    {
      "source": "${localWorkspaceFolder}/credentials.json",
      "target": "/home/node/.config/qiita-cli/credentials.json",
      "type": "bind"
    }
  ]
```

## GitHub の Personal Access Token の設定

次は Github の Personal Access Token の設定をしていきます。(リポジトリはあらかじめ作成しておいてください)

### GitHub CLI のインストール

`devcontainer.json` に下記を追加します。
コンテナ内で`gh`コマンドを使えるようにするためです。

```.devcontainer/devcontainer.json
  "features": {
    ~~省略~~
    "ghcr.io/devcontainers/features/github-cli:1": {
      "version": "latest"
    },
  }
```

### .gitignore に.ssh を追加

次に、`.gitignore`に`.ssh`を追加します。

```.gitignore
~~~~
++ .ssh
```

#### コンテナの起動

次に、コンテナを起動します。
`⌘ + Shift + P` でコマンドパレットを開き、`Dev Containers: Rebuild Without Cache and Reopen in Container`を選択します。(リポジトリに移動している状態で実行してください)

#### GitHub にログイン

次に、GitHub にログインをします。
下記コマンドを実行します。

```bash
gh auth login

? What account do you want to log into?  [Use arrows to move, type to filter]
> GitHub.com
  GitHub Enterprise Server

? What is your preferred protocol for Git operations on this host?  [Use arrows to move, type to filter]
> HTTPS
  SSH

? Authenticate Git with your GitHub credentials? (Y/n) Y

? How would you like to authenticate GitHub CLI?  [Use arrows to move, type to filter]
  Login with a web browser
> Paste an authentication token

Tip: you can generate a Personal Access Token here https://github.com/settings/tokens ← こちらのURLにアクセスしてトークンを発行してください
The minimum required scopes are 'repo', 'read:org', 'workflow'. ← こちらのスコープを最低限必要になります
? Paste your authentication token: **************************************** ← ここにトークンを貼り付ける
- gh config set -h github.com git_protocol https
✓ Configured git protocol
! Authentication credentials saved in plain text
✓ Logged in as {username}
```

ログインが完了すると、`/home/node/.ssh`に SSH の鍵が保存されます。
`id_rsa`と`id_rsa.pub`が保存されているので、これをリポジトリのルートに`.ssh`を作成し、コピーします。

#### devcontainer.json にSSHの情報をマウント

`devcontainer.json` に、ファイルをマウントする設定を追加します。

```.devcontainer/devcontainer.json
  "mounts": [
    ~~省略~~
    {
      "source": "${localWorkspaceFolder}/.ssh",
      "target": "/home/node/.ssh",
      "type": "bind"
    }
  ]
```

これでコンテナをリビルドしても、コンテナ内で GitHub にアクセスできるようになりました。

## 作成中の記事が意図せずに公開される

これは、GitHub Actions でデフォルトで public 配下にある記事が公開されます。
まだ公開しないときは、`private: true`にしておいてください。
また、初期設定では、限定共有記事を含めないようになっているので、`qiita.config.json`に以下の設定を追加してください。

```qiita.config.json
  "includePrivate": true
```

Qiita は一度公開した記事は非公開ができないので、注意してください。

## 公開した記事を編集反映をした次回の GitHub Actions 起動時にロールバックされる

これは、GitHub Actions で記事を公開する際に、Github が直接、public 配下の記事を編集します。(ID の変更と更新日時の変更)
そのため、push をしたあとは、リモートリポジトリから pull をして、記事を更新してください。

また、記事を公開すると`{ID}.md`が生成されます。(記事が生成されないこともあります。その場合はローカルファイルを編集でいいと思います。)
以降は、元のローカルで作成していた記事ファイルを削除し、`{ID}.md`を編集するようにします。(この運用方法以外で、ベストプラクティスを知っている方教えてください)

常に公開された`{ID}.md`記事を修正するようにし、Web 上での編集は避けるようにすることをオススメします。

# おわりに

これでローカル環境を汚さずに快適な記事執筆体験ができるようになりました。
みなさんもぜひ Qiita CLI と DevContainer を使って、快適な執筆活動をしましょう 🙌