PHPExcelを使ってみよう

github: https://github.com/PHPOffice/PHPExcel

なんか古そうだかDLしてみる
$ git clone https://github.com/PHPOffice/PHPExcel.git

<?php

require_once './PHPExcel/Classes/PHPExcel.php';

$objBook = new PHPExcel();

$objSheet = $objBook->getActiveSheet();

$objSheet->setCellValue('A1', 'ABCDEFG');
$objSheet->setCellValue('A2', 123.56);
$objSheet->setCellValue('A3', TRUE);
$objSheet->setCellValue('A4', '=IF(A3, CONCATENATE(A1, " ", A2), CONCATENATE(A2, " ", A1))');
$objWriter = PHPExcel_IOFactory::createWriter($objBook, "Excel2007");
$objWriter->save('test.xlsx');
exit();
?>

$ sudo apt-get install php-zip

うん、OK

[Docker] 基本操作

docker runは docker pull, docker create, docker startを順番に実行する
docker pullはダウンロード済みのときは再度ダウンロードはしない

$ docker pull httpd:2.4

### latest
タグ名を省略したときは最新版を意味するlatestという特殊なタグが指定されたものとみなされます。
本番環境でDockerを利用するのであれば、タグ名を省略せずに明示的に指定して、特定のイメージに固定することが殆ど
コンテナの定期的なアップデートは必須

### Docker コンテナの作成
コンテナを作成するには docker create を使う
$ sudo docker create –name my-apache-app -p 8080:80 -v “$PWD”:/usr/local/apache2/htdocs/ httpd:2.4
オプションを上記では –name, -p, -v を指定しているが、その他にもさまざまなオプションを指定できる

### nameオプションによる名前付
コンテナの名前をつける –nameオプションはほぼ使用する

### pオプションによるポート設定
-pオプションはポート番号をマッピング

### vオプションによるマウント設定
コンテナの特定ディレクトリに、ホストのディレクトリをマウントする設定

### Dockerコンテナの開始と停止
Docker start *

### -dit
「-dit」オプションを指定しなければ、コンテナがフォアグラウンドで実行されてしまう
-d: デタッチモード
-i: インタラクティブモード
-t: 擬似端末を割り当て

なるほどー

[Docker] Apacheのdockerを動かす

Docker hub
https://hub.docker.com/_/httpd
-> httpdをdownloadします

$ sudo docker run -dit –name my-apache-app -p 8080:80 -v “$PWS”:/usr/local/apache2/htdocs/ httpd:2.4

$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d6766e52c1e httpd:2.4 “httpd-foreground” About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, :::8080->80/tcp my-apache-app

### コンテナの停止と再開
$ sudo docker stop my-apache-app
$ sudo docker start my-apache-app

### ログ出力
$ sudo docker logs my-apache-app

### イメージの破棄
rmを使うにはコンテナが停止状態にならなければいけない
$ sudo docker stop my-apache-app
$ sudo docker rm my-apache-app
$ sudo docker image rm httpd:2.4

なるほど、この辺は基礎というか、ある程度理解している

[Docker] ベースイメージの考え方

Dockerイメージの種類
1. 基本的なLinuxディストリビューションだけのイメージ
2. アプリケーション入りのイメージ
L web server(apache, nginx)
L database server(MySQL, MariaDB, PostgreSQL)
L WordPress, Redmin, Roundcube

業務システムでDockerを使う場合は、LinuxのみDockerイメージを使ってコンテナを作り、そこに自社開発したシステムをインストールして使うことがほとんど
※アプリケーション入りのDockerイメージは、イメージの大きさを小さくするために、最低限のコマンドやライブラリしか入ってなかったり、特殊な初期起動設定がされているため
それをカスタムDockerイメージとして作成する

なるほど、Linux系で開発するのか、、、
非常に勉強になったぜ…

[GitLab] GitLab Container Registryによるコンテナイメージの管理

Docker HubやGoogle container Registryと同様に、GitLabにもGitLab Container Registryが備わっている。

$ docker login registry.gitlab.com
$ docker build -t registry.gitlab.com/hoge/myproject .
$ docker push registry.gitlab.com/hoge/myproject

