Study/AWS

[AWS] Lambda를 활용해 CI/CD trigger 만들기

Dream Amal 2024. 4. 22.

AWS의 Code Series를 활용해서 CI/CD 파이프라인을 구축할 때, 

Code Commit, Code Build, Code Pipeline으로 EKS에 MSA 서비스를 배포하고, 운영한 적이 있습니다.

 

Code Commit에 프로젝트를 하나로 묶어 관리하기를 원했으나,

commit 하는 순간 해당 Code commit을 참조하고 있는 모든 Code pipeline이 동시에 실행된다는 문제가 발생합니다.

 

Code Commit 구성

제가 만든 Code Commit repo는 아래와 같은 구조를 가지고 있었습니다.

BOB-project/
├──gateway/
│	├──source/
│	└── ...
├──web-app/
│	├──source/
│	└── ...
├──customer-service/   	
│	├──source/
│	└── ...
└── ...

 

하나의 code commit repo 안에 서비스 별로 source code를 정리해두었기 때문에

서비스 별로 만들어 둔 pipeline이 모두 실행되는 문제를 해결하기 위해서는

aws lambda를 활용한 trigger를 반드시 생성해야 합니다.

 

Lambda 실행 코드

import boto3
from botocore.exceptions import ClientError

# CodePipeline 클라이언트 생성
codepipeline_client = boto3.client('codepipeline')

# 각 서비스와 해당 CodePipeline 이름 매핑
services_to_pipeline = {
	# '디렉터리 이름' : '파이프라인 이름'
    'cloud-gateway': 'BoB-cloud-gateway-PIPELINE',
    'web-app': "BoB-web-app-PIPELINE",
    'customers-service': 'BoB-customers-service-PIPELINE',
    'vets-service': 'BoB-vets-service-PIPELINE',
    'visits-service': 'BoB-visits-service-PIPELINE'
}

def lambda_handler(event, context):
    # EventBridge에서 repository_name, commit_id 추출
    repository_name = event['detail']['repositoryName']
    commit_id = event['detail']['commitId']

    # 모든 서비스에 대해 변경 사항 확인 및 CodePipeline 시작
    for service_path, pipeline_name in services_to_pipeline.items():
        if is_change_in_service(repository_name, commit_id, service_path):
            print(f"Changes detected in '{service_path}/' for commit {commit_id}. Starting the CodePipeline.")
            start_codepipeline(pipeline_name)
        else:
            # 변경사항이 없으면 종료
            print(f"No changes detected in '{service_path}/' for commit {commit_id}. No action taken.")

def is_change_in_service(repository_name, commit_id, service_path, region_name='ap-northeast-2'):
    client = boto3.client('codecommit', region_name=region_name)
    
    try:
        response = client.get_differences(
            repositoryName=repository_name,
            afterCommitSpecifier=commit_id
        )
        
        # 디렉터리에 대한 변경 사항이 있는지 확인
        for difference in response['differences']:
            if 'afterBlob' in difference and 'path' in difference['afterBlob']:
                if difference['afterBlob']['path'].startswith(service_path + '/'):
                    return True
        return False
    except ClientError as e:
        print(f"An error occurred: {e}")
        return False

def start_codepipeline(pipeline_name):
    try:
        response = codepipeline_client.start_pipeline_execution(name=pipeline_name)
        return response
    except ClientError as e:
        print(f"An error occurred when starting CodePipeline: {e}")
        return None

 

Lambda 실행 결과

위와 같이 트리거를 생성하여 적용해 주면 원하는 pipeline만 실행되는 것을 확인할 수 있습니다.

 

Code pipeline에서 확인해 봤을 때에도, Latest source revisions 가 각각 변경된 것을 확인할 수 있습니다.

 

728x90

댓글