diff --git a/.github/workflows/deploy_to_gcp.yml b/.github/workflows/deploy_to_gcp.yml new file mode 100644 index 0000000..051d0dd --- /dev/null +++ b/.github/workflows/deploy_to_gcp.yml @@ -0,0 +1,38 @@ +name: Gitea Deploy to GCP + +on: + workflow_dispatch: + + pull_request: + branches: + - deploy-prd + - deploy-dev + paths: + - 'src/**' + - 'terraform/**' + +jobs: + deploy: + name: Deploy to GCP + runs-on: gcloud-tf + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Check Deploy Tools + run: | + gcloud --version + terraform --version + + + # - name: Set up Cloud SDK + # uses: google-github-actions/setup-gcloud@v1 + # with: + # project_id: ${{ secrets.GCP_PROJECT_ID }} + # service_account_key: ${{ secrets.GCP_SA_KEY }} + # export_default_credentials: true + + # - name: Run deployment script + # run: | + # chmod +x ./deploy.sh + # ./deploy.sh diff --git a/.gitignore b/.gitignore index 00b439c..2015f53 100644 --- a/.gitignore +++ b/.gitignore @@ -172,3 +172,10 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +# terraform.tfstate files +_*.tfvars +.terraform/ +.terraform.lock.hcl +*.tfstate +*.tfstate.backup +*deploy.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..91fd4eb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.12-slim + +# 必要なパッケージをインストール +RUN apt-get update && apt-get install -y \ + curl + +# pythonパッケージのインストール +COPY requirements.txt . +RUN pip install --upgrade pip +RUN pip install --no-cache-dir -r requirements.txt + +# 作業ディレクトリを設定 +WORKDIR /app + +# アプリケーションコードをコピー +COPY ./src /app + +# コンテナ起動時に実行されるコマンドを指定 +CMD ["python", "main.py"] \ No newline at end of file diff --git a/readme/components_design/AGENT.md b/readme/components_design/AGENT.md new file mode 100644 index 0000000..fe51108 --- /dev/null +++ b/readme/components_design/AGENT.md @@ -0,0 +1,61 @@ + +# エージェントへの目的 + +`terraform`フォルダを確認して`readme/components_design`フォルダに +.drawioファイル(XML形式)で作成してください + +## 役割 + +あなたはシステム構成を考える専門家です。 + +## 規約 + +【要件】 + +* 出力ファイルは`system_components.drawio`としてください。 +* リクエストに指定がない場合は環境変数は`_dev.tfvars`を優先してください。 +* サービスアカウントやロールなどは記載しなくて良い。 +* **重要**terraformに存在しないコンポーネントは使用しないこと +* ユーザーが利用するコンポーネント図と、開発者が利用するコンポーネント図は分離してください + + +【レイアウト要件】 +- Region、VPCを大きな枠で表現 + - Region: 最も外側の枠として配置 + - VPC: Regionの内側に配置 +- 接続線が重ならないよう、コンポーネントを階段状に配置 +- 各コンポーネント間の間隔を100px以上確保 +- ユーザーはVPCの外側に配置(インターネット経由でアクセスする想定) +- コンポーネントは左から右に向かってデータフローを表現(User → Frontend → Backend → Database) + +【スタイル要件】 + +**枠のスタイル:** +- VPC: `fillColor=#D5E8D4;strokeColor=#82b366;dashed=1;verticalAlign=top;fontStyle=1;fontSize=14` +- Region: `fillColor=#E1F5FE;strokeColor=#01579B;dashed=1;verticalAlign=top;fontStyle=1;fontSize=14` +- 枠のラベルは左上に配置(`align=left;spacingLeft=10;spacingTop=5`) + +**接続線:** +- 双方向通信: `endArrow=classic;startArrow=classic;strokeWidth=2` +- 単方向通信: `endArrow=classic;strokeWidth=2` +- HTTPSアクセス: `strokeColor=#4285F4`(青) +- データベース接続: `strokeColor=#DB4437`(赤) +- ストレージアクセス: `strokeColor=#34A853`(緑) +- 接続線にラベルを付ける(例: "HTTPS", "API", "SQL") + +【座標とサイズの目安】 +- Region枠: 幅800-1000px、高さ500-700px +- VPC枠: Region内部で余白50px程度、幅700-900px、高さ400-600px +- コンポーネントアイコン: 78x78 または 80x80 +- コンポーネント間の横間隔: 150-200px +- コンポーネント間の縦間隔: 100-150px + + +**アイコン:** + +- ユーザー/クライアントアイコン + - `shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.user`(共通で使用可能) + +- コンポーネントのアイコンについて以下のマップを参考にしてください + - 以下のアイコンを使用する場合、必ず対応する mxCell テンプレートを使用すること。 + - id / x / y / width / height / parent などは適宜書き換えて構いません。 diff --git a/readme/deploy.md b/readme/deploy.md new file mode 100644 index 0000000..fea0c58 --- /dev/null +++ b/readme/deploy.md @@ -0,0 +1,76 @@ +# デプロイの方法について + +## インストール方法 + +MACの場合 + +```sh +brew tap hashicorp/tap +brew install hashicorp/tap/terraform +# 確認 +terraform -version +``` + + +## 環境について + +* terraform +* google cloud + * Cloud Run Job + +## 実行する方法 + +```sh +# 初期化を実行する +cd terraform +# Terraformの初期化 +terraform init +# アーティファクトやバケットについては先に生成する +terraform apply \ +-var-file=_dev.tfvars \ +-auto-approve \ +-target="google_artifact_registry_repository.repo" +# DockerファイルをビルドしてGARにプッシュする場合 +cd ../ +# 1. Artifact Registryへの認証設定(初回のみ実行) +source deploy.env +gcloud auth configure-docker "${AR_REGION}-docker.pkg.dev" +# arm64 +source deploy.env +gcloud builds submit --tag "${IMAGE_URI}" . +echo "${IMAGE_URI}" + +# デプロイするコンポーネントを確認する +cd terraform +terraform plan \ +-var-file=_dev.tfvars \ +-var="hash_suffix=${HASH_SUFFIX}" + +# デプロイを実行する +terraform apply \ +-var-file=_dev.tfvars \ +-var="hash_suffix=${HASH_SUFFIX}" \ +-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 +``` + +### CI/CDでデプロイを実行する場合 + +**Github(Gitea) Acrtionsで実行する場合** + + +**Cloud Buildで実行する場合** + + +### Big Quderyにデータが取得できた場合をトリガーにしてJOBを実行する方法 diff --git a/scripts/deploy/init_terraform.sh b/scripts/deploy/init_terraform.sh new file mode 100644 index 0000000..7e57d64 --- /dev/null +++ b/scripts/deploy/init_terraform.sh @@ -0,0 +1,19 @@ +#!/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} +ENV=${ENV:-dev} +REPO_NAME=${REPO_NAME:-unknown} + +cd "$TF_DIR" + +# --- terraform init 実行 --- +terraform init \ + -backend-config="bucket=${TF_STATE_BUCKET}" \ + -backend-config="prefix=${REPO_NAME}/${ENV}" \ + \ No newline at end of file diff --git a/terraform/af.tf b/terraform/af.tf new file mode 100644 index 0000000..fd4fcf8 --- /dev/null +++ b/terraform/af.tf @@ -0,0 +1,5 @@ +resource "google_artifact_registry_repository" "repo" { + location = var.region + repository_id = "cicd-repo-${var.env_name}" + format = "DOCKER" +} \ No newline at end of file diff --git a/terraform/platform.tf b/terraform/platform.tf new file mode 100644 index 0000000..17fcd21 --- /dev/null +++ b/terraform/platform.tf @@ -0,0 +1,10 @@ +# Google CloudのAPIを有効化 + +resource "google_project_service" "services" { + for_each = toset([ + "run.googleapis.com", + "artifactregistry.googleapis.com", + "cloudbuild.googleapis.com", + ]) + service = each.key +} \ No newline at end of file diff --git a/terraform/provider.tf b/terraform/provider.tf new file mode 100644 index 0000000..fdeb7be --- /dev/null +++ b/terraform/provider.tf @@ -0,0 +1,5 @@ +# Google Providerの設定 +provider "google" { + project = var.project_id + region = var.region +} \ No newline at end of file diff --git a/terraform/run_job.tf b/terraform/run_job.tf new file mode 100644 index 0000000..c6be644 --- /dev/null +++ b/terraform/run_job.tf @@ -0,0 +1,29 @@ +# Cloud Run Jobのリソース +# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_job +resource "google_cloud_run_v2_job" "job" { + name = "${var.job_name}-${var.env_name}-job" + location = var.region + + + template { + template { + # サービスアカウントを指定 + service_account = google_service_account.job_sa.email + + containers { + image = "${var.region}-docker.pkg.dev/${var.project_id}/cicd-repo-${var.env_name}/run-job-${var.job_name}-image:${var.hash_suffix}" + resources { + limits = { + cpu = var.cpu_limit + memory = var.memory_limit + } + } + } + + timeout = var.timeout + + } + } + +} + diff --git a/terraform/sa.tf b/terraform/sa.tf new file mode 100644 index 0000000..798cc12 --- /dev/null +++ b/terraform/sa.tf @@ -0,0 +1,14 @@ +resource "google_service_account" "job_sa" { + account_id = "sa-${var.job_name}-${var.env_name}" + display_name = "Cloud Run Job Service Account for ${var.job_name} in ${var.env_name} environment" + description = "Cloud Run Job Service Account for ${var.job_name} in ${var.env_name} environment" + project = var.project_id +} + +# IAM role assignment +# Cloud Run Job実行に必要な権限を付与 +resource "google_project_iam_member" "run_job_invoker" { + project = var.project_id + role = "roles/run.invoker" + member = "serviceAccount:${google_service_account.job_sa.email}" +} \ No newline at end of file diff --git a/terraform/sample.tfvars b/terraform/sample.tfvars new file mode 100644 index 0000000..b094684 --- /dev/null +++ b/terraform/sample.tfvars @@ -0,0 +1,10 @@ +project_id = "プロジェクトIDを指定してください" +region = "asia-northeast1" +env_name = "dev" + +job_name = "ジョブ名を指定してください" +# コンテナイメージ(CI/CDから渡される想定) + +cpu_limit = "1" +memory_limit = "512Mi" +timeout = "1800s" diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..c298ec6 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,54 @@ +# 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 "job_name" { + description = "The name of the Cloud Run Job." + type = string + default = "get-news-ai" +} + + +# コンテナイメージのハッシュ値変数定義(CI/CDから渡される想定) +variable "hash_suffix" { + description = "The container image for the Cloud Run Job." + type = string + default = null +} + + +# Cloud Run Jobの設定変数 +variable "cpu_limit" { + description = "The CPU limit for the Cloud Run Job container." + type = string + default = "1" +} + +variable "memory_limit" { + description = "The memory limit for the Cloud Run Job container." + type = string + default = "512Mi" +} + +variable "timeout" { + description = "The task timeout in seconds for the Cloud Run Job." + type = string + default = "1800s" +} \ No newline at end of file