SiG Staff Blog

福井と金沢にある株式会社SIG 総合研究所で働きたい方、ご連絡ください。

symphony4のDoctrin使うとエラーメッセージが文字化けしてる

doctrineコマンドを実行するとエラーになっちゃう。

しかも文字化けしてる。。。

ターミナルもDBの文字コードutf-8にしてるのになんでやろ。。。

解決

php bin/console doctrine:database:create

とかを実行すると、 エラーになってエラーメッセージが文字化けすることがある。

config/package/doctrine.yml

の charset utf-8mb4になっているからUTF-8にする。

RDSを作るとデフォルトの文字コードがlaten-1になってしまう

ポチポチとRDSを作るとデフォルトの文字コードがlaten-1になってしまう問題

ポチポチとOKOKでRDSを作成すると文字コードがlaten-1になってしまって、困るという話。

原因

そもそも、パラメータグループで設定をしないといけなかった。

対処

パラメータグループを作成する

左のメニューからパラメータグループを選ぶ。

f:id:Bee_Flim:20180328141730p:plain

適当に入力していく。

f:id:Bee_Flim:20180328141736p:plain

パラメータの絞り込みができるので、 character で絞り込む。

f:id:Bee_Flim:20180328141739p:plain

とりあえず、絞り込みがされたものを選択をする。

UTF-8と1 を設定する。

f:id:Bee_Flim:20180328141743p:plain

RDSの作成

いつものように作成する。

f:id:Bee_Flim:20180328141719p:plain

適当に入れる。

f:id:Bee_Flim:20180328141723p:plain

パラメータグループに先ほど作成したものが出てくるので、それを選ぶ。 出てこなかったときは、パラメータグループ作るときに指定したバージョンを確認する。

f:id:Bee_Flim:20180328141727p:plain

もうインスタンスとかテーブルとか作っちゃってたら

インスタンス作たけど、テーブルは作ってないとき

インスタンスの画面がから変更ができます。

テーブル作っちゃったとき

DBの文字コード変換機能を使えばOK。

EC2に作ったNginxにLet's Encryptを導入する

オレオレ証明からLet's Encriptに変更する

前提

yakisaba.hatenablog.jp の通りにサーバーが立っている事。

注意

EC2のパブリックDNSだと登録できないそう。
適当にドメインを取ってみて試してみる

ドメインを取得して、Route53にAレコードを追加する

  1. お名前.comとかでDNSを取得する。
  2. EC2のダッシュボードを開き、左側にあるElastic IPを選択する。
  3. 新しいIPの割り当てを選択して、IPを取得する。
  4. 作成したものを右クリックして、アドレスの割り当てを選択して、EC2インスタンスに割り当てる。
  5. 作成されたIPアドレスをメモしておく。
  6. Route53を開き、Hosted Zoneを開く。
  7. create hosted zoneを選択して、Domain Nameに作成したドメインをいれて、作成をする。
  8. 作成したゾーンを選択してgo to recordを選ぶ。
  9. create recordを選択して、下のように設定して作成する。
  10. NSレコードの内容をコピーして、取得したドメインのネームサーバーに設定する。
  11. nslookup www.ドメインIPアドレスと紐づいているかチェックする。

必要なツールをインストール

# gitのインストール
$ sudo yum install git

# Let's Encryptのツールをインストール
$ git clone https://github.com/certbot/certbot ~/certbot
$ cd ~/certbot

証明書の発行

# ドメイン名、メアドは取得したものを使う
$ sudo ./certbot-auto certonly --webroot -w ドキュメントルート -d 取得したドメイン名 -m 自身のメールアドレス  --debug

証明書が出来上がるので、それを /etc/nginx/conf.d/default.conf に登録する。

/etc/nginx/conf.d/default.conf

  ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;

確認

nginxを再起動して接続してみて、https + http2で繋がっていればOK

継続的に取得するようにする

# 毎月1日の1時に強制的に更新する。
0 1 1 * * root /nome/ec2-user/certbot/certbot-auto renew --force-renewal && service nginx restart

