#!/bin/bash set -e OUTPUT_FILE=".gitlab-ci.generated.yml" yaml_escape() { echo "$1" | sed 's/"/\\"/g' } cat > "$OUTPUT_FILE" << 'EOF' workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "main"' - if: '$CI_COMMIT_BRANCH =~ /^feature\/.*/' - if: '$CI_PIPELINE_SOURCE == "pipeline"' - when: always variables: TERRAFORM_IMAGE_NAME: ${TERRAFORM_IMAGE_NAME} YC_IAM_TOKEN: ${YC_IAM_TOKEN} YC_TOKEN: ${YC_IAM_TOKEN} YC_STAGE_FOLDER_ID: ${YC_STAGE_FOLDER_ID} YC_PROD_FOLDER_ID: ${YC_PROD_FOLDER_ID} YC_PREPROD_FOLDER_ID: ${YC_PREPROD_FOLDER_ID} S3_ACCESS_KEY: ${S3_ACCESS_KEY} S3_SECRET_KEY: ${S3_SECRET_KEY} S3_STATE_BUCKET: ${S3_STATE_BUCKET} AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} stages: - validate - plan - apply EOF find live -name "terragrunt.hcl" -not -path "*/.terragrunt-cache/*" | sort | while read -r config_file; do component_dir=$(dirname "$config_file") relative_path=$(echo "$component_dir" | sed 's|^live/||') # live/{env}/{component}/terragrunt.hcl env=$(echo "$relative_path" | cut -d'/' -f1) component=$(echo "$relative_path" | cut -d'/' -f2) if [ -z "$component" ] || [ "$component" = "$env" ]; then continue fi job_prefix="${env}-${component}" case "$env" in stage) folder_var="YC_STAGE_FOLDER_ID" ;; prod) folder_var="YC_PROD_FOLDER_ID" ;; preprod) folder_var="YC_PREPROD_FOLDER_ID" ;; *) folder_var="YC_FOLDER_ID" ;; esac cat >> "$OUTPUT_FILE" << EOF validate-${job_prefix}: stage: validate image: \${TERRAFORM_IMAGE_NAME} variables: TG_ROOT: "${component_dir}" ENVIRONMENT: "${env}" YC_FOLDER_ID: "\${${folder_var}}" YC_TOKEN: "\${YC_IAM_TOKEN}" S3_ACCESS_KEY: "\${S3_ACCESS_KEY}" S3_SECRET_KEY: "\${S3_SECRET_KEY}" S3_STATE_BUCKET: "\${S3_STATE_BUCKET}" TG_TF_PATH: "/usr/local/bin/terraform" AWS_ACCESS_KEY_ID: "\${AWS_ACCESS_KEY_ID}" AWS_SECRET_ACCESS_KEY: "\${AWS_SECRET_ACCESS_KEY}" before_script: - echo "TG_ROOT=\${TG_ROOT}" - echo "CI_PROJECT_DIR=\${CI_PROJECT_DIR}" - export AWS_ACCESS_KEY_ID="\${AWS_ACCESS_KEY_ID}" - export AWS_SECRET_ACCESS_KEY="\${AWS_SECRET_ACCESS_KEY}" - export S3_ACCESS_KEY="\${S3_ACCESS_KEY}" - export S3_SECRET_KEY="\${S3_SECRET_KEY}" - cd \${TG_ROOT} - ls -la - rm -rf .terragrunt-cache - export TF_PLUGIN_CACHE_DIR=/root/.terraform.d/plugins script: - env | grep -E "(S3_|AWS_)" || echo "No S3/AWS vars found" - terragrunt init -reconfigure - terragrunt validate-inputs - terragrunt validate rules: - if: '\$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '\$CI_COMMIT_BRANCH == "master" || \$CI_COMMIT_BRANCH == "main"' - if: '\$CI_COMMIT_BRANCH =~ /^feature\/.*/' - if: '\$CI_PIPELINE_SOURCE == "pipeline"' interruptible: true EOF cat >> "$OUTPUT_FILE" << EOF plan-${job_prefix}: stage: plan image: \${TERRAFORM_IMAGE_NAME} variables: TG_ROOT: "${component_dir}" ENVIRONMENT: "${env}" YC_FOLDER_ID: "\${${folder_var}}" YC_TOKEN: "\${YC_IAM_TOKEN}" S3_ACCESS_KEY: "\${S3_ACCESS_KEY}" S3_SECRET_KEY: "\${S3_SECRET_KEY}" S3_STATE_BUCKET: "\${S3_STATE_BUCKET}" TG_TF_PATH: "/usr/local/bin/terraform" AWS_ACCESS_KEY_ID: "\${AWS_ACCESS_KEY_ID}" AWS_SECRET_ACCESS_KEY: "\${AWS_SECRET_ACCESS_KEY}" before_script: - echo "${TG_ROOT}" - export AWS_ACCESS_KEY_ID="\${AWS_ACCESS_KEY_ID}" - export AWS_SECRET_ACCESS_KEY="\${AWS_SECRET_ACCESS_KEY}" - cd \${TG_ROOT} - ls -la - rm -rf .terragrunt-cache script: - terragrunt init -reconfigure || true - echo "=== Checking generated backend.tf ===" - find .terragrunt-cache -name "backend.tf" -exec echo "=== {} ===" \; -exec head -15 {} \; 2>/dev/null || echo "No backend.tf found" - echo "=== Environment variables ===" - env | grep -E "(S3_|AWS_)" || echo "No S3/AWS vars found" - exit 1 - terragrunt plan -out=tfplan rules: - if: '\$CI_COMMIT_BRANCH == "master" || \$CI_COMMIT_BRANCH == "main"' - if: '\$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '\$CI_COMMIT_BRANCH =~ /^feature\/.*/' - if: '\$CI_PIPELINE_SOURCE == "pipeline"' interruptible: true artifacts: paths: - "\${TG_ROOT}/tfplan" - "\${TG_ROOT}/.terragrunt-cache/**/*" expire_in: 1 week when: always EOF if [ "$env" = "prod" ]; then when_clause="manual" else when_clause="on_success" fi cat >> "$OUTPUT_FILE" << EOF apply-${job_prefix}: stage: apply image: \${TERRAFORM_IMAGE_NAME} variables: TG_ROOT: "${component_dir}" ENVIRONMENT: "${env}" YC_FOLDER_ID: "\${${folder_var}}" YC_TOKEN: "\${YC_IAM_TOKEN}" S3_ACCESS_KEY: "\${S3_ACCESS_KEY}" S3_SECRET_KEY: "\${S3_SECRET_KEY}" S3_STATE_BUCKET: "\${S3_STATE_BUCKET}" TG_TF_PATH: "/usr/local/bin/terraform" AWS_ACCESS_KEY_ID: "\${AWS_ACCESS_KEY_ID}" AWS_SECRET_ACCESS_KEY: "\${AWS_SECRET_ACCESS_KEY}" before_script: - echo "${TG_ROOT}" - export AWS_ACCESS_KEY_ID="\${AWS_ACCESS_KEY_ID}" - export AWS_SECRET_ACCESS_KEY="\${AWS_SECRET_ACCESS_KEY}" - cd \${TG_ROOT} - ls -la - rm -rf .terragrunt-cache script: - terragrunt init -reconfigure || true - echo "=== Checking generated backend.tf ===" - find .terragrunt-cache -name "backend.tf" -exec echo "=== {} ===" \; -exec head -15 {} \; 2>/dev/null || echo "No backend.tf found" - echo "=== Environment variables ===" - env | grep -E "(S3_|AWS_)" || echo "No S3/AWS vars found" - exit 1 - terragrunt apply tfplan rules: - if: '\$CI_COMMIT_BRANCH == "master" || \$CI_COMMIT_BRANCH == "main"' when: ${when_clause} - if: '\$CI_COMMIT_BRANCH =~ /^feature\/.*/' when: ${when_clause} - if: '\$CI_PIPELINE_SOURCE == "pipeline"' when: ${when_clause} interruptible: true dependencies: - plan-${job_prefix} EOF done echo "Pipeline generated successfully: $OUTPUT_FILE" echo "Found components:" find live -name "terragrunt.hcl" -not -path "*/.terragrunt-cache/*" | sed 's|live/||; s|/terragrunt.hcl||' | sort