From 93d0319796069a84a2140c3affa1cf61f5957eec Mon Sep 17 00:00:00 2001 From: WayneGoosen <13494899+WayneGoosen@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:50:12 +0200 Subject: [PATCH] feat: start part 4 draft --- ...oyment-guide-part-4-github-tf-workflow.mdx | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 src/content/blog/streamlit-deployment-guide-part-4-github-tf-workflow.mdx diff --git a/src/content/blog/streamlit-deployment-guide-part-4-github-tf-workflow.mdx b/src/content/blog/streamlit-deployment-guide-part-4-github-tf-workflow.mdx new file mode 100644 index 0000000..cf20df7 --- /dev/null +++ b/src/content/blog/streamlit-deployment-guide-part-4-github-tf-workflow.mdx @@ -0,0 +1,224 @@ +--- +heroImage: /src/assets/images/Terraform.png +category: CICD +description: >- + A step-by-step guide to configure a GitHub Workflow that executes Terraform commands to provision Infrastructure on Azure. +pubDate: 2024-07-16 +draft: true +tags: + - terraform + - azure + - iac + - github +title: >- + Streamlit Deployment Guide Part 4: GitHub Workflow for Terraform Apply & Destroy +--- + +This showcases a GitHub Workflow walkthrough of executing the necessary Terraform commands to provision and tear down the Azure resources for the Streamlit application. It continues a series detailing the process of deploying a Streamlit app to Azure, broken down into the following parts: + +- [**Part 1**: Containerizing a Streamlit app.](https://blog.waynegoosen.com/post/streamlit-deployment-guide-part-1-containerization/) +- [**Part 2**: GitHub Workflow for Building and Publishing to ghcr.io](https://blog.waynegoosen.com/post/streamlit-deployment-guide-part-2-github-workflow/) +- [**Part 3**: Azure Infrastructure via Terraform](https://blog.waynegoosen.com/post/streamlit-deployment-guide-part-3-azure-infra/) +- **Part 4**: GitHub Workflow for Terraform Apply & Destroy **You are here** 😊 + +Do you want to deploy your Streamlit application on Azure right now? Use the [template repository](https://github.com/WayneGoosen/azure-streamlit-poc) 🚀 + +## TL;DR + +See the [completed GitHub Workflow](#completed-workflow). + +## Prerequisites + +A basic understanding of GitHub Actions is required and the Workflow assumes you have the files from Part 3: + +- /infra/main.tf +- /infra/providers.tf +- /infra/variables.tf +- /infra/locals.tf +- /infra/web-app.tf + +If you have your own Terraform configuration, ensure all the dependent files are available and are stored within /infra folder for this Workflows to function correctly. + +## Create a GitHub Workflow + +The Workflow file should be stored within the following folder: `.github/workflows/`. A concise name could be `docker-image-build-and-push.yaml`. + +### Completed Apply Workflow + +```yaml +name: Terraform Plan & Apply Infrastructure + +on: + push: + branches: ['main'] + paths: + - 'infra/**' + tags: + - '*' + workflow_dispatch: + +env: + TF_VAR_resource_group_name: 'rg-streamlit-poc' + WORKING_DIRECTORY: './infra' + +jobs: + terraform: + runs-on: ubuntu-latest + environment: production + permissions: + id-token: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # image name needs to be lowercase, some accounts have uppercase letters + - name: Get owner/repo name and convert to lowercase + id: get-image-name + run: echo "image-name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + + - name: Extract image tag + id: extract-tag + run: | + if [[ $GITHUB_REF == refs/tags/* ]]; then + TAG=${GITHUB_REF#refs/tags/} + else + TAG=$(git describe --tags --abbrev=0) + fi + echo "tag=$TAG" >> $GITHUB_OUTPUT + + - name: Azure login + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_ENTRA_ID_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_ENTRA_ID_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.8.4 + + - name: Terraform fmt + id: fmt + run: terraform fmt -check + continue-on-error: true + + - name: Terraform Init + id: init + working-directory: ${{ env.WORKING_DIRECTORY }} + env: + ARM_CLIENT_ID: ${{ secrets.AZURE_ENTRA_ID_CLIENT_ID }} + ARM_TENANT_ID: ${{ secrets.AZURE_ENTRA_ID_TENANT_ID }} + ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + ARM_USE_OIDC: true + run: terraform init + + - name: Terraform Validate + id: validate + working-directory: ${{ env.WORKING_DIRECTORY }} + run: terraform validate -no-color + + - name: Terraform Plan + id: plan + env: + ARM_CLIENT_ID: ${{ secrets.AZURE_ENTRA_ID_CLIENT_ID }} + ARM_TENANT_ID: ${{ secrets.AZURE_ENTRA_ID_TENANT_ID }} + ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + ARM_USE_OIDC: true + TF_VAR_docker_image_name: '${{ steps.get-image-name.outputs.image-name }}:${{ steps.extract-tag.outputs.tag }}' + working-directory: ${{ env.WORKING_DIRECTORY }} + run: terraform plan -no-color + continue-on-error: false + + - name: Terraform Apply (auto-approve) + working-directory: ${{ env.WORKING_DIRECTORY }} + env: + ARM_CLIENT_ID: ${{ secrets.AZURE_ENTRA_ID_CLIENT_ID }} + ARM_TENANT_ID: ${{ secrets.AZURE_ENTRA_ID_TENANT_ID }} + ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + ARM_USE_OIDC: true + TF_VAR_docker_image_name: '${{ steps.get-image-name.outputs.image-name }}:${{ steps.extract-tag.outputs.tag }}' + run: terraform apply -auto-approve +``` + +#### Workflow Walkthrough + +##### Workflow Definition + +```yaml +name: Docker Image Build and Push +``` + +The name of the workflow which is shown under the Actions tab. This allows you to set a readable name for your Workflow, if omitted the file name will be shown. + +##### Triggers + +```yaml +on: + push: + branches: ['main'] + paths: + - 'app/**' + workflow_dispatch: +``` + +The workflow triggers on pushes to the "main" branch and only if the changes are made in the 'app' directory. The 'workflow_dispatch' allows the workflow to be triggered manually. + +### Completed Destroy Workflow + +```yaml +name: Terraform Destroy Inrastructure + +on: workflow_dispatch + +env: + TF_VAR_docker_image_name: 'waynegoosen/azure-streamlit-poc:0.1.2' + TF_VAR_resource_group_name: 'rg-streamlit-poc' + WORKING_DIRECTORY: './infra' + +jobs: + terraform: + runs-on: ubuntu-latest + environment: production + permissions: + id-token: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Azure login + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_AD_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_AD_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.8.0 + + - name: Terraform Init + id: init + working-directory: ${{ env.WORKING_DIRECTORY }} + env: + ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }} + ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }} + ARM_USE_OIDC: true + run: terraform init + + - name: Terraform Destroy (auto-approve) + id: destroy + working-directory: ${{ env.WORKING_DIRECTORY }} + env: + ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }} + ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }} + ARM_USE_OIDC: true + run: terraform destroy -auto-approve +```