Skip to content

Merge pull request #14 from escalopa/dev #67

Merge pull request #14 from escalopa/dev

Merge pull request #14 from escalopa/dev #67

Workflow file for this run

name: Deploy to Yandex Cloud
on:
push:
branches:
- main
- dev
workflow_dispatch:
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: true
env:
TERRAFORM_VERSION: 1.6.3
GOOSE_VERSION: 3.26.0
GO_VERSION: 1.21
APP_CONFIG_PATH: config.json
jobs:
setup:
name: Setup Environment
runs-on: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
outputs:
cache_key: ${{ steps.set-cache-key.outputs.cache_key }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
echo "::notice::Workspace: $WORKSPACE"
- name: Set cache key
id: set-cache-key
run: |
CACHE_KEY="${{ runner.os }}-${{ github.ref_name }}-terraform-${{ hashFiles('**/.terraform.lock.hcl') }}"
echo "cache_key=$CACHE_KEY" >> $GITHUB_OUTPUT
echo "::notice::Cache key: $CACHE_KEY"
- name: Setup Terraform Environment
uses: ./.github/actions/setup-terraform
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
service_account_key: ${{ secrets.SERVICE_ACCOUNT_KEY }}
app_config: ${{ secrets.APP_CONFIG }}
app_config_path: ${{ env.APP_CONFIG_PATH }}
workspace: ${{ env.WORKSPACE }}
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
cache_key: ${{ steps.set-cache-key.outputs.cache_key }}
lint:
name: Code Linting
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go modules
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-${{ github.ref_name }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-${{ github.ref_name }}-go-
- name: Install revive
run: go install github.com/mgechev/revive@latest
- name: Run revive
run: revive -config revive.toml -formatter friendly ./...
migrate:
name: Database Migration
runs-on: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
echo "::notice::Workspace: $WORKSPACE"
- name: Install YC CLI
run: |
curl -sSL https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash
echo "${HOME}/yandex-cloud/bin" >> $GITHUB_PATH
- name: Authenticate YC CLI
env:
YC_SERVICE_ACCOUNT_KEY: ${{ secrets.SERVICE_ACCOUNT_KEY }}
YC_CLOUD_ID: ${{ secrets.CLOUD_ID }}
YC_FOLDER_ID: ${{ secrets.FOLDER_ID }}
run: |
echo "$YC_SERVICE_ACCOUNT_KEY" > iam.json
yc config set service-account-key iam.json
yc config set cloud-id "$YC_CLOUD_ID"
yc config set folder-id "$YC_FOLDER_ID"
- name: Generate short-lived IAM token
run: |
export YDB_ACCESS_TOKEN=$(yc iam create-token)
echo "YDB_ACCESS_TOKEN=$YDB_ACCESS_TOKEN" >> $GITHUB_ENV
- name: Install Goose
run: |
GOOSE_VERSION="${{ env.GOOSE_VERSION }}"
wget -q "https://github.com/pressly/goose/releases/download/v${GOOSE_VERSION}/goose_linux_x86_64" -O goose
chmod +x goose
mkdir -p $HOME/.goose
mv goose $HOME/.goose/
echo "$HOME/.goose" >> $GITHUB_PATH
- name: Run Goose migrations
env:
GOOSE_DRIVER: ydb
GOOSE_DBSTRING_BASE: ${{ secrets.DB_CONNECTION_STRING }}
run: |
export PATH="$HOME/.goose:$PATH"
cd migrations
# Add token and query options to connection string
GOOSE_DBSTRING="${GOOSE_DBSTRING_BASE}&token=${YDB_ACCESS_TOKEN}&go_query_mode=scripting&go_fake_tx=scripting&go_query_bind=declare,numeric"
export GOOSE_DBSTRING
echo "::notice::Running Goose migrations for $WORKSPACE environment"
goose up
echo "::notice::Migration completed successfully for $WORKSPACE environment"
continue-on-error: false
validate:
name: Terraform Validate
runs-on: ubuntu-latest
needs: setup
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
echo "::notice::Workspace: $WORKSPACE"
- name: Setup Terraform Environment
uses: ./.github/actions/setup-terraform
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
service_account_key: ${{ secrets.SERVICE_ACCOUNT_KEY }}
app_config: ${{ secrets.APP_CONFIG }}
app_config_path: ${{ env.APP_CONFIG_PATH }}
workspace: ${{ env.WORKSPACE }}
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
cache_key: ${{ needs.setup.outputs.cache_key }}
- name: Terraform Format Check
run: terraform fmt -check -recursive
continue-on-error: false
- name: Terraform Validate
run: terraform validate
plan:
name: Terraform Plan
runs-on: ubuntu-latest
needs: [setup, lint, validate]
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
outputs:
plan-exists: ${{ steps.plan.outputs.exitcode }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
echo "::notice::Workspace: $WORKSPACE"
- name: Setup Terraform Environment
uses: ./.github/actions/setup-terraform
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
service_account_key: ${{ secrets.SERVICE_ACCOUNT_KEY }}
app_config: ${{ secrets.APP_CONFIG }}
app_config_path: ${{ env.APP_CONFIG_PATH }}
workspace: ${{ env.WORKSPACE }}
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
cache_key: ${{ needs.setup.outputs.cache_key }}
- name: Terraform Plan
id: plan
env:
TF_VAR_cloud_id: ${{ secrets.CLOUD_ID }}
TF_VAR_folder_id: ${{ secrets.FOLDER_ID }}
run: |
terraform plan -out=tfplan
terraform show tfplan
apply:
name: Terraform Apply
runs-on: ubuntu-latest
needs: [setup, plan, migrate]
if: always() && needs.plan.result == 'success' && (needs.migrate.result == 'success' || needs.migrate.result == 'skipped')
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
outputs:
dispatcher_function_id: ${{ steps.outputs.outputs.dispatcher_function_id }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
echo "::notice::Workspace: $WORKSPACE"
- name: Setup Terraform Environment
uses: ./.github/actions/setup-terraform
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
terraform_wrapper: 'false'
service_account_key: ${{ secrets.SERVICE_ACCOUNT_KEY }}
app_config: ${{ secrets.APP_CONFIG }}
app_config_path: ${{ env.APP_CONFIG_PATH }}
workspace: ${{ env.WORKSPACE }}
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
cache_key: ${{ needs.setup.outputs.cache_key }}
- name: Backup current state
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
mkdir -p state-backups
terraform state pull > state-backups/terraform-$WORKSPACE-${TIMESTAMP}-${{ github.run_id }}.tfstate
- name: Upload state backup
uses: actions/upload-artifact@v4
with:
name: terraform-state-backup-${{ env.WORKSPACE }}-${{ github.run_id }}
path: state-backups/
retention-days: 90
- name: Terraform Apply
env:
TF_VAR_cloud_id: ${{ secrets.CLOUD_ID }}
TF_VAR_folder_id: ${{ secrets.FOLDER_ID }}
run: terraform apply -auto-approve
continue-on-error: false
- name: Export Terraform Outputs
id: outputs
run: |
DISPATCHER_FUNCTION_ID=$(terraform output -raw dispatcher_function_id)
echo "dispatcher_function_id=$DISPATCHER_FUNCTION_ID" >> $GITHUB_OUTPUT
echo "::notice::Dispatcher Function ID: $DISPATCHER_FUNCTION_ID"
hook:
name: Setup Telegram Webhooks
runs-on: ubuntu-latest
needs: [apply]
if: needs.apply.result == 'success'
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
echo "::notice::Workspace: $WORKSPACE"
- name: Load application config
uses: ./.github/actions/load-config
with:
app_config: ${{ secrets.APP_CONFIG }}
app_config_path: ${{ env.APP_CONFIG_PATH }}
- name: Get Dispatcher Function ID
run: |
DISPATCHER_FUNCTION_ID="${{ needs.apply.outputs.dispatcher_function_id }}"
echo "DISPATCHER_FUNCTION_ID=$DISPATCHER_FUNCTION_ID" >> $GITHUB_ENV
echo "::notice::Dispatcher Function ID: $DISPATCHER_FUNCTION_ID"
- name: Execute webhook setup script
run: |
echo "::notice::Config file: ${{ env.APP_CONFIG_PATH }}"
echo "::notice::Dispatcher function ID: $DISPATCHER_FUNCTION_ID"
chmod +x _scripts/hook.sh
bash _scripts/hook.sh
continue-on-error: false
- name: Verify webhook setup
run: |
echo "::notice::Webhook setup completed successfully for $WORKSPACE environment"
summary:
name: Deployment Summary
runs-on: ubuntu-latest
needs: [setup, validate, lint, migrate, plan, apply, hook]
if: always()
steps:
- name: Set workspace
run: |
WORKSPACE=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
echo "WORKSPACE=$WORKSPACE" >> $GITHUB_ENV
- name: Generate summary
run: |
echo "## Deployment Summary - $WORKSPACE environment" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Validate | ${{ needs.validate.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Code Linting | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Database Migration | ${{ needs.migrate.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Terraform Plan | ${{ needs.plan.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Terraform Apply | ${{ needs.apply.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Webhook Setup | ${{ needs.hook.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Workspace:** $WORKSPACE" >> $GITHUB_STEP_SUMMARY
echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "**Cache Key:** ${{ needs.setup.outputs.cache_key }}" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.apply.outputs.dispatcher_function_id }}" != "" ]; then
echo "**Dispatcher Function ID:** ${{ needs.apply.outputs.dispatcher_function_id }}" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "**Manual Trigger:** Yes" >> $GITHUB_STEP_SUMMARY
fi