CI/CD Integration
Continuous integration and deployment automation with Utah. Learn how to integrate Utah scripts into CI/CD pipelines, automate deployments, and manage build processes.
Prerequisites
- Understanding of CI/CD concepts
 - Experience with build pipelines
 - Knowledge of containerization (Docker)
 - Familiarity with version control (Git)
 
Pipeline Integration Patterns
Build Pipeline Script
script.description("Build and test application in CI pipeline");
args.define("--environment", "-e", "Target environment", "string", false, "development");
args.define("--build-number", "-b", "Build number", "string", true);
args.define("--skip-tests", "-s", "Skip test execution", "boolean", false, false);
let environment: string = args.get("--environment");
let buildNumber: string = args.get("--build-number");
let skipTests: boolean = args.has("--skip-tests");
// Set up build environment
script.enableDebug(false);
console.log("Starting build ${buildNumber} for ${environment}");
// Validate environment
let validEnvironments: string[] = ["development", "staging", "production"];
if (!array.contains(validEnvironments, environment)) {
  console.log("❌ Invalid environment: ${environment}");
  console.log("Valid environments: ${array.join(validEnvironments, ", ")}");
  exit(1);
}
// Check prerequisites
function validateBuildEnvironment(): void {
  console.log("Validating build environment...");
  let requiredTools: string[] = ["node", "npm", "docker", "git"];
  for (let tool: string in requiredTools) {
    if (!os.isInstalled(tool)) {
      console.log("❌ Required tool missing: ${tool}");
      exit(1);
    } else {
      let version: string = "$(${tool} --version | head -1)";
      console.log("✅ ${tool}: ${version}");
    }
  }
}
// Install dependencies
function installDependencies(): void {
  console.log("Installing dependencies...");
  if (fs.exists("package.json")) {
    `$(npm ci)`;
    console.log("✅ NPM dependencies installed");
  }
  if (fs.exists("requirements.txt")) {
    `$(pip install -r requirements.txt)`;
    console.log("✅ Python dependencies installed");
  }
  if (fs.exists("Gemfile")) {
    `$(bundle install)`;
    console.log("✅ Ruby dependencies installed");
  }
}
// Run tests
function runTests(): void {
  if (skipTests) {
    console.log("⏭️  Skipping tests (--skip-tests flag)");
    return;
  }
  console.log("Running tests...");
  if (fs.exists("package.json")) {
    let packageContent: string = fs.readFile("package.json");
    let packageData: object = json.parse(packageContent);
    if (json.has(packageData, ".scripts.test")) {
      `$(npm test)`;
      console.log("✅ JavaScript tests passed");
    }
  }
  if (fs.exists("pytest.ini") || fs.exists("setup.py")) {
    `$(python -m pytest)`;
    console.log("✅ Python tests passed");
  }
  if (fs.exists("Rakefile")) {
    `$(rake test)`;
    console.log("✅ Ruby tests passed");
  }
}
// Build application
function buildApplication(): void {
  console.log("Building application...");
  // Frontend build
  if (fs.exists("package.json")) {
    let packageContent: string = fs.readFile("package.json");
    let packageData: object = json.parse(packageContent);
    if (json.has(packageData, ".scripts.build")) {
      `$(npm run build)`;
      console.log("✅ Frontend build completed");
    }
  }
  // Docker build
  if (fs.exists("Dockerfile")) {
    let imageName: string = "myapp:${buildNumber}";
    "$(docker build -t ${imageName} .)";
    console.log("✅ Docker image built: ${imageName}");
    // Tag for environment
    let envTag: string = "myapp:${environment}-latest";
    "$(docker tag ${imageName} ${envTag})";
    console.log("✅ Tagged for environment: ${envTag}");
  }
}
// Generate build artifacts
function generateArtifacts(): void {
  console.log("Generating build artifacts...");
  let artifactsDir: string = "artifacts";
  fs.createDirectory(artifactsDir);
  // Build metadata
  let buildInfo: object = {
    "build_number": buildNumber,
    "environment": environment,
    "timestamp": `$(date -Iseconds)`,
    "git_commit": `$(git rev-parse HEAD)`,
    "git_branch": `$(git rev-parse --abbrev-ref HEAD)`,
    "node_version": `$(node --version 2>/dev/null || echo "N/A")`,
    "docker_version": `$(docker --version 2>/dev/null || echo "N/A")`
  };
  fs.writeFile("${artifactsDir}/build-info.json", json.stringify(buildInfo));
  // Copy important files
  if (fs.exists("dist")) {
    "$(cp -r dist ${artifactsDir}/")`;
  }
  if (fs.exists("build")) {
    "$(cp -r build ${artifactsDir}/")`;
  }
  console.log("✅ Artifacts generated in ${artifactsDir}/");
}
// Main build process
validateBuildEnvironment();
installDependencies();
runTests();
buildApplication();
generateArtifacts();
console.log("🎉 Build ${buildNumber} completed successfully for ${environment}");
Deployment Script
script.description("Deploy application to target environment");
args.define("--environment", "-e", "Target environment", "string", true);
args.define("--version", "-v", "Version to deploy", "string", true);
args.define("--rollback", "-r", "Rollback to previous version", "boolean", false, false);
args.define("--dry-run", "-d", "Dry run mode", "boolean", false, false);
let environment: string = args.get("--environment");
let version: string = args.get("--version");
let isRollback: boolean = args.has("--rollback");
let isDryRun: boolean = args.has("--dry-run");
if (isDryRun) {
  console.log("🧪 Running in DRY RUN mode - no actual changes will be made");
}
// Environment configuration
let envConfig: object = {
  "staging": {
    "replicas": 2,
    "namespace": "staging",
    "domain": "staging.myapp.com"
  },
  "production": {
    "replicas": 5,
    "namespace": "production",
    "domain": "myapp.com"
  }
};
if (!json.has(envConfig, ".${environment}")) {
  console.log("❌ Unknown environment: ${environment}");
  exit(1);
}
let config: object = json.get(envConfig, ".${environment}");
let replicas: number = json.getNumber(config, ".replicas");
let namespace: string = json.getString(config, ".namespace");
let domain: string = json.getString(config, ".domain");
console.log("Deploying to ${environment} environment");
console.log("Version: ${version}");
console.log("Replicas: ${replicas}");
console.log("Namespace: ${namespace}");
console.log("Domain: ${domain}");
// Pre-deployment checks
function preDeploymentChecks(): void {
  console.log("Running pre-deployment checks...");
  // Check if kubectl is available and configured
  if (!os.isInstalled("kubectl")) {
    console.log("❌ kubectl not found");
    exit(1);
  }
  // Check cluster connectivity
  let clusterInfo: string = `$(kubectl cluster-info 2>&1 | head -1)`;
  if (!string.contains(clusterInfo, "is running")) {
    console.log("❌ Cannot connect to Kubernetes cluster");
    exit(1);
  }
  console.log("✅ Kubernetes cluster accessible");
  // Check namespace exists
  let nsExists: string = "$(kubectl get namespace ${namespace} 2>/dev/null && echo "exists" || echo "missing")";
  if (string.trim(nsExists) != "exists") {
    console.log("❌ Namespace ${namespace} does not exist");
    exit(1);
  }
  console.log("✅ Namespace ${namespace} exists");
  // Check if image exists
  if (!isDryRun) {
    let imageExists: string = "$(docker manifest inspect myapp:${version} >/dev/null 2>&1 && echo "exists" || echo "missing")";
    if (string.trim(imageExists) != "exists") {
      console.log("❌ Docker image myapp:${version} not found");
      exit(1);
    }
    console.log("✅ Docker image myapp:${version} exists");
  }
}
// Backup current deployment
function backupCurrentDeployment(): void {
  console.log("Backing up current deployment...");
  let backupDir: string = "backups/${environment}";
  fs.createDirectory(backupDir);
  let timestamp: string = `$(date +%Y%m%d_%H%M%S)`;
  let backupFile: string = "${backupDir}/deployment-${timestamp}.yaml";
  if (!isDryRun) {
    "$(kubectl get deployment myapp -n ${namespace} -o yaml > ${backupFile} 2>/dev/null || echo "No existing deployment")";
    if (fs.exists(backupFile)) {
      console.log("✅ Deployment backed up to ${backupFile}");
    }
  } else {
    console.log("🧪 Would backup to ${backupFile}");
  }
}
// Deploy application
function deployApplication(): void {
  if (isRollback) {
    console.log("Rolling back to previous version...");
    if (!isDryRun) {
      "$(kubectl rollout undo deployment/myapp -n ${namespace})";
      console.log("✅ Rollback initiated");
    } else {
      console.log("🧪 Would rollback deployment");
    }
  } else {
    console.log("Deploying version ${version}...");
    // Read deployment manifest template from file
    let deploymentManifest: string = fs.readFile("deployment-template.yaml");
    // Replace placeholders with actual values
    deploymentManifest = string.replace(deploymentManifest, "{{NAMESPACE}}", namespace);
    deploymentManifest = string.replace(deploymentManifest, "{{REPLICAS}}", replicas + "");
    deploymentManifest = string.replace(deploymentManifest, "{{VERSION}}", version);
      containers:
      - name: myapp
        image: myapp:${version}
        ports:
        - containerPort: 3000
        env:
        - name: ENVIRONMENT
          value: "${environment}"
        - name: VERSION
          value: "${version}"
`;
    let manifestFile: string = "deployment-${environment}.yaml";
    fs.writeFile(manifestFile, deploymentManifest);
    if (!isDryRun) {
      "$(kubectl apply -f ${manifestFile})";
      console.log("✅ Deployment applied");
    } else {
      console.log("🧪 Would apply deployment manifest: ${manifestFile}");
    }
  }
}
// Wait for deployment to complete
function waitForDeployment(): void {
  if (isDryRun) {
    console.log("🧪 Would wait for deployment completion");
    return;
  }
  console.log("Waiting for deployment to complete...");
  let timeout: number = 300; // 5 minutes
  "$(kubectl rollout status deployment/myapp -n ${namespace} --timeout=${timeout}s)";
  // Check if deployment is ready
  let readyReplicas: string = "$(kubectl get deployment myapp -n ${namespace} -o jsonpath='{.status.readyReplicas}')";
  let desiredReplicas: string = "$(kubectl get deployment myapp -n ${namespace} -o jsonpath='{.spec.replicas}')";
  if (readyReplicas == desiredReplicas) {
    console.log("✅ Deployment completed: ${readyReplicas}/${desiredReplicas} replicas ready");
  } else {
    console.log("❌ Deployment failed: ${readyReplicas}/${desiredReplicas} replicas ready");
    exit(1);
  }
}
// Health check
function performHealthCheck(): void {
  if (isDryRun) {
    console.log("🧪 Would perform health checks");
    return;
  }
  console.log("Performing health checks...");
  // Get pod IPs
  let podIPs: string[] = "$(kubectl get pods -n ${namespace} -l app=myapp -o jsonpath='{.items[*].status.podIP}')".split(" ");
  for (let podIP: string in podIPs) {
    if (string.trim(podIP) != "") {
      let healthCheck: string = "$(curl -s -o /dev/null -w "%{http_code}" http://${podIP}:3000/health 2>/dev/null || echo "000")";
      if (healthCheck == "200") {
        console.log("✅ Health check passed for pod ${podIP}");
      } else {
        console.log("❌ Health check failed for pod ${podIP} (HTTP ${healthCheck})");
      }
    }
  }
}
// Update service configuration
function updateService(): void {
  console.log("Updating service configuration...");
  // Read service manifest template from file
  let serviceManifest: string = fs.readFile("service-template.yaml");
  // Replace placeholders with actual values
  serviceManifest = string.replace(serviceManifest, "{{NAMESPACE}}", namespace);
  let serviceFile: string = "service-${environment}.yaml";
  fs.writeFile(serviceFile, serviceManifest);
  if (!isDryRun) {
    "$(kubectl apply -f ${serviceFile})";
    console.log("✅ Service updated");
  } else {
    console.log("🧪 Would update service: ${serviceFile}");
  }
}
// Post-deployment tasks
function postDeploymentTasks(): void {
  console.log("Running post-deployment tasks...");
  // Update deployment metadata
  let deploymentInfo: object = {
    "environment": environment,
    "version": version,
    "timestamp": `$(date -Iseconds)`,
    "replicas": replicas,
    "namespace": namespace,
    "domain": domain,
    "deployed_by": `$(whoami)`,
    "rollback": isRollback
  };
  let deploymentLogFile: string = "deployments/${environment}-deployments.log";
  fs.createDirectory("deployments");
  let currentLog: string = "";
  if (fs.exists(deploymentLogFile)) {
    currentLog = fs.readFile(deploymentLogFile);
  }
  fs.writeFile(deploymentLogFile, currentLog + json.stringify(deploymentInfo) + "\n");
  // Send notification (example)
  if (!isDryRun) {
    console.log(`📢 Deployment notification would be sent here`);
  }
  console.log("✅ Post-deployment tasks completed");
}
// Main deployment process
preDeploymentChecks();
backupCurrentDeployment();
deployApplication();
waitForDeployment();
performHealthCheck();
updateService();
postDeploymentTasks();
if (isRollback) {
  console.log("🔄 Rollback completed for ${environment}");
} else {
  console.log("🚀 Deployment completed: ${version} → ${environment}");
}
GitHub Actions Integration
GitHub Actions Workflow
script.description("GitHub Actions CI/CD workflow integration");
// This script is designed to run within GitHub Actions
// Environment variables are automatically available
let githubEvent: string = env.get("GITHUB_EVENT_NAME") || "";
let githubRef: string = env.get("GITHUB_REF") || "";
let githubSha: string = env.get("GITHUB_SHA") || "";
let githubActor: string = env.get("GITHUB_ACTOR") || "";
console.log("GitHub Event: ${githubEvent}");
console.log("GitHub Ref: ${githubRef}");
console.log("Commit SHA: ${githubSha}");
console.log("Actor: ${githubActor}");
// Determine environment based on branch
function determineEnvironment(): string {
  if (githubRef == "refs/heads/main" || githubRef == "refs/heads/master") {
    return "production";
  } else if (githubRef == "refs/heads/staging") {
    return "staging";
  } else if (githubRef.startsWith("refs/heads/")) {
    return "development";
  } else if (githubRef.startsWith("refs/pull/")) {
    return "preview";
  } else {
    return "unknown";
  }
}
let environment: string = determineEnvironment();
console.log("Determined environment: ${environment}");
// Set GitHub Actions outputs
function setOutput(name: string, value: string): void {
  console.log("::set-output name=${name}::${value}");
}
// Set GitHub Actions environment variables
function setEnvVar(name: string, value: string): void {
  console.log("::set-env name=${name}::${value}");
}
// Create GitHub Actions step summary
function addStepSummary(markdown: string): void {
  let summaryFile: string = env.get("GITHUB_STEP_SUMMARY") || "";
  if (summaryFile != "") {
    let currentContent: string = "";
    if (fs.exists(summaryFile)) {
      currentContent = fs.readFile(summaryFile);
    }
    fs.writeFile(summaryFile, currentContent + markdown + "\n");
  }
}
// Install dependencies for CI
function installCIDependencies(): void {
  console.log("Installing CI dependencies...");
  // Install Utah CLI if not present
  if (!os.isInstalled("utah")) {
    console.log("Installing Utah CLI...");
    `$(curl -L https://github.com/polatengin/utah/releases/latest/download/utah-linux-amd64 -o /usr/local/bin/utah)`;
    `$(chmod +x /usr/local/bin/utah)`;
    console.log("✅ Utah CLI installed");
  }
  // Install other dependencies based on project type
  if (fs.exists("package.json")) {
    `$(npm ci)`;
    console.log("✅ NPM dependencies installed");
  }
}
// Run quality checks
function runQualityChecks(): boolean {
  console.log("Running quality checks...");
  let passed: boolean = true;
  let results: string[] = [];
  // Linting
  if (fs.exists("package.json")) {
    let exitCode: string = `$(npm run lint 2>&1; echo $?)`;
    if (string.endsWith(string.trim(exitCode), "0")) {
      console.log("✅ Linting passed");
      results[array.length(results)] = "✅ Linting: Passed";
    } else {
      console.log("❌ Linting failed");
      results[array.length(results)] = "❌ Linting: Failed";
      passed = false;
    }
  }
  // Security scan
  if (fs.exists("package.json")) {
    let auditResult: string = `$(npm audit --audit-level high 2>&1; echo $?)`;
    if (string.endsWith(string.trim(auditResult), "0")) {
      console.log("✅ Security audit passed");
      results[array.length(results)] = "✅ Security Audit: Passed";
    } else {
      console.log("⚠️  Security vulnerabilities found");
      results[array.length(results)] = "⚠️ Security Audit: Issues found";
    }
  }
  // Generate summary
  let summary: string = "## Quality Check Results\n\n${results.join("\n")}\n";
  addStepSummary(summary);
  return passed;
}
// Build and test
function buildAndTest(): boolean {
  console.log("Building and testing...");
  // Compile Utah scripts
  let utahFiles: string[] = `$(find . -name "*.shx" -not -path "./node_modules/*")`.split("\n");
  for (let utahFile: string in utahFiles) {
    if (string.trim(utahFile) != "") {
      console.log("Compiling ${utahFile}...");
      let compileResult: string = "$(utah compile ${utahFile} 2>&1; echo $?)";
      if (!string.endsWith(string.trim(compileResult), "0")) {
        console.log("❌ Failed to compile ${utahFile}");
        return false;
      }
      console.log("✅ Compiled ${utahFile}");
    }
  }
  // Run tests
  if (fs.exists("package.json")) {
    let testResult: string = `$(npm test 2>&1; echo $?)`;
    if (!string.endsWith(string.trim(testResult), "0")) {
      console.log("❌ Tests failed");
      return false;
    }
    console.log("✅ All tests passed");
  }
  return true;
}
// Create release artifacts
function createReleaseArtifacts(): void {
  if (environment != "production") {
    console.log("Skipping artifact creation for non-production environment");
    return;
  }
  console.log("Creating release artifacts...");
  let artifactsDir: string = "release-artifacts";
  fs.createDirectory(artifactsDir);
  // Package Utah scripts
  let utahFiles: string[] = `$(find . -name "*.shx" -not -path "./node_modules/*")`.split("\n");
  let compiledScripts: string[] = [];
  for (let utahFile: string in utahFiles) {
    if (string.trim(utahFile) != "") {
      let compiledFile: string = string.replace(utahFile, ".shx", ".sh");
      if (fs.exists(compiledFile)) {
        compiledScripts[array.length(compiledScripts)] = compiledFile;
      }
    }
  }
  // Create release package
  if (array.length(compiledScripts) > 0) {
    let releasePackage: string = "${artifactsDir}/utah-scripts-${string.substring(githubSha, 0, 8)}.tar.gz";
    let tarCmd: string = "tar -czf ${releasePackage}";
    for (let script: string in compiledScripts) {
      tarCmd += " ${script}";
    }
    "$(${tarCmd})";
    console.log("✅ Release package created: ${releasePackage}");
    setOutput("release-package", releasePackage);
  }
  // Create deployment manifest
  let deploymentManifest: object = {
    "version": string.substring(githubSha, 0, 8),
    "environment": environment,
    "timestamp": `$(date -Iseconds)`,
    "branch": githubRef,
    "actor": githubActor,
    "scripts": compiledScripts
  };
  let manifestFile: string = "${artifactsDir}/deployment-manifest.json";
  fs.writeFile(manifestFile, json.stringify(deploymentManifest));
  console.log("✅ Deployment manifest created: ${manifestFile}");
  setOutput("deployment-manifest", manifestFile);
}
// Main CI/CD workflow
function runCICD(): void {
  let success: boolean = true;
  try {
    installCIDependencies();
    let qualityPassed: boolean = runQualityChecks();
    let buildPassed: boolean = buildAndTest();
    if (!qualityPassed || !buildPassed) {
      success = false;
    } else {
      createReleaseArtifacts();
    }
    // Set outputs for subsequent steps
    setOutput("environment", environment);
    setOutput("success", success + "");
    setOutput("version", string.substring(githubSha, 0, 8));
    // Generate final summary
    let status: string = success ? "✅ SUCCESS" : "❌ FAILED";
    let summary: string = "## CI/CD Pipeline Result: ${status}\n\n";
    summary += "- **Environment**: ${environment}\n";
    summary += "- **Version**: ${string.substring(githubSha, 0, 8)}\n";
    summary += "- **Quality Checks**: ${qualityPassed ? "✅ Passed" : "❌ Failed"}\n";
    summary += "- **Build & Test**: ${buildPassed ? "✅ Passed" : "❌ Failed"}\n";
    addStepSummary(summary);
    if (!success) {
      exit(1);
    }
  } catch {
    console.log("❌ Pipeline failed with errors");
    setOutput("success", "false");
    exit(1);
  }
}
runCICD();
console.log("🎉 CI/CD pipeline completed successfully");
Jenkins Integration
Jenkins Pipeline Script
script.description("Jenkins pipeline integration for Utah projects");
// Jenkins environment variables
let buildNumber: string = env.get("BUILD_NUMBER") || "unknown";
let jobName: string = env.get("JOB_NAME") || "unknown";
let workspace: string = env.get("WORKSPACE") || ".";
let gitBranch: string = env.get("GIT_BRANCH") || "unknown";
let gitCommit: string = env.get("GIT_COMMIT") || "unknown";
console.log("Jenkins Build: ${jobName} #${buildNumber}");
console.log("Branch: ${gitBranch}");
console.log("Commit: ${gitCommit}");
console.log("Workspace: ${workspace}");
// Stage: Checkout and Setup
function setupStage(): void {
  console.log("=== SETUP STAGE ===");
  // Change to workspace directory
  "$(cd ${workspace})";
  // Clean previous artifacts
  if (fs.exists("artifacts")) {
    `$(rm -rf artifacts)`;
  }
  fs.createDirectory("artifacts");
  // Validate workspace
  if (!fs.exists(".git")) {
    console.log("❌ Not a git repository");
    exit(1);
  }
  console.log("✅ Setup completed");
}
// Stage: Build
function buildStage(): void {
  console.log("=== BUILD STAGE ===");
  // Install dependencies
  if (fs.exists("package.json")) {
    `$(npm install)`;
    console.log("✅ NPM dependencies installed");
  }
  // Compile Utah scripts
  let utahFiles: string[] = `$(find . -name "*.shx" -not -path "./node_modules/*")`.split("\n");
  let compilationResults: object[] = [];
  for (let utahFile: string in utahFiles) {
    if (string.trim(utahFile) != "") {
      console.log("Compiling ${utahFile}...");
      let startTime: number = parseInt(`$(date +%s)`);
      let compileResult: string = "$(utah compile ${utahFile} 2>&1; echo "EXIT_CODE:$?")";
      let endTime: number = parseInt(`$(date +%s)`);
      let resultParts: string[] = string.split(compileResult, "EXIT_CODE:");
      let exitCode: string = "1";
      let output: string = compileResult;
      if (array.length(resultParts) > 1) {
        exitCode = string.trim(resultParts[1]);
        output = resultParts[0];
      }
      let duration: number = endTime - startTime;
      let result: object = {
        "file": utahFile,
        "success": exitCode == "0",
        "duration": duration,
        "output": output
      };
      compilationResults[array.length(compilationResults)] = result;
      if (exitCode == "0") {
        console.log("✅ Compiled ${utahFile} (${duration}s)");
      } else {
        console.log("❌ Failed to compile ${utahFile}");
        console.log(compileResult);
      }
    }
  }
  // Generate compilation report
  let reportFile: string = "artifacts/compilation-report.json";
  fs.writeFile(reportFile, json.stringify(compilationResults));
  // Check if any compilation failed
  let failedCount: number = 0;
  for (let result: object in compilationResults) {
    let successValue: string = json.get(result, ".success");
    if (successValue != "true") {
      failedCount++;
    }
  }
  if (failedCount > 0) {
    console.log("❌ ${failedCount} compilation(s) failed");
    exit(1);
  }
  console.log("✅ Build stage completed");
}
// Stage: Test
function testStage(): void {
  console.log("=== TEST STAGE ===");
  // Run unit tests
  if (fs.exists("package.json")) {
    let packageContent: string = fs.readFile("package.json");
    let packageData: object = json.parse(packageContent);
    if (json.has(packageData, ".scripts.test")) {
      console.log("Running JavaScript tests...");
      `$(npm test)`;
      console.log("✅ JavaScript tests passed");
    }
  }
  // Run Utah script tests
  let testFiles: string[] = `$(find . -name "*.test.shx" -not -path "./node_modules/*")`.split("\n");
  for (let testFile: string in testFiles) {
    if (string.trim(testFile) != "") {
      console.log("Running ${testFile}...");
      "$(utah ${testFile})";
      console.log("✅ ${testFile} passed");
    }
  }
  console.log("✅ Test stage completed");
}
// Stage: Package
function packageStage(): void {
  console.log("=== PACKAGE STAGE ===");
  // Create distribution package
  let distDir: string = "artifacts/dist";
  fs.createDirectory(distDir);
  // Copy compiled scripts
  let compiledFiles: string[] = `$(find . -name "*.sh" -not -path "./node_modules/*" -not -path "./artifacts/*")`.split("\n");
  for (let file: string in compiledFiles) {
    if (string.trim(file) != "") {
      let filename: string = `$(basename "${file}")`;
      let destFile: string = "${distDir}/${filename}";
      fs.copy(file, destFile);
      console.log("📦 Packaged ${file} → ${destFile}");
    }
  }
  // Create version info
  let versionInfo: object = {
    "build_number": buildNumber,
    "job_name": jobName,
    "git_branch": gitBranch,
    "git_commit": gitCommit,
    "build_timestamp": `$(date -Iseconds)`,
    "built_by": "Jenkins"
  };
  fs.writeFile("${distDir}/version.json", json.stringify(versionInfo));
  // Create tarball
  let packageName: string = "utah-scripts-${buildNumber}.tar.gz";
  let packagePath: string = "artifacts/${packageName}";
  "$(cd artifacts && tar -czf ${packageName} dist/)";
  if (fs.exists(packagePath)) {
    let packageSize: string = "$(du -h ${packagePath} | cut -f1)";
    console.log("✅ Package created: ${packagePath} (${packageSize})");
  } else {
    console.log("❌ Package creation failed");
    exit(1);
  }
  console.log("✅ Package stage completed");
}
// Stage: Archive
function archiveStage(): void {
  console.log("=== ARCHIVE STAGE ===");
  // Archive artifacts for Jenkins
  let archivePattern: string = "artifacts/**/*";
  console.log("Archiving artifacts: ${archivePattern}");
  // Generate build summary
  let summary: object = {
    "build_info": {
      "number": buildNumber,
      "job": jobName,
      "branch": gitBranch,
      "commit": gitCommit,
      "timestamp": `$(date -Iseconds)`
    },
    "artifacts": {
      "compilation_report": "artifacts/compilation-report.json",
      "distribution": "artifacts/dist/",
      "package": "artifacts/utah-scripts-${buildNumber}.tar.gz"
    },
    "status": "success"
  };
  fs.writeFile("artifacts/build-summary.json", json.stringify(summary));
  console.log("✅ Archive stage completed");
}
// Stage: Deploy (conditional)
function deployStage(): void {
  console.log("=== DEPLOY STAGE ===");
  // Only deploy from main/master branch
  if (gitBranch != "origin/main" && gitBranch != "origin/master") {
    console.log("⏭️  Skipping deploy for branch: ${gitBranch}");
    return;
  }
  console.log("Deploying to staging environment...");
  // Extract package for deployment
  let packagePath: string = "artifacts/utah-scripts-${buildNumber}.tar.gz";
  let deployDir: string = "deploy";
  fs.createDirectory(deployDir);
  "$(cd deploy && tar -xzf ../${packagePath})";
  // Deploy scripts (example - copy to deployment location)
  let deploymentPath: string = "/opt/utah-scripts";
  if (fs.exists(deploymentPath)) {
    // Backup current deployment
    let backupPath: string = "${deploymentPath}.backup.${buildNumber}";
    "$(cp -r ${deploymentPath} ${backupPath})";
    console.log("📁 Current deployment backed up to ${backupPath}");
  }
  // Deploy new version
  "$(cp -r deploy/dist/* ${deploymentPath}/ 2>/dev/null || echo "Deploy path not accessible")";
  console.log("✅ Deploy stage completed");
}
// Main pipeline execution
function runPipeline(): void {
  try {
    setupStage();
    buildStage();
    testStage();
    packageStage();
    archiveStage();
    deployStage();
    console.log("🎉 Pipeline completed successfully: ${jobName} #${buildNumber}");
  } catch {
    console.log("❌ Pipeline failed");
    // Generate failure report
    let failureReport: object = {
      "build_number": buildNumber,
      "job_name": jobName,
      "failure_timestamp": `$(date -Iseconds)`,
      "git_info": {
        "branch": gitBranch,
        "commit": gitCommit
      }
    };
    fs.createDirectory("artifacts");
    fs.writeFile("artifacts/failure-report.json", json.stringify(failureReport));
    exit(1);
  }
}
runPipeline();
Container Registry Integration
Docker Registry Management
script.description("Manage Docker registry operations for CI/CD");
args.define("--registry", "-r", "Docker registry URL", "string", false, "docker.io");
args.define("--repository", "-p", "Repository name", "string", true);
args.define("--tag", "-t", "Image tag", "string", true);
args.define("--action", "-a", "Action (build|push|pull|scan)", "string", true);
let registry: string = args.get("--registry");
let repository: string = args.get("--repository");
let tag: string = args.get("--tag");
let action: string = args.get("--action");
let fullImageName: string = "${registry}/${repository}:${tag}";
console.log("Docker Registry Operation: ${action}");
console.log("Image: ${fullImageName}");
// Build Docker image
function buildImage(): void {
  console.log("Building Docker image...");
  if (!fs.exists("Dockerfile")) {
    console.log("❌ Dockerfile not found");
    exit(1);
  }
  // Build image
  "$(docker build -t ${fullImageName} .)";
  // Verify image was built
  let imageExists: string = "$(docker images -q ${fullImageName})";
  if (string.trim(imageExists) != "") {
    console.log("✅ Image built successfully: ${fullImageName}");
    // Get image size
    let imageSize: string = "$(docker images ${fullImageName} --format "table {{.Size}}" | tail -1)";
    console.log("Image size: ${imageSize}");
  } else {
    console.log("❌ Failed to build image: ${fullImageName}");
    exit(1);
  }
}
// Push image to registry
function pushImage(): void {
  console.log("Pushing image to registry...");
  // Login to registry (assumes credentials are configured)
  if (registry != "docker.io") {
    "$(docker login ${registry})";
  }
  // Push image
  "$(docker push ${fullImageName})";
  // Verify push
  let pushResult: string = "$(docker manifest inspect ${fullImageName} >/dev/null 2>&1 && echo "success" || echo "failed")";
  if (string.trim(pushResult) == "success") {
    console.log("✅ Image pushed successfully: ${fullImageName}");
  } else {
    console.log("❌ Failed to push image: ${fullImageName}");
    exit(1);
  }
}
// Pull image from registry
function pullImage(): void {
  console.log("Pulling image from registry...");
  "$(docker pull ${fullImageName})";
  // Verify pull
  let imageExists: string = "$(docker images -q ${fullImageName})";
  if (string.trim(imageExists) != "") {
    console.log("✅ Image pulled successfully: ${fullImageName}");
  } else {
    console.log("❌ Failed to pull image: ${fullImageName}");
    exit(1);
  }
}
// Scan image for vulnerabilities
function scanImage(): void {
  console.log("Scanning image for vulnerabilities...");
  // Check if scanning tool is available
  if (os.isInstalled("trivy")) {
    console.log("Using Trivy for vulnerability scanning...");
    "$(trivy image ${fullImageName})";
  } else if (os.isInstalled("docker-scan")) {
    console.log("Using Docker scan for vulnerability scanning...");
    "$(docker scan ${fullImageName})";
  } else {
    console.log("⚠️  No vulnerability scanner available");
    console.log("Consider installing Trivy or enabling Docker scan");
  }
}
// Execute action
let validActions: string[] = ["build", "push", "pull", "scan"];
if (!array.contains(validActions, action)) {
  console.log("❌ Invalid action: ${action}");
  console.log("Valid actions: ${array.join(validActions, ", ")}");
  exit(1);
}
if (action == "build") {
  buildImage();
} else if (action == "push") {
  pushImage();
} else if (action == "pull") {
  pullImage();
} else if (action == "scan") {
  scanImage();
}
Best Practices
Pipeline Error Handling
// Robust error handling for CI/CD pipelines
function runWithRetry(command: string, maxRetries: number = 3): boolean {
  for (let attempt: number = 1; attempt <= maxRetries; attempt++) {
    console.log("Attempt ${attempt}/${maxRetries}: ${command}");
    let result: string = "$(${command} 2>&1; echo "EXIT_CODE:$?")";
    let resultParts: string[] = string.split(result, "EXIT_CODE:");
    let exitCode: string = "1";
    if (array.length(resultParts) > 1) {
      exitCode = string.trim(resultParts[1]);
    }
    if (exitCode == "0") {
      console.log("✅ Command succeeded on attempt ${attempt}");
      return true;
    } else {
      console.log("❌ Command failed on attempt ${attempt}");
      if (attempt < maxRetries) {
        console.log("Retrying in 10 seconds...");
        `$(sleep 10)`;
      }
    }
  }
  console.log("❌ Command failed after ${maxRetries} attempts");
  return false;
}
// Environment validation
function validateCIEnvironment(): boolean {
  let requiredVars: string[] = ["CI", "BUILD_NUMBER", "GIT_COMMIT"];
  for (let varName: string in requiredVars) {
    let value: string = env.get(varName) || "";
    if (value == "") {
      console.log("❌ Required environment variable missing: ${varName}");
      return false;
    }
  }
  return true;
}
Performance Optimization
// Cache management for faster builds
function manageBuildCache(): void {
  let cacheDir: string = ".utah-cache";
  fs.createDirectory(cacheDir);
  // Cache compiled scripts
  let sourceFiles: string[] = "$(find . -name "*.shx" -newer ${cacheDir}/last-build 2>/dev/null || find . -name "*.shx")".split("\n");
  if (array.length(sourceFiles) == 1 && string.trim(sourceFiles[0]) == "") {
    console.log("✅ No sources changed, using cache");
    return;
  }
  console.log("Building ${array.length(sourceFiles)} changed files...");
  // Update cache timestamp
  "$(touch ${cacheDir}/last-build)";
}
Next Steps
- Docker Integration - Containerize Utah applications
 - Cloud Automation - Deploy to cloud platforms
 - Performance Optimization - Optimize CI/CD pipelines
 
CI/CD integration with Utah enables powerful automation workflows while maintaining flexibility and reliability across different platforms and environments.