コンテナイメージの名前を変数化

job01:
  stages:
    - build
    - test
    - deploy

  variables:
    CONTAINER_NAME: ${CI_PROJECT_NAME}_${APP_NAME}
    CONTAINER_IMAGE: ${CI_REGISTRY}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/${APP_NAME}

  packaged_web_app:
    stage: packaged
    before_script:
      - docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
    script:
      - cd ./${APP_NAME}
      - docker build . -t ${CONTAINER_IMAGE}
    only:
      - branches
    except:
      - master
    tags:
      - shell
      - gitlab-runner01

  deploy_web_demo:
    stage: deploy
    variables:
      SERVICE_DOMAIN: gitlab-service.example.com
    before_script:
      - docker rm -f ${CONTAINER_NAME} || true
    script:
      - docker run --name ${CONTAINER_NAME} -p 80:8080 -d ${CONTAINER_IMAGE}
      - sleep 3
      - curl http://${SERVICE_DOMAIN}/${APP_NAME}
    only:
      - master
    when: manual
    environment:
      name: production
      url: http://${SERVICE_DOMAIN}/${APP_NAME}/
    tags:
      - shell
      - gitlab-runner01  

なるほど、大まかにイメージはできてきた

[GitLab CD] 継続的デプロイ: Pipeline

デプロイを自動化してリリースの安定化が求められる
Pipelineにてjobを組み合わせ、デプロイをコードによって自動化する機能
Review Appsでアーティファクトの確認

### ステージの定義
.gitlab-ci.yml

job01:
  stages:
    - build
    - test
    - deploy

  Build_Job01:
    stage: build
    script:
      - "sudo docker run centos:latest echo Build01"

  Test_Job1:
    stage: test
    script:
      - "sudo docker run centos:latest echo Test01"

  Test_Job2:
    stage: test
    script:
      - "sudo docker run centos:latest echo Test02"

  Deploy_Job1:
    stage: deploy
    script:
      - "sudo docker run centos:latest echo Deploy01"

stageのリストに記載した順番に実行される
whenパラメータ: on_success, on_failure, always, manual

### whenパラメータの例

job01:
  stages:
    - build
    - cleanup_build

  Build_Job01:
    stage: build
    script:
      - "docker run centos:latest echo BuildProcess"

  Cleanup_Build_Job01:
    stage: cleanup_build
    script:
      - "docker rm -f $(sudo docker ps -qa --filter 'status=exited')"
    when: on_failure

### dependenciesパラメータの例

