sakutarou’s blog

とりあえずWeb系技術をゆるく書いていく

GitHub Appsを作ってみたら色々詰まって苦労した。。。

開発合宿でGitHub Appsでアプリを初めて作ってみました
自分が詰まったところを中心に情報を残します

fusic.co.jp

GitHub 連携

GitHubで何かしら連携をやろうと考えた場合以下が考えられます。
上3つは今でも使ったことがあるのですが、GitHub Appsは全く使ったことがありませんでした。
なので今回は GitHub Apps にトライしてみました。

GitHub Appsって何?

特徴としては以下

  • organization単位にインストールすることが可能(個人アカウントで作成することも可能)
  • 特定のリポジトリのみにアクセス権を与えることが可能
  • 詳細な権限設定とWebhookが利用可能
  • JWT認証をすることでAPIコールも可能
  • 一般公開も可能(自分の組織に限定することも可能)

要は、OAuthなど今まで個人に紐づいていたものが組織に紐づいて、且つ WebhookとAPIコールもくっついてくるすっごい便利なものだよと

GitHub Appsの登録

とりあえず最初にAppsの登録をします。
ここで Webhookや権限などを設定しておきます。

Creating a GitHub App | GitHub Developer Guide

JWT認証

APIをコールする為には、JWT認証を行いトークンを取得する必要があります。
ここでがっつり詰まってしまいました。

どうすればいいの

このURLに対して証明書と一緒にPOSTを送信するだけ!
すっごい簡単!
※ :installation_id は自身のものに修正する
https://api.github.com/installations/:installation_id/access_tokens

つまりポイントその1

そもそも installation_id って何!

WebHookリクエストの一部としてくっついてきます。

  # 上省略
  "installation": {
    "id": XXXXXX
  }

これでPOSTが送信できる!

つまりポイントその2

何をPOSTすればいいのか分からない!
以下をPOSTします。

- "iat": 現在日時タイムスタンプ,
- "exp": 発行するJWTの失効日時タイムスタンプ(最大10分), 
- "iss": GitHub App's identifier

GitHub App's identifier 何これ!
こいつが何かわかりませんでした。。。

作成したGitHub AppsのGeneralページにある AboutのIDGitHub App's identifier になります。
Private key も 同じ場所にあります。

つまりポイント3

ヘッダーは以下を指定する

"Authorization": "Bearer 作成したJWT",
"Accept": "application/vnd.github.machine-man-preview+json"

何つくったの?

GitHub + Amazon API Gateway + AWS Lambda *+ PythonGitHubラベル管理アプリを作りました。
ソースコードを整理できたら公開するかも。。。

参考URL

https://qiita.com/icoxfog417/items/fe411b94b8e7ae229e3e

Authentication options for GitHub Apps | GitHub Developer Guide

Travis CIみたいなGitHub連携アプリってどうやって作るんだ

GitHubで使われている Travis CI のような連携アプリを作りたい!
と思いついたので、まずはステータスを切り替えれるようにするところまで進んでみる。
※セキュリティとか置いておいて、まずは必要最低限まで

f:id:sakutarou:20170219234506p:plain

アプリケーション作成

以下の順番でアプリケーション作成画面まで進む。
[GitHub] - [Settings] - [OAuth applications] - [Register a new application]

進めたらアプリケーション作成

f:id:sakutarou:20170219235408p:plain

f:id:sakutarou:20170219235422p:plain

callback URL Client ID Client Secret をメモっておきます。

OAuth認証

まず、GitHubにアクセス
Client ID には先ほどメモっておいたものを使います。

https://github.com/login/oauth/authorize?client_id={Client ID}&scope=repo:status

認証を行うと callback URL に設定したURLに code が戻ってきます。

http://example.com/oauths/callback?code={コード}

次に コード を利用して、アクセストークンを取得します。
取得した、 コード Client ID Client Secret を利用します。

https://github.com/login/oauth/access_token?code={コード}&client_id={Client ID}&client_secret={Client Secret}

GitHubステータス変更

以下のAPIを実行して対象プルリクエストの head => sha を取得する

https://api.github.com/repos/:owner/:repo/pulls

- :owner => GitHubユーザー
- :repo => リポジトリ

以下のURLに対して必要な情報をPOSTします。

https://api.github.com/repos/:owner/:repo/statuses/:sha

- :owner => githubユーザー
- :repo => リポジトリ名
- :sha => pullsで取得した sha

POST値

JSONで以下の内容をPOSTする

  • state : pending, success, error, failure のいづれか
  • target_url : 詳細ページへのリンク
  • description : 説明
  • context : 見出し

その他

アクセストークンの使い方

Authorization: token {アクセストークン} の形でヘッダーに組み込む

  or

?access_token={アクセストークン} の形でGET値のパラメーター組み込む

