Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ER 782 Create app service to host web application dev subscription #653

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions .github/workflows/azure-deploy-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
name: 'HfEYP App Deploy [Azure - DEV]'

on:
workflow_dispatch:
push:
branches:
- main
paths-ignore:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array of files to ignore might want looking at. Some of these files don't exist in this project and should be removed but others might also need to be added in their place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Agree on this point.

Copy link
Contributor Author

@ebrett ebrett Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did look at them and removed the ones below - the ones I kept were either there or could be added but should probably still be ignored.

  - .pa11yci
  - uml/*

- '**/*.md'
- .docker*
- .env.example
- .gitignore
- .tool-versions
- .yardopts
- bin/*
- docker-compose.*
- terraform/**
- terraform-azure/**

# Permissions for OIDC authentication
permissions:
id-token: write
contents: write
packages: write

env:
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
DOCKER_IMAGE: ghcr.io/dfe-digital/help-for-early-years-providers

jobs:
build-and-deploy:
runs-on: ubuntu-latest
environment: development

steps:
- name: Check workflow concurrency
uses: softprops/turnstyle@v1
with:
poll-interval-seconds: 20
same-branch-only: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Checkout the repository to the GitHub Actions runner

- name: Checkout Code
uses: actions/checkout@v4

# Create and boot Docker image builder
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: v0.9.1

# Login to the container registry
- name: Login to Github Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push docker image from builder target
uses: docker/build-push-action@v5
with:
context: .
build-args: BUILDKIT_INLINE_CACHE=1
cache-from: |
${{ env.DOCKER_IMAGE }}-dev:builder
push: true
tags: ${{ env.DOCKER_IMAGE }}-dev:builder
target: builder

- name: Build and push docker image from help-for-early-years-providers-gems-node-modules target
uses: docker/build-push-action@v5
with:
context: .
build-args: BUILDKIT_INLINE_CACHE=1
cache-from: |
${{ env.DOCKER_IMAGE }}-dev:gems-node-modules
push: true
tags: ${{ env.DOCKER_IMAGE }}-dev:gems-node-modules
target: help-for-early-years-providers-gems-node-modules

- name: Build and push docker image from assets-precompile target
uses: docker/build-push-action@v5
with:
context: .
build-args: BUILDKIT_INLINE_CACHE=1
cache-from: |
${{ env.DOCKER_IMAGE }}-dev:assets-precompile
push: true
tags: ${{ env.DOCKER_IMAGE }}-dev:assets-precompile
target: assets-precompile

- name: Build and push docker image from production target
uses: docker/build-push-action@v5
with:
context: .
build-args: |
BUILDKIT_INLINE_CACHE=1
SHA=${{ github.sha }}
cache-from: |
type=registry,ref=${{ env.DOCKER_IMAGE }}-prod:latest
push: true
tags: |
${{ env.DOCKER_IMAGE }}-prod:latest
${{ env.DOCKER_IMAGE }}-prod:${{ github.sha }}
target: production

# Login to Azure using OIDC
- name: Login to Azure CLI
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# Deploy Web Application
- name: Deploy to Azure App Services
uses: azure/webapps-deploy@v2
with:
app-name: ${{ vars.WEBAPP_NAME }}
images: ${{ env.DOCKER_IMAGE }}:${{ github.sha }}
19 changes: 19 additions & 0 deletions terraform-azure/local.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,23 @@ locals {
"WEB_CONCURRENCY" = var.webapp_config_web_concurrency
"WEBSITES_CONTAINER_START_TIME_LIMIT" = 1800
}

webapp_slot_app_settings = {
"ENVIRONMENT" = var.environment
"DATABASE_URL" = var.webapp_slot_database_url
"WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"
"GOVUK_APP_DOMAIN" = "london.cloudapps.digital" #TODO: Remove this dependency post-migration to Azure
"GOVUK_WEBSITE_ROOT" = "ey-recovery-dev" #TODO: Remove this dependency post-migration to Azure
"DOMAIN" = var.webapp_config_domain
"FEEDBACK_URL" = var.webapp_config_feedback_url
"NODE_ENV" = var.webapp_config_node_env
"RAILS_ENV" = var.webapp_config_rails_env
"RAILS_LOG_TO_STDOUT" = var.webapp_config_rails_log_to_stdout
"RAILS_MASTER_KEY" = var.webapp_config_rails_master_key
"RAILS_MAX_THREADS" = var.webapp_config_rails_max_threads
"RAILS_SERVE_STATIC_FILES" = var.webapp_config_rails_serve_static_files
"TRACKING_ID" = var.tracking_id
"WEB_CONCURRENCY" = var.webapp_config_web_concurrency
"WEBSITES_CONTAINER_START_TIME_LIMIT" = 1800
}
}
71 changes: 71 additions & 0 deletions terraform-azure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,74 @@ resource "azurerm_resource_group" "rg" {
ignore_changes = [tags]
}
}

# Create Network resources
module "network" {
source = "./terraform-azure-network"

environment = var.environment
location = var.azure_region
resource_group = azurerm_resource_group.rg.name
resource_name_prefix = var.resource_name_prefix
domain_name_label = var.webapp_name
kv_certificate_authority_label = "GlobalSignCA"
kv_certificate_authority_name = "GlobalSign"
kv_certificate_authority_username = var.kv_certificate_authority_username
kv_certificate_authority_password = var.kv_certificate_authority_password
kv_certificate_authority_admin_email = var.admin_email_address
kv_certificate_authority_admin_first_name = var.kv_certificate_authority_admin_first_name
kv_certificate_authority_admin_last_name = var.kv_certificate_authority_admin_last_name
kv_certificate_authority_admin_phone_no = var.kv_certificate_authority_admin_phone_no
kv_certificate_label = var.kv_certificate_label
kv_certificate_subject = var.kv_certificate_subject
}

# Create Database resources
module "database" {
source = "./terraform-azure-database"

environment = var.environment
location = var.azure_region
resource_group = azurerm_resource_group.rg.name
resource_name_prefix = var.resource_name_prefix
psqlfs_subnet_id = module.network.psqlfs_subnet_id
psqlfs_dns_zone_id = module.network.psqlfs_dns_zone_id
psqlfs_sku = var.psqlfs_sku
psqlfs_storage = var.psqlfs_storage
psqlfs_username = var.psqlfs_username
psqlfs_password = var.psqlfs_password
psqlfs_geo_redundant_backup = var.psqlfs_geo_redundant_backup
psqlfs_ha_enabled = var.psqlfs_ha_enabled
depends_on = [module.network]
}

# Create Web Application resources
module "webapp" {
source = "./terraform-azure-web"

environment = var.environment
location = var.azure_region
resource_group = azurerm_resource_group.rg.name
resource_name_prefix = var.resource_name_prefix
as_service_principal_object_id = var.as_service_principal_object_id
asp_sku = var.asp_sku
webapp_admin_email_address = var.admin_email_address
webapp_subnet_id = module.network.webapp_subnet_id
webapp_name = var.webapp_name
webapp_app_settings = local.webapp_app_settings
webapp_slot_app_settings = local.webapp_slot_app_settings
webapp_docker_image = var.webapp_docker_image
webapp_docker_image_tag = var.webapp_docker_image_tag
webapp_docker_registry_url = var.webapp_docker_registry_url
webapp_session_cookie_name = "_help_for_early_years_providers_session"
webapp_custom_domain_name = var.custom_domain_name
webapp_custom_domain_cert_secret_label = var.kv_certificate_label
webapp_health_check_path = "/health"
webapp_health_check_eviction_time_in_min = 10
agw_subnet_id = module.network.agw_subnet_id
agw_pip_id = module.network.agw_pip_id
kv_id = module.network.kv_id
kv_cert_secret_id = module.network.kv_cert_secret_id
kv_mi_id = module.network.kv_mi_id
depends_on = [module.network, module.database]
}
7 changes: 6 additions & 1 deletion terraform-azure/terraform-azure-database/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ variable "resource_name_prefix" {
type = string
}

variable "environment" {
description = "Environment to deploy resources"
type = string
}

variable "psqlfs_subnet_id" {
description = "ID of the delegated Subnet for the Database Server"
type = string
Expand Down Expand Up @@ -53,4 +58,4 @@ variable "psqlfs_geo_redundant_backup" {
variable "psqlfs_ha_enabled" {
description = "Enable high availability"
type = bool
}
}
7 changes: 1 addition & 6 deletions terraform-azure/terraform-azure-network/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ output "webapp_subnet_id" {
value = azurerm_subnet.webapp_snet.id
}

output "app_worker_subnet_id" {
description = "ID of the delegated Subnet for the Background Worker"
value = azurerm_subnet.app_worker_snet.id
}

output "agw_subnet_id" {
description = "ID of the Subnet for the App Gateway"
value = var.environment != "development" ? azurerm_subnet.agw_snet[0].id : null
Expand All @@ -51,4 +46,4 @@ output "kv_cert_secret_id" {
output "kv_mi_id" {
description = "ID of the Managed Identity for the Key Vault"
value = var.environment != "development" ? azurerm_user_assigned_identity.kv_mi[0].id : null
}
}
5 changes: 5 additions & 0 deletions terraform-azure/terraform-azure-web/appgateway.tf
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ resource "azurerm_application_gateway" "agw" {
max_capacity = 10
}

gateway_ip_configuration {
name = "${var.resource_name_prefix}-agw-ipc"
subnet_id = var.agw_subnet_id
}

identity {
type = "UserAssigned"
identity_ids = [var.kv_mi_id]
Expand Down
12 changes: 6 additions & 6 deletions terraform-azure/terraform-azure-web/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ variable "webapp_admin_email_address" {
sensitive = true
}

variable "webapp_worker_count" {
description = "Number of Workers for the App Service Plan"
type = string
}

variable "webapp_name" {
description = "Name for the Web Application"
type = string
Expand All @@ -55,6 +50,11 @@ variable "webapp_app_settings" {
type = map(string)
}

variable "webapp_slot_app_settings" {
description = "App Settings are exposed as environment variables"
type = map(string)
}

variable "webapp_docker_registry_url" {
description = "URL to the Docker Registry"
type = string
Expand Down Expand Up @@ -126,4 +126,4 @@ variable "kv_cert_secret_id" {
variable "kv_mi_id" {
description = "ID of the Managed Identity for the Key Vault"
type = string
}
}
6 changes: 3 additions & 3 deletions terraform-azure/terraform-azure-web/webapp.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ resource "azurerm_service_plan" "asp" {
resource_group_name = var.resource_group
os_type = "Linux"
sku_name = var.asp_sku
worker_count = var.webapp_worker_count

lifecycle {
ignore_changes = [tags]
}

#checkov:skip=CKV_AZURE_212:Argument not available
#checkov:skip=CKV_AZURE_225:Ensure the App Service Plan is zone redundant
}

# Create Web Application
Expand Down Expand Up @@ -109,7 +109,7 @@ resource "azurerm_linux_web_app_slot" "webapp_slot" {
app_service_id = azurerm_linux_web_app.webapp.id
https_only = true
virtual_network_subnet_id = var.webapp_subnet_id
app_settings = var.webapp_app_settings
app_settings = var.webapp_slot_app_settings

site_config {
app_command_line = var.webapp_startup_command
Expand Down Expand Up @@ -365,4 +365,4 @@ resource "azurerm_app_service_certificate_binding" "webapp_custom_domain_cert_bi
hostname_binding_id = azurerm_app_service_custom_hostname_binding.webapp_custom_domain[0].id
certificate_id = azurerm_app_service_certificate.webapp_custom_domain_cert[0].id
ssl_state = "SniEnabled"
}
}
6 changes: 6 additions & 0 deletions terraform-azure/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ variable "webapp_database_url" {
sensitive = true
}

variable "webapp_slot_database_url" {
description = "URL to the Database"
type = string
sensitive = true
}

variable "webapp_docker_registry_url" {
description = "URL to the Docker Registry"
type = string
Expand Down