Posted at

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

More than 3 years have passed since last update.


はじめに

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


使うサービス


  • Lambda

  • API Gateway

  • S3

  • Backlog (SVN)

lambda.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


描いた


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の使い途はまだまだあるので、どんどん使っていければと思います!