UserAgentが必須である

ヘッダーにユーザーエージェントとして、 アプリ名 を指定する

とりあえず、ここまで
次はhook処理

Vagrant + Hyper-Vでboxを作成する

自分の開発環境はVagrant + Hyper-Vを使っているのですが、 今回ノートPCを新しく購入したこともあって、ゼロからVagrantを起動しようとしたら自分が利用していたboxの公開が終了してました。。。

Vagrant + Hyper-Vは選択肢少ないんですよね。。。

なので今回はbox作成をメモ代わりに残しておこうと思います。
Windows + Hyper-Vなこともあって色々躓きました。。。

ここに記載する内容は必要最低限にしてあります。

CentOS7のイメージ(iso)からOSを起動する

以下のURLからCentOSのイメージをダウンロードして、CentOSを立ち上げます。
自分は Minimal ISOCentOS7 64bit を利用しました。

Download CentOS

hypervkvpdのインストール

hypervkvpd をインストールしておかないと Waiting for the machine to report its IP address... と出たところでタイムアウトします。

yum install hypervkvpd
systemctl enable hypervkvpd

vagrantユーザーの作成 + 鍵ファイルの設置

passwd # rootのパスワードはvagrantに設定
useradd -g wheel vagrant
passwd vagrant # vagrantのパスワードはvagrantに設定
mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh

cd /home/vagrant/.ssh
curl -k -L -o authorized_keys 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub'
chmod 600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant:wheel /home/vagrant/.ssh

その他設定

systemctl stop firewalld
systemctl disable firewalld

vi /etc/selinux/config
- SELINUX=enforcing
+ SELINUX=disabled

vi /etc/sysctl.d/disable_ipv6.conf

+ net.ipv6.conf.all.disable_ipv6 = 1
+ net.ipv6.conf.default.disable_ipv6 = 1

vi /etc/sysconfig/network-scripts/ifcfg-eth0
- UUID=XXXXXXXXXXX

sudoの設定

visudo

# コメントアウトを外す
%wheel  ALL=(ALL)       NOPASSWD: ALL

キャッシュの削除

完成するbox自体のサイズを小さくするために、キャッシュを削除しておきます。

yum clean all
rm ~/.bash_history
history -c

OSの終了

shutdown -h now

作成したOSをエクスポートする

Hyper-V マネージャーを開いて、仮想マシンをエクスポートします。

f:id:sakutarou:20170213000715p:plain

boxの作成(その1)

エクスポートしたフォルダを開くと以下のようになってるはずです。

  • Snapshots
  • Virtual Hard Disks
  • Virtual Machines

上記のうち、 Snapshots は不要なので削除します。

boxの作成(その2)

エクスポートしたフォルダに metadata.json を作成する。
最低限以下のような内容になります。

{
    "name": "sakutarou/centos7",
    "provider": "hyperv"
}

作成後、以下になります。

  • Virtual Hard Disks
  • Virtual Machines
  • metadata.json

boxの作成(その3)

Virtual Hard Disks , Virtual Machines , metadata.json の3つ選択した状態で、zip圧縮します。
※この時、上階層のフォルダを選択してzip圧縮するではなく、3つを選択して圧縮してください。

zipファイルが完成後、拡張子を .box に変更してください。

これでbox完成です。

boxとして利用する

以下のコマンドを実行すれば、作成したboxファイルを利用することが出来ます。

vagrant box add --name "sakutarou/centos7" "centos7.box"

もしくは、atlasにアップするなどして利用してください。

その他

これ使ったら、もっと簡単に作成できるかも?
何も試してないけど

github.com

などなど

CentOS7でPowerShellを実行する

さて、別にPowerShellを日頃からばりばり使っているわけではありません。
コマンドじゃないとめんどくさいときに、やっとPowerShell出てきてやっと使うレベルです。
あとは、Vagrant立ち上げるとき。。。

なぜ、CentOS7でPoserShellなのかというと、ついにWindowsから「コマンドプロンプト」が消えるらしいです。

そもそも、自分は開発OS自体はWindowsなので、使えた方がいろいろと効率がいいはずです。きっと。。。たぶん。。。
とりあえずトライ!

http://business.newsln.jp/news/201612072350480000.html

インストール

yum install https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.13/powershell-6.0.0_alpha.13-1.el7.centos.x86_64.rpm

実行

powershell で実行できます。

powershell

PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS /root>

とりあえずコマンドレットの数を計測してみる

必要かは別として、Windows10 と CentOS7 を比較すると2500くらいは差がありますね。。。

# CentOS 7
Get-Command | measure | select count

Count
-----
  349
# Windows10
Get-Command | measure | select count

Count
-----
 2725

参考

github.com

CakePHP3のMiddleware導入

この記事は 「Fusic Advent Calendar 2016の6日目」になります

使ってますか?Middleware

これですね。CakePHP3.3から導入されている機能ですね。
http://book.cakephp.org/3.0/ja/controllers/middleware.html

Middlewareって何?

アクセスに対するリクエスト、レスポンスに対して処理を挟むことができます。 処理を挟むといわれると、Controllerには initialize とかありますけどもっと前に処理を挟むことが可能になります。なります。

また、 PSR-7 に互換しているため、 Packagist などで公開されている PSR-7 互換のライブラリを利用することが可能となります。

例えば、 Laravelで利用されているMiddlewareをCakePHPで利用するということも可能になります。(Laravelに依存していなければ)

どのタイミングで動くの?

初期だと以下の順番で動作します。

  1. ErrorHandlerMiddleware(リクエスト処理)
  2. AssetMiddleware(リクエスト処理)
  3. RoutingMiddleware(リクエスト処理)
  4. CakePHP
  5. RoutingMiddleware(レスポンス処理)
  6. AssetMiddleware(レスポンス処理)
  7. ErrorHandlerMiddleware(レスポンス処理)

この図のようにMiddlewareを複数重ねていくイメージで動作します。

Untitled (3).png

どんなところで使えるの?

認証やリクエストオブジェクトやレスポンスオブジェクトの加工、IPアドレス制限などアプリケーションが起動する前の処理などは適した処理だと言えると思います。 レスポンス側だと、ログ出力や実行時間の計測などがいいのでしょうか。

上記の図でもそうですが、 initializeはアプリケーションが起動した後になります。 認証などは起動前の処理でいいものはいろいろとあると思われます。

Middlewareサンプル

1メソッドの中で、リクエスト処理、レスポンス処理を行います。 癖はありますね。

<?php

// src/Middleware/TrackingCookieMiddleware.php の中で
namespace App\Middleware;

class TrackingCookieMiddleware
{
    public function __invoke($request, $response, $next)
    {
        // ここでリクエスト処理

        $response = $next($request, $response);

        // ここでレスポンス処理

        return $response;
    }
}

Middlewareの使い方

Middlewareの起動などの設定は src/Application.php に記述します。 必要なMiddlewareを追記してきます。

注意点としては、作成したMiddlewareの __invoke にrequest, responseオブジェクトが渡ってきますが、 それぞれ、 Zend\Diactoros\ServerRequest, Zend\Diactoros\Response になっており、 Cake\Network\Request, Cake\Network\Response とは違うことに注意が必要です。

webroot/index.php$server->run() の引数に利用したいオブジェクトを渡すと、Cake\Network\Request, Cake\Network\Response など使いたいオブジェクトに切り替えることが可能です。

メンテナンス画面表示用プラグイン作ってみた

Middlewareの勉強がてら、 Maintenanceプラグインを作ってみました。 簡単にメンテナンス画面に切り替えるためのプラグインになります。

https://github.com/fusic/maintenance/

CakePHP3のRouteクラス3種

CakePHP3でRouteクラスを利用してるのでしょうか? Router::scope などはよく使うのですが、 DashedRouteInflectedRouteRedirectRoute は頻繁には利用せず毎回調べてるので備忘録程度に残しておきます。

ようはどういうURLでアクセスするかというやつですね。

DashedRoute

特に気にしていない場合は、DashedRouteを利用していると思います。

  • アクセスするURL => /my-controller/my-action
  • クラス => MyController::myAction

InflectedRoute

CakePHP2までと同じようなURLでアクセスしたい場合はこちらですね

  • アクセスするURL => /my_controller/my_action
  • クラス => MyController::myAction

RedirectRoute

これは少し毛色の違うRouteです。
特定のURLにアクセスされたら、別ページにRedirectしたい場合があると思います。
RedirectRouteを使えばRouteだけでRedirect可能です。

  • アクセスするURL => /my-controller/my-action
  • アクセスしたいURL => http://example.com

使い方

routes.php に記述するだけです。

$routes->connect('/', ['redirect' => 'http://example.com'], ['routeClass' => 'RedirectRoute']);

その他

全体をInflectedRouteにしたい

デフォルトのRouteを指定する

Router::defaultRouteClass(InflectedRoute::class);

Vagrantで使用するプロバイダを指定する

タイトル通りですが、「Vagrantで使用するプロバイダを指定する」方法の備忘録です。

Vagrantを使用してる人は「VirtualBox」を使ってる人が多いと思うので、ほとんど使うことはないでしょうか?

自分はWindows上で「Vagrant + Hyper-V」を使っているので、毎度毎度 vagrant up --provider=hyperv と入力するのがめんどくさいのです。

設定内容

環境変数VAGRANT_DEFAULT_PROVIDER を設定するだけです。
設定する値は使いたいプロバイダです。自分の場合だと hyperv ですね。

簡単!