skip to content
鰭狀漏斗

用 EventBridge Scheduler 在一段時間內只執行一次 CodeBuild 建置

/ 閱讀時間 3 分鐘

目次

延續上次的文章,我後來選擇使用 lambda function URL 來讓 webhook 觸發 CodeBuild 建置。不過如果直接讓 lambda function 觸發的話,每次 commit push 都會觸發一次建置,這樣會讓免費時數消耗的有點快,所以我想讓時間相近的 commit push 只觸發一次建置。

我找到最簡單的方法是用 EventBridge Scheduler:

Amazon EventBridge 排程器是無伺服器排程器,可讓您從單一受管的中央服務建立、執行及管理任務。

簡單說 EventBridge Scheduler 就是讓你可以設定指定時間(一次性排程)或是間隔一定時間(Cron 型排程)對 AWS 服務執行動作的排程器。

要達到目的,我們可以建立一個指定時間的排程觸發 CodeBuild 建置,然後由 lambda function 設定觸發時間。

如果排程的時間是過去的,代表已經執行過,所以設定一定時間後執行。如果是未來的時間,代表這個一定時間內 webhook lambda function 已經執行過,設定排程執行時間了,所以就不另外設定執行時間。

要建立排程,可以到 Amazon EventBridge,選擇排程器下的排程,點選「建立排程」。設定好排程名稱並且選擇一次性排程,並指定一個過去的時間後,目標這邊我們選擇的是範本化目標的 CodeBuild - StartBuild。選擇目標後,下面會讓你選擇要觸發的 CodeBuild 專案。好了之後就可以按下一步,然後建立排程。

建立完排程後還要改 lambda function,要加入的程式碼大概像這樣:

import boto3
event_bridge_scheduler_client = boto3.client('scheduler')
def schedule_event():
"""Schedule event to EventBridge Scheduler"""
try:
response = event_bridge_scheduler_client.get_schedule(
Name='<scheduler-name>'
)
if response['ScheduleExpression'].startswith('at'):
schuduled_time = parser.parse(response['ScheduleExpression'][3:-1])
if schuduled_time >= datetime.now():
return
event_bridge_scheduler_client.update_schedule(
Name='<scheduler-name>',
FlexibleTimeWindow={
'Mode': 'OFF'
},
ScheduleExpression='at(' + (datetime.now() + timedelta(minutes=5)).strftime('%Y-%m-%dT%H:%M:%S') + ')',
Target=response['Target']
)
except BaseException as err:
raise PutEventError('Put Events Failed')

這段程式碼的 schedule_event() 會對排程時間在過去的 <scheduler-name> 排程設定一個新的時間,這樣就可以保證在一定時間內,不論有多少次 commit push 都只會觸發一次建置。

當然這段程式碼中並沒有執行 schedule_event() 函式,請自行在 lambda function 中找合適的地方執行這個函式。

參考資料