AWS Lambdaを使ってBacklogとS3を連携

#はじめに
　これまで静的ページ配信のために、AWSコンソールからS3の設定を行い、ファイルをアップしていました。数が増えてきて毎回ぽちぽちやるのは大変になり、自動化できたら楽だなあというのと、静的コンテンツとはいえバージョン管理したいよね、という要望が出てきたので、AWS Lambdaを使ってBacklogとS3を連携して、コンテンツのアップロードを自動化するシステムを作ってみました。

#使うサービス

- Lambda
- API Gateway
- S3
- Backlog (SVN)

![lambda.png](https://qiita-image-store.s3.amazonaws.com/0/101095/5567a98e-27af-2087-3d3f-9d9b0c7633f2.png)

- 今回は図の②③④を紹介します。
- バージョン管理にgitでなく、svnを使うのはデザイナーさんやディレクターさんでも使えるようにです。
- Lambda, Gatewayの設定とBacklogのwebhookについては↓を参照。

http://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/getting-started.html
http://www.backlog.jp/help/adminsguide/webhook-setting/userguide2493.html

#描いた

```lang:filename
var async = require('async');
var request = require('request');
var aws = require('aws-sdk');
aws.config.update({
  accessKeyId: 'your_key',
  secretAccessKey: 'your_secret_key',
  region: 'your_region'
});
var s3 = new aws.S3({ apiVersion: '2006-03-01' });

exports.handler = function(event, context) {

    var project = event.project.projectKey;
    var root = '';

    getDir(project, root, function(dir1){
        getDir(project, dir1, function(dir2){
            putContent(project, dir1 + dir2);
        });
    });
};

/**
 *  ディレクトリ名を返す関数
 **/
function getDir(project, dir, callback){

    var exec = require('child_process').exec;
    var cmd = "curl --user your_username:your_password https://your_domain.backlog.jp/svn/" + project + "/" + dir + " | grep href | grep -oE '\"([^\.]*)\"' | sed -e 's/\"//g'";

    exec(cmd, function(error, stdout, stderr) {

        dirs = stdout.split('\n');

        var i = 0;
        async.whilst(function start(){

            return i < dirs.length;

        }, function main(done){

            callback(dirs[i]);

            i++;
            done();

        }, function result(err){
            if (err) console.error(err);
        });
    })
}

/**
 *  S3にアップする関数
 **/
function putContent(project, dir){

    var exec = require('child_process').exec;
    var cmd = "curl --user your_username:your_password https://your_domain.backlog.jp/svn/" + project + "/" + dir + "| grep href | grep -oE '\".*\..*\"' | sed -e 's/\"//g' | grep -v ../";
    var files = [];

    exec(cmd, function(error, stdout, stderr) {

        files = stdout.split('\n');

        var i = 0;
        async.whilst(function start(){

            return i < files.length;

        }, function main(done){

            if(files[i] != ""){

                var key = files[i];

                var options = {
                    url: 'https://your_domain.backlog.jp/svn/' + project + '/' + dir + key,
                    auth: {
                        user: "your_username",
                        password: "your_password"
                    }
                };

                if(/.*image.*/.test(dir + key)){

                    options['encoding'] = null;

                }

                request.get(options, function (error, response, body) {

                    if (!error && response.statusCode == 200) {

                        var params = {
                            ACL: 'public-read',
                            Bucket: 'your_bucket',
                            Key: dir + key,
                            Body: body,
                        };


                        if (/.*html.*/.test(dir + key)) {

                            params['ContentType'] = 'text/html';

                        } else if (/.*css.*/.test(dir + key)) {

                            params['ContentType'] = 'text/css';

                        } else if (/.*js.*/.test(dir + key)) {

                            params['ContentType'] = 'text/javascript';

                        } else {

                            params['ContentType'] = response.headers['content-type'];

                        }

                        s3.putObject(params, function(err, data) {
                            if(err) console.log(err);
                        });

                    } else {
                        console.log('error: '+ response.statusCode);
                    }
                })
            }

            i++;
            done();

        }, function result(err){
            if (err) console.error(err);
        });
    })
}
```

#できたこと

Backlogのsvnリポジトリにコミットするだけで、リポジトリ内のファイルがS3にコピーされるようになりました。これでファイルの公開をデザイナーさんだけでできるようになります。

#苦労した点

- backlogからのwebhookで返ってくる情報が少ない
 - 公式サイトにはgitのwebhookのサンプルしか書いてなかったが、実際に返ってきたjsonはサンプルと違う、情報が少ない :tada: 
 - svnはより少ない :confetti_ball: 
- 画像のアップロード
 - S3にアップした画像が壊れていると表示されて困っていたが、requestモジュールで画像を取得するときは以下の設定が必要だった

        `options['encoding'] = null;`

#まとめ

- Lambda, node.jsなどなどきちんと使うの初めてで色々苦労しましたが、新しいサービスを積極的に使えるのは面白かったです。Lambdaの使い途はまだまだあるので、どんどん使っていければと思います！