🐘 🔧 DevOps Automation with TuskLang & PHP
🔧 DevOps Automation with TuskLang & PHP
Introduction
DevOps automation is the key to rapid, reliable software delivery. TuskLang and PHP let you build sophisticated automation pipelines with config-driven CI/CD, infrastructure as code, and monitoring that accelerates development and reduces risk.Key Features
- CI/CD pipeline automation - Infrastructure as code - Automated testing - Deployment automation - Monitoring automation - Configuration managementExample: DevOps Configuration
[devops]
ci_provider: github_actions
deployment_target: kubernetes
testing: @go("devops.RunTests")
deployment: @go("devops.Deploy")
monitoring: @go("devops.Monitor")
infrastructure: @go("devops.ManageInfrastructure")
PHP: CI/CD Pipeline Implementation
<?phpnamespace App\DevOps;
use TuskLang\Config;
use TuskLang\Operators\Env;
use TuskLang\Operators\Metrics;
use TuskLang\Operators\Go;
class CICDPipeline
{
private $config;
private $github;
private $docker;
private $kubernetes;
public function __construct()
{
$this->config = new Config();
$this->github = new GitHubClient();
$this->docker = new DockerClient();
$this->kubernetes = new KubernetesClient();
}
public function runPipeline($event)
{
try {
// Parse event
$branch = $event['ref'] ?? 'main';
$commit = $event['after'] ?? '';
// Run tests
$testResults = $this->runTests($branch, $commit);
if (!$testResults['success']) {
$this->failPipeline('Tests failed');
return false;
}
// Build image
$imageTag = $this->buildImage($branch, $commit);
// Deploy to staging
if ($branch === 'develop') {
$this->deployToStaging($imageTag);
}
// Deploy to production
if ($branch === 'main') {
$this->deployToProduction($imageTag);
}
// Record metrics
Metrics::record("pipeline_success", 1, [
"branch" => $branch,
"commit" => $commit
]);
return true;
} catch (\Exception $e) {
$this->failPipeline($e->getMessage());
Metrics::record("pipeline_failure", 1, [
"branch" => $branch ?? 'unknown',
"error" => get_class($e)
]);
return false;
}
}
private function runTests($branch, $commit)
{
$testConfig = $this->config->get("devops.testing", []);
$results = [
'unit' => $this->runUnitTests(),
'integration' => $this->runIntegrationTests(),
'e2e' => $this->runE2ETests()
];
$success = true;
foreach ($results as $type => $result) {
if (!$result['success']) {
$success = false;
$this->reportTestFailure($type, $result);
}
}
return [
'success' => $success,
'results' => $results
];
}
private function runUnitTests()
{
$command = $this->config->get("devops.testing.unit.command", "vendor/bin/phpunit");
$args = $this->config->get("devops.testing.unit.args", []);
$process = new Process(array_merge([$command], $args));
$process->run();
return [
'success' => $process->isSuccessful(),
'output' => $process->getOutput(),
'error' => $process->getErrorOutput()
];
}
private function runIntegrationTests()
{
$command = $this->config->get("devops.testing.integration.command", "vendor/bin/phpunit");
$args = $this->config->get("devops.testing.integration.args", ["--testsuite=integration"]);
$process = new Process(array_merge([$command], $args));
$process->run();
return [
'success' => $process->isSuccessful(),
'output' => $process->getOutput(),
'error' => $process->getErrorOutput()
];
}
private function runE2ETests()
{
$command = $this->config->get("devops.testing.e2e.command", "vendor/bin/behat");
$args = $this->config->get("devops.testing.e2e.args", []);
$process = new Process(array_merge([$command], $args));
$process->run();
return [
'success' => $process->isSuccessful(),
'output' => $process->getOutput(),
'error' => $process->getErrorOutput()
];
}
private function buildImage($branch, $commit)
{
$imageName = $this->config->get("devops.docker.image_name", "myapp");
$imageTag = "{$imageName}:{$branch}-{$commit}";
$buildConfig = [
'context' => '.',
'dockerfile' => 'Dockerfile',
'tags' => [$imageTag],
'buildargs' => [
'APP_ENV' => $branch === 'main' ? 'production' : 'staging',
'GIT_COMMIT' => $commit
]
];
$this->docker->build($buildConfig);
// Push to registry
$registry = $this->config->get("devops.docker.registry");
if ($registry) {
$this->docker->push($imageTag);
}
return $imageTag;
}
private function deployToStaging($imageTag)
{
$namespace = $this->config->get("devops.kubernetes.staging_namespace", "staging");
$deployment = $this->createDeployment('staging', $imageTag, [
'replicas' => 2,
'namespace' => $namespace
]);
$this->kubernetes->applyDeployment($deployment);
// Run smoke tests
$this->runSmokeTests('staging');
}
private function deployToProduction($imageTag)
{
$namespace = $this->config->get("devops.kubernetes.production_namespace", "production");
// Blue-green deployment
$currentDeployment = $this->getCurrentDeployment('production');
$newDeployment = $this->createDeployment('production-new', $imageTag, [
'replicas' => 3,
'namespace' => $namespace
]);
// Deploy new version
$this->kubernetes->applyDeployment($newDeployment);
// Wait for new deployment to be ready
$this->waitForDeployment('production-new', $namespace);
// Run health checks
if (!$this->runHealthChecks('production-new')) {
$this->rollbackDeployment('production', $currentDeployment);
throw new \Exception('Health checks failed');
}
// Switch traffic to new deployment
$this->switchTraffic('production-new');
// Remove old deployment
if ($currentDeployment) {
$this->kubernetes->deleteDeployment($currentDeployment);
}
}
private function createDeployment($name, $imageTag, $config = [])
{
return [
'apiVersion' => 'apps/v1',
'kind' => 'Deployment',
'metadata' => [
'name' => $name,
'namespace' => $config['namespace'] ?? 'default'
],
'spec' => [
'replicas' => $config['replicas'] ?? 1,
'selector' => [
'matchLabels' => [
'app' => $name
]
],
'template' => [
'metadata' => [
'labels' => [
'app' => $name
]
],
'spec' => [
'containers' => [
[
'name' => $name,
'image' => $imageTag,
'ports' => [
['containerPort' => 9000]
],
'env' => $this->getDeploymentEnvironment($config['namespace']),
'resources' => $this->getResourceRequirements($config['namespace'])
]
]
]
]
]
];
}
private function getDeploymentEnvironment($namespace)
{
$env = [];
// Add environment-specific variables
$envVars = $this->config->get("devops.environment.{$namespace}", []);
foreach ($envVars as $key => $value) {
$env[] = [
'name' => $key,
'value' => $value
];
}
return $env;
}
private function getResourceRequirements($namespace)
{
return $this->config->get("devops.resources.{$namespace}", [
'requests' => [
'memory' => '128Mi',
'cpu' => '100m'
],
'limits' => [
'memory' => '512Mi',
'cpu' => '500m'
]
]);
}
}
Infrastructure as Code
<?phpnamespace App\DevOps\Infrastructure;
use TuskLang\Config;
class InfrastructureManager
{
private $config;
private $terraform;
private $ansible;
public function __construct()
{
$this->config = new Config();
$this->terraform = new TerraformClient();
$this->ansible = new AnsibleClient();
}
public function provisionInfrastructure($environment)
{
$infraConfig = $this->config->get("devops.infrastructure.{$environment}", []);
// Generate Terraform configuration
$terraformConfig = $this->generateTerraformConfig($environment, $infraConfig);
// Apply Terraform
$this->terraform->init();
$this->terraform->plan($terraformConfig);
$this->terraform->apply($terraformConfig);
// Configure servers with Ansible
$this->configureServers($environment, $infraConfig);
return true;
}
private function generateTerraformConfig($environment, $config)
{
$tfConfig = [
'terraform' => [
'required_version' => '>= 1.0',
'required_providers' => [
'aws' => [
'source' => 'hashicorp/aws',
'version' => '~> 4.0'
],
'kubernetes' => [
'source' => 'hashicorp/kubernetes',
'version' => '~> 2.0'
]
]
],
'provider' => [
'aws' => [
'region' => $config['region'] ?? 'us-east-1'
]
],
'resource' => []
];
// Add VPC
if ($config['vpc'] ?? true) {
$tfConfig['resource']['aws_vpc'] = [
'main' => [
'cidr_block' => $config['vpc_cidr'] ?? '10.0.0.0/16',
'tags' => [
'Name' => "{$environment}-vpc",
'Environment' => $environment
]
]
];
}
// Add EKS cluster
if ($config['eks'] ?? false) {
$tfConfig['resource']['aws_eks_cluster'] = [
'main' => [
'name' => "{$environment}-cluster",
'role_arn' => $config['eks_role_arn'],
'vpc_config' => [
'subnet_ids' => $config['subnet_ids'] ?? []
]
]
];
}
// Add RDS instance
if ($config['rds'] ?? false) {
$tfConfig['resource']['aws_db_instance'] = [
'main' => [
'identifier' => "{$environment}-db",
'engine' => $config['db_engine'] ?? 'mysql',
'instance_class' => $config['db_instance_class'] ?? 'db.t3.micro',
'allocated_storage' => $config['db_storage'] ?? 20,
'username' => $config['db_username'] ?? 'admin',
'password' => $config['db_password'],
'skip_final_snapshot' => $environment !== 'production'
]
];
}
return $tfConfig;
}
private function configureServers($environment, $config)
{
$playbook = $this->generateAnsiblePlaybook($environment, $config);
$this->ansible->runPlaybook($playbook, [
'inventory' => $this->getInventory($environment),
'extra_vars' => $config['ansible_vars'] ?? []
]);
}
private function generateAnsiblePlaybook($environment, $config)
{
return [
'name' => "Configure {$environment} servers",
'hosts' => $environment,
'become' => true,
'tasks' => [
[
'name' => 'Update package cache',
'apt' => [
'update_cache' => true
]
],
[
'name' => 'Install required packages',
'apt' => [
'name' => $config['packages'] ?? ['nginx', 'php-fpm', 'mysql-client'],
'state' => 'present'
]
],
[
'name' => 'Configure PHP',
'template' => [
'src' => 'php.ini.j2',
'dest' => '/etc/php/8.2/fpm/php.ini'
]
],
[
'name' => 'Configure Nginx',
'template' => [
'src' => 'nginx.conf.j2',
'dest' => '/etc/nginx/sites-available/default'
]
],
[
'name' => 'Start and enable services',
'systemd' => [
'name' => '{{ item }}',
'state' => 'started',
'enabled' => true
],
'loop' => ['php8.2-fpm', 'nginx']
]
]
];
}
private function getInventory($environment)
{
$inventory = $this->config->get("devops.inventory.{$environment}", []);
return [
'all' => [
'hosts' => $inventory['hosts'] ?? [],
'vars' => $inventory['vars'] ?? []
]
];
}
}
Automated Testing
<?phpnamespace App\DevOps\Testing;
use TuskLang\Config;
class AutomatedTesting
{
private $config;
private $testRunner;
public function __construct()
{
$this->config = new Config();
$this->testRunner = new TestRunner();
}
public function runAllTests($environment = 'staging')
{
$testConfig = $this->config->get("devops.testing", []);
$results = [
'unit' => $this->runUnitTests(),
'integration' => $this->runIntegrationTests($environment),
'e2e' => $this->runE2ETests($environment),
'performance' => $this->runPerformanceTests($environment),
'security' => $this->runSecurityTests()
];
$this->generateTestReport($results);
return $results;
}
private function runUnitTests()
{
$config = $this->config->get("devops.testing.unit", []);
return $this->testRunner->run('phpunit', [
'command' => $config['command'] ?? 'vendor/bin/phpunit',
'args' => $config['args'] ?? [],
'coverage' => $config['coverage'] ?? true
]);
}
private function runIntegrationTests($environment)
{
$config = $this->config->get("devops.testing.integration", []);
// Set up test database
$this->setupTestDatabase($environment);
return $this->testRunner->run('phpunit', [
'command' => $config['command'] ?? 'vendor/bin/phpunit',
'args' => array_merge($config['args'] ?? [], ['--testsuite=integration']),
'env' => [
'APP_ENV' => 'testing',
'DB_DATABASE' => "test_{$environment}"
]
]);
}
private function runE2ETests($environment)
{
$config = $this->config->get("devops.testing.e2e", []);
return $this->testRunner->run('behat', [
'command' => $config['command'] ?? 'vendor/bin/behat',
'args' => $config['args'] ?? [],
'env' => [
'BASE_URL' => $this->getEnvironmentUrl($environment)
]
]);
}
private function runPerformanceTests($environment)
{
$config = $this->config->get("devops.testing.performance", []);
return $this->testRunner->run('artillery', [
'command' => $config['command'] ?? 'artillery',
'args' => array_merge($config['args'] ?? [], ['run', 'performance.yml']),
'env' => [
'TARGET_URL' => $this->getEnvironmentUrl($environment)
]
]);
}
private function runSecurityTests()
{
$config = $this->config->get("devops.testing.security", []);
return $this->testRunner->run('snyk', [
'command' => $config['command'] ?? 'snyk',
'args' => array_merge($config['args'] ?? [], ['test'])
]);
}
private function setupTestDatabase($environment)
{
$dbConfig = $this->config->get("devops.testing.database.{$environment}", []);
$pdo = new PDO(
$dbConfig['dsn'],
$dbConfig['username'],
$dbConfig['password']
);
// Create test database
$pdo->exec("CREATE DATABASE IF NOT EXISTS test_{$environment}");
$pdo->exec("USE test_{$environment}");
// Run migrations
$migrations = $this->config->get("devops.testing.migrations", []);
foreach ($migrations as $migration) {
$sql = file_get_contents($migration);
$pdo->exec($sql);
}
}
private function generateTestReport($results)
{
$report = [
'timestamp' => date('c'),
'summary' => [
'total' => count($results),
'passed' => 0,
'failed' => 0
],
'results' => $results
];
foreach ($results as $type => $result) {
if ($result['success']) {
$report['summary']['passed']++;
} else {
$report['summary']['failed']++;
}
}
// Save report
$reportPath = $this->config->get("devops.testing.report_path", "reports");
file_put_contents("{$reportPath}/test-report.json", json_encode($report, JSON_PRETTY_PRINT));
// Send notification if tests failed
if ($report['summary']['failed'] > 0) {
$this->sendTestFailureNotification($report);
}
}
private function getEnvironmentUrl($environment)
{
$urls = $this->config->get("devops.environments", []);
return $urls[$environment] ?? "https://{$environment}.example.com";
}
}