From 04bcd218a7a1fddee2eb9b681151441080cf119f Mon Sep 17 00:00:00 2001 From: Italo Pessoa Date: Thu, 12 Sep 2024 18:37:34 -0300 Subject: [PATCH] ci: configure terraform pipeline (#8) * ci: configure tfvars file * fix the use of local env variables * fix environment variable * copilot said this is the right way * okay, now that's to verbose * vai assim mesmo * fix workflow * fix tfvars file * update default variables * trigger new plan * add BMB_MYSQL_DATABASE --- .github/workflows/terraform.yaml | 119 +++++++++++++++++++++++++++++-- init/schema.sql | 57 +++++++++++++++ main.tf | 24 +++---- output.tf | 2 +- providers.tf | 7 +- variables.tf | 16 ++++- 6 files changed, 200 insertions(+), 25 deletions(-) create mode 100644 init/schema.sql diff --git a/.github/workflows/terraform.yaml b/.github/workflows/terraform.yaml index 9ddf005..df85c88 100644 --- a/.github/workflows/terraform.yaml +++ b/.github/workflows/terraform.yaml @@ -2,6 +2,7 @@ name: 'Terraform build' on: push: + branches: [ "main" ] pull_request: env: @@ -15,6 +16,27 @@ permissions: jobs: + terraform-settings: + name: "Terraform Settings" + runs-on: ubuntu-latest + + steps: + - name: Config + run: | + cat < db.auto.tfvars + cluster_name = "${{ vars.BMB_MYSQL_CLUSTER }}" + database_name = "${{ vars.BMB_MYSQL_DATABASE }}" + vpc_name = "${{ vars.BMB_EKS_CLUSTER_VPC }}" + username = "${{ secrets.BMB_MYSQL_USER }}" + password = "${{ secrets.BMB_MYSQL_PASSWORD }}" + EOF + + - name: Upload Configuration + uses: actions/upload-artifact@v4 + with: + name: database-config + path: db.auto.tfvars + test: name: 'Test' runs-on: ubuntu-latest @@ -28,6 +50,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Download Configuration + uses: actions/download-artifact@v4 + with: + name: database-config + - name: Setup Terraform uses: hashicorp/setup-terraform@v1 with: @@ -41,12 +68,11 @@ jobs: run: terraform test sonarcloud: - needs: [test] if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' name: SonarCloud runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: SonarCloud Scan @@ -55,8 +81,85 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + terraform-plan: + needs: [test, terraform-settings] + if: github.event_name == 'pull_request' + environment: dev + name: "Terraform Plan" + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download Configuration + uses: actions/download-artifact@v4 + with: + name: database-config + + - name: Upload Configuration + uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.3.1 + id: plan-upload + with: + workspace: ${{ env.TF_WORKSPACE }} + directory: ${{ env.CONFIG_DIRECTORY }} + speculative: true + + - name: Create Plan Run + uses: hashicorp/tfc-workflows-github/actions/create-run@v1.3.1 + id: plan-run + with: + workspace: ${{ env.TF_WORKSPACE }} + configuration_version: ${{ steps.plan-upload.outputs.configuration_version_id }} + plan_only: true + + - name: Get Plan Output + uses: hashicorp/tfc-workflows-github/actions/plan-output@v1.3.1 + id: plan-output + with: + plan: ${{ fromJSON(steps.plan-run.outputs.payload).data.relationships.plan.data.id }} + + - name: Update PR + uses: actions/github-script@v7 + id: plan-comment + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // 1. Retrieve existing bot comments for the PR + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const botComment = comments.find(comment => { + return comment.user.type === 'Bot' && comment.body.includes('Terraform Cloud Plan Output') + }); + const output = `#### Terraform Cloud Plan Output + \`\`\` + Plan: ${{ steps.plan-output.outputs.add }} to add, ${{ steps.plan-output.outputs.change }} to change, ${{ steps.plan-output.outputs.destroy }} to destroy. + \`\`\` + [Terraform Cloud Plan](${{ steps.plan-run.outputs.run_link }}) + `; + // 3. Delete previous comment so PR timeline makes sense + if (botComment) { + github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + }); + } + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: output + }); + deploy: - needs: [test] + needs: [test, terraform-settings] if: github.ref == 'refs/heads/main' name: "Terraform Apply" runs-on: ubuntu-latest @@ -65,7 +168,12 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + - name: Download Configuration + uses: actions/download-artifact@v4 + with: + name: database-config - name: Upload Configuration uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.3.1 @@ -81,11 +189,10 @@ jobs: workspace: ${{ env.TF_WORKSPACE }} configuration_version: ${{ steps.apply-upload.outputs.configuration_version_id }} message: "Plan Run from GitHub Actions CI ${{ github.sha }}" - TF_VAR_vpc_name: "\"teste\"" - name: Apply uses: hashicorp/tfc-workflows-github/actions/apply-run@v1.3.1 - if: fromJSON(steps.apply-run.outputs.payload).data.attributes.actions.IsConfirmable && false + if: fromJSON(steps.apply-run.outputs.payload).data.attributes.actions.IsConfirmable && ${{ vars.TF_AUTO_APPROVE == 'true' }} id: apply with: run: ${{ steps.apply-run.outputs.run_id }} diff --git a/init/schema.sql b/init/schema.sql new file mode 100644 index 0000000..1460bb0 --- /dev/null +++ b/init/schema.sql @@ -0,0 +1,57 @@ +use techchallenge; + +create table IF NOT EXISTS Customers +( + Id char(36) not null + primary key, + Cpf varchar(11) not null, + Name varchar(100) null, + Email varchar(100) null +); + + +create table IF NOT EXISTS Products +( + Id char(36) not null comment 'product id' + primary key, + Name varchar(100) not null, + Description varchar(200) not null, + Category int not null, + Price decimal(10,2) not null, + Images varchar(1000) null +); + + +create table IF NOT EXISTS Orders +( + Id char(36) not null, + CustomerId char(36) null, + PaymentId char(36) null, + Status int not null, + Created datetime null, + Updated datetime null, + TrackingCode varchar(7) null +); + + +create table IF NOT EXISTS OrderItems +( + OrderId char(36) not null, + ProductId char(36) not null, + ProductName varchar(200) not null, + UnitPrice decimal not null, + Quantity int null +); + +create table IF NOT EXISTS Payments +( + Id char(36) not null, + OrderId char(36) not null, + Status int not null, + Created datetime null, + Updated datetime null, + PaymentType int not null, + ExternalReference varchar(36) not null, + Amount decimal(10,2) not null, + PRIMARY KEY (Id, OrderId) +); \ No newline at end of file diff --git a/main.tf b/main.tf index 55740f5..b3d5206 100644 --- a/main.tf +++ b/main.tf @@ -46,7 +46,7 @@ data "aws_subnets" "public_subnets" { } data "aws_subnet" "subnet" { - for_each = toset(concat(data.aws_subnets.public_subnets.ids, data.aws_subnets.private_subnets.ids)) + for_each = toset(concat(data.aws_subnets.private_subnets.ids)) id = each.value } @@ -54,8 +54,8 @@ module "aurora_db_serverless_cluster" { source = "terraform-aws-modules/rds-aurora/aws" version = "~> 9.9.0" - name = "${var.cluster_name}" - database_name = "techchallenge" + name = var.cluster_name + database_name = var.database_name engine = "aurora-mysql" engine_mode = "serverless" storage_encrypted = true @@ -69,7 +69,7 @@ module "aurora_db_serverless_cluster" { master_password = var.password manage_master_user_password = false - autoscaling_enabled = false + autoscaling_enabled = false vpc_id = data.aws_vpc.vpc.id db_subnet_group_name = var.vpc_name security_group_rules = { @@ -78,12 +78,12 @@ module "aurora_db_serverless_cluster" { } } - publicly_accessible = true - apply_immediately = true + publicly_accessible = true + apply_immediately = true # enabled_cloudwatch_logs_exports = ["general"] - enable_http_endpoint = true - monitoring_interval = 0 - skip_final_snapshot = true + enable_http_endpoint = true + monitoring_interval = 0 + skip_final_snapshot = true serverlessv2_scaling_configuration = { min_capacity = 1 @@ -91,7 +91,7 @@ module "aurora_db_serverless_cluster" { } tags = { - Terraform = "true" + Terraform = "true" + Environment = var.environment } - -} \ No newline at end of file +} diff --git a/output.tf b/output.tf index 52f847e..806ec9b 100644 --- a/output.tf +++ b/output.tf @@ -7,7 +7,7 @@ output "subnet_cidr_blocks" { } output "cluster" { - value = module.aurora_db_serverless_cluster + value = module.aurora_db_serverless_cluster sensitive = true } diff --git a/providers.tf b/providers.tf index 8f78e40..3a469ce 100644 --- a/providers.tf +++ b/providers.tf @@ -12,10 +12,11 @@ provider "aws" { profile = var.profile region = var.region alias = "us-east-1" - + default_tags { - tags = { + tags = { ManagedBy = "Terraform" + "teste" = "teste" } } -} \ No newline at end of file +} diff --git a/variables.tf b/variables.tf index b464d4a..88eb601 100644 --- a/variables.tf +++ b/variables.tf @@ -18,17 +18,27 @@ variable "vpc_name" { variable "cluster_name" { type = string - default = "techchallenge-mysql" + default = "techchallenge-mysql-default" +} + +variable "database_name" { + type = string + default = "techchallenge-default" } variable "username" { type = string sensitive = true - default = "techchallenge" + default = "techchallenge-default" } variable "password" { type = string sensitive = true - default = "F#P9ia-3" + default = "F#P9ia-3-default" +} + +variable "environment" { + default = "dev" + type = string }