EC2にNginxサーバーを立てて、PHPが動くようにしてから、オレオレ証明書でhttps化をする

EC2にNginxサーバーを立てて、PHPが動くようにしてから、オレオレ証明書https化をする

なんでオレオレ証明書

Let's Encryptを試す前に、オレオレ証明書でサーバーを立ててみてからやろうと思ったから。

前提

  • EC2サーバーを立てれる。
  • linuxの事をなんとなく知っている。

早速開始

phpが動くようにする

EC2にphpとNginxをインストール

$ sudo yum install php71 php71-devel php71-fpm php71-mysql php71-mysqlnd php71-mbstring php71-pdo php71-zip
$ sudo yum install nginx

設定ファイルを変更

/etc/php-fpm.d/www.conf

# 下のように変更する
user = nginx
group = nginx
listen.user = nginx
listen.group = nginx

/etc/nginx/conf.d/default.conf

DocumentRootは/home/ec2-user/www/publicにしました。

server {
   listen       80;
   server_name  EC2のパブリックドメイン;
   root         /home/ec2-user/www/public;
    location / {
        root   /home/ec2-user/www;
        index  index.html index.htm index.php;
    }

    location ~ \.php$ {
        root           /home/ec2-user/www/public;
        fastcgi_pass   unix:/var/run/php-fpm/www.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

}

誰でも見れるようにパーミッションの変更

$ sudo chmod 755 /home/ec2-user/

確認

いつものphpinfoの出力をするindex.phpを作って、
/home/ec2-user/wwwにindex.phpを置いて動作させてみる。

$ sudo service nginx start

ログの場所

何かエラーが出たらログを確認してみましょう。

$ sudo tail -f /var/log/nginx/error.log

403が出た時はパーミッションエラーの可能性があるので、www下のファイルの権限をチェック。

503の時は/etc/php-fpm.d/www.confのlistenと/etc/nginx/conf.d/default.confのfastcgi_passの内容が違うからかもしれないです。同じものにしないといけないとのこと。

/etc/php-fpm.d/www.confのlisten

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = /var/run/php-fpm/www.sock   <-- これ[f:id:Bee_Flim:20180322192006p:plain]

/etc/nginx/conf.d/default.confのfastcgi_pass

   location ~ \.php$ {
       root           /home/ec2-user/www/public;
       fastcgi_pass   unix:/var/run/php-fpm/www.sock;  <-- これ
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       include        fastcgi_params;
   }

SSL and Http2の設定をする

sshキーの作成をする

sudo mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
sudo openssl req -new -x509 -sha256 -newkey rsa:2048 -days 365 -nodes -out /etc/nginx/ssl/nginx.pem -keyout /etc/nginx/ssl/nginx.key

nginxの設定を更新

/etc/nginx/conf.d/default.conf

# 80 portで接続に来た場合、httpsへ転送する
server {
    listen       80;
    server_name  EC2のパブリックサーバー名;
    return 301 https://$host$request_uri;
}

server {
   # sslとhttp2を追記
   listen       443 ssl http2;
   server_name  EC2のパブリックサーバー名;
   root         /home/ec2-user/www;

   # ssl keyを追加する
   ssl_certificate /etc/nginx/ssl/nginx.pem;
   ssl_certificate_key /etc/nginx/ssl/nginx.key;

   # 前方秘匿性の確立
   ssl_ciphers  ECDHE+AESGCM:DHE+AESGCM:HIGH:!aNULL:!MD5;

   # キャッシュ等の設定
   ssl_session_timeout 5m;
   ssl_prefer_server_ciphers on;

   # httpAccessがあっても強制でhttpsにする
   add_header Strict-Transport-Security "max-age=15768000; includeSubdomains";

   location / {
       root   /home/ec2-user/www;
       index  index.html index.htm index.php;
   }

   location ~ \.php$ {
       root           /home/ec2-user/www;
       fastcgi_pass   unix:/var/run/php-fpm/www.sock;
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       include        fastcgi_params;
   }

}

確認

chromeのエクステンションHTTP/2 and SPDY indicatorを入れて確認する。

chrome.google.com

f:id:Bee_Flim:20180322192006p:plain

TypeScriptとSASSを使うVue.jsの開発環境を作成する。

TypeScriptとSASSを使うVue.jsの開発環境を作成する。

前提

  • nodeがインストール済みである。
  • npmコマンドをなんとなく知っている。
  • なんとなく、vue.jsを知ってる。(https://www.youtube.com/watch?v=mZY1yyrlJWUのシリーズを見ておくといいかも)

早速やる

ライブラリのインストール

sassはタグに設定するだけで使えるようになるので、TypeScriptだけインストールする。

# とりあえず、 vue-cliをインストールする
$ npm i -g vue-cli

# webpackペースのプロジェクトを作成する
$ vue init webpack frontend_src

# typescriptで必要なものをプロジェクトにインストール
$ cd frontend_src
$ npm install
$ npm i -D typescript ts-loader vue-class-component

typescriptの設定

tsconfig.jsonファイルをfrontend_srcに作成して、下のように設定する。

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "module": "es2015",
    "moduleResolution": "node",
    "noImplicitAny": true,
    "target": "es6",
    "lib": ["dom", "es6", "es2015.promise"]
  },
  "include": [
    "./src/**/*.ts"
  ]
}

