Readme Terraform #65
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CD-Deploy | |
on: | |
push: | |
branches: | |
- main | |
- develop | |
pull_request: | |
branches: | |
- main | |
- develop | |
paths: | |
- './**' | |
- './terraform/**' | |
- './integration_tests/**' | |
jobs: | |
build-push-deploy: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check out repo | |
uses: actions/checkout@v3 | |
- name: Configure AWS Credentials | |
uses: aws-actions/configure-aws-credentials@v1 | |
with: | |
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-region: "eu-central-1" | |
- uses: hashicorp/setup-terraform@v2 | |
with: | |
terraform_wrapper: false | |
# Define the infrastructure | |
- name: TF plan | |
id: tf-plan | |
working-directory: 'terraform' | |
run: | | |
terraform init -backend-config="key=mlops-zoomcamp-prod.tfstate" -reconfigure | |
terraform plan -var-file=vars/prod.tfvars | |
- name: TF Apply | |
id: tf-apply | |
working-directory: 'terraform' | |
if: ${{ steps.tf-plan.outcome }} == 'success' | |
run: | | |
terraform apply -auto-approve -var-file=vars/prod.tfvars | |
echo "::set-output name=ecr_repo::$(terraform output ecr_repo | xargs)" | |
echo "::set-output name=predictions_stream_name::$(terraform output predictions_stream_name | xargs)" | |
echo "::set-output name=model_bucket::$(terraform output model_bucket | xargs)" | |
echo "::set-output name=lambda_function::$(terraform output lambda_function | xargs)" | |
# Build-Push | |
- name: Login to Amazon ECR | |
id: login-ecr | |
uses: aws-actions/amazon-ecr-login@v1 | |
- name: Build, tag, and push image to Amazon ECR | |
id: build-image-step | |
working-directory: "terraform" | |
env: | |
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} | |
ECR_REPOSITORY: ${{ steps.tf-apply.outputs.ecr_repo }} | |
IMAGE_TAG: "latest" # ${{ github.sha }} | |
run: | | |
# Ensure the build context includes the necessary files for the Docker build | |
ls -la | |
docker build -t ${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_TAG} . | |
aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin ${ECR_REGISTRY} | |
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | |
echo "::set-output name=image_uri::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" | |
# Deploy | |
- name: Get model artifacts | |
# The steps here are not suited for production. | |
# In practice, retrieving the latest model version or RUN_ID from a service like MLflow or DVC can also be integrated into a CI/CD pipeline. | |
# But due to the limited scope of this workshop, we would be keeping things simple. | |
# In practice, you would also have a separate training pipeline to write new model artifacts to your Model Bucket in Prod. | |
id: get-model-artifacts | |
working-directory: "terraform" | |
env: | |
MODEL_BUCKET_DEV: "mlflow-tracking-remote" | |
MODEL_BUCKET_PROD: ${{ steps.tf-apply.outputs.model_bucket }} | |
run: | | |
# export RUN_ID=$(aws s3api list-objects-v2 --bucket ${MODEL_BUCKET_DEV} \ | |
# --query 'sort_by(Contents, &LastModified)[-1].Key' --output=text | cut -f2 -d/) | |
export RUN_ID=aa806b4bc4044777a0a25d5b8a24d7d5 | |
aws s3 sync s3://${MODEL_BUCKET_DEV} s3://${MODEL_BUCKET_PROD} | |
echo "::set-output name=run_id::${RUN_ID}" | |
- name: Update Lambda | |
env: | |
LAMBDA_FUNCTION: ${{ steps.tf-apply.outputs.lambda_function }} | |
PREDICTIONS_STREAM_NAME: ${{ steps.tf-apply.outputs.predictions_stream_name }} | |
MODEL_BUCKET: ${{ steps.tf-apply.outputs.model_bucket }} | |
RUN_ID: ${{ steps.get-model-artifacts.outputs.run_id }} | |
run: | | |
variables="{ \ | |
PREDICTIONS_STREAM_NAME=$PREDICTIONS_STREAM_NAME, MODEL_BUCKET=$MODEL_BUCKET, RUN_ID=$RUN_ID \ | |
}" | |
STATE=$(aws lambda get-function --function-name $LAMBDA_FUNCTION --region "eu-central-1" --query 'Configuration.LastUpdateStatus' --output text) | |
while [[ "$STATE" == "InProgress" ]] | |
do | |
echo "sleep 5sec ...." | |
sleep 5s | |
STATE=$(aws lambda get-function --function-name $LAMBDA_FUNCTION --region "eu-west-1" --query 'Configuration.LastUpdateStatus' --output text) | |
echo $STATE | |
done | |
aws lambda update-function-configuration --function-name $LAMBDA_FUNCTION \ | |
--environment "Variables=${variables}" |