iPhoneで開発するという選択肢(Pythonista3,Termius)

# この記事について
個人でDjangoアプリケーションの開発をしているのですが、Pythonista3というモバイルIDEの存在を知りスマホで開発を行えたら出先でもアプリ開発できるなと思い、早速アプリをインストールして使ってみました。
結果、素晴らしいアプリでした！が、やはり色々と制約はあり、試行錯誤の結果それなりに便利な環境にすることができましたので、そのことを記事にしました。
※各種自動化のコードを開発しましたので載せています
※かなり長い記事になってしまいました

# 使用ツール
**デバイス**

* iPhone 11 (iOS15)

* Windows 10 Home PC

**メインで使用したアプリ類**

* Pythonista3 (<https://apps.apple.com/jp/app/pythonista-3/id1085978097>)

* Termius (<https://termius.com/>)(<https://apps.apple.com/jp/app/termius-ssh-client/id549039908>)

* GitHubアプリ (<https://apps.apple.com/jp/app/github/id1477376905>)

* AWS Console (<https://apps.apple.com/jp/app/aws-console/id580990573>)

**その他使ったもの**

* Amazon EC2 (<https://aws.amazon.com/jp/ec2/?ec2-whats-new.sort-by=item.additionalFields.postDateTime&ec2-whats-new.sort-order=desc>)

* python (<https://www.python.org/downloads/>)

* git (<https://git-scm.com/downloads>)

* GitHub (<https://github.co.jp/>)

* shell script (<https://shellscript.sunone.me/>)

* Docker (<https://hub.docker.com/>)

* Bitwarden (<https://bitwarden.com/>)

* iOS Shortcuts (<https://apps.apple.com/jp/app/%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88/id915249334>)

* AWS CloudFormation (<https://aws.amazon.com/jp/cloudformation/>)

* screen (<https://linuxjm.osdn.jp/html/GNU_screen/man1/screen.1.html>)

# Pythonista3インストール
開発の主役たるID。App Storeからインストール(1200円)。

# Pythonista3セットアップ
## staShのセットアップ
Pythonista3ではstaShというモジュールを入れることでbashのようなシェルの操作が実現可能。
(ただし使える機能は限定的になるので、過信は禁物。)
使えるコマンドは下記の通り。
>alias, cat, cd, clear, cowsay, cp, crypt, curl, cut
diff, django-admin, dropbox_setup, du, easy_config, echo, edit, exit, fg, find, 
ftpserver, gci, gh, git, grep, head, httpserver, jobs, kill, latte, ln, logout, 
ls, mail, man, mc, md5sum, mkdir, monkeylord, more, mount, mv, openin, pbcopy, 
pbpaste, ping, pip, printenv, printhex, ptinstaller, pwd, python, python3, quicklook, 
rm, rmdir, scp, selfupdate, sha1sum, sha256sum, sort, source, sqlformat, 
sqlite, ssh, ssh-keygen, stashconf, tail, tar, telnet, totd, touch, umount, 
uniq, unzip, version, wc, webviewer, wget, whatis, which, wol, xargs, zip, 

<https://tarown.com/software/python/2019/06/04/pythonista3_django/>

こちらの記事の前半手順でstaShのセットアップを行う。

>1）画面を左にスワイプしてコンソールを開く
>
>2）インストールコマンド`import requests as r; exec(r.get('http://bit.ly/get-stash').text)`をコンソールで実行
>
>3）Pythonista3再起動
>
>4）ファイルエクスプローラー画面から`launch_stash.py`を開いて、右上の再生ボタンで実行

## gitリポジトリ作成 or クローン
開発用のローカルリポジトリを作成。</br>
既存のプロジェクトでありかつプライベートリポジトリをクローンしたかったので、公開鍵をGithubに登録する必要があった。</br>
方法としては、</br>
1) staShにて、`ssh-keygen`コマンドで鍵ペアを生成</br>
2) GitHubに公開鍵を登録</br>
3) `git clone`の実施</br>

を行う。</br>

`ssh-keygen`コマンドで生成される鍵のデフォルト格納先は、`〜/.ssh`</br>
で、ホームディレクトリはデフォルトの場所である`Documents`の一階層上になる。</br>
`cat id_rsa.pub`</br>
して中身をクリップボードにコピーしてブラウザ上からGithubに鍵登録実施。</br>
<details>
    <summary>GitHubへの鍵登録</summary>
    <img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/goto_accountsettings.png" width="30%"><img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/gh_inaccountsettings.png" width="30%"><img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/gh_inaccountsettings2.png" width="30%">
    <p>iPhoneを横向きにしないと表示されない</p>
    <img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/github_addkey2.png" width="60%">

</details>

鍵登録の実施後、`git clone git@github.com:<username>/<reponame>.git`


git利用時の注意点として、確認時点でpython3モードでのgitが使えなかった(実行時エラーが発生)ので、**gitコマンドを使う時だけpython2モードに切り替えて作業行う必要があった**

<details>
    <summary>Python2モードに切り替え</summary>
    <img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/pythonista_top.png" width="30%"><img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/settings_in_pythonista.png" width="30%">
</details>

## pipについて
Pythonista3だとpipコマンド自体は存在するが、使える機能が限定的なので、(**確認時点でrequirements.txtを使っての依存関係制御が使えなかった**)実行環境は別途AWSで構築することに。</br>
requirements.txtを使っての依存関係制御が使えなくても問題なければ、Pythonista3をテスト用実行環境に使うのもありだと思う。

## venvについて
Pythonista3利用にあたる留意事項として、私の環境だと**venvのような仮想環境が使えなかった。**
iPhoneアプリというそれ自体がサンドボックスという環境において、流石にpython仮想環境までは実現出来なくともやむなし、という感じ。地の環境(サンドボックス環境)を使う場合はpipでインストールするものを適切に管理していく必要がある。

# アプリ版GitHubインストール
App Storeからインストール。
これがあることでリモートリポジトリのソースを確認しやすい。
IssuesやPull Requestの確認ややり取りも容易に行えますのでとても優秀なアプリ。

# アプリ版AWS Consoleインストール
App Storeからインストール。
セキュリティグループへのルール追加に使う。
その他出来ることとして、EC2の起動停止、Elastic IP割り当てなど。</br>
その他も色々出来ることはあるのですが、現状ではあくまでも既存のリソースに対する確認や一部操作が出来るのみで、新規リソース作成に関しては基本的にブラウザのコンソールから行うしか無さそう。

# パスワード入力の自動化(オプショナル)
ブラウザからAWSやGitHubを使う事もあり、その際にIDパスワード入力が手間になるので、自動化しておくと楽。</br>
Bitwardenというソフトを使って実現。(iPhone組み込みのパスワード記録機能でも実現可能)</br>
Bitwardenについてはこちらのやりすぎセキュリティさんの記事(<https://excesssecurity.com/how-to-use-bitwarden/>)が詳しい。</br>
AWSマネジメントコンソールにアクセスすると、Face IDと連動してIDパスワードを自動入力させることが可能。
<details>
    <summary>IDパスワード自動入力</summary>
    <p>AWSマネジメントコンソールへのログイン</p>
    <img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/bitwardenaws1.png" width="30%"><img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/bitwardenaws2.png" width="30%">
    <p>GitHubへのログイン</p>
    <img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/bitwardengithub1.png" width="30%"><img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/bitwardengithub2.png" width="30%">

</details>

また、iPhoneからこれらのサイトを操作する上でのTipsとして、画面を横向きにするというのが結構大事。縦向きだとウィンドウ枠の関係で見切れてしまうメニューが横向きだと表示される、ということがよくある・・・。

# Termiusインストール
TeraTermのようにリモートホストにSSHアクセスして操作出来るターミナルソフト。App Storeからインストール。
Tabキーでの補完が非常にスムーズ。また、CtrlキーはLinuxホスト操作時に頻繁に使うが、こちらも同時押し状態を直感的に操作可能。

無料版で問題なく使えているが、有料版だと下記のような機能がある。
>・SFTP
>
>・AWSからのリソースインポート
>
>・複数タブ表示
>
>・オートコンプリート
>
>・スニペット
>
>・組織やチーム向けの高度な権限設定

https://termius.com/pricing

# Termiusでキーペアを作成
ホーム画面のKeychainから行う。
今回はSecureEncraveKeyではなく、通常のGenerate Keyから作成。
作成した公開鍵部分をメール等でPCに送付しておく。

# キーペア登録
AWSマネジメントコンソールからTermiusで生成したキーペア(正確には公開鍵)の登録を行う。AWSマネジメントコンソールのiPhoneからの操作は非常に骨が折れるのでPCから行うのがおすすめ。

1) EC2ダッシュボード>キーペア>キーペアの作成</br>
2) 公開鍵の文字列をコピー&ペーストで登録

# EC2作成
EC2インスタンスの作成を行う。
キーペアは、先ほどインポートしたものを選択。
キーペアは後になって変更が難しいので、ここは間違えないように気をつける。

# セキュリティグループ編集
EC2のセキュリティグループを編集し、iPhoneの IPアドレスからEC2にssh出来るようにする。

# ホスト登録し、SSH
Termiusのhostsのメニューから行う。</br>

1) New Hostを選択し、</br>
2) hostname(パブリックIPまたはホスト名)、username(ec2-user)、key(先ほど作成したキー)を入力する。

# コンテナ実行環境構築(オプショナル)
アプリケーションの実行環境に関して、スケーラブルでかつ環境依存しない形を目指して、VMではなくコンテナ上に構築する形にした。
EC2上にコンテナ実行環境を作る為に実施したコマンドは下記。

```
sudo yum install docker
sudo systemctl start docker
sudo usermod -a -G docker ec2-user
sudo systemctl enable docker
```
これらと先に述べた鍵の生成・登録、アプリケーションのための設定をひとまとめにしてセットアップスクリプト化したものが下記。

* *鍵の生成時の対話入力を自動化するサブスクリプト[genkey.exp]*</br>
expectを使用して対話入力を自動化。

* *EC2のセットアップを行うスクリプト[setup.sh]*</br>
ウィザード形式でセットアップを行う。</br>
機能は</br>
・gitのセットアップ</br>
・Dockerのセットアップ</br>
・Dockerfile内で使うファイル類や変数のセットアップ</br>
・SSH公開鍵の作成(genkey.expを呼び出す)</br>
・ローカルホストにgit cloneしてリポジトリ取得</br>
・取得してきたリポジトリからDockerfileとrequirements.txtをカレントに持ってくる</br>
・ビルド時に使うためにホストの.sshディレクトリをカレントにコピーする</br>
・Dockerfileのビルドを実行</br>
・docker runのコマンドを表示</br>
・ログディレクトリセットアップ、ログ出力</br>
・OSを判定してOSごとに処理内容を変える(現在Amazon LunuxとUbuntuのみ対応)</br>
など。

* *Djangoアプリケーションを動かすDockerfile[Dockerfile.sample]*</br>
DjangoをDockerコンテナで動かすためのファイル。</br>
ビルドはsetup.sh内にて実行。</br>
・sshの鍵をホストからコピー</br>
・コピーした鍵を使ってGitHubにSSH</br>
・ソースをクローンして取得(ユーザー名とリポジトリ名はsetup.shにて対話入力で受け取ったものを使う)</br>
・settings.py内のALLOWED_HOSTSの設定</br>
・依存関係のインストール</br>
・DBのマイグレーション</br>
など。

https://gist.github.com/miyabi-sakai/1a58a980cb24d1525a14b5c2942f1ff3

# ショートカットでセキュリティグループの設定を楽にする(オプショナル)
iOSのショートカットアプリを活用して、セキュリティグループの設定を少しだけ楽にできる。

Pythonista3で次のスクリプトを作成しておく
*IPアドレス取得を行うサブスクリプト[convert-ip.py]*

```py:convert-ip.py
import re
import clipboard

input=clipboard.get()

def func(input):
	result=re.search('[1-9][0-9]{0,2}\.[1-9][0-9]{0,2}\.[1-9][0-9]{0,2}\.[1-9][0-9]{0,2}',input).group()
	clipboard.set(result+"/32")
	
func(input)
```

ショートカット名:らくらくIP設定

```
アクション名：URL
値：https://checkip.amazonaws.com

アクション名：Safari/Webページの内容を取得
値：URLのWebページの内容を取得

アクション名：書類/入力からテキストを取得
値：Webページの内容からテキストを取得

アクション名：共有/クリップボードにコピー
値：テキストをクリップボードにコピー

アクション名：PYTHONISTA/スクリプトを実行
値：convert-ip.pyに'(何も入れない)'を渡して実行

アクション名：スクリプティング/Appを開く
値：AWS Consoleを開く
```
<details>
    <summary>ショートカット</summary>
    <img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/rakurakuip1.png" width="30%"><img src="https://extremecoolbucketpublic.s3.ap-northeast-1.amazonaws.com/rakurakuip2.png" width="30%">    
</details>

# cfn構成して構築自動化(オプショナル)
EC2とセキュリティグループだけ設定してしまえば開発環境は揃うが、cfnを利用して構築自動化しておくことでRDSやS3、Route53など連携して使う必要があるリソースをまとめて構築、追加、削除などが可能。
ただこの場合、iPhoneからだとマネジメントコンソールの操作が辛いので、aws cli実行環境として専用のEC2を作っておくとTermiusで繋いでそこからaws cloudformation create-stack等叩けるのでとても楽だと思う。
私はこの部分は妥協してcfnテンプレート周りはPCを使って行っています。

(手軽な手段として、boto3をiPhoneにインストールしてそこからcreate-stackを実行するというのをおもいつくが、Pythonista3上でpip install boto3したところ、バグによりインストール不可だった。詳細はこちら(https://github.com/ywangd/stash/issues/405))

# 複数ターミナル使う(オプショナル)
無料プランにおいてはターミナルのタブ機能は利用出来ないのだが、EC2環境ではscreenコマンドを使用すると、擬似的に複数ターミナル立ち上げが実現可能。
</br>

* `screen`    スクリーン機能起動

* `CTRL+a`    スクリーン作成

* `CRTL+a Tab`スクリーン移動

* `CTRL+a c`  現在のスクリーンで入力開始

* `CTRL+a X`  スクリーン閉じる

* `killall screen` スクリーン機能終了

# PC環境から同じEC2インスタンス内で作業する(オプショナル)
PC環境から同じiPhone環境とEC2インスタンスで作業したい場合、別途キーペアの追加が必要。</br>
1）PCからssh-keygenコマンドでキーペアを作成</br>
2）id_rsa.pubをコピーしてメール等でiPhoneへ送付</br>
3）iPhoneからTermiusでEC2へ接続</br>
4）任意の場所でvi new-key.pubして公開鍵のテキストを貼り付けして保存</br>
5）cat new-key.pub >> /home/ec2-user/.ssh/authorized_keys</br>
6）rm new-key.pub</br>
7）PCのIPを確認して、セキュリティグループのインバウンドルール22番ポートに追加する</br>
8）秘密鍵を指定してsshできる事を確認</br>

ただしDockerで開発している場合はDocker for Desktopを使う事でPC側でアプリケーション実行環境を再現できるので、無理にこの手順を行う必要はない。

# 開発
実際の開発の流れとしては、</br>
①Pythonista3でgit cloneして既存プロジェクトをPythonista3にインポート(新規で開発する場合はgit initでリポジトリ作成)</br>
②Pythonista3上でコードを開発、改修</br>
③staShを利用して開発したソースコードをリモートリポジトリに反映</br>
④必要であればブランチを分けて開発したり、Issuesで機能の進捗やバグの管理、プルリク等を使ってレビュー依頼など、Githubアプリを利用して実施</br>
⑤アプリケーションの動作確認はTerminusを使ってEC2上に構築したDockerホストを都度立ち上げ実施。フォアグラウンドでコンテナを動かしたりなどでターミナルが複数必要な時はscreenを利用して対応</br>
⑥Windows(またはMac)PCでは、モバイルで使ったEC2を共用して使うこともできるし、Docker for Desktopを使うことでローカルでの開発も可能</br>
⑥使い終わったリソースはAWS  Consoleアプリやcfnを利用して都度クリーンアップ</br>
のようになる

# 最後に
モバイルIDEとしてPythonista3、ターミナルソフトとしてTermiusというのは今回確かに「使える」という事が分かりましたが、一方で単体だと出来ることにはどうしても制約が出てきますので、色々なツール類を組み合わせて使っていくとやりたい事が実現できる感じになるのかなと思います。
ただ私が今回やってみて出来なかった部分に関しても機能アップデートで改善されたりしていくことは十分期待できます。(また私のやり方が悪かっただけで実は方法次第で出来るということもあるかと思います。)
何かありましたらコメントで教えて頂けたら幸いです。