RubyとserverlessでSlackへ定期投稿するLambda関数を書く


serverless frameworkを使って、1日1回実行するSlackへの投稿をLambdaの上に最近公式サポートされたRubyで書きます。

下準備

Slack appを作って適当なチャンネルにintegrateしてwebhook urlを取得しておいてください。あとserverlessとrubyのインストールもお忘れなく。

作る

serverless create --template aws-ruby --path lottery とすると以下のような構造のディレクトリができます。

lottery > tree
.
├── handler.rb
└── serverless.yml

0 directories, 2 files

作成されたhandler.rbhelloメソッドを変更します。

require 'json'
require 'slack-notifier'

def hello(event:, context:)
  notifier = Slack::Notifier.new 'https://hooks.slack.com/services/xxxxxxxxxxxx' do
    defaults channel: '#general',
             link_names: 1
  end
  notifier.post text: '一日一善'
end

次にserverless.yamlに定期実行させる処理を追加します。

functions:
  hello:
    handler: handler.hello
    events:
      - schedule: cron(00 00 * * *)

上の設定では毎日0時0分に定期実行されるようになっています。時刻の設定はcrontabと同じ記法が使えます。(参考: tutorial-scheduled-events-schedule-expressions)

これが終わったらserverless deployするだけであとは毎日Slackに投稿されるようになります。

注意事項

serverlessの管理下にgemをインストールする

bundle install --path vendor/bundle でserverlessの管理下にgemをインストールするか、Lambda Layerを使いましょう。

Init error when loading handler handler.lottery
{
"errorMessage": "cannot load such file -- slack/post",
"errorType": "Init<LoadError>",
"stackTrace": [
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
"/var/task/handler.rb:2:in `<top (required)>'",
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'"
]
}

Rubyのバージョンを合わせる

LambdaでサポートするRubyのランタイムはバージョン2.5.0なので、ローカルでも2.5系を入れましょう。

// 上と同じエラーです
Init error when loading handler handler.lottery
{
"errorMessage": "cannot load such file -- slack/post",
"errorType": "Init<LoadError>",
"stackTrace": [
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
"/var/task/handler.rb:2:in `<top (required)>'",
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
"/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'"
]
}

scheduleのrateは時間の単数/複数に注意

serverless.yml中のscheduleにはrateを使うこともできます。

    events:
      - schedule: rate(1 minute)

ここで気をつけるべきなのは時間が単数か複数かどうかというところで、例えば 1 minutes とするとエラーが出ます。同じように 10 minute でもエラーが出ます。1 minutesはちょっと許してほしい気持ちがありますけど。

  Serverless Error ---------------------------------------

  An error occurred: HelloEventsRuleSchedule1 - Parameter ScheduleExpression is not valid. (Service: AmazonCloudWatchEvents; Status Code: 400; Error Code: ValidationException; Request ID: 329bfa3f-f7c9-11e8-9332-xxxxxxxx).