Merge pull request #14 from escalopa/dev #67
This file contains hidden or 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
| 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 |