-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
static site infra; github workflow to auto-deploy
- Loading branch information
Showing
13 changed files
with
307 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
name: deploy prod | ||
on: | ||
push: | ||
branches: | ||
- main | ||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
environment: prod | ||
permissions: | ||
contents: 'read' | ||
id-token: 'write' | ||
steps: | ||
- name: Check out repository code | ||
uses: actions/checkout@v4 | ||
- name: log in to GCP | ||
id: auth | ||
uses: google-github-actions/auth@v2 | ||
with: | ||
token_format: access_token | ||
project_id: ${{ secrets.PROJECT_ID }} | ||
workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }} | ||
service_account: ${{ secrets.DEPLOY_SERVICE_ACCOUNT }} | ||
- name: 'Set up gcloud' | ||
uses: 'google-github-actions/setup-gcloud@v2' | ||
- name: Build & deploy site | ||
steps: | ||
- run: apt install hugo | ||
- run: hugo | ||
- run: hugo deploy | ||
- run: gcloud compute url-maps invalidate-cdn-cache blog-prod --path "/*" --async |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
.env | ||
*.lock | ||
*.swp | ||
public | ||
terraform.tfstate* | ||
.terraform | ||
.terraform* |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# `opentofu/` | ||
|
||
This folder contains [OpenTofu](https://opentofu.org/) code to deploy a basic static site. | ||
|
||
## Setup | ||
|
||
Install opentofu, then configure a `.env` like so and `source` it: | ||
|
||
``` | ||
export GOOGLE_CLOUD_PROJECT=$SOME_VALUE_FROM_GCP_CONSOLE | ||
export GOOGLE_REGION=us-central1 | ||
export TF_VAR_dns_record="blog" | ||
export TF_VAR_dns_zone_name="micro-nova.com" | ||
export TF_VAR_env="prod" | ||
export CLOUDFLARE_API_TOKEN="your token here" # create a cloudflare token that is IP limited to the office and expires in 2yrs | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
resource "google_storage_bucket" "static_site" { | ||
name = "${var.dns_name}.${var.dns_zone_name}" | ||
location = "US" | ||
force_destroy = true | ||
|
||
uniform_bucket_level_access = false | ||
|
||
website { | ||
main_page_suffix = "index.html" | ||
not_found_page = "404.html" | ||
} | ||
cors { | ||
origin = ["http://${var.dns_name}.${var.dns_zone_name}"] | ||
method = ["GET", "HEAD", "PUT", "POST", "DELETE"] | ||
response_header = ["*"] | ||
max_age_seconds = 3600 | ||
} | ||
} | ||
|
||
resource "google_storage_default_object_access_control" "public_rule" { | ||
bucket = google_storage_bucket.static_site.name | ||
role = "READER" | ||
entity = "allUsers" | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
resource "google_certificate_manager_certificate" "default" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this resource is restrictive | ||
managed { | ||
domains = [ | ||
google_certificate_manager_dns_authorization.default.domain, | ||
] | ||
dns_authorizations = [ | ||
google_certificate_manager_dns_authorization.default.id, | ||
] | ||
} | ||
} | ||
|
||
resource "google_certificate_manager_dns_authorization" "default" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this resource is restrictive | ||
description = "The default dnss" | ||
domain = "${var.dns_name}.${var.dns_zone_name}" | ||
} | ||
|
||
resource "google_certificate_manager_certificate_map" "certificate_map" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this resource is restrictive | ||
} | ||
|
||
resource "google_certificate_manager_certificate_map_entry" "default" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this resource is restrictive | ||
map = google_certificate_manager_certificate_map.certificate_map.name | ||
certificates = [google_certificate_manager_certificate.default.id] | ||
matcher = "PRIMARY" | ||
} | ||
|
||
resource "cloudflare_record" "cert_record" { | ||
zone_id = data.cloudflare_zone.zone.id | ||
name = google_certificate_manager_dns_authorization.default.dns_resource_record[0].name | ||
type = google_certificate_manager_dns_authorization.default.dns_resource_record[0].type | ||
value = google_certificate_manager_dns_authorization.default.dns_resource_record[0].data | ||
ttl = 600 | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
data "github_repository" "repo" { | ||
full_name = var.repo_name | ||
} | ||
|
||
resource "google_iam_workload_identity_pool" "github" { | ||
workload_identity_pool_id = "github-${data.github_repository.repo.name}-${var.env}" | ||
} | ||
|
||
resource "google_iam_workload_identity_pool_provider" "github" { | ||
workload_identity_pool_id = google_iam_workload_identity_pool.github.workload_identity_pool_id | ||
workload_identity_pool_provider_id = "github" | ||
display_name = "Github" | ||
description = "OIDC identity pool provider for automated deployments from Github -> Cloud Run" | ||
attribute_condition = "assertion.repository_owner == 'micro-nova' && assertion.repository_id == '${data.github_repository.repo.repo_id}'" | ||
attribute_mapping = { | ||
"google.subject" = "assertion.sub" | ||
"attribute.actor" = "assertion.actor" | ||
"attribute.repository" = "assertion.repository" | ||
"attribute.repository_owner" = "assertion.repository_owner" | ||
"attribute.repository_id" = "assertion.repository_id" | ||
} | ||
oidc { | ||
issuer_uri = "https://token.actions.githubusercontent.com" | ||
} | ||
} | ||
|
||
resource "google_service_account" "github" { | ||
account_id = "${data.github_repository.repo.name}-${var.env}" | ||
display_name = "Service account used for deploying new Docker images from github" | ||
} | ||
|
||
resource "google_service_account_iam_binding" "github" { | ||
service_account_id = google_service_account.github.name | ||
role = "roles/iam.workloadIdentityUser" | ||
members = [ | ||
"principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github.name}/attribute.repository/${data.github_repository.repo.full_name}" | ||
] | ||
} | ||
|
||
resource "google_project_iam_custom_role" "static_site_cdn" { | ||
role_id = "${var.dns_name}_${var.env}_cdn" | ||
title = "invalidate CDN for static site, ${data.github_repository.repo.name}-${var.env}" | ||
description = "Limited scope role for github to deploy the static site" | ||
permissions = [ | ||
"compute.urlMaps.get", | ||
"compute.urlMaps.invalidateCache", | ||
] | ||
} | ||
|
||
resource "google_project_iam_binding" "static_site_cdn" { | ||
project = data.google_project.project.project_id | ||
role = google_project_iam_custom_role.static_site_cdn.name | ||
members = [ | ||
"serviceAccount:${google_service_account.github.email}" | ||
] | ||
} | ||
|
||
resource "google_project_iam_custom_role" "static_site_bucket" { | ||
role_id = "${var.dns_name}_${var.env}_bucket" | ||
title = "deploy static site to bucket, ${data.github_repository.repo.name}-${var.env}" | ||
description = "Limited scope role for github to deploy the static site" | ||
permissions = [ | ||
"storage.objects.create", | ||
"storage.objects.delete", | ||
"storage.objects.get", | ||
"storage.objects.getIamPolicy", | ||
"storage.objects.list", | ||
"storage.objects.update", | ||
] | ||
} | ||
|
||
|
||
resource "google_project_iam_binding" "static_site_bucket" { | ||
project = data.google_project.project.project_id | ||
role = google_project_iam_custom_role.static_site_bucket.name | ||
members = [ | ||
"serviceAccount:${google_service_account.github.email}" | ||
] | ||
|
||
condition { | ||
title = "only_static_bucket_contents" | ||
expression = "resource.type == 'storage.googleapis.com/Object' && resource.name.startsWith('projects/_/buckets/${google_storage_bucket.static_site.name}/')" | ||
} | ||
} | ||
|
||
|
||
resource "github_repository_environment" "repo" { | ||
repository = data.github_repository.repo.name | ||
environment = var.env | ||
} | ||
|
||
resource "github_actions_environment_secret" "oidc_workload_provider" { | ||
repository = data.github_repository.repo.name | ||
environment = github_repository_environment.repo.environment | ||
secret_name = "WORKLOAD_IDENTITY_PROVIDER" | ||
plaintext_value = google_iam_workload_identity_pool_provider.github.name | ||
} | ||
|
||
resource "github_actions_environment_secret" "project_id" { | ||
repository = data.github_repository.repo.name | ||
environment = github_repository_environment.repo.environment | ||
secret_name = "PROJECT_ID" | ||
plaintext_value = data.google_project.project.project_id | ||
} | ||
|
||
resource "github_actions_environment_secret" "deploy_service_account" { | ||
repository = data.github_repository.repo.name | ||
environment = github_repository_environment.repo.environment | ||
secret_name = "DEPLOY_SERVICE_ACCOUNT" | ||
plaintext_value = google_service_account.github.email | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
data "cloudflare_zone" "zone" { | ||
name = var.dns_zone_name | ||
} | ||
|
||
resource "cloudflare_record" "record" { | ||
zone_id = data.cloudflare_zone.zone.id | ||
name = var.dns_name | ||
value = google_compute_global_forwarding_rule.rule.ip_address | ||
type = "A" | ||
proxied = false | ||
ttl = 600 | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
resource "google_compute_backend_bucket" "backend_bucket" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this is restrictive | ||
bucket_name = "${var.dns_name}.${var.dns_zone_name}" | ||
enable_cdn = true | ||
} | ||
|
||
resource "google_compute_target_https_proxy" "lb" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this is restrictive | ||
url_map = google_compute_url_map.map.id | ||
certificate_map = "//certificatemanager.googleapis.com/${google_certificate_manager_certificate_map.certificate_map.id}" | ||
} | ||
|
||
resource "google_compute_url_map" "map" { | ||
name = "${var.dns_name}-${var.env}" # the regex for this is restrictive | ||
|
||
default_service = google_compute_backend_bucket.backend_bucket.self_link | ||
} | ||
|
||
resource "google_compute_global_forwarding_rule" "rule" { | ||
name = "${var.dns_name}-${var.env}" | ||
port_range = "443" | ||
load_balancing_scheme = "EXTERNAL_MANAGED" | ||
ip_protocol = "TCP" | ||
target = google_compute_target_https_proxy.lb.id | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
data "google_project" "project" {} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
provider "github" { | ||
owner = "micro-nova" | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
terraform { | ||
backend "gcs" { | ||
bucket = "engineering-blog-tfstate" | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
variable "env" { | ||
description = "The env, ie prod, dev, test" | ||
type = string | ||
} | ||
|
||
variable "dns_name" { | ||
description = "The bare dns record used to instantiate various services; does not include the zone." | ||
type = string | ||
default = "blog" | ||
} | ||
|
||
variable "dns_zone_name" { | ||
description = "The DNS zone name in which to place the above DNS record" | ||
type = string | ||
default = "micro-nova.com" | ||
} | ||
|
||
variable "region" { | ||
description = "The region to deploy services into. Most things default to the provider region, but some resources need it hardcoded" | ||
type = string | ||
default = "us-central1" | ||
} | ||
|
||
variable "repo_name" { | ||
description = "The repo name to use for setting up OIDC auth between Github <-> Google Cloud for deploys. ex: micro-nova/support_tunnel" | ||
type = string | ||
default = "micro-nova/engineering-blog" | ||
} |