本稿は社内発表用の開発経験の浅い初心者向けです。
前提
コンセプト
社内で若手の技術力が云々、みたいな問題が挙がることがあります。
技術力が向上しない原因はセンスの問題もありますが、モチベーションに依るところも大きいのではないでしょうか。
例えばプログラミングをやりたい!というモチベーションはどこから来るのでしょうか?
これは私の超個人的な考えですが、作ったものを誰かに「すげぇ!」と言ってもらえることに尽きる気がします。
因みに私は大学のCの授業でif文を習った翌週には講師を倒すテキストゲームを作って友達に遊んでもらいました。
無論、SEはプログラミングだけできれば良いというわけでは全くありませんが、プログラミングの楽しみというか喜びを味わったことのない人に自ら勉強しろと言うのは酷なことですし、成果も上がらないでしょう。
というわけで、誰かに「すげぇ!」と言ってもらえる環境=自作Webアプリをインターネットに公開できる環境を用意しましょう、というのがコンセプトです。
やりたいこと×やれる環境=イノベーション
枯れ果てたおっさんと違って若者はやりたいことがまだ眠っているはずです。
やりたいことがある若者にそれが実現できる環境を用意してやればイノベーションが生まれる。かもしれない。
但し、無料で。
これ、大事だと思います。
それなりに経験積んだエンジニアがクラウド破産するのは自己責任かもしれませんが、初心者がうっかりで開けた穴で何十万と請求が来たりとか、そうでなくともそれを恐れて手出しするのをやめちゃったら元も子もないじゃないですか?
なので、ありがちなクレジットカードを登録したら使える無料枠じゃ意味ない。
無料枠を使い切ったときに勝手に停止することが大事なんだ!
あと、いつの間にか規約変わってて請求が来るとかいう恐ろしい事件も起こる。
⇒(解決済み) IBM Cloudからの不意打ち請求はあろうことか2重請求だった
クレジットカードさえ登録してなければ何がどうなろうと安心だ!
しかも5分で。
長いと見てくれないから。じゃなくてそれくらいハードル低いよということをお伝えしたい。
想定するターゲット
・研修でJavaを一応習った。
・HTMLは何となくわかる。
・Gitは聞いたことがある。
・研修でプログラミングはやったけど開発業務に従事していないor自分の好きなものを作る機会がない。
・自分で考えて作ったWebアプリを誰かに見せたいけど、どうやってインターネットに公開するのか分からない。
準備
Windows10マシンを用意する。
なぜならMacなんぞを持っている意識高い人間はこんな記事読まなくても多分自力で何とかなる。
勉強会とか行くとみんな当然のようにMac持っていて肩身が狭い。
Qiitaの入門系の記事の前提環境もMacばかりでつらい。
みんなお金があったらMac買え。
Windows7は捨てろ。
Gitをインストールする。
Git公式
PCモニタみたいな画像の中に「Download X.XX.XX for Windows」みたいなボタンがある。
インストールしてください。
インストールは全部脳死でNext押しておけば良いです(これ読んでるような人は)。
「Gitって何?」という方へおすすめのページ。
いまさらだけどGitを基本から分かりやすくまとめてみた
君には1時間でGitについて知ってもらう(with VSCode)
…さて、前提知識なしで読んですんなり頭に入る人がどれだけいるか?
ざっくり言うとGitはソースコードの状態を記録しておいて、いつでもやり直したり、チームのみんなで共有したりする為に、ソースコードのバージョンを管理(構成管理ともいう)するソフトウェア。
Visual Studio Codeをインストールする。
Visual Studio Codeはメジャーなソースコードエディタ、つまりソースコードを編集する為のソフトウェア。
これさえ使っておけばとりあえず大抵困らない。大抵。
Visual Studio Code公式
「今すぐダウンロード」⇒「↓ Windows」みたいなボタンからダウンロード。
因みにこのボタン、この前まで「今すぐ無料でダウンロードする」だったよ?
インストールは全部脳死で「次へ」押しておけば良いです(これ読んでるような人は)。
Visual Studio Codeを日本語化する。
これを読んでるような人はきっと英語が大嫌いでしょうから日本語化しておきましょう。
- Visual Studio Codeを起動する。
- メニューの「view」を選択する。
- 「command palette」を選択する。
- 「configure display language」と入力しようとしている内に、きっとサジェストされるのでそれを選択する。
- 「en」と「install additional language...」というメニューが表示されるので後者を選択する。
- 左に拡張言語パックが出てくるので、「Japanese Language Pack for Visual Studio Code」を探して選択する。
- 「Install」という緑色の地味なボタンを押す。
- Visual Studio Codeを再起動する。
Visual Studio CodeをJava用に拡張する。
Visual Studio CodeはJavaプログラム開発専用のエディタではないので。
- Visual Studio Codeのウィンドウの左のバー上にある田んぼの田が発狂して崩壊したような拡張機能ボタンを押す。
- 検索ボックスに「Java Extension Pack」と入力して探し、選択する。
- 「Install」という緑色の地味なボタンを押す。
- マシンにJDK入ってないと画面右下に「× Java 8 or more recent is required to run. Please download and install a recent JDK(JDK入ってないぞボケ)」みたいなポップアップが出て怒られる。JDKインストール済みの場合は以降の手順は不要。
- 「command palette」を選択する。
- 「java: Configure Java Runtime」と入力しようとしている内に、きっとサジェストされるのでそれを選択する。
- Configure Java Runtimeの画面が開いてJDKのインストール状況が確認できます。
- 画面をスクロールすると「Install」カテゴリに青い「Download」ボタンがあるので押す。
- 「Codeが外部Webサイトを開けるようにしますか?」みたいなダイアログが表示された場合は「開く」ボタンを押す。
- AdoptOpenJDKというJDKを直接ダウンロードできるのでそのままインストールする。
- インストールは全部脳死で「次へ」押しておけば良いです(これ読んでるような人は)。
- インストール完了後に環境変数を設定し、ついでにVisual Studio Codeを再起動する。
環境変数名 | 環境変数値(例) |
---|---|
JAVA_HOME | C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot |
PATH | C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot\bin |
Visual Studio CodeをSpring Boot用に拡張する。
Spring Bootは後で出てきます。
Spring Boot Extension Packマーケットプレイス
- 「Install」という緑色の地味なボタンを押す。
- Visual Studio Codeが開くのでしつこく「Install」という緑色の地味なボタンを押す。
Spring Bootのプロジェクトファイルを用意する。
Spring BootはJavaのアプリケーション向けフレームワークであるSpringの派生の一種です。
とりあえず今は「Spring Bootを使えばWebアプリケーションを楽に作れる」と認識しておいてもらえれば良いでしょう。
既に自作のSpring BootによるWebアプリがあればそれでいいし、或いはどっかからクローンしてきてもいいのだけど、
何のこっちゃって人がいると思うので、その前提で進めます。
以下の手順で用意しましょう。
このサイトからSpring Bootアプリケーションの雛型を簡単に作成することができます。
Spring Initializr
「Dependencies」の欄以外は全てデフォルトのままで良いです。
(すぐデザインが変わりますが)「ADD DEPENDENCIES」ボタンを押してDependencies(依存性)に追加しましょう。
「依存性」とは、そのプロジェクトで使用するライブラリという理解で良いです。
候補が表示されますのでその中から「Spring Web」と「Thymeleaf」を選択してください(検索ボックスも使えます)。
「Spring Web」はWebアプリケーション用のライブラリです。
「Thymeleaf」はテンプレートエンジンと呼ばれるものの一種で、Webアプリケーションが表示するHTMLを効率よく生成する為のライブラリです。
2つを選択した状態で「GENERATE」ボタンを押すとSpring Bootアプリケーションの雛型プロジェクトファイル(demo.zip)をダウンロードできます。
ダウンロードしたdemo.zipをC:\workspace
配下に解凍しておきましょう(場所は変えても良いです)。
さて、雛型の状態ではSpring Bootアプリケーションを起動する為の最低限のソースファイルしか入っていませんので、この状態ではWebアプリケーションとして役に立ちません。起動するだけで何もできない、まさに聳え立つクソ。
さて、Visual Studio Codeのメニューから「ファイル」⇒「フォルダーを開く」でC:\workspace\demo
を開きます。
Visual Studio Codeのエクスプローラーからsrc\main\java\com\example\demo\DemoApplication.java
を開いてみましょう。
こちらのクラスにmainメソッドがあります。
これを実行することでWebアプリケーションに必要なコンテナを含むSpring Bootアプリケーションが起動します。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
同フォルダにSampleController.javaという名前で(別に何でもいいけど)ファイルを作りましょう。
demo
フォルダを右クリック⇒「新しいファイル」を押して名前を入力してください。
自動的にエディタが開かれると思いますので中身を以下のように書き換えてください。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class SampleController {
@RequestMapping("/add")
public String add(Model model, @RequestParam("a") int a, @RequestParam("b") int b) {
model.addAttribute("result", a + b);
return "result";
}
}
Controllerと名前を付けているのは、MVCモデルに基づいた名前です。
Controllerはユーザのリクエストを制御します。
MVCモデルについて
中身についてですが、このコントローラが何をするか。
アプリケーションは人の役に立たなければなりません。ということで、人様の役に立つ機能を実装します。
ズバリ、足し算。
上のコードは「addというアドレスにアクセスがあった場合、2つのリクエストパラメータを合算した値をmodel
という領域にresult
という名前で保存して、result
という名前のViewへ遷移する」ということをしています。
model
はMVCモデル上のModelに相当します。Modelはビジネスロジックを担当し、Viewから参照されるデータを保存します。
ViewはMVCモデル上で入出力を担当するレイヤーです。
今回はHTMLを表示したいので、HTMLを表示するViewに処理を任せます。
プロジェクトファイルを作成するときにThymeleafというライブラリをDependenciesに追加しましたよね。
Thymeleafはsrc\main\resources\templates
配下からresult.html
を探します。
まだ作ってないのでないんですけど。
というわけで用意します。
templates
フォルダを右クリック⇒「新しいファイル」を押して名前を入力してください。
ファイル名は「result.html」にします。
中身を以下のように書き換えてください。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Result</title>
</head>
<body>
★★★
<h1 th:text="${result}"></h1>
☆☆☆
</body>
</html>
このHTMLファイルはテンプレートエンジンであるThymeleafが解釈するためのテンプレートファイルです。
このファイルが直接ユーザの見ているブラウザに表示されるのではなく、このファイルを元に動的な部分を編集してブラウザに応答します。
上のファイルで動的な部分は${result}
ですね。これはcontrollerでmodel
にresult
という名前で保存された値を表示するという動きになります。
HTMLタグの中にあるth:
から始まる属性はThymeleaf用の属性です。
さて、これをローカルマシン上で動かしてみましょう。
Visual Studio Codeのメニューから「実行」⇒「デバッグの開始」でデバッグ実行されます。
以下のような感じのログが流れたら準備完了です。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.0.RELEASE)
2020-06-10 02:43:31.001 INFO 10456 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on XXX-Machine with PID 10456 (C:\workspace\demo\target\classes started by quinq in C:\workspace\demo)
2020-06-10 02:43:31.004 INFO 10456 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2020-06-10 02:43:32.007 INFO 10456 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-06-10 02:43:32.017 INFO 10456 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-06-10 02:43:32.018 INFO 10456 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.35]
2020-06-10 02:43:32.075 INFO 10456 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-06-10 02:43:32.075 INFO 10456 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1026 ms
2020-06-10 02:43:32.199 INFO 10456 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-06-10 02:43:32.363 INFO 10456 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-06-10 02:43:32.373 INFO 10456 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.68 seconds (JVM running for 2.13)
ブラウザで以下のURLにアクセスしてみてください。5+3のリクエストです。
http://localhost:8080/add?a=5&b=3
こんな画面が出たら成功です。答えは8。これ合ってるよね?
★★★
8
☆☆☆
ついでにテストを実装しておきましょう。
既にテストケース格納用のディレクトリ\src\test\java\com\example\demo
が用意されています。
\src\main\
じゃなくて\src\test\
ですのでお間違えなく。
そのdemo
フォルダを右クリック⇒「新しいファイル」を押して名前を入力してください。
ファイル名は「SampleControllerTest.java」にします。
中身を以下のように書き換えてください。
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
@ExtendWith(SpringExtension.class)
@WebMvcTest(SampleController.class)
public class SampleControllerTests {
@Autowired
private MockMvc mockMvc;
@Test
void add() throws Exception {
this.mockMvc.perform(get("/add").param("a", "5").param("b", "3")).andDo(print()).andExpect(status().isOk())
.andExpect(view().name("result")).andExpect(model().attribute("result", 8));
}
}
パラメータ5と3をリクエストしたらモデルに8が設定されることを確認するテストです。
中身の詳細は追々理解していけば良いです。
テストケースが足りないって?今はそれどころではない。
SampleControllerTests.javaファイル内の
public class SampleControllerTests {
のすぐ上に
Run Test | Debug Test
みたいなリンクが現れるでしょう。
そのリンクを押せばテストが実行されます。
Java Test Reportが開いてテストadd
がPassed
と表示されましたでしょうか?
これでテストケースを備えたSpring Bootプロジェクトが用意できましたね。
いよいよ準備完了です!
あ、因みに準備は15分にカウントしないからね。
デプロイ
先程あなたが用意したSpring Bootを使ったWebアプリ。
インターネットに公開する為には、インターネットからアクセスできる場所にWebアプリを配備しなければなりません。配備のことをデプロイといいます。
Heroku
世の中何かを利用すればコストがかかりますが、タダで使わせてくれるものもあります。
Herokuプラットフォームはその1つで、更にクレジットカードの登録なしに使わせてくれる、非常にありがたい稀有なサービスです(制約はあるが)。タダより高い物はない。
ソースコードをHerokuのビルドシステムにデプロイすると、アプリをビルドし、Dynoというアプリケーションの実行環境にデプロイしてくれます。
Herokuの特徴的なところとして、Herokuの用意してくれる特定のGitリポジトリにソースコードをpushすることでWebアプリがビルドされ、デプロイされる、という点があります。
Herokuアカウントを取得する。
とりあえずHerokuのアカウントを取得します。
Heroku公式
安心の日本語。
- 右上の「新規登録」ボタンを押します。
- 必要な項目を入力し「無料アカウント作成」ボタンを押します。
- 入力したメールアドレス宛にメールが送られてきます。
- 受信したメールの本文にあるリンクをクリックします。
- 好きなパスワードを入力し「パスワードを設定しログインする」ボタンを押します。パスワードは記号必須です(面倒)。
- 登録完了しました。「ここをクリックして次へ進む」ボタンを押します。
- ダッシュボードの画面に遷移しますので「Create new app」ボタンを押します。
- Herokuアプリ名を入力して「Create app」ボタンを押します。Herokuアプリ名はURLにもなります。リージョンも選べますがとりあえずそのままで良いです。
- Herokuアプリが作成されます。
Heroku CLIをインストールする。
さてHerokuアプリをローカルで管理する為にHeroku CLIというものが必要になります。CLIとはコマンドラインインタフェースのことで、とりあえずコマンドプロンプト上で動くプログラムという認識で良いかと思います。
- 画面内に「Download and install the
Heroku CLI
.」のリンクがあると思いますのでクリックしてください。 - Windows用の「64-bit installer」ボタンを押してインストーラーをダウンロードしてください(32bitの人いる?)。
- インストールは全部脳死で「next」押しておけば良いです(これ読んでるような人は)。
- インストール完了するとコマンドプロンプトでHerokuコマンドが使えるようになっています。
Herokuと連携する。
コマンドプロンプトからHerokuへログインしてみましょう。
$ heroku login
なんかキーを押すように促されるのでなんか押しましょう(q以外)。
ブラウザが立ち上がり、Herokuのサイトが開きます。
「Log In」ボタンを押しましょう。
これでこのマシンはHerokuと連携できるようになりました。
ローカルでリポジトリを作成する。
コマンドプロンプトでC:\workspace\demo
を開きましょう。
素直にCDしても良いですが、エクスプローラでC:\workspace\demo
を開いている際にアドレスバーにcmd
と打ち込むとC:\workspace\demo
に遷移した状態でコマンドプロンプトが開きます。便利。
素直にGit Bash開けって?はいはい。
まずローカルリポジトリを作成します。
以下のコマンドを打ったフォルダには、配下に.git
という隠しフォルダが生成されそのままローカルリポジトリになります。
$ git init
次に以下のコマンドで、プロジェクトディレクトリ配下を丸ごとバージョン管理対象に追加します。
$ git add .
この時点ではまだコミット、つまりリポジトリへは登録されていません。
以下のコマンドでリポジトリに登録(コミット)します。
コメントは何でも良いですが、内容が分かるものにしてください。
$ git commit -m "コミットコメント"
さて、gitをインストールしてから何もしてない人はここで
*** Please tell me who you are.(誰だよおまえ)
と怒られたのではないかと思います。
この場合、次のコマンドで名前を登録します。グローバルオプションを付けておくと他のリポジトリでも有効になります。
$ git config --global user.name "ユーザ名"
ついでにメールアドレスも登録します。
$ git config --global user.email メールアドレス
再度コミットコマンドを実行してください。
Herokuリポジトリに登録する。
前述したようにソースコードをHerokuアプリに紐づくHerokuリポジトリに登録することでWebアプリがデプロイできます。
まず、以下のコマンドで、そのHerokuリポジトリをローカルリポジトリに対するリモートリポジトリとして登録します。
$ heroku git:remote -a Herokuアプリ名
次にコミットしたものを以下のpushコマンドでリモートリポジトリに反映します。
push先のブランチは必ずmasterブランチでなければなりません。
$ git push heroku master
大量のログが流れていきますが、無事成功すれば
remote: [INFO] BUILD SUCCESS
…
remote: http://Herokuアプリ名.herokuapp.com/ deployed to Heroku
というログが出て、確かにWebアプリがビルドされ、デプロイされていることが分かるかと思います。
さて、では、そのWebアプリを見に行ってみましょう。
上のURLをぶっ叩いてもいいですし、以下のコマンドでも開けます。
$ heroku open
いかがでしょうか?
えー、この記事の通りに素直にSpring Bootのプロジェクトファイルを用意してしまった場合、エラー画面が出たんじゃないかと思います。
大丈夫です。まだ慌てる時間ではありません。
インデックスページを用意していないからルートのアドレスにアクセスしてもエラーになるんですよね。
以下のURLなら大丈夫です!
http://Herokuアプリ名.herokuapp.com/add?a=5&b=3
いかがでしょうか?(しつこい)
これでもうインターネットに公開されています。
あなたのWebアプリが世に出てしまいました。
アプリ上で著作権を侵害すれば訴えられますし、ヤバいものを公開すればタイーホです。気を付けましょう。
5分たったかな?
CI/CDを考える。
CI/CD
(Continuous Integration / Continuous Delivery(&Deployment):継続的インテグレーション/継続的デリバリー(&デプロイ)) とは、アプリケーション開発において、修正、テスト、マージ、ステージに自動化を取り入れて、アプリケーションを提供する頻度を高める手法です。
参考ページ
CI/CD とは-継続的インテグレーション/継続的デリバリー|Red Hat
継続的インテグレーションがなされているというのは、修正が定期的にビルドされ、テストされ、共通リポジトリに統合されていることを指します。
継続的デリバリー或いはデプロイでは継続的インテグレーションを受けて本番用のリポジトリにリリースされ、テストされ、更に本番環境にデプロイされます。
このように修正からリリースまでのプロセス、これを開発パイプラインを自動化することで細かい粒度で修正をコミット、マージすることが可能になり、それはバグや競合の早期検出を可能にし、アプリのリリース頻度と速度を向上させることができます。
これはアジャイル開発と非常に相性がいい手法です。
なぜならばアジャイルの神髄は速度だから。
さて、Herokuはリポジトリにコミットした時点で本番環境にリリースされるので、今の状態でもある意味継続的デプロイがされていると言えるかもしれません…が、1人で開発している場合はこのままでもいいのですが、グループで開発しようとなるとリモートリポジトリがHerokuで、しかもpushしたら即リリースというのはちょっと都合が悪い。
幸いなことにHerokuはGitHubと連携しているのでGitHubのリポジトリを使用してグループでの開発を可能にしてみましょう。
GitHubアカウントを取得する。
GitHubは先ほど出てきたGitをオンラインで提供してくれるサービスです。
GitHub公式
- 右上の「サインアップ」ボタンを押します。
- 必要な項目を入力します。なんか人間の証明とかいってクイズ解かされます。
- 「Select a plan」ボタンを押します。
- 個人で開発するなら「Individual」プラン、チームで開発するなら「Team」プランを選択します。
- 「Free」プランを選択します。
- 仕事とか興味とか聞かれるので適当に回答を。
- 「Complete setup」ボタンを押します。
- 入力したメールアドレス宛にメールが送られてきます。
- 受信したメールの本文にあるリンクをクリックします。
- アカウント登録完了です。
GitHubリポジトリを作成する。
HerokuのGitリポジトリと連携する為のGitHubリポジトリを作成していきましょう。
- 左上の「Create repository」ボタンを押します。
- リポジトリ名を適当に入力します。
- 公開して誰に見られても良ければ「Public」、公開したくなければ「Private」を選択します。無難に「Private」を推奨しておきます。誤って何かマズいものを登録してしまってもとりあえず安心ですから。
- 「Initialize this repository with a README」というチェックボタンにチェックするとリポジトリにデフォルトのREADME.mdファイルが作成され、これからローカルリポジトリの内容をpushする際に競合が発生するのでチェックしないでおきましょう。
- 「Create repository」ボタンを押します。
- リポジトリ登録完了です。
画面内に記載されているURLがあなたのGitリポジトリのURLです。
https://github.com/Gitアカウント名/GitHubリポジトリ名.git
「Private」で作成している場合、リポジトリは非公開リポジトリとなり、作成したアカウント以外からのアクセスはできません。
しかし他のGithubアカウントをコラボレータとして登録すれば参照できるようになります。チームで開発する際に利用してください。
作成直後のリポジトリは空っぽです。
この画面を開きっぱなしにして次に行ってください。
GitHubリポジトリに反映する。
再びコマンドプロンプトでC:\workspace\demo
を開きましょう。
作成したGitHubリポジトリをリモートリポジトリとして登録します。
名前はoriginにします。慣習的に。
$ git remote add origin https://github.com/Gitアカウント名/GitHubリポジトリ名.git
これでリモートリポジトリはHerokuとGitHubのリポジトリの2つになりましたね。リモートリポジトリの一覧は以下のコマンドで確認できます。想定通りの結果になっていますか?
$ git remote
heroku
origin
さて、さっきGitHubに作成したリポジトリは空っぽなので、ローカルリポジトリの内容をpushしましょう。
$ git push origin master
pushしようとするとGitHubに認証させられますのでGitHubのアカウントとパスワードでログインしてください。
一度認証すれば以降は求められなくなります。
pushが完了したのでGitHub上で確認しましょう。
先程開きっぱなしにした画面を更新してみてください。
作成したWebアプリのソースコード群が登録されているはずです。
これであなたの家が炎上してPCが消し炭になっても大丈夫です。
Heroku開発パイプラインを設定する。
さて、今度はHerokuで開発パイプラインを設定して、GitHub上のリポジトリにコミットした内容を自動でデプロイできるようにしていきます。
ただ、残念なことに(無料では)自動試験が動かないのです。
CI/CDを真っ当に実現するには自動ビルドに伴って自動テストを行いたいのですが、Herokuで自動テストを動かすにはHeroku CIというアドオンが必要で、そのアドオンを有効化するのは有料なのです。
なのでまぁ、今回はなんちゃってCI/CDということでお許しください。
まず開発パイプラインを作成します。
- Herokuダッシュボードから画面右上の「New <>」みたいなボタンを押して「Create new pipeline」を選択します。
- 適当にパイプライン名を入力します。
- 「Connect to GitHub」ボタンを押します。
- GitHubの認可画面が開いて、Herokuとの連携を認可するかを聞かれます。
- 「Authorize heroku」ボタンを押します。
- 「Create pipeline」ボタンを押します。
- パイプラインの画面が開きます。
次に開発パイプラインをGitHubリポジトリと連携させます。
- 「Settings」タブを選択します。
- 「Connect to GitHub」欄にある「Search」ボタンを押して、GitHubで作成したリポジトリを検索、選択してください。
- 「Connect」ボタンを押します。
- これでHerokuの開発パイプラインがGitHubのリポジトリと連携されました。
- 「Pipeline」タブを選択します。
画面内に
REVIEW APPS ⇒ STAGING ⇒ PRODUCTION
という流れが表示されています。これがパイプラインです。
REVIEW APPSは名前の通りレビュー用アプリです。
STAGING(ステージング)は試験用アプリです。
PRODUCTIONは製品アプリ、つまりこれがインターネットに公開されるアプリになります。
まずレビュー用アプリから設定していきます。
- 「Enable Review Apps」ボタンを押します。
- 画面右にダイアログが表示されるので「Create new review apps for new pull requests automatically」にチェックします。
- ダイアログの「Enable Review Apps」ボタンを押します。
これでGitHubリポジトリにプルリクエストが発行された場合にレビュー用のアプリが自動的に作成されるようになりました。
プルリクエストは、「自分が修正した内容をあなたのリポジトリにマージしてください」という要求です。ここでは、開発用に用意したブランチにおける修正を、インターネットに公開している製品アプリに反映したい場合にプルリクエストを発行することになります。
プルリクエストの内容がマージされたレビュー用アプリが自動生成されるので、マージ前に自動試験を行い、品質を担保することが可能になるということです。課金していればですが。
課金しなくともレビュー用アプリを開いて(手動で)試験することもできます。
次に試験用アプリを設定します。
- STAGING欄にある「Add app」ボタンを押します。
- 「Create new app…」ボタンを押します。
- 画面右にダイアログが表示されるので試験用アプリ名を入力します。
- ダイアログの「Create app」ボタンを押します。
- STAGING欄にある「<>」を縦にしたようなボタンを押します。
- 「Configure automatic deploys...」を選択します。
- デプロイするブランチにmasterが選択されているので、そのまま「Enable Automatic Deploys」ボタンを押します。この際、「Wait for CI to pass before deploy」のチェックボックスがありますが、これは「デプロイの前に継続的インテグレーションがパス、つまり試験結果が正常であることの確認を待つかどうか」です。ただこれさっき書いた通り有料のやつなので非課金だとテストが動きません。非課金の場合無視されると書いてあるサイトもあったのですが、私が試した限りでは自動デプロイが動作しなくなったので多分チェックしちゃいけないっぽい。まぁチェックしたところでテストが動かないんじゃ意味ないですが。
- これで自動デプロイが有効になりました。GitHubのmasterブランチに新しくコミットされた場合、試験用アプリが自動生成されます。間違って「Disable Automatic Deploysボタンを押さないでください。
STAGING欄の「Open app」ボタンを押せば試験用アプリが開きます。(手動で)試験することもできます。
最後に製品用アプリの設定です。
- PRODUCTION欄にある「Add app」ボタンを押します。
- テキストボックスに最初に作成したHerokuアプリ名を入力して検索します。
- 以上です。製品用アプリについてはあえて自動デプロイは有効にしないでおきます。最後のリリース判定は人間の手で行いたい!という趣味です。もちろん自動デプロイを有効にして、プルリクエストをマージしたらリリースまで自動化することも可能です。お試しあれ。
GitHub Actionsで継続的インテグレーションを実現する。
さて、絶対に課金はしたくないでござるが、やっぱ自動試験はしたい。
そんな絶対非課金マンに送るのがGitHub Actions。
GitHubのリポジトリ画面から「Actions」タブを開きましょう。
GitHub Actionsの詳細は割愛しますが、様々なワークフローを自動化するもので、最初から様々なテンプレートが用意されています。
Java with MavenはMavenを利用したJavaアプリの継続的インテグレーションのワークフローテンプレートです。
テンプレートの中身は簡単に言うと、
「masterブランチにpushかpull requestが行われた際にmavenのpackageコマンドを動かします」
というワークフローです。つまりビルドとテストが自動実行されるというわけです。
- Java with Maven欄の「Set up this workflow」ボタンを押します。
- maven.yamlという定義ファイルの内容が表示されます。
- 右端の「Start commit」ボタンを押します。
- コミットコメントを入力して「Commit new file」ボタンを押します。
- GitHubリポジトリに継続的インテグレーションのワークフローが設定されました。
これで、Herokuの開発パイプラインと合わせて「なんちゃってCI/CD環境」が整備されたので、次からCI/CDを体験していきます。
作業用ブランチを切る。
ここまではリポジトリにmasterブランチしか存在しませんでした。一人で開発する場合にはそれでも良いかもしれませんが、チームで開発する場合には並行作業が必要となるでしょうから不都合が生じてきます。
各作業者が、作業用のブランチを作成して、そのブランチ上で作業を進めた方が効率的です。
作業用ブランチの作業が完了後、masterブランチに対してプルリクエストを発行します。プルリクエストを受けて、レビュアーが内容を検証し、問題なければマージします。今日は登場人物が一人しかいないので自作自演になりますが。
では再びコマンドプロンプトでC:\workspace\demo
を開きましょう。
以下のコマンドで作業用ブランチを切ることができます。
$ git checkout -b 作業用ブランチ名
ここまでずっとGitコマンドを使用してきましたが、コマンドの代わりにVisual Studio Code上のGUI操作でも可能です。
参考ページ
VSCodeでのGitの基本操作まとめ
機能追加する。
せっかくなのでここで機能追加してみましょう。
足してばっかりじゃ疲れるので引き算機能を追加することにします。
足し算と引き算があればどこへでも行ける。
まぁパラメータに負数を指定すれば機能追加する必要はないけどな。
Visual Studio Codeを開きましょう。
SampleController.javaを以下のように改修します。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class SampleController {
@RequestMapping("/add")
public String add(Model model, @RequestParam("a") int a, @RequestParam("b") int b) {
model.addAttribute("result", a + b);
return "result";
}
// 追加したところ はじまり
@RequestMapping("/sub")
public String sub(Model model, @RequestParam("a") int a, @RequestParam("b") int b) {
model.addAttribute("result", a + b);
return "result";
}
// 追加したところ おわり
}
subというアドレスに対応しました。ほぼほぼaddのコピーです。
subはsubtract(引く)の略です。三河屋じゃないです。
returnで返却しているView名がaddと同じですが、結果を表示するという機能は同じで良いので、そのまま使用します。
機能追加分をテストを追加する。
機能を改修したならばそれに合わせてテストコードも改修する必要があります。
今回は引き算機能を追加したので、引き算用のテストケースを追加します。
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
@ExtendWith(SpringExtension.class)
@WebMvcTest(SampleController.class)
public class SampleControllerTests {
@Autowired
private MockMvc mockMvc;
@Test
void add() throws Exception {
this.mockMvc.perform(get("/add").param("a", "5").param("b", "3")).andDo(print()).andExpect(status().isOk())
.andExpect(view().name("result")).andExpect(model().attribute("result", 8));
}
// 追加したところ はじまり
@Test
void sub() throws Exception {
this.mockMvc.perform(get("/sub").param("a", "5").param("b", "3")).andDo(print()).andExpect(status().isOk())
.andExpect(view().name("result")).andExpect(model().attribute("result", 2));
}
// 追加したところ おわり
}
こちらもほぼほぼコピーです。
パラメータ5と3をリクエストしたら5-3ですからモデルに2が設定されることを確認するテストです。…合ってるよね?
さて、本来ならここでテストを実行するところですが、この機能追加を担当したのはいい加減なSEなので、無試験で作業を終わらせた…ということにしましょう(テストコードを書いているところは律儀だが)。
リポジトリに反映する。
まず修正内容をステージングに追加する(ここでは変更内容をコミット対象として認識することと思ってください)為に、最初の時と同じく以下のコマンドを実行します。新ファイルがない時でも必要です。
$ git add .
改修内容をローカルリポジトリにコミットします。
$ git commit -m "コミットコメント"
リモートリポジトリorigin(GitHubリポジトリ)にpushします。herokuにpushしないでください(その時点でリリースされてしまうから)。
$ git push origin 作業用ブランチ名
これでGitHubリポジトリ上にローカルリポジトリと同じく作業用ブランチが登録されました。
masterブランチへのプルリクエストを発行し、マージする。
ではGitHubリポジトリ上で作業用ブランチの改修内容をmasterリポジトリにマージしていきます。
- GitHubリポジトリの画面上の「New pull request」ボタンを押します。
- Compare changesという差分比較用の画面が開かれます。
-
base:master▼ ← compare:master▼
みたいな欄がありますので、compareの方の▼を押して比較対象の方のブランチを作業用ブランチに切り替えてください。 - 欄の横に緑色のチェックマークと「Able to merge」の文字が表示されるでしょう。競合が発生せず、マージ可能ということを示しています。
- その下のプルリクエストタイトル欄にコミット時のコメントが入っており、更に下にプルリクエストコメントを入力する欄があります。本来はここでマージ作業者向けにプルリクエストの内容を説明します。
- 「Create pull request」ボタンを押します。
- プルリクエストの発行完了です。
ここでHerokuのパイプラインの画面を見てみると、REVIEW APPSに発行したプルリクエストの内容のレビュー用アプリが作成されているのが分かります。
ビルドエラーの場合、非課金でも「ビルドエラーだからビルドログ確認しろや!」というメールは飛んできます。小さな親切。
さて、GitHubのリポジトリの「Pull requests」タブが開かれていると思いますが、何やら赤いバツ印が付いていませんか?
そう、GitHub Actionsによる自動テストが機能し、そのテストでコケたということをお知らせしてくれているのですね。
「Details」のリンクをクリックして詳細を確認してみましょう。
「Build with Maven」に×がついています。
更に詳細内容を確認すると、機能追加分のテストケースが失敗していることが分かりますね。
そう、実は先程の機能追加内容が間違っていたんですね。
// 追加したところ はじまり
@RequestMapping("/sub")
public String sub(Model model, @RequestParam("a") int a, @RequestParam("b") int b) {
model.addAttribute("result", a + b); // + じゃなくて - にしないとダメだった。
return "result";
}
// 追加したところ おわり
既に自力で見つけていて「ここ間違っとるやんけ!修正したろ!」と勝手に修正し試験に成功してしまった読者の方、すいませんでした。
なにはともあれ、レビュアーがレビューする前に、プルリクエスト発行した怠慢SEが試験実行してなかったことが白日の下に晒されましたね。他人の「試験シマシタ」は信じてはいけないのです。
// 追加したところ はじまり
@RequestMapping("/sub")
public String sub(Model model, @RequestParam("a") int a, @RequestParam("b") int b) {
model.addAttribute("result", a - b); // + から - にした。
return "result";
}
// 追加したところ おわり
念の為、テストを実行し、テストsubがPassedと表示されることを確認しましょう。
問題なければ再pushしてください。再pushすることでプルリクエストの内容が自動的に変更されます。
$ git add .
$ git commit -m "コミットコメント"
$ git push origin 作業用ブランチ名
GitHubリポジトリの「Pull request」タブを再表示してみてください。
無事にグリーンの文字で「All checks have passed」と表示されているかと思います。
さて、試験は通っているけれどもそもそも怠慢SEのテストコードはもとよりコード自体もレビュー未の状態です。
「Pull request」タブの画面から差分を確認できますので、内容をしっかり確認し、問題なければ「Confirm merge」ボタンを押しましょう。
本番リリースする。
Herokuパイプラインの画面に戻ってください。
STAGING欄に新しい試験用アプリがデプロイされていることが確認できると思います。
このステージングの状態が開発者から運用担当者に引き渡された状態と言ってもいいかもしれません。
この試験用アプリの受け入れ確認が完了したテイで、話を進めます。
受け入れ確認の結果が偉い人に確認され、製品アプリを本番リリースする承認が下りたというテイです。
STAGING欄の「Promote to production」ボタンを押します。
「Promote」ダイアログが表示されます。
最後にこのボタンを押すと本番リリースです。「Promote」
リリースが完了しましたので、インターネット上で動作確認してみましょう。
ちゃんと引き算できていますでしょうか?
★★★
2
☆☆☆
おわりに
今回はここまでです。
これをベースにオリジナリティの溢れるアプリを作成して誰かに見てもらいましょう!
【おまけ】マネタイズについて。
最後にマネタイズの話をします。
マネタイズとは、一般的に、事業から収益が得られる仕組みを作ることです。
Webアプリを作って生きていくには収益が得られなければ話になりません。
素晴らしいWebアプリを作ることができたら次はそれを収益に変えることを考えましょう。
Webアプリで収益を得る方法は一つではありません。
その1:ユーザに課金する。
もっともダイレクトに金を巻き上げる方法ですが、最も困難な方法とも言えます。
人はネットでできることに金を払うという意識があまりありません。
10円たりとて課金させるのは極めて困難と言わざるを得ないです。
なぜなら世の中タダで使えるサービスが多いから(Herokuしかり、GitHubしかり)。
LINEですら課金率は半分以下だとかなんとか。
有名なラーメンハゲのセリフではありませんが「金をもらう」ということはサービスに責任を負うということであり、最悪賠償もあり得ます。
その2:広告収入を得る。
その2っていうか紹介するのはこれで終わりですが、広告を掲載して広告主からインセンティブを得る方法です。
まぁ現実的に考えてこの方法しか、普通はないです。
最もメジャーなのがGoogle AdSenseです。
しかし、広告を掲載する為には審査に合格しないといけません。
つまりアプリがコンテンツとして既に完成していて、まともに人の役に立つ状態じゃないと合格できないとのことです。
更にプライバシーポリシーの提示など色々な条件を満たさないといけません。
因みに自分で広告をクリックしたり、同一人物が複数回クリックしたりしただけですぐアカウント停止を食らったりします。
あとおまけにGoogle AdSenseはサブドメインの使用を許していないので
Herokuアプリ名.herokuapp.com/
↑このURLだと申請が通らないというわけです。
申請する為には独自ドメインを持つ必要があります。
dokuji-domain.com
↑こんな感じにならにといけない。
世の中には独自ドメインを取得するサービスがあるんですが、まともなところはお金がかかります。
聞いたこともないようなトップレベルドメインなら無料で使えるサイトもあるようです。
freenom
ただ、無料で使える代わりに、想定されたアクセス数を超えなければいけないとか制限があったりしますので、よく考えて選ぶ必要があります。
願わくばドメイン料金がゴミに思えるほどのアクセス数と広告収入を稼いで頂きたいと思います。