job01:
  stages:
    - build
    - test
    - deploy

  variables:
    APP_NAME: 'web_demo'
    CONTAINER_NAME: ${CI_PROJECT_NAME}_${APP_NAME}

  Build_app01:
    stage: build
    script:
      - cd ./app01
      - gradle war
    artifacts:
      paths:
        - app01/build/libs/*.war

  Build_app02:
    stage: build
    script:
      - cd ./app02
      - gradle war
    artifacts:
      paths:
        - app02/build/libs/*.war

  test_app01:
    stage: test
    script:
      - cd ./app01
      - gradle test
    dependencies:
      - build_app01

  test_app02:
    stage: test
    script:
      - cd ./app02
      - gradle test
    dependencies:
      - build_app02

  deploy:
    stage: deploy
    script:
      - cp app*/build/libs/*.war /usr/local/tomcat/webapps
      - systemctl start tomcat.service

  build_web_demo:
    stage: build
    image: gradle:4.4.1-jdk8
    script:
      - cd ./${APP_NAME}
      - gradle war
      - gradle test
    artifacts:
      paths:
        - ${APP_NAME}/build/libs/*war
      expire_in: 10 min
    tags:
      - docker
      - gitlab-runner01

  test_web_demo:
    stage: test
    variables:
      TEST_CONTENT: GitLab
    script:
      - docker run --name ${CONTAINER_NAME} -d ${APP_NAME}
      - sleep 5
      - export CONTAINER_ADDRESS='docker inspect -f "{{ .NetworkSettings.IPAddress}}" ${CONTAINER_NAME}'
      - wget --post-data="name=${TEST_CONTENT}" http://${CONTAINER_ADDRESS}:8080/${APP_NAME}/hello
      - grep ${TEST_CONTENT} ./hello
    after_script:
      - rm -v ./hello
      - docker rm -f ${CONTAINER_NAME} || true
    tags:
      - shell
      - gitlab-runner01

  deploy_web_demo:
    stage: deploy
    variables:
      SERVICE_DOMAIN: gitlab-service.example.com
    before_script:
      - docker rm -f ${CONTAINER_NAME} || true
    script:
      - docker run --name ${CONTAINER_NAME} -p 80:8080 -d ${APP_NAME}
      - sleep 3
      - curl http://${SERVICE_DOMAIN}/${APP_NAME}/
    tags:
      - shell
      - production-gitlab-runner01

Dockerfile

FROM tomcat:latest
COPY build/libs/*.war /usr/local/tomcat/webapps
CMD ["catalina.sh", "run"]

うーむ、build, test, deployを書いていくのはわかった。

[GitLab CI/CD Jobs] 基本設定

GitLab CI/CDにおけるジョブは「.gitlab-ci.yml」に定義する

.gitlab-ci.yml

job01:
  script:
    - uname -r
    - ps
    - hostname

Job02:
  script:
    - ./build.sh
    - ./test.sh

– Scriptパラメータ利用例

job01:
  script:
    - uname -a
    - ./scripts/build.sh
    - bundle exec rspec spec/requests/

– only, expectパラメータ

job01:
  only:
    - /^script-.*$/
  except:
    - tags

only, exceptで使用できるオプション
branches, tags, pushes, schedules, web

– variablesパラメータ

job01:
  variables:
    PROXY_PATH: 'http://proxy.example.com'
    FLAGS: '-0'
  script:
    - 'https_proxy=$PROXY_PATH curl $FLAGS https://gitlab.com/gitlab-org/gitlab-ce/repository/archive.tar.gz'

– tagパラメータ
プロジェクト内で実行可能なRunnerのリストから特定のRunnerを選択する際に使用
指定したタグを利用し、それにマッチしたRunnerだけにジョブを渡す

job01:
  tags:
    - shell
    - gitlab-runner01

– artifactsパラメータ
ジョブの実行結果をアーティファクトとして保存する際の定義を行う
name, untracked, when, expire_in

job01:
  artifacts:
    name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
    untracked: true
    expire_in: 10 min
    paths:
      - ./artifacts

### pythonを実行するサンプル

job01:
  script:
    - python ./scripts/hello.py
  only:
    - master
  tags:
    - shell
    - gitlab-runner01

.gitlab-ci.ymlでbuildとテストを自動化するところまではわかった。
.gitlab-ci.ymlでDockerのbuildをどうやるかが問題か…

[GitLab] CI(継続的インテグレーション)

継続的CIにはJenkins, Travis CI, Circle CIなどがよく利用される
GitLab CI/CDのジョブ機能を使うことによって、ビルドツールやテストツールと連携したインテグレーションの自動化が可能となる

### GitLab CI/CD Jobs
– マルチプラットフォーム: Go, Linux, Windows, FreeBSD, Dockerなどどのプラットフォーム上でもジョブが実行可
– Merge Requestとの連携: Merge Request後のビルド実行確認ができる
– 並列分散実行: 複数のGitLab runnerプロセスにより並列にビルド実行が可能
– オートスケール: ジョブのオートスケールを実現
– アーティファクトの管理: ブラウザ上から利用可能
L Dockerのレジストリ機能とも簡単に連携できる

### GitLab Runner
GitLab CI/CD上から指示されたスクリプトを実行したり、一時的にDockerコンテナを生成してジョブを実行するプロセス
※コンテナをRunnerする場合は2通りある
1. DockerホストにRunnerをインストールしてコンテナをジョブとして起動
2. DockerコンテナをRunnerとして、コンテナ内でジョブを実行

### Executorの種類
– Shell Executor: Runnerが導入されているサーバ上でビルドやテストを実行できるシンプルなExcecutor
– Docker Executor: Docker APIを通してDocker Engineと接続することによって、コンテナから各ビルド作業を実行
– Virtual Box Executor: VirtualBoxのVMを利用したビルド環境を提供 sshとbashを経由
– SSH Executor: SSH接続可能な特定サーバに対してコマンドをSSH経由で送りつける
– Kubernetes Executor: Kubernetes API経由でクラスタ上のPodを作成してビルドを実施。.gitlab-ci.yml内で定義されたServiceパラメータごとに新たにコンテナが生成されビルド、テストを実施

### Runnerの種類
Shared Runners(共有のRunnerで処理)とSpecific Runners(特定のプロジェクトのジョブのみ実行)の2種類がある
Go言語で作成されており、1つのプロセスで複数のExecutorを登録できる

GitLabの開発フローとコード管理

Merge Requestを利用したレビュープロセス

1. 保護ブランチワークフロー: 開発メンバー全員が1つのGithubプロジェクトを利用
2. フォークワークフロー:管理者やレビューアのみがリポジトリを操作できるようになっており、開発者はプロジェクトReporterアクセス権限もに付与されており、自身のリポジトリ上で開発を行う

ブランチに対して権限を付与することで、対象ブランチの偶発的な更新や削除を防ぐ

ブランチの作成
$ git checkout -b
ブランチ削除
$ git branch -d

$ git add new_feature.py
$ touch new_feature.py
$ git add .
$ git commit -m “[Add]new feature library Ref #1”
$ git push origin develop

### Merge Requestの作成
マージ先にはmasterが指定されている
開発規模の肥大化を避けるためにも小さい単位でのMerge Requestが望まれる。ただし開発の生産性と複雑度に依存する
Merge Requestがマージされると同時にテストの自動化が必要(シンタックスエラー、デプロイエラーなど)

### ブランチ戦略 GitLab Flow
機能ブランチ(Feature Branch)とMasterブランチ(Master Branch)
環境ごとにブランチを作りmasterからpre-production, productionにmerge requestを送る

なるほど〜
開発工程においてbranchの設計って凄い大事なんやな〜

Gitによるチーム開発

1. ブランチの作成
$ git branch
* master
$ git branch develop
$ git branch
develop
* master

2.ブランチの切り替え
$ git checkout develop
Switched to branch ‘develop’
$ echo -e “# GitLab Project\nObjects for GitLab” > README.md
$ cat README.md
# GitLab Project
Objects for GitLab
$ git add -u
$ git commit -m “[Modify]Update title in README.md”
[develop 895daf2] [Modify]Update title in README.md
1 file changed, 2 insertions(+)
$ git log

3.ブランチのマージ
$ git checkout master
$ git merge develop
$ cat README.md
# GitLab Project
Objects for GitLab

リモートリポジトリの活用
-> メインのリポジトリをリモートリポジトリ側に置き、各自ローカルリポジトリの更新をマージしていくことでチーム開発を進めていく

$ git branch -a
develop
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
$ git remote add gitlab https://gitlab.com/h3377/myproject.git

### リモートリポジトリの反映
$ git fetch gitlab
$ get merge FETCH_HEAD
// fetchとmergeを同時に行えるpullの方が早いが、コンフリクトを起きたときはfetch, mergeで対応する
$ git pull gitlab HEAD

### リモートリポジトリへの送信
$ vi README.md
$ git add -u
$ git commit -m “[UPDATE]Add description for README.md”
[master 79bed9e] [UPDATE]Add description for README.md
1 file changed, 1 insertion(+), 1 deletion(-)
$ git push gitlab HEAD

### Issue Tracker
– Group Issues: グループ共通の課題チケット
– Project Issues: プロジェクトで個別に割り当てられるチケット
– マイルストーンの作成
– Labels: 各課題チケットを分類するためのカテゴリ(bug, confirmed, ciritial, discussion, documentation, enhancement, suggestion, supportなどがデフォルト)
 -> チケット駆動開発(TiDD)

### Issue Board
チケットの優先順位とステータスを管理