diff --git a/infrastructure/foundation/Jenkinsfile b/infrastructure/foundation/Jenkinsfile index 8282f83..1ee31ad 100644 --- a/infrastructure/foundation/Jenkinsfile +++ b/infrastructure/foundation/Jenkinsfile @@ -24,7 +24,7 @@ pipeline { ) string( name: 'PROJECT_NAME', - defaultValue: 'nvhi-atsila-microservice', + defaultValue: 'enterprise-cicd', description: 'Project name for resource naming' ) string( @@ -102,8 +102,10 @@ pipeline { echo "✅ Found: $file" done - # Make scripts executable - chmod +x bootstrap.sh cleanup.sh + # Make scripts executable (if they aren't already) + chmod +x bootstrap.sh cleanup.sh || { + echo "⚠️ Could not make scripts executable, but continuing..." + } echo "✅ Repository structure validated" ''' @@ -118,37 +120,91 @@ pipeline { sh ''' if ! command -v terraform &> /dev/null; then echo "Installing Terraform ${TF_VERSION}..." - wget -q https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip - unzip -o terraform_${TF_VERSION}_linux_amd64.zip + + # Check if wget is available + if ! command -v wget &> /dev/null; then + echo "❌ wget not available. Please install Terraform manually or use a different base image." + exit 1 + fi + + # Download and install Terraform + wget -q https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip || { + echo "❌ Failed to download Terraform" + exit 1 + } + + unzip -o terraform_${TF_VERSION}_linux_amd64.zip || { + echo "❌ Failed to unzip Terraform" + exit 1 + } + chmod +x terraform - sudo mv terraform /usr/local/bin/ || mv terraform /tmp/ - export PATH="/tmp:$PATH" + + # Try to move to system path, fallback to local + if sudo mv terraform /usr/local/bin/ 2>/dev/null; then + echo "✅ Terraform installed to /usr/local/bin/" + elif mv terraform /tmp/ 2>/dev/null; then + export PATH="/tmp:$PATH" + echo "✅ Terraform installed to /tmp/ (added to PATH)" + else + echo "⚠️ Could not install Terraform to system path. Using local copy." + export PATH=".:$PATH" + fi + + # Cleanup + rm -f terraform_${TF_VERSION}_linux_amd64.zip fi echo "Terraform version:" - terraform version + terraform version || { + echo "❌ Terraform installation failed or not accessible" + exit 1 + } ''' // Verify AWS credentials and permissions via Jenkins credential store - withCredentials([ - aws(credentialsId: "${params.AWS_CREDENTIALS_ID}"), - string(credentialsId: "${params.AWS_REGION_ID}", variable: 'AWS_REGION') - ]) { - sh ''' - echo "AWS CLI version:" - aws --version - - echo "Verifying Jenkins stored AWS credentials..." - echo "AWS Region: ${AWS_REGION}" - aws sts get-caller-identity - - echo "Testing AWS permissions..." - aws ec2 describe-vpcs --max-items 1 --region ${AWS_REGION} > /dev/null && echo "✅ EC2 permissions OK" || echo "⚠️ EC2 permissions limited" - aws s3 ls > /dev/null 2>&1 && echo "✅ S3 permissions OK" || echo "⚠️ S3 permissions limited" - aws dynamodb list-tables --region ${AWS_REGION} > /dev/null 2>&1 && echo "✅ DynamoDB permissions OK" || echo "⚠️ DynamoDB permissions limited" - - echo "✅ Jenkins credential store authentication verified" - ''' + try { + withCredentials([ + aws(credentialsId: "${params.AWS_CREDENTIALS_ID}"), + string(credentialsId: "${params.AWS_REGION_ID}", variable: 'AWS_REGION') + ]) { + sh ''' + echo "AWS CLI version:" + aws --version || { + echo "❌ AWS CLI not available. Please install AWS CLI in Jenkins container." + exit 1 + } + + echo "Verifying Jenkins stored AWS credentials..." + echo "AWS Region: ${AWS_REGION}" + + # Test AWS credentials + aws sts get-caller-identity || { + echo "❌ AWS credentials validation failed" + echo "Check that credential IDs '${AWS_CREDENTIALS_ID}' and '${AWS_REGION_ID}' exist in Jenkins" + exit 1 + } + + echo "Testing AWS permissions..." + aws ec2 describe-vpcs --max-items 1 --region ${AWS_REGION} > /dev/null && echo "✅ EC2 permissions OK" || echo "⚠️ EC2 permissions limited" + aws s3 ls > /dev/null 2>&1 && echo "✅ S3 permissions OK" || echo "⚠️ S3 permissions limited" + aws dynamodb list-tables --region ${AWS_REGION} > /dev/null 2>&1 && echo "✅ DynamoDB permissions OK" || echo "⚠️ DynamoDB permissions limited" + + echo "✅ Jenkins credential store authentication verified" + ''' + } + } catch (Exception e) { + error """ +❌ AWS Credentials Setup Failed: ${e.getMessage()} + +🔧 Check these in Jenkins: +1. Manage Jenkins → Manage Credentials → Global +2. Verify credential exists: '${params.AWS_CREDENTIALS_ID}' (Type: AWS Credentials) +3. Verify credential exists: '${params.AWS_REGION_ID}' (Type: Secret text) +4. Ensure AWS CLI is installed in Jenkins container + +💡 Or run with different credential IDs if yours are named differently. + """ } } } @@ -190,11 +246,47 @@ sonar.tags=terraform,infrastructure,enterprise-cicd """ // Run SonarQube analysis - withSonarQubeEnv('SonarQube') { - sh ''' - echo "🔍 Running SonarQube analysis on Terraform infrastructure..." - sonar-scanner - ''' + try { + withSonarQubeEnv('SonarQube') { + sh ''' + echo "🔍 Running SonarQube analysis on Terraform infrastructure..." + + # Check if sonar-scanner is available + if command -v sonar-scanner &> /dev/null; then + sonar-scanner + else + echo "⚠️ sonar-scanner not found. Attempting to use docker fallback..." + if command -v docker &> /dev/null; then + docker run --rm -v "$(pwd):/usr/src" sonarsource/sonar-scanner-cli + else + echo "❌ Neither sonar-scanner nor docker available" + echo "Please install SonarQube Scanner or skip SonarQube analysis" + exit 1 + fi + fi + ''' + } + } catch (Exception e) { + echo "❌ SonarQube analysis failed: ${e.getMessage()}" + echo "💡 Consider running with SKIP_SONAR=true or configure SonarQube properly" + + if (params.ACTION == 'apply') { + def proceed = input( + message: 'SonarQube analysis failed. How do you want to proceed?', + parameters: [ + choice( + name: 'DECISION', + choices: ['Abort', 'Continue without SonarQube'], + description: 'SonarQube failed - your decision' + ) + ] + ) + if (proceed == 'Abort') { + error "Pipeline aborted due to SonarQube failure" + } + } else { + error "SonarQube analysis failed for ${params.ACTION} action" + } } } } @@ -211,32 +303,55 @@ sonar.tags=terraform,infrastructure,enterprise-cicd steps { script { timeout(time: 5, unit: 'MINUTES') { - def qg = waitForQualityGate() - if (qg.status != 'OK') { - echo "❌ SonarQube Quality Gate failed: ${qg.status}" - echo "Quality gate details: ${qg}" + try { + def qg = waitForQualityGate() + if (qg.status != 'OK') { + echo "❌ SonarQube Quality Gate failed: ${qg.status}" + echo "Quality gate details: ${qg}" + + if (params.ACTION == 'apply' && !params.AUTO_APPROVE) { + def proceed = input( + message: 'SonarQube Quality Gate failed. How do you want to proceed?', + parameters: [ + choice( + name: 'DECISION', + choices: ['Abort', 'Proceed anyway'], + description: 'Quality gate failed - your decision' + ) + ] + ) + if (proceed == 'Abort') { + error "Deployment aborted due to quality gate failure" + } + } else if (params.ACTION == 'apply' && params.AUTO_APPROVE) { + echo "⚠️ Quality gate failed but AUTO_APPROVE is enabled, proceeding..." + } else { + error "Quality gate failed and action is ${params.ACTION}" + } + } else { + echo "✅ SonarQube Quality Gate passed" + } + } catch (Exception e) { + echo "❌ Quality Gate check failed: ${e.getMessage()}" + echo "💡 This might be due to SonarQube server issues or configuration problems" - if (params.ACTION == 'apply' && !params.AUTO_APPROVE) { + if (params.ACTION == 'apply') { def proceed = input( - message: 'SonarQube Quality Gate failed. How do you want to proceed?', + message: 'Quality Gate check failed (server error). Proceed anyway?', parameters: [ choice( name: 'DECISION', - choices: ['Abort', 'Proceed anyway'], - description: 'Quality gate failed - your decision' + choices: ['Abort', 'Proceed without quality gate'], + description: 'SonarQube server error - your decision' ) ] ) if (proceed == 'Abort') { - error "Deployment aborted due to quality gate failure" + error "Pipeline aborted due to quality gate server error" } - } else if (params.ACTION == 'apply' && params.AUTO_APPROVE) { - echo "⚠️ Quality gate failed but AUTO_APPROVE is enabled, proceeding..." } else { - error "Quality gate failed and action is ${params.ACTION}" + echo "⚠️ Quality gate check failed for ${params.ACTION}, but continuing..." } - } else { - echo "✅ SonarQube Quality Gate passed" } } } @@ -322,7 +437,7 @@ common_tags = { ManagedBy = "jenkins" Pipeline = "foundation-layer" BuildNumber = "${BUILD_NUMBER}" - GitCommit = "${GIT_COMMIT}" + GitCommit = "${env.GIT_COMMIT ?: 'unknown'}" } EOF fi