build/webpack.base.conf.jsを書き換える。

module.exports = {
    entry: {
      // エントリポイントの拡張子を.js→.tsに変更
      app: './src/main.ts'
    },
    output: {
      path: config.build.assetsRoot

// ----- 略 -----

    },
    resolve: {
      // extensionsに'.ts'を追加
      extensions: ['.js', '.vue', '.json', '.ts'],
      // ----- 略 -----
    }

      // test: /\.js$/,の下あたりに追加する
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        include: [resolve('src'), resolve('test')],
        options: {
          appendTsSuffixTo: [/\.vue$/]
        }
      },

// ----- 略 -----
}

jsファイルをtsファイルにする。

  • ./src/main.js を ./src/main.ts
  • ./src/router/index.js を ./src/router/index.ts に変更する。

Vueファイルで使用言語を指定する。

  • src/App.vueとsrc/components/HelloWorld.vueのscriptタグにlang="ts"を追加する。

App.vue

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

@Component({
  name: 'app'
})
export default class App extends Vue {
}
</script>

HelloWorld.vue

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

@Component({
  name: 'HelloWorld'
})

export default class Hello extends Vue {
  msg = 'Welcome to Your Vue.js App'
}
</script>

<style scoped lang="scss">
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;

  .test {
    font-size: 80px;
  }
}
a {
  color: #42b983;
}
</style>

build結果をAPサーバーのディレクトリにしたかったので、設定する

config/index.js

  build: {
    // これを書き換える
    index: path.resolve(__dirname, '../../public/index.html'),

    // これも書き換える
    assetsRoot: path.resolve(__dirname, '../../public'),

// 略

  }

build出来るか試してみる

# サーバーが自動で立ち上がって画面が表示される。
$ npm run build

起動させてみる

# サーバーが自動で立ち上がって画面が表示される。
$ npm run dev

loaderでエラーになる場合

vue-cliでテンプレートを作成すると、webpack3.x系がインストールされるが、
ts-loaderは自前でインストールしているので4.x系がインストールされます。(2018/3)

ts-loader4.x系はwebpack4.x系で使ってね。webpack3.xで使いたいならts-loaderも3.x系を使ってとREADMEに書いてあるので、
package.jsonを編集して3.x系がインストールされるようにすると、コンパイルが通ります。

やってみて

コンパイルエラーが出てしまったところに詰まったけど、それ以外は結構すんなりできました。

RESTサーバーを作って、fetch apiを使ってデータ通信をしよう。 RESTじゃなくて、GraphQLがいいって話も聞くけど、とりあえずRESTだ。

BacklogでPR(Spring F/W)があったらJenkins(AWS)がコードレビューの一部をしてくれて、結果をSlackに通知してくれるようにする。~その7~

jenkinsの設定をする

jenkinsで各チェックが動くように設定をしていきます。

jenkinsにジョブを追加する。

1.jenkinsのダッシュボードを開く f:id:Bee_Flim:20180217164213p:plain

2.新しいジョブをクリックして、適当な名前を付けて”Mavenプロジェクトのビルド”を選択する。 f:id:Bee_Flim:20180217164218p:plain

Git、Mavenの設定をする。

1.[jenkinsの管理]->[Global Tool Configuration]を選択する。

2.Gitの所にエラーがないか確認する。

3.Mavenの所に、適当に名前を付けて自動インストールにチェックをする。*1

Slack連携の為に設定をする。

1.[jenkinsの管理]->[システムの設定]を選択する。 f:id:Bee_Flim:20180217164227p:plain

2.webhook設定の所に、slackのtokenキーを設定して、

3.endpointにslackのURLを指定する。”https://[チーム名].slack.com” f:id:Bee_Flim:20180217164223p:plain

ジョブの設定をする。

基本設定

  1. ダッシュボードに先ほど作ったジョブがあるので、選択する。
  2. 左のメニューにある[設定]を開く。
  3. プロジェクト名、説明を適当に設定する。
  4. Backlogにチェックを入れて、Backlog URLに"https://<スペースID>.backlog.jp/projects/<プロジェクトキー>"を設定する。
  5. ユーザー、パスワードはそのプロジェクトが見れるユーザーを指定する。(ブランクでも良い)
  6. APIキーには、前回Backlogの設定で取得したキーを設定する。 f:id:Bee_Flim:20180217164253p:plain

ソースコード管理の設定

  1. Gitを選択する。
  2. リポジトリURLにはbacklogのgitリポジトリを設定する。
  3. 認証情報の追加ボタンを押下して、種類に”ユーザー名とパスワード”を選択して、ユーザー名とパスワードにbacklogのアカウント情報を登録する。
  4. 認証情報に追加したアカウントが表示されるので、それを選択する。
  5. nulabさんのblog( Jenkins Backlog Pluginで、ビルド結果をプルリクエストに通知! | ヌーラボ )では、

    高度な設定 > Refspec : “+refs/pull/:refs/remotes/origin/pr/

を指定すると、プルリクエストが取れると書かれていたのですがプルリク時にうまく動かないので、その設定はブランクにしてビルドするブランチに**を指定することでプルリクエストがマージされたときに発動するようにしました。*2

pipelineの方には、プルリクエストを処理できるようになっているみたいで、今度試してみようと思います。

f:id:Bee_Flim:20180217164303p:plain

ビルドトリガの設定

  1. SCMをポーリングにチェックを入れます。 f:id:Bee_Flim:20180217164306p:plain

ビルド設定

  1. checkstyleやPMDなどのチェックを入れていく。
  2. 高度な設定を開いて、常に実行にチェックを入れる。
  3. 未解決タスクはテストコードを対象外にしたいので、パスを指定する。

f:id:Bee_Flim:20180217164309p:plain f:id:Bee_Flim:20180217164314p:plain f:id:Bee_Flim:20180217164317p:plain f:id:Bee_Flim:20180217164321p:plain f:id:Bee_Flim:20180217164324p:plain

ビルド後の処理

  1. JaCoCo、Slack Notification、Step Counterにチェックを入れる。
  2. Slack Notificationの高度な設定を開いて、"Team Subdomain"にチーム名を入れる。(”https://[チーム名].slack.com”のチーム名の部分)
  3. "Integration Token"にSlackのJenkinsCIで取得したトークンを設定する。
  4. "Project Channel"に通知をしたいchannelを指定する。
  5. 通知したいタイミングにチェックを入れる。
  6. Step Counterにはカウント対象のファイルを指定する。テストコードを除きたい場合は、除外するファイルパターンにテストコードのパスを指定する。 f:id:Bee_Flim:20180217164331p:plain f:id:Bee_Flim:20180217164341p:plain f:id:Bee_Flim:20180217164334p:plain

試してみる。

eclipseにテストコードを追加する。 f:id:Bee_Flim:20180217172130p:plain

こんな感じの適当な物を作成。

/*
 * ソースコード
 */
@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

    public int addCalc(int x, int y) {
        return x + y;
    }

    public int minusCalc() {
      //FIXME テストを修正する事
      String bug = null;
      bug.toCharArray();
      return 1;
    }
  public void sample() {
    //Some thing
  }
}
/*
 * テストコード
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

  @Autowired
  DemoApplication demo;

  @Test
  public void 加算の成功テスト() {
    assertEquals("成功", 3, demo.addCalc(1, 2));
  }

  @Test
  public void 加算の失敗テスト() {
    assertNotEquals("値が違う", 4, demo.addCalc(1, 2));
  }

  @Test
  public void 加算の失敗テスト2() {
    assertEquals("値が違う2", 4, demo.addCalc(1, 20));
  }

  @Test
  public void 加算の失敗テスト3() {
    assertEquals("値が違う3", 4, demo.addCalc(1, 20));
  }

}

Backlogにブランチをプッシュして、masterにプルリクエストを送信します。 そのあと、そのブランチをもう一度pushすると処理が走りました。

こんな感じで、実行結果が表示されました。 f:id:Bee_Flim:20180217164237p:plain

Slackにも通知が来るようになりました。 f:id:Bee_Flim:20180217172548p:plain

おわりに

一応、通知が来るようになったんですが、プルリクエストがあった時にチェックをしたいので、マージ時に実行されるのはいまいちですね。 デプロイする時にはこれでもよさそうな気がします。 pipelineを使うと、出来るようになるらしいので試してみます。

気になった事

ブランチをプッシュした後プルリクエストを送った後にそのブランチを更新しないと実行されないので、 実際の運用時に

”ブランチ作ったらとりあえずプッシュ、その後プルリクエストを送る前にプッシュしてもらう”

って運用が必要になるかと思いました。

*1:自分でmavenyumでインストー ルしてもOK。sudo yun install maven

*2:BacklogのWebHookの履歴を見ていると、プルリクエスト後のGitプッシュの通知でJenkinsのビルドが走っているようで、プルリクエスト前のGitプッシュでは実行されないので、なぜなのかWebHookの内容を見ていると送信している内容が少し違っていました。 ブランチをプッシュした後プルリクエストを送った後に、そのブランチを更新するとJenkinsが動き出したのでJenkins plug-inとWebHookの仕様が微妙にイケてないのかもしれない。

BacklogでPR(Spring F/W)があったらJenkins(AWS)がコードレビューの一部をしてくれて、結果をSlackに通知してくれるようにする。~その6~

pom.xmlの設定をする

jenkinsで実行されるようにpom.xmlの設定を行います。

pluginの設定を行う

mavenの事をあまり知らないのですが、とりあえず下のように設定しました。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>demo</name>
  <description>Demo project for Spring Boot</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <!-- checkstyleの定義ファイルの場所を指定する -->
    <checkstyle.config.location>config/checkstyle/google-checks.xml</checkstyle.config.location>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
     <!-- checkstyleやらPMDとかの設定をする。 -->
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <phase>test</phase>
          </execution>
        </executions>
        <configuration>
          <violationSeverity>warning</violationSeverity>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>findbugs-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <phase>test</phase>
            <goals>
              <goal>findbugs</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <failOnError>true</failOnError>
          <xmlOutput>true</xmlOutput>
          <outputEncoding>UTF-8</outputEncoding>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.0</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>default-report</id>
            <goals>
              <goal>report</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>

  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
        <version>3.0.0</version>
      </plugin>
    </plugins>
  </reporting>

</project>

終わりに

mavenの事が全然わからなかったので、下の本を読んで勉強してこようと思います。