From eefb3caa2ed3ba9baac30b0b685c29f272f418fa Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 14 Dec 2025 15:42:03 +0100 Subject: [PATCH 1/6] fix tests --- src/__tests__/routes.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/__tests__/routes.test.js b/src/__tests__/routes.test.js index 179a361..a978757 100644 --- a/src/__tests__/routes.test.js +++ b/src/__tests__/routes.test.js @@ -564,7 +564,7 @@ describe('API Routes', () => { .get('/v1/static/reports/data.json') .expect(500); - expect(res.body).toHaveProperty('error', 'Failed to retrieve file'); + expect(res.body).toHaveProperty('error', 'Server failed to respond'); expect(res.body).toHaveProperty('details'); }); @@ -576,7 +576,7 @@ describe('API Routes', () => { .get('/v1/static/reports/data.json') .expect(500); - expect(res.body).toHaveProperty('error', 'Failed to retrieve file'); + expect(res.body).toHaveProperty('error', 'Server failed to respond'); }); it('should handle stream errors during file read', async () => { @@ -852,7 +852,7 @@ describe('API Routes', () => { .get('/v1/static/reports/data.json') .expect(500); - expect(res.body).toHaveProperty('error', 'Failed to retrieve file'); + expect(res.body).toHaveProperty('error', 'Server failed to respond'); expect(res.body).toHaveProperty('details'); }); @@ -864,7 +864,7 @@ describe('API Routes', () => { .get('/v1/static/reports/data.json') .expect(500); - expect(res.body).toHaveProperty('error', 'Failed to retrieve file'); + expect(res.body).toHaveProperty('error', 'Server failed to respond'); }); it('should handle stream errors during file read', async () => { From 063486e3f647f0cc3f47dc049932388a325e7663 Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 14 Dec 2025 16:02:35 +0100 Subject: [PATCH 2/6] cache clean not required --- src/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Dockerfile b/src/Dockerfile index 5b22681..c6e66db 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -4,10 +4,11 @@ WORKDIR /app COPY package*.json ./ -RUN --mount=type=cache,target=/root/.npm npm ci --only=production --quiet --no-fund --no-audit && npm cache clean --force +RUN --mount=type=cache,target=/root/.npm \ + npm ci --omit=dev --no-fund --no-audit COPY . . ENV PORT=8080 -CMD ["npx", "functions-framework", "--target=app"] \ No newline at end of file +CMD ["npx", "functions-framework", "--target=app"] From 16d750ad02f5b1d426bb56a7181de60c01eac86f Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 14 Dec 2025 21:53:47 +0100 Subject: [PATCH 3/6] consolidate deployment by introducing backend configs and a Makefile --- .github/workflows/deployment.yaml | 76 +++---------------- Makefile | 8 ++ terraform/backend-dev.hcl | 2 + terraform/backend-prod.hcl | 2 + .../{modules => }/cdn-glb/cloud_armor.tf | 0 terraform/{modules => }/cdn-glb/main.tf | 0 terraform/{modules => }/cdn-glb/outputs.tf | 0 terraform/{modules => }/cdn-glb/variables.tf | 0 terraform/dev/main.tf | 36 --------- terraform/dev/variables.tf | 19 ----- terraform/{prod => }/main.tf | 33 ++++---- terraform/{modules => }/run-service/main.tf | 0 .../{modules => }/run-service/outputs.tf | 0 .../{modules => }/run-service/variables.tf | 0 terraform/{prod => }/variables.tf | 3 +- 15 files changed, 43 insertions(+), 136 deletions(-) create mode 100644 Makefile create mode 100644 terraform/backend-dev.hcl create mode 100644 terraform/backend-prod.hcl rename terraform/{modules => }/cdn-glb/cloud_armor.tf (100%) rename terraform/{modules => }/cdn-glb/main.tf (100%) rename terraform/{modules => }/cdn-glb/outputs.tf (100%) rename terraform/{modules => }/cdn-glb/variables.tf (100%) delete mode 100644 terraform/dev/main.tf delete mode 100644 terraform/dev/variables.tf rename terraform/{prod => }/main.tf (60%) rename terraform/{modules => }/run-service/main.tf (100%) rename terraform/{modules => }/run-service/outputs.tf (100%) rename terraform/{modules => }/run-service/variables.tf (100%) rename terraform/{prod => }/variables.tf (85%) diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml index 27c42bd..ed3ac04 100644 --- a/.github/workflows/deployment.yaml +++ b/.github/workflows/deployment.yaml @@ -19,13 +19,13 @@ jobs: npm ci npm run test - deploy_development: - if: github.ref == 'refs/heads/development' + deploy: + if: github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main' runs-on: ubuntu-latest needs: [test] defaults: run: - working-directory: ./terraform/dev + working-directory: ./terraform steps: - uses: actions/checkout@v6 - name: Google Cloud Auth @@ -36,68 +36,17 @@ jobs: - uses: hashicorp/setup-terraform@v3 - - name: Terraform fmt - id: fmt - run: terraform fmt -check - continue-on-error: true - - - name: Terraform Init - id: init - run: terraform init - - - name: Terraform Validate - id: validate - run: terraform validate -no-color - - - name: Terraform Plan - id: plan + - name: Set environment variable depending on the branch name run: | - terraform plan -no-color - continue-on-error: true - - - name: Terraform Plan status - if: steps.plan.outcome == 'failure' - run: exit 1 - - - name: Terraform Apply - id: apply - run: | - terraform apply -auto-approve - - deploy_production: - if: github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - needs: [test] - defaults: - run: - working-directory: ./terraform/prod - steps: - - uses: actions/checkout@v6 - - name: Google Cloud Auth - uses: 'google-github-actions/auth@v3' - with: - project_id: 'httparchive' - credentials_json: ${{ env.PIPELINE_SA_KEY }} + if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + echo "ENV=prod" >> $GITHUB_ENV + elif [[ "${{ github.ref }}" == "refs/heads/development" ]]; then + echo "ENV=dev" >> $GITHUB_ENV + fi - - uses: hashicorp/setup-terraform@v3 - - - name: Terraform fmt - id: fmt - run: terraform fmt -check - continue-on-error: true - - - name: Terraform Init - id: init - run: terraform init - - - name: Terraform Validate - id: validate - run: terraform validate -no-color - - - name: Terraform Plan + - name: Terraform Validate & Plan id: plan - run: | - terraform plan -no-color + run: make tf_plan ENV=${{ env.ENV }} continue-on-error: true - name: Terraform Plan status @@ -106,5 +55,4 @@ jobs: - name: Terraform Apply id: apply - run: | - terraform apply -auto-approve + run: make tf_apply ENV=${{ env.ENV }} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8596808 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +.PHONY: * +ENV ?= dev + +tf_plan: + cd terraform/ && terraform init -reconfigure -backend-config=backend-$(ENV).hcl -upgrade && terraform fmt -check && terraform validate && terraform plan --var="environment=$(ENV)" + +tf_apply: + cd terraform/ && terraform init -reconfigure -backend-config=backend-$(ENV).hcl && terraform apply -auto-approve --var="environment=$(ENV)" diff --git a/terraform/backend-dev.hcl b/terraform/backend-dev.hcl new file mode 100644 index 0000000..ffdab14 --- /dev/null +++ b/terraform/backend-dev.hcl @@ -0,0 +1,2 @@ +bucket = "tfstate-httparchive" +prefix = "tech-report-apis/dev" diff --git a/terraform/backend-prod.hcl b/terraform/backend-prod.hcl new file mode 100644 index 0000000..0f243ae --- /dev/null +++ b/terraform/backend-prod.hcl @@ -0,0 +1,2 @@ +bucket = "tfstate-httparchive" +prefix = "tech-report-apis/prod" diff --git a/terraform/modules/cdn-glb/cloud_armor.tf b/terraform/cdn-glb/cloud_armor.tf similarity index 100% rename from terraform/modules/cdn-glb/cloud_armor.tf rename to terraform/cdn-glb/cloud_armor.tf diff --git a/terraform/modules/cdn-glb/main.tf b/terraform/cdn-glb/main.tf similarity index 100% rename from terraform/modules/cdn-glb/main.tf rename to terraform/cdn-glb/main.tf diff --git a/terraform/modules/cdn-glb/outputs.tf b/terraform/cdn-glb/outputs.tf similarity index 100% rename from terraform/modules/cdn-glb/outputs.tf rename to terraform/cdn-glb/outputs.tf diff --git a/terraform/modules/cdn-glb/variables.tf b/terraform/cdn-glb/variables.tf similarity index 100% rename from terraform/modules/cdn-glb/variables.tf rename to terraform/cdn-glb/variables.tf diff --git a/terraform/dev/main.tf b/terraform/dev/main.tf deleted file mode 100644 index 7688c4b..0000000 --- a/terraform/dev/main.tf +++ /dev/null @@ -1,36 +0,0 @@ -terraform { - required_version = ">=1.11.0" - - backend "gcs" { - bucket = "tfstate-httparchive" - prefix = "tech-report-apis/dev" - } - required_providers { - docker = { - source = "kreuzwerker/docker" - version = ">=3.6.2" - } - google = { - source = "hashicorp/google" - version = ">=7.13.0" - } - } -} - -provider "google" { - project = var.project - region = var.region -} - -module "endpoints" { - source = "./../modules/run-service" - project = var.project - environment = var.environment - source_directory = "../../src" - service_name = "report-api" - region = var.region - environment_variables = { - "PROJECT" = var.project - "DATABASE" = var.project_database - } -} diff --git a/terraform/dev/variables.tf b/terraform/dev/variables.tf deleted file mode 100644 index e864e10..0000000 --- a/terraform/dev/variables.tf +++ /dev/null @@ -1,19 +0,0 @@ -variable "project" { - description = "The project name" - type = string - default = "httparchive" -} -variable "region" { - type = string - default = "us-central1" -} -variable "environment" { - description = "The environment name" - type = string - default = "dev" -} -variable "project_database" { - type = string - description = "The database name" - default = "tech-report-api-prod" // TODO: Update this to the DEV database name -} diff --git a/terraform/prod/main.tf b/terraform/main.tf similarity index 60% rename from terraform/prod/main.tf rename to terraform/main.tf index 20fd3b5..8e76e4e 100644 --- a/terraform/prod/main.tf +++ b/terraform/main.tf @@ -1,40 +1,43 @@ terraform { - backend "gcs" { - bucket = "tfstate-httparchive" - prefix = "tech-report-apis/prod" - } + required_version = ">=1.11.0" + + backend "gcs" {} + required_providers { docker = { source = "kreuzwerker/docker" - version = "3.6.2" + version = ">=3.6.2" } google = { - source = "hashicorp/google" + source = "hashicorp/google" + version = ">=7.13.0" } } } provider "google" { - project = var.project - region = var.region + project = var.project + region = var.region } module "endpoints" { - source = "./../modules/run-service" + source = "./run-service" project = var.project environment = var.environment - source_directory = "../../src" - service_name = "report-api" + source_directory = "../src" + service_name = "report-api" region = var.region - min_instances = 1 + min_instances = var.environment == "prod" ? 1 : 0 environment_variables = { "PROJECT" = var.project - "DATABASE" = var.project_database + "DATABASE" = "${var.project_database}prod" // TODO: Update this to use ${var.environment} } } module "cdn_glb" { - source = "./../modules/cdn-glb" + count = var.environment == "prod" ? 1 : 0 + + source = "./cdn-glb" project = var.project region = var.region @@ -45,7 +48,7 @@ module "cdn_glb" { load_balancer_name = "httparchive-load-balancer" name_prefix = "report-api" - neg_name = "report-api-prod" + neg_name = "report-api-${var.environment}" backend_service_name = "report-api" ssl_cert_name = "google-managed2" https_proxy_name = "httparchive-load-balancer-target-proxy-2" diff --git a/terraform/modules/run-service/main.tf b/terraform/run-service/main.tf similarity index 100% rename from terraform/modules/run-service/main.tf rename to terraform/run-service/main.tf diff --git a/terraform/modules/run-service/outputs.tf b/terraform/run-service/outputs.tf similarity index 100% rename from terraform/modules/run-service/outputs.tf rename to terraform/run-service/outputs.tf diff --git a/terraform/modules/run-service/variables.tf b/terraform/run-service/variables.tf similarity index 100% rename from terraform/modules/run-service/variables.tf rename to terraform/run-service/variables.tf diff --git a/terraform/prod/variables.tf b/terraform/variables.tf similarity index 85% rename from terraform/prod/variables.tf rename to terraform/variables.tf index 6d16cb1..0967bb4 100644 --- a/terraform/prod/variables.tf +++ b/terraform/variables.tf @@ -10,10 +10,9 @@ variable "region" { variable "environment" { description = "The environment name" type = string - default = "prod" } variable "project_database" { type = string description = "The database name" - default = "tech-report-api-prod" + default = "tech-report-api-" } From e578e40c3e33fda119893e5d1a930ccb204025f2 Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 14 Dec 2025 21:57:29 +0100 Subject: [PATCH 4/6] default working directory --- .github/workflows/deployment.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml index ed3ac04..432674c 100644 --- a/.github/workflows/deployment.yaml +++ b/.github/workflows/deployment.yaml @@ -23,9 +23,6 @@ jobs: if: github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main' runs-on: ubuntu-latest needs: [test] - defaults: - run: - working-directory: ./terraform steps: - uses: actions/checkout@v6 - name: Google Cloud Auth From 1b65478e1a993668432b7ddb75df04ef7f086981 Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:43:15 +0100 Subject: [PATCH 5/6] refactor(deployment): streamline Terraform deployment steps and remove redundant environment variable setting --- .github/workflows/deployment.yaml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml index a96b0bd..bde6311 100644 --- a/.github/workflows/deployment.yaml +++ b/.github/workflows/deployment.yaml @@ -19,9 +19,6 @@ jobs: deploy: runs-on: ubuntu-latest needs: [test] - defaults: - run: - working-directory: ${{ github.ref == 'refs/heads/main' && './terraform/prod' || './terraform/dev' }} steps: - uses: actions/checkout@v6 @@ -33,19 +30,8 @@ jobs: - uses: hashicorp/setup-terraform@v4 - - name: Set env vars - run: | - echo "ENV=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}" >> $GITHUB_ENV - - - name: Terraform fmt - id: fmt - run: terraform fmt -check - - - name: Terraform Validate - id: validate - run: make tf_apply ENV=${{ env.ENV }} - - name: Terraform Apply id: apply run: | + ENV=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }} make tf_apply ENV=${{ env.ENV }} From a76c48458ee303631da41746b608558073b7f03b Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:47:17 +0100 Subject: [PATCH 6/6] fix(deployment): improve branch handling logic for Terraform apply step --- .github/workflows/deployment.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml index bde6311..5e6bb34 100644 --- a/.github/workflows/deployment.yaml +++ b/.github/workflows/deployment.yaml @@ -33,5 +33,12 @@ jobs: - name: Terraform Apply id: apply run: | - ENV=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }} - make tf_apply ENV=${{ env.ENV }} + if [ "${GITHUB_REF}" = "refs/heads/main" ]; then + ENV=prod + elif [ "${GITHUB_REF}" = "refs/heads/development" ]; then + ENV=dev + else + echo "Unsupported branch for deployment: ${GITHUB_REF}" + exit 1 + fi + make tf_apply ENV="$ENV"