Compare commits
6 Commits
common1.0.
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 460f097d1e | |||
| b9ef4422fb | |||
| f16a505d24 | |||
| 9a3ee9efe3 | |||
| 4857e68f93 | |||
| df4c0cfdd7 |
62
.github/workflows/deploy_to_gcp.yml
vendored
Normal file
62
.github/workflows/deploy_to_gcp.yml
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
name: Gitea Deploy to GCP
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- deploy-prd
|
||||||
|
- deploy-dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
gcp-deploy:
|
||||||
|
name: Deploy to GCP
|
||||||
|
runs-on: gcloud-tf
|
||||||
|
env:
|
||||||
|
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
|
||||||
|
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
|
||||||
|
REPO_NAME: ${{ github.repository }}
|
||||||
|
COMPONENT_NAME: ${{ vars.COMPONENT_NAME }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Check Deploy Tools
|
||||||
|
run: |
|
||||||
|
ls -la
|
||||||
|
echo "Checking gcloud and terraform versions..."
|
||||||
|
gcloud --version
|
||||||
|
terraform --version
|
||||||
|
|
||||||
|
- name: Check Gcloud auth
|
||||||
|
run: |
|
||||||
|
echo "HOME: ${HOME}"
|
||||||
|
printf '%s' "$GCP_SA_KEY" > $HOME/sa.json
|
||||||
|
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/sa.json"
|
||||||
|
|
||||||
|
gcloud auth activate-service-account --key-file="$GOOGLE_APPLICATION_CREDENTIALS"
|
||||||
|
gcloud config set project "$GCP_PROJECT_ID"
|
||||||
|
|
||||||
|
echo "Check gcloud"
|
||||||
|
gcloud config list
|
||||||
|
gcloud --version
|
||||||
|
|
||||||
|
- name: Exec Terraform init shell
|
||||||
|
run: |
|
||||||
|
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/sa.json"
|
||||||
|
./scripts/deploy/init_terraform.sh
|
||||||
|
|
||||||
|
- name: Exec Terraform plan shell
|
||||||
|
run: |
|
||||||
|
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/sa.json"
|
||||||
|
./scripts/deploy/plan_terraform.sh
|
||||||
|
|
||||||
|
- name: Exec Terraform apply shell
|
||||||
|
run: |
|
||||||
|
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/sa.json"
|
||||||
|
./scripts/deploy/apply_terraform.sh
|
||||||
|
|
||||||
|
- name: Clean up Gcloud auth file
|
||||||
|
run: |
|
||||||
|
rm -f $HOME/sa.json
|
||||||
|
echo "Cleaned up Gcloud auth file."
|
||||||
|
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
@ -171,3 +171,11 @@ cython_debug/
|
|||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
# terraform.tfstate files
|
||||||
|
_*.tfvars
|
||||||
|
.terraform/
|
||||||
|
.terraform.lock.hcl
|
||||||
|
*.tfstate
|
||||||
|
*.tfstate.backup
|
||||||
|
*deploy.env
|
||||||
57
readme/deploy.md
Normal file
57
readme/deploy.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# デプロイの方法について
|
||||||
|
|
||||||
|
## インストール方法
|
||||||
|
|
||||||
|
MACの場合
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew tap hashicorp/tap
|
||||||
|
brew install hashicorp/tap/terraform
|
||||||
|
# 確認
|
||||||
|
terraform -version
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 環境について
|
||||||
|
|
||||||
|
* terraform
|
||||||
|
* google cloud
|
||||||
|
* Cloud Fucntions
|
||||||
|
|
||||||
|
## ローカル実行する方法
|
||||||
|
|
||||||
|
ローカルで実行する場合はバックエンドを修正する必要がある
|
||||||
|
`provider.tf`の次の文をコメントアウトする
|
||||||
|
|
||||||
|
```tf
|
||||||
|
terraform {
|
||||||
|
# backend "gcs" {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# 初期化を実行する
|
||||||
|
cd terraform
|
||||||
|
# Terraformの初期化
|
||||||
|
terraform init
|
||||||
|
# デプロイするコンポーネントを確認する
|
||||||
|
terraform plan -var-file=dev.tfvars
|
||||||
|
|
||||||
|
# デプロイを実行する
|
||||||
|
terraform apply \
|
||||||
|
-var-file=dev.tfvars \
|
||||||
|
-auto-approve
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
ローカルでビルドで試す場合
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# デフォルトでビルドする場合
|
||||||
|
docker build -t cloud-run-job-base .
|
||||||
|
# arm64でビルドしたい場合
|
||||||
|
docker buildx build -platform linux/amd64,linux/arm64 -t cloud-run-job-base .
|
||||||
|
# Dockerを実行する(1回だけ実行してコンテナインスタンスを削除する場合)
|
||||||
|
docker run --rm cloud-run-job-base:latest
|
||||||
|
```
|
||||||
|
|
||||||
26
scripts/deploy/applay_terraform.sh
Executable file
26
scripts/deploy/applay_terraform.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Safe mode(when error,kill script)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 変数の設定({HOME}/hash.txt からハッシュ値を取得)
|
||||||
|
TF_DIR=${TF_DIR:-terraform}
|
||||||
|
ENV=${ENV:-dev}
|
||||||
|
|
||||||
|
cd "$TF_DIR"
|
||||||
|
|
||||||
|
# --- デプロイ条件 ---
|
||||||
|
if [[ "${BRANCH_NAME:-}" =~ ^.*deploy$ ]]; then
|
||||||
|
echo "Start terraform apply (ENV=${ENV}, DIR=${TF_DIR}) ..."
|
||||||
|
else
|
||||||
|
echo "Skip terraform apply (branch=${BRANCH_NAME:-})"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- plan 結果があるか確認 ---
|
||||||
|
if [[ ! -f tfplan ]]; then
|
||||||
|
echo "ERROR: tfplan not found in $(pwd). Run plan step first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
terraform apply -auto-approve tfplan
|
||||||
21
scripts/deploy/init_terraform.sh
Executable file
21
scripts/deploy/init_terraform.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Safe mode(when error,kill script)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TF_DIR=${TF_DIR:-terraform}
|
||||||
|
|
||||||
|
# GCS S3などで保存する
|
||||||
|
TF_STATE_BUCKET=${TF_STATE_BUCKET:-cicd-tfstate-bucket-20250906}
|
||||||
|
ENV=${ENV:-dev}
|
||||||
|
REPO_NAME=${REPO_NAME:-unknown}
|
||||||
|
|
||||||
|
cd "$TF_DIR"
|
||||||
|
echo "$REPO_NAME"
|
||||||
|
|
||||||
|
|
||||||
|
# # --- terraform init 実行 ---
|
||||||
|
terraform init \
|
||||||
|
-backend-config="bucket=${TF_STATE_BUCKET}" \
|
||||||
|
-backend-config="prefix=${REPO_NAME}/${ENV}" \
|
||||||
|
|
||||||
21
scripts/deploy/plan_terraform.sh
Executable file
21
scripts/deploy/plan_terraform.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Safe mode(when error,kill script)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 変数の設定({HOME}/hash.txt からハッシュ値を取得)
|
||||||
|
TF_DIR=${TF_DIR:-terraform}
|
||||||
|
ENV=${ENV:-dev}
|
||||||
|
|
||||||
|
cd "$TF_DIR"
|
||||||
|
|
||||||
|
if [ -f "${ENV}.tfvars" ]; then
|
||||||
|
terraform plan \
|
||||||
|
-out=tfplan \
|
||||||
|
-var-file="${ENV}.tfvars"
|
||||||
|
|
||||||
|
else
|
||||||
|
# error raise
|
||||||
|
echo "ERROR: ${ENV}.tfvars not found in $(pwd)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@ -1,10 +1,6 @@
|
|||||||
from flask import Request
|
from flask import Request
|
||||||
import functions_framework
|
import functions_framework
|
||||||
|
|
||||||
import os
|
|
||||||
os.environ["ENV"]="dev" # For testing purposes
|
|
||||||
|
|
||||||
|
|
||||||
from utils.custom_logger import get_logger
|
from utils.custom_logger import get_logger
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@ -18,6 +14,7 @@ def main(request: Request):
|
|||||||
# Headerを取得する
|
# Headerを取得する
|
||||||
ua = request.headers.get("User-Agent", "Unknown")
|
ua = request.headers.get("User-Agent", "Unknown")
|
||||||
logger.info(f"User-Agent: {ua}")
|
logger.info(f"User-Agent: {ua}")
|
||||||
|
logger.debug(f"Request Method: {request.method}")
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
logger.info("Processing GET request")
|
logger.info("Processing GET request")
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
functions-framework==3.*
|
functions-framework==3.*
|
||||||
|
google-cloud-logging
|
||||||
|
|||||||
@ -11,18 +11,20 @@ class CoogelCustomLogger():
|
|||||||
self.logger = logging.getLogger(name)
|
self.logger = logging.getLogger(name)
|
||||||
self.logger.setLevel(logging.INFO)
|
self.logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
if not self.logger.handlers:
|
||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
handler.setLevel(logging.INFO)
|
handler.setLevel(logging.INFO)
|
||||||
# メッセージのみ(フォーマットなし)
|
# メッセージのみ(フォーマットなし)
|
||||||
formatter = logging.Formatter("%(message)s")
|
formatter = logging.Formatter("%(message)s")
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
if not self.logger.handlers:
|
|
||||||
self.logger.addHandler(handler)
|
self.logger.addHandler(handler)
|
||||||
|
|
||||||
|
# 親ロガー(root)への伝播を止める → 二重出力防止
|
||||||
|
self.logger.propagate = False
|
||||||
|
|
||||||
def _log(self, message,level="INFO",**fields):
|
def _log(self, message,level="INFO",**fields):
|
||||||
payload = {
|
payload = {
|
||||||
"serverity": level,
|
"severity": level,
|
||||||
"message": f"{message}",
|
"message": f"{message}",
|
||||||
**fields
|
**fields
|
||||||
}
|
}
|
||||||
@ -39,7 +41,7 @@ class CoogelCustomLogger():
|
|||||||
|
|
||||||
def exception(self, message, **fields):
|
def exception(self, message, **fields):
|
||||||
payload = {
|
payload = {
|
||||||
"serverity": "ERROR",
|
"severity": "ERROR",
|
||||||
"message": f"{message}",
|
"message": f"{message}",
|
||||||
**fields
|
**fields
|
||||||
}
|
}
|
||||||
|
|||||||
6
terraform/dev.tfvars
Normal file
6
terraform/dev.tfvars
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
project_id = "gcp-devel-project"
|
||||||
|
region = "asia-northeast1"
|
||||||
|
env_name = "dev"
|
||||||
|
|
||||||
|
component_name = "base"
|
||||||
|
|
||||||
38
terraform/function.tf
Normal file
38
terraform/function.tf
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Cloud Functionのリソース
|
||||||
|
# 第2世代Cloud Function (Cloud Functions 2nd Gen) を使用
|
||||||
|
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloudfunctions2_function
|
||||||
|
# 第1世代Cloud Function (Cloud Functions 1st Gen) を使用する場合はこちらを参照
|
||||||
|
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloudfunctions_function
|
||||||
|
|
||||||
|
|
||||||
|
resource "google_cloudfunctions2_function" "function" {
|
||||||
|
name = "cf-${var.env_name}-${var.component_name}"
|
||||||
|
location = var.region
|
||||||
|
description = "${var.component_name}のCloud Function"
|
||||||
|
|
||||||
|
build_config {
|
||||||
|
runtime = var.runtime
|
||||||
|
entry_point = var.entry_point
|
||||||
|
source {
|
||||||
|
storage_source {
|
||||||
|
bucket = google_storage_bucket.bucket.name
|
||||||
|
object = google_storage_bucket_object.source.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
environment_variables = {
|
||||||
|
ENV = var.env_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service_config {
|
||||||
|
max_instance_count = var.max_instance_count
|
||||||
|
min_instance_count = var.min_instance_count
|
||||||
|
timeout_seconds = var.timeout_seconds
|
||||||
|
available_memory = var.available_memory
|
||||||
|
|
||||||
|
service_account_email = google_service_account.account.email
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
9
terraform/platform.tf
Normal file
9
terraform/platform.tf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Google CloudのAPIを有効化
|
||||||
|
|
||||||
|
resource "google_project_service" "services" {
|
||||||
|
for_each = toset([
|
||||||
|
"run.googleapis.com",
|
||||||
|
"cloudfunctions.googleapis.com",
|
||||||
|
])
|
||||||
|
service = each.key
|
||||||
|
}
|
||||||
9
terraform/provider.tf
Normal file
9
terraform/provider.tf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
terraform {
|
||||||
|
# backend "gcs" {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Google Providerの設定
|
||||||
|
provider "google" {
|
||||||
|
project = var.project_id
|
||||||
|
region = var.region
|
||||||
|
}
|
||||||
24
terraform/sa.tf
Normal file
24
terraform/sa.tf
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
resource "google_service_account" "account" {
|
||||||
|
account_id = "sa-${var.env_name}-${var.component_name}"
|
||||||
|
display_name = "Cloud Run Job Service Account for ${var.env_name} in ${var.component_name} environment"
|
||||||
|
description = "Cloud Run Job Service Account for ${var.env_name} in ${var.component_name} environment"
|
||||||
|
project = var.project_id
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cloud FunctionのIAM設定
|
||||||
|
resource "google_cloudfunctions2_function_iam_member" "invoker" {
|
||||||
|
project = google_cloudfunctions2_function.function.project
|
||||||
|
location = google_cloudfunctions2_function.function.location
|
||||||
|
cloud_function = google_cloudfunctions2_function.function.name
|
||||||
|
role = "roles/cloudfunctions.invoker"
|
||||||
|
member = "serviceAccount:${google_service_account.account.email}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cloud Run ServiceのIAM設定
|
||||||
|
resource "google_cloud_run_service_iam_member" "cloud_run_invoker" {
|
||||||
|
project = google_cloudfunctions2_function.function.project
|
||||||
|
location = google_cloudfunctions2_function.function.location
|
||||||
|
service = google_cloudfunctions2_function.function.name
|
||||||
|
role = "roles/run.invoker"
|
||||||
|
member = "serviceAccount:${google_service_account.account.email}"
|
||||||
|
}
|
||||||
6
terraform/sample.tfvars
Normal file
6
terraform/sample.tfvars
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
project_id = "プロジェクトIDを指定してください"
|
||||||
|
region = "asia-northeast1"
|
||||||
|
env_name = "dev"
|
||||||
|
|
||||||
|
component_name = "ジョブ名を指定してください"
|
||||||
|
|
||||||
18
terraform/storage.tf
Normal file
18
terraform/storage.tf
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
provider = google
|
||||||
|
name = "${var.component_name}-gcf-source" # Every bucket name must be globally unique
|
||||||
|
location = var.region
|
||||||
|
uniform_bucket_level_access = true
|
||||||
|
}
|
||||||
|
|
||||||
|
data "archive_file" "default" {
|
||||||
|
type = "zip"
|
||||||
|
output_path = "/tmp/function-source.zip"
|
||||||
|
source_dir = "../src/"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_object" "source" {
|
||||||
|
name = "function-source.zip"
|
||||||
|
bucket = google_storage_bucket.bucket.name
|
||||||
|
source = data.archive_file.default.output_path
|
||||||
|
}
|
||||||
62
terraform/variables.tf
Normal file
62
terraform/variables.tf
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# GCPプロジェクトIDとリージョン、環境名、ジョブ名の変数定義
|
||||||
|
variable "project_id" {
|
||||||
|
description = "The ID of the GCP project to deploy resources into."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
variable "region" {
|
||||||
|
description = "The GCP region to deploy resources into."
|
||||||
|
type = string
|
||||||
|
default = "asia-northeast1" # 東京
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "env_name" {
|
||||||
|
description = "The environment name for the deployment."
|
||||||
|
type = string
|
||||||
|
default = "dev"
|
||||||
|
validation {
|
||||||
|
condition = contains(["dev", "staging", "prd"], var.env_name)
|
||||||
|
error_message = "env_name must be one of: dev, staging, prd."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "component_name" {
|
||||||
|
description = "The name of the Cloud Function."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cloud Functino の設定変数
|
||||||
|
variable "runtime" {
|
||||||
|
description = "The runtime environment for the Cloud Function."
|
||||||
|
type = string
|
||||||
|
default = "python312"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "entry_point" {
|
||||||
|
description = "The entry point function for the Cloud Function."
|
||||||
|
type = string
|
||||||
|
default = "main"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "max_instance_count" {
|
||||||
|
description = "The maximum number of instances for the Cloud Function."
|
||||||
|
type = number
|
||||||
|
default = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "min_instance_count" {
|
||||||
|
description = "The minimum number of instances for the Cloud Function."
|
||||||
|
type = number
|
||||||
|
default = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "timeout_seconds" {
|
||||||
|
description = "The timeout duration for the Cloud Function in seconds."
|
||||||
|
type = number
|
||||||
|
default = 60
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "available_memory" {
|
||||||
|
description = "The amount of memory available to the Cloud Function."
|
||||||
|
type = string
|
||||||
|
default = "256M"
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user