20200703のReactに関する記事は5件です。

Reactで<input type="date" />を使う時の無効な日付(2月31日とか)を表示させないやり方

はじめに

Reactで<input type="date" />を使って、日付を選択するフォームを作った時に、2月31日とかの無効な日付も選択できてしまうのを防ぎたいと思ったので実装してみました。

デモ

codesandboxでソースと動きが確認できます。

inputタグだと味気ないので、material-uiのTextFieldコンポーネントを使ってますが、機能自体は同じです。

日付選択を作る

dateで日付の状態を管理します。
valuedateを受け渡して、onChangeイベントを受け取って状態を更新する普通の処理です。

App.js
export default function App() {
  const [date, setDate] = useState("");

  return (
    <div className="App">
      <FormControl variant="outlined">
        <TextField
          variant="outlined"
          type="date"
          value={date}
          onChange={e => onChangeDate(e}
        />
      </FormControl>
    </div>
  );
}

とりあえずonChangeDateはそのまま状態を更新してみる。

App.js
const onChangeDate = (e) => {
  setDate(e.target.value);
}

↑キーとかで選択すると、こんな風に無効な日付が選択できてしまうんですよね・・・
image.png

onChangeDateでいい感じに調整する

問題点としては

  • 2月は閏年があるので、28or29日
  • 4/6/9/11月は30日まで

なので、一個前の状態dateを参照して、書き換えていきます。

無効な日付の時のe.target.valueには値が入ってないので、値が入っている時はそのまま状態を更新します。

それ以外の場合は月ごとに分岐して書いていきます。

App.js
const onChangeDate = (e) => {

  if (e.target.value) {
    setDate(e.target.value);
  } else {
    const nowYear = date.slice(0, 4);
    const nowMonth = date.substr(5, 2);
    const nowDate = date.slice(-2);

    if (nowDate !== "01") {
      setDate(`${nowYear}-${nowMonth}-01`);
    }
    else{
      switch (nowMonth) {
        case "02":
          if ((nowYear * 1) % 4 === 0) {
            setDate(`${nowYear}-${nowMonth}-29`);
          } else {
            setDate(`${nowYear}-${nowMonth}-28`);
          }
          break;
        case "04":
        case "06":
        case "09":
        case "11":
          setDate(`${nowYear}-${nowMonth}-30`);
          break;
        default:
          break;
      }
    }
  }
}

これで無効な日付がとりあえず入らないようになりました!!

ただ、これだと3/31から月を2月に変更(↓矢印)すると、3/1に一回なってしまいます。

ちょっと気持ち悪いですね。。。

しかし、e.target.valueに値が入ってこないのですし、年月日のどの値を変更したかもわからないため、
どうしようもなさげです。

世に出回っているカレンダーアプリとかの日付は、普通に2/31日とか選択できるようになっていて、保存できないようにしていたりするのでこれがベストプラクティスなのでしょうかね。

まとめ

今回は日付選択の無効な日付を表示させないようにしてみました。

まだ気持ち悪いのでベストプラクティスをご存じの方はコメントをお願いします!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React

Reactについて調べたので備忘録として残しておく

公式ページで体系的な知識が付けられる
https://ja.reactjs.org/docs/getting-started.html

VSCodeで開発する。インストールは以下からできる。
https://qiita.com/psychoroid/items/7d85ae6bade4a67aedb1

高さを100%にしても画面と同じ大きさにならないことがあった。以下が参考になる。
https://qiita.com/shouchida/items/205fed63b886681661bd

React、Recoilの基本(チェックボックス付きの一覧表に使えそう)
https://qiita.com/serinuntius/items/3d6519988233d7ba643c

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ReduxとReact Hooksを活用してトーストを実装する

「保存に成功しました」だったり「クーポンの適応に失敗しました」だったり
ユーザーに何かしらの内容を一時的に伝えたい時があると思います。

そのような時に用いられる通知のUIの一種であるトーストを実装していきます。
イメージとしてはこのようなものです

toast.gif

トーストの要件

下記の要件を満たすトーストを作っていきます。

  • 1つずつ順番に表示される
  • 表示されてちょっと経ったら自動で消える
  • どのコンポーネントからでも新しいトーストを追加できる
  • デザインはがんばらない

実装

1. トーストの情報を保持する場所を用意する

どこからでも追加と参照ができるように、ReduxのStoreに持たせます。
Store自体の設定については割愛します。

// toast.ts
import { Reducer, AnyAction } from 'redux'
import { isType, actionCreatorFactory } from 'typescript-fsa'
import { useSelector } from 'react-redux'

export type Toast = {
  message: string
}
type Toasts = Toast[]

// action
const actionCreator = actionCreatorFactory('TOAST')
export const Push = actionCreator<{ toast: Toast }>('PUSH')
export const Shift = actionCreator('SHIFT')

// reducer
const initialState: Toasts = []
export const reducer: Reducer<Toasts> = (
  state: Toasts = initialState,
  action: AnyAction,
) => {
  if (isType(action, Push)) {
    const { toast } = action.payload
    return state.concat([toast])
  }

  if (isType(action, Shift)) {
    return state.slice(1)
  }

  return state
}
export default reducer

// selector
export const GetToasts = (): Toasts => useSelector(
  (state: { toasts: Toasts }) => state.toasts,
)

Stateをファイルの中で定義していますが
プロジェクトに合わせて読み込むと良いと思います。

2. トーストを表示するコンポーネントを用意する

このコンポーネントでは表示の状態を管理するためにuseState
トーストの変化を監視するためにuseEffectといったReact Hooksの機能を用います。

トーストの情報はStoreに保存し、selectorも用意してあるので
どこからでも簡単に呼び出せます。

// ToastContainer.tsx
import React, { useState, useEffect } from 'react'
import { useDispatch } from 'react-redux'

import { GetToasts, Shift } from 'toast.ts'
import style from 'style.scss'

const timeout = async (ms: number) => (
  new Promise((resolve: () => void): void => {
    setTimeout(() => resolve(), ms)
  })
)

const ToastContainer: React.FC = () => {
  const toasts = GetToasts()
  const [visible, setVisible] = useState(false)
  const dispatch = useDispatch()

  useEffect(() => {
    if (toasts.length === 0 || visible) {
      return
    }

    const showToast = async () => {
      setVisible(true)
      await timeout(3000)
      setVisible(false)
      await timeout(500)
      dispatch(Shift())
    }

    showToast()
  }, [toasts])

  return (
    <div className={style.toastContainer}>
      <div className={`${style.toast} ${visible && style.visible}`}>
        {toasts.length > 0 && toasts[0].message}
      </div>
    </div>
  )
}

export default ToastContainer

トーストの表示の流れはこのようになります

  1. toastsが増えたら監視しているuseEffectが発火
  2. トーストが見えるようにvisibletrueに変更
  3. ちょっと経ったらvisiblefalseに変更して隠す
  4. dispatch(Shift())で先頭のtoastsを削除
  5. toastsが更新されるのでuseEffectがもう一度発火
  6. まだtoastsがあったら2に戻る

あとは適当にcssを当ててあげればOKです

// style.scss
.toast {
  width: 320px;
  padding: 16px 0;
  color: #fff;
  text-align: center;
  background-color: red;
  opacity: 0;
  transition: opacity .6s;

  &.show {
    opacity: 1;
    transition: opacity .2s;
  }
}

3. トーストを追加する

Reduxでトーストを管理しているので、どこで追加しても大丈夫です。
例えば何かしらのAPIを呼んだときはこのようにトーストを追加します

save()
  .then(() => dispatch(Push({ toast: { message: '保存しました' } })))
  .catch(() => dispatch(Push({ toast: { message: '保存に失敗しました' } })))

トーストの内容に応じて色を変えたりしたい場合は、typeなども持たせましょう。

まとめ

バリデーションや表示の仕方に関しては実装したい仕様に合わせて適宜変更して下さい。
React Hooksを使うと煩雑だった処理がすっきり書けるので楽しいです。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PackerとAnsibleを使用してAlibaba Cloud ECSインスタンス上にReact JSアプリケーションイメージを作成する

このガイドでは、Packerを使ってAlibaba Cloud ECSインスタンス上にマシンイメージを構築する方法と、マシンイメージに持たせたいものを書くためのAnsibleについてお話します。

前提条件

このガイドに従うために専門家である必要はありません。必要なのは、Alibaba CloudのアカウントとAccess keyだけです。こちらのリンクをクリックすると、Alibaba Cloud上でのアクセスキーの作成方法が表示されます。

ステップ1:パッカーのインストール

私たちのシステムにpackerをインストールするには、packerの公式インストールページに従うか、パッケージマネージャ、Windows用のchocolateyとmacOS用のhomebrewを使用することができます。パッケージマネージャを使えば、パスに環境変数を追加する手間が省けます。

chocolatey を使って Windows に packer をインストールするには

1、chocolatey パッケージマネージャをインストールします。chocolatey をインストールするには、管理者として cmd を開き、以下のコマンドを貼り付けて chocolatey パッケージマネージャをインストールします。

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

2、chocolatey がインストールされていることを確認するには、 choco -v コマンドを実行します。

3、以下のコマンドを実行して、packerをインストールします。

choco install packer

4、packerのインストールを確認するには、次のように実行します。

packer -v

5、Packerのバージョンがインストールされているはずです。
インストールプロセスを示すGif画像

image.png

homebrewを使ってMacOSにpackerをインストールするには

1、homebrewがまだインストールされていない場合は、インストールしてください。macOSにhomebrewをインストールするには、ターミナルを開いて以下のコマンドを貼り付けます。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2、以下のコマンドを実行して、packerをインストールします。

brew install packer

3、packerのインストールを確認するには、以下を実行します。

packer -v

4、Packerのバージョンがインストールされているはずです。
MacOSへのインストールを示すGif画像
image.png

ステップ2: Reactアプリのマシンイメージを構築する

マシンイメージを構築するには、テンプレートファイルを作成する必要があります。テンプレート ファイルは、構築するイメージを定義するために使用します。テンプレートファイルはJSON形式で、Packerの様々なコンポーネントを設定する異なるキーのセットを持っています。

1、example.jsonという名前のテンプレートファイルを作成し、以下のコードを貼り付けます。

  {
      "variables": {
        "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
        "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
      },
      "builders": [{
        "type": "alicloud-ecs",
        "access_key": "{{user `access_key`}}",
        "secret_key": "{{user `secret_key`}}",
        "region": "us-west-1",
        "image_name": "ReactJS-Application",
        "instance_type": "ecs.t5-lc2m1.nano",
        "source_image": "ubuntu_16_0402_32_20G_alibase_20180409.vhd",
        "io_optimized":"true",
        "image_force_delete":"true",
        "ssh_username": "root",
        "internet_charge_type": "PayByTraffic"
      }],
      "provisioners": [{
        "type": "shell",
        "script": "installAnsible.sh"
       },{
       "type": "ansible",
      "playbook_file": "playbook.yml"
     }]
    }

変数セクションでは、テンプレートファイル内のどこでも使用できる変数を定義し、
env関数を指定して環境変数からaccess_keysecret_keyの値を取得しています。

ビルダーセクションには、特定のビルダーを設定するJSONオブジェクトの配列が含まれています。ビルダーは、マシンを作成し、そのマシンをイメージに変換する役割を担う packer のコンポーネントです。

プロビジョナーセクションでは、組み込みのソフトウェアやサードパーティ製のソフトウェアを使用して、起動後のマシンイメージをインストールしたり設定したりします。このガイドでは、プロビジョナーとして ansibleshell を使います。

2、ALICLOUD_ACCESS_KEYALICLOUD_SECRET_KEYをエクスポートするには、ターミナルで以下のコマンドを実行します。

 export ALICLOUD_SECRET_KEY="YOUR_ALICLOUD_ACCESS_KEY"
   export ALICLOUD_SECRET_KEY="YOUR_ALICLOUD_SECRET_KEY"

3、playbook.ymlという名前の新しいAnsibleファイルを作成し、以下のコードを貼り付けます。example.jsonplaybook.ymlは同じディレクトリまたはフォルダに作成します。

   ---
     - hosts: all
       become: true

       vars:
         NODEJS_VERSION: 8
         domain: "localhost"

       tasks:
       - name: Add gpg key for nodejs
         apt_key:
           url:  "https://deb.nodesource.com/gpgkey/nodesource.gpg.key"
           state: present
       - name: Add nodejs LTS to apt repository
         apt_repository:
           repo: "deb https://deb.nodesource.com/node_{{ NODEJS_VERSION }}.x {{ ansible_distribution_release }} main"
           state: present
           update_cache: yes
       - name: Install nodejs
         apt:
           name: nodejs
           state: present
       - name: Setup React application
         shell:
            cmd: |
              npx create-react-app my-app # Setup our react application
              cd /root/my-app
              npm install -g pm2   # Install Pm2, A nodejs process manager which enables us to run our application in the background process
       - name: Install nginx
         apt:
           name: nginx
           state:  present
           update_cache: yes
       - name: Remove nginx default configuration
         file:
           path: /etc/nginx/sites-enabled/default
           state: absent
       - name: enable reverse proxy # This enables us to use the public IP without passing in the port on our browser address bar
         shell:
           cmd: |
             cat > /etc/nginx/sites-available/my-app <<EOF
             server {
               listen 80;
               server_name {{ domain }};
               location / {
                 proxy_pass 'http://127.0.0.1:3000';
               }
             }
             EOF
       - name: create symlinks for nginx configuration # make sure the nginx configuration files are always the same.
         file:
           src:  /etc/nginx/sites-available/my-app
           dest: /etc/nginx/sites-enabled/my-app
           state: link
         notify:
         - restart nginx
       handlers:
         - name: restart nginx # restart nginx service
           service:
             name: nginx
             state: restarted

4、テンプレートファイルを検証するには、packer validate example.jsonを実行します。これにより、テンプレートファイルに構文エラーなどのエラーがないことを確認します。
5、packer build example.jsonを実行してReactJSイメージをビルドします。

ステップ3: Reactイメージを使ってインスタンスを起動する

先ほど作成した画像を使用してインスタンスを作成するには、以下の手順に従います。

1、アリババクラウドコンソールにログオン
2、ダッシュボードのサイドナビゲーションバーにあるElastic Compute Serviceをクリックします。
3、インスタンスを作成するには、[Create Instance] の説明が記載されたボタン、またはこのリンクをクリックします。
4、基本設定では、以下の操作を行います。

----- 1、課金方法については、「Pay-As-You-Go」をクリックしてください。
----- 2、地域については、ドロップダウンをクリックして、US West 1 (Silicon Valley)を選択してください。
----- 3、インスタンスタイプでは、「エントリーレベル(共有)」をクリックします。
----- 4、画像は「Custom Image」ボタンをクリックします。Custom Imageの下のドロップダウンメニューをクリックして、作成したイメージはReactJS-Applicationを選択します。
----- 5、Next: Networkingボタンをクリックします。

5、2つ目のステップであるネットワーキングについては、以下の手順に従ってください。
-----1、Networkセクションでは、「VPC」ドロップダウンメニューをクリックし、デフォルトのVPCを選択します。
-----2、Security Groupセクションでは、「ポート設定に移動」をクリックして、アプリケーションのポートを設定します。
-----3、Add Security Group Ruleをクリックし、Port Rangeを80に、Authorization Objectsを0.0.0.0.0/0に設定します。これを繰り返しますが、ポート範囲を3000に設定します。
ポート80はHTTPリクエストのためのもので、ポート300`はリアクトアプリケーションが実行されているポートです。
-----4、セキュリティグループを設定したら、次へをクリックします。Next: System Configurations ボタンをクリックします。

6、3番目のステップであるシステム設定については、以下の手順に従ってください。
-----1、詳細設定(インスタンスRAMのロールまたはクラウドイニットに基づく)ドロップダウンをクリックして、以下のコードをユーザーデータフィールドボックスに貼り付けます。

#!/usr/bin/env bash
cd /root/my-app
pm2 start /root/my-app/node_modules/react-scripts/bin/react-scripts.js --name my-app -- start

上記のスクリプトはインスタンスの作成時に実行されるので、アプリケーションを起動するためにインスタンスに SSH 接続する必要はありません。

7、プレビューボタンをクリック
8、利用規約に同意し、「インスタンスの作成」ボタンをクリックします。
9、インスタンスが起動したら、インターネットの IP アドレスをコピーしてブラウザのアドレスバーに貼り付けます。ReactアプリケーションのWebページが表示されるはずです。
インスタンスを起動するプロセスを示すgif画像は以下の通りです。

image.png

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webhooksを使ったReactアプリのデプロイとUbuntuでのSlackの統合

このチュートリアルでは、Ubuntuを使用したAlibaba Cloud Elastic Compute Service (ECS)インスタンス上でWebhooksを使用してSlackの通知をトリガーします。

本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。

前提条件

1、Alibaba Cloud Elastic Compute Service (ECS)を有効化し、有効な支払い方法を確認する必要があります。新規ユーザーの場合は、Alibaba Cloudアカウントで無料アカウントを取得することができます。ECSインスタンスのセットアップ方法がわからない場合は、このチュートリアルまたはクイックスタートガイドを参照してください。ECSインスタンスは、少なくとも2GB RAMと1コアプロセッサを搭載している必要があります。
2、Alibaba Cloudから登録されたドメイン名。すでにAlibaba Cloudまたは他のホストからドメインを登録している場合は、そのドメインネームサーバーレコードを更新することができます。
3、ドメイン名は、あなたのAlibaba Cloud ECSのIPアドレスを指している必要があります。
4、Alibaba CloudのVNCコンソールまたはPCにインストールされているSSHクライアントにアクセスします。
5、サーバーのホスト名を設定し、root権限を持つユーザーを作成します。

Ubuntuのシステムを更新する

パッケージのインストールを進める前に、以下のコマンドを使用してUbuntuシステムをアップデートしてください。このコマンドを実行するには、root ではないユーザーから sudo 権限でログインすることを忘れないでください。このコマンドを実行すると、Is this ok? 'y'と入力してEnterキーを押します。

# sudo apt update && sudo apt upgrade

Nginxサーバーのインストール

nginxサーバーをインストールするためには、以下の手順に従う必要があります。

ステップ1

インストールするには、以下のコマンドを実行します。

# sudo apt-get install nginx

ステップ2

以下のコマンドを実行してNginxサーバーを起動します。

# sudo systemctl start nginx

Nginxサーバーの状態を確認するには、以下のコマンドを実行します。

# sudo systemctl status nginx

インストールを確認するには、アリババクラウドECSのIPアドレスか、IPアドレスを指したドメイン名でアクセスします。私の場合はドメイン名経由でアクセスし、以下の画面が読み込まれました。

Gitのインストール

ローカルマシンだけでなく、サーバーにもgitをインストールする必要があります。Gitをインストールして設定するには、以下の手順に従います。

ステップ1

Gitをインストールするには、コマンドを実行します。

# sudo apt-get install git

ステップ 2 (オプション)

以下のコマンドを実行して Git を設定します。名前と有効なメールアドレスを指定してコミットメッセージに正しい情報が含まれるようにします。

# git config --global user.name "Aareez"
# git config --global user.email "xyz@example.com"

Node.js のインストール

Node.jsは、ブラウザの外でJSコードを実行するクロスプラットフォーム・オープンソースのJSランタイム環境です。Node.jsのバージョンはUbuntuのデフォルトリポジトリにあります。PPAを使用してNode.jsをインストールするには、以下の手順に従ってください。

以下のコマンドを実行して、お好みのバージョンのスクリプトを取得します。

# curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh

では、以下のコマンドでスクリプトを実行します。

# sudo bash nodesource_setup.sh

インストールするには、コマンドを実行します。

# sudo apt-get install -y nodejs

これで無事にNode.jsのインストールが完了しました。

gccとg++をインストール

また、ネイティブアドオンを構築するための開発ツールも必要になるかもしれません。それらをインストールするには、コマンドを実行します。

# sudo apt-get install gcc g++

Yarnのインストール

Yarn パッケージマネージャをインストールするには、以下のコマンドを実行します。

 # curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
 #  echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
# sudo apt-get update && sudo apt-get install yarn

npmを動作させるためには、build-essentialをインストールする必要があります。インストールするには以下のコマンドを実行してください。

# sudo apt-get install build-essential

create-react-appを使ってReactアプリを作成する

まず、create-react-appでWebhookをテストするためのアプリケーションを構築します。この後、GitHubのリポジトリを作成し、そのリポジトリにプロジェクトのコードをプッシュする必要があります。

create-react-appのノードモジュールをグローバルリポジトリに追加するには、以下のコマンドを実行してシェルから利用できるようにする必要があります。

# sudo npm install -g create-react-app

aareez-projectという名前のプロジェクトを作成するには、以下のコマンドを実行します。

# sudo create-react-app aareez-project

以下のコマンドで作成したプロジェクトディレクトリに移動します。

# cd aareez-project

aareez-projectディレクトリにあるgitでリポジトリを初期化します。そのためには、以下のコマンドを実行します。

# sudo git init

ここで、GitHub の URL と一緒にリモートオリジンを追加します。

# sudo git remote add origin https://github.com/itsaareez1/react-example

プロジェクトディレクトリにあるファイルをステージします。

# sudo git add 

それらをコミットし、以下のコマンドを実行してリポジトリにプッシュします。

# sudo git commit -m "initial commit"
# sudo git push -f origin master

React用ディレクトリの設定とNginxサーバーの設定

ここでは、Githubのリポジトリからreactアプリのクローンを取得する必要があります。

ルートディレクトリに移動します。

# cd ~

これでGithubからファイルをクローンします。

# sudo git clone https://www.github.com/itsaareez1/react-example 

上記のgitリンクを使ってプロジェクトをクローンします。

コマンドでcloneディレクトリに移動します。

# cd react-example

Nginxが動作するようにindex.htmlやJSファイル、CSSファイルなどのページを格納したフォルダを作成するには、yarnのbuildコマンドを実行する必要があります。

# sudo yarn && sudo yarn build

ここで、Nginx経由でファイルにアクセスできるようにするために、シンボリックリンクを作成する必要があります。Nginxはアプリケーションを/var/wwwディレクトリに配置します。 シンボリックリンクの作成は以下のコマンドを実行してください。

# sudo ln -s ~/react-example /var/www/react-example

Nginxがシンボリックリンクを正しく動作させるための権限を付与するには、以下のコマンドを実行します。

# sudo chmod -R 755 /var/www

ここで、利用可能なサイトディレクトリにnginxサーバーブロックを設定します。以下のコマンドを実行すると、ファイルが開きます。

# sudo nano /etc/nginx/sites-available/react

開いたファイルに以下のテキストをコピーし、softpedia.xyzをドメイン名またはECSのIPアドレスに変更して保存してください。

server {
        listen 80;

        root /var/www/react-example/build;
        index index.html index.htm index.nginx-debian.html;

        server_name softpedia.xyz;

        location / {
                try_files $uri /index.html;
        }
}

ここで、利用可能なサイトディレクトリにある react の設定用のシンボリックリンクを、有効になっているサイトディレクトリに作成します。

# sudo ln -s /etc/nginx/sites-available/react /etc/nginx/sites-enabled/react

nginxの構文が正しいかどうかを確認するには、以下のコマンドを実行します。

# sudo nginx -t

設定をロードするには、nginx サーバーを再起動します。

# sudo systemctl restart nginx

すべての設定が正しく行われているかどうかを確認するために、ブラウザでIPアドレスやドメインにアクセスすると、以下のような画面が表示されます。

image.png

Webhooks のインストールと設定

設定可能なエンドポイントを持つ HTTP サーバをフックと呼びます。Webhook サーバは、いくつかの HTTP リクエストを受信したときに、設定可能なルールのセットに従ったカスタマイズ可能なコードを実行します。

ホームに移動する

# cd ~

webhookをダウンロードします。

# sudo wget https://github.com/adnanh/webhook/releases/download/2.6.6/webhook-linux-amd64.tar.gz

ダウンロードしたフォルダを展開します。

# sudo tar -xvf webhook-linux-amd64.tar.gz

バイナリを/usr/local/binに移動して、自分の環境で利用できるようにします。

# sudo mv webhook-linux-amd64/webhook /usr/local/bin

ダウンロードしたフォルダを削除します。

# sudo rm -rf webhook-linux-amd64*

ここで、主にサードパーティ製のアプリケーションを配置するoptフォルダ内に、スクリプトとフックのためのディレクトリを作成します。

# sudo mkdir /opt/scripts

# sudo mkdir /opt/hooks

これらのディレクトリの権限をユーザ名に割り当てます。

# sudo chown -R aareez:aareez /opt/scripts
# sudo chown -R aareez:aareez /opt/hooks

GitHubがHTTPリクエストを送信すると、JSON配列ファイルで定義されたルールに基づいてwebhookが起動されます。ここで、webhook用の設定ファイルを作成する必要があります。そのためには、以下のコマンドを実行します。

# sudo nano /opt/hooks/hooks.json

開いたファイルに以下のテキストをコピーします。

[
  {
    "id": "redeploy-app",
    "execute-command": "/opt/scripts/redeploy.sh",
    "command-working-directory": "/opt/scripts",
    "pass-arguments-to-command":
    [
      {
        "source": "payload",  
        "name": "head_commit.message"
      },
      {
        "source": "payload",
        "name": "pusher.name"
      },
      {
        "source": "payload",
        "name": "head_commit.id"
      }
    ],
    "trigger-rule":
    {
      "and":
      [
        {
          "match":
          {
            "type": "payload-hash-sha1",
            "secret": "654321Ab", 
            "parameter":
            {
              "source": "header",
              "name": "X-Hub-Signature"
            }
          }
        },
        {
          "match":
          {
            "type": "value",
            "value": "refs/heads/master",
            "parameter":
            {
              "source": "payload",
              "name": "ref"
            }
          }
        }
      ]
    }
  }
]

GitHub の通知を設定する

GitHub リポジトリで、master へのコミットが発生した際に HTTP リクエストが発生するように設定するには、以下の手順に従う必要があります。

1、GitHub リポジトリを開き、以下のように設定をクリックします。
image.png

2、この後、Webhooksセクションに移動します。

image.png

3、Webhookの追加ボタンをクリックします。
image.png

4、Payload URL には http://your_server_ip:9000/hooks/redeploy-app と入力してください。softpedia.xyzをECSのIPアドレスまたはドメインに置き換えることを忘れないでください。Content typeには、option application/jsonを選択します。hooks.jsonファイルでは、秘密鍵654321Abを使用していますが、任意のものを使用することができます。秘密鍵には654321Abを使用します。その後、Just the push eventオプションを選択します。アクティブチェックボックスにチェックを入れて、Add webhookボタンをクリックします。

image.png

これで、あなたや誰かが GitHub リポジトリにコミットするたびに、GitHub はコミットイベントに関する情報を含む Payload を含む POST リクエストを送信するようになりました。

リデプロイスクリプトを書く

redeploy.shスクリプトにWebhookを指定しているので、スクリプトを作成する必要があります。以下のコマンドを実行して、スクリプトを書くためのファイルを開きます。

# sudo nano /opt/scripts/redeploy.sh

以下のコードをコピーして、開いたファイルに貼り付けてください。

#!/bin/bash -e

function cleanup {
      echo "Error occoured"
      # !!Placeholder for Slack notification
}
trap cleanup ERR

commit_message=$1 # head_commit.message
pusher_name=$2 # pusher.name
commit_id=$3 # head_commit.id

# !!Placeholder for Slack notification

cd ~/react-example/
sudo git pull origin master
sudo yarn && yarn build

            # !!Placeholder for Slack notification 

以下のコマンドでスクリプトを実行可能な状態にします。

# sudo chmod +x /opt/scripts/redeploy.sh

Nginxは/var/wwwフォルダにreact-exampleを置くように設定されているため、上記のスクリプトを実行するとビルドディレクトリが更新され、新しいファイルがサーバに送られてきます。

## run webhook server to test configuration. Execute the command below for it.
# webhook -hooks /opt/hooks/hooks.json -verbose

すべてが正常に動作すると、以下のような画面が表示されます。

image.png

テストのためには、Webhookを起動したまま、複製セッションを開き、以下のコマンドを実行してください。

# sudo git commit --allow-empty -m "Trigger notification"
# sudo git push origin master

以下のような画面が表示されるはずです。

image.png

Slackの通知を統合する

Slackの通知を追加するには、redeploy.shを修正してSlackからの通知を送受信するようにします。Slackの設定は以下の手順で行います。

1、左上のドロップダウンメニューをクリックし、「Slackのカスタマイズ」を選択します。
2、次に、アプリの設定に移動します。
3、管理パネルで、「統合を選択」を選択します。
4、Incoming Hooks integrationを検索します。
5、Add Configurationをクリックします。
6、チャンネルを選択または作成します。
7、Add Incoming Webhooks integrationをクリックします。
Slackのウェブフック設定が表示されます。WebhookのURLをメモしておきます。コマンドを使ってredeploy.shスクリプトを開きます。

# sudo nano /opt/scripts/redeploy.sh

前のコードを削除し、以下のコードを追加します。slack_webhook_urlWebhookのURLに置き換えることを忘れないでください。

#!/bin/bash -e

function cleanup {
      echo "Error occoured"
      curl -X POST -H 'Content-type: application/json' --data "{
              \"text\": \"Error occoured while building app with changes from ${pusher_name} (${commit_id} -> ${commit_message})\",
              \"username\": \"buildbot\",
              \"icon_url\": \"https://i.imgur.com/JTq5At3.png\"
      }" your_slack_webhook_url
}
trap cleanup ERR

commit_message=$1 # head_commit.message
pusher_name=$2 # pusher.name
commit_id=$3 # head_commit.id

curl -X POST -H 'Content-type: application/json' --data "{
        \"text\": \"Started building app with changes from ${pusher_name} (${commit_id} -> ${commit_message})\",
        \"username\": \"buildbot\",
        \"icon_url\": \"https://i.imgur.com/JTq5At3.png\"
}" your_slack_webhook_url

cd ~/react-example/
sudo git pull origin master
sudo yarn && sudo yarn build

curl -X POST -H 'Content-type: application/json' --data "{
        \"text\": \"Build and deploy finished with changes from ${pusher_name} (${commit_id} -> ${commit_message})\",
        \"username\": \"buildbot\",
        \"icon_url\": \"https://i.imgur.com/JTq5At3.png\"
}" your_slack_webhook_url

テストは、Webhookを起動した状態で、セッションを複製して以下のコマンドを実行してください。

# sudo git commit --allow-empty -m "Trigger notification"
# sudo git push origin master

これで完了です! Slackチャンネルでは、開始・終了したアプリケーションのビルドに関する通知やメッセージを受け取ることができます。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む