Files
spicy-automation/resources/README.md
Ryan Wilson 68684df471 Initial commit: Spicy CDK automation framework
Jenkins shared library and CDK constructs for AWS infrastructure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-11-18 22:21:00 -08:00

280 lines
9.9 KiB
Markdown

# Spicy Automation
AWS CDK infrastructure and Jenkins shared library for Spicy automation. This replaces the legacy Ansible/CloudFormation approach with type-safe TypeScript and integrated Jenkins pipelines.
## Quick Start
### Minimal VPC Deployment
Create a `Jenkinsfile` in your VPC repository:
```groovy
@Library(["spicy-automation@main"]) _
spicyVPC(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-vpc",
ownerTag: "MyTeam",
productTag: "myproduct",
componentTag: "vpc",
)
```
### Minimal ECS Cluster Deployment - Using CloudFormation Imports
**Minimal props:** Only `vpcStackName` and `numberOfAzs` required. VPC info auto-imports from VPC stack exports.
```groovy
@Library(["spicy-automation@main"]) _
spicyECSCluster(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-ecs-cluster",
vpcStackName: "my-vpc", // Auto-imports VPC ID, CIDR, subnets, and AZs
numberOfAzs: 3,
ownerTag: "MyTeam",
productTag: "myproduct",
componentTag: "ecs-cluster",
environment: "dev"
)
```
**Explicit IDs (backward compatible):**
```groovy
spicyECSCluster(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-ecs-cluster",
vpcId: "vpc-12345678",
vpcCidrBlock: "10.0.0.0/16",
availabilityZones: "ca-central-1a,ca-central-1b,ca-central-1c",
privateSubnetIds: "subnet-aaa,subnet-bbb,subnet-ccc",
ownerTag: "MyTeam",
productTag: "myproduct",
componentTag: "ecs-cluster",
environment: "dev"
)
```
### ECS Service with Mixed Capacity (EC2 + Fargate Burst) - Minimal Props
**Minimal props:** Only `clusterName` required. VPC info auto-imports from CloudFormation exports.
```groovy
@Library(["spicy-automation@main"]) _
spicyECSService(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-api-dev",
serviceName: "my-api",
clusterName: "my-ecs-cluster", // VPC stack name and VPC ID auto-import from cluster stack exports
image: "nexus.kodeniks.com/docker-hosted/my-api:latest",
containerPort: 3000,
capacityProviderStrategy: [
[capacityProvider: "my-ecs-cluster-ec2", base: 2, weight: 3],
[capacityProvider: "FARGATE_SPOT", weight: 1],
],
ownerTag: "MyTeam",
productTag: "myproduct",
componentTag: "api",
environment: "dev"
)
```
**Explicit IDs (backward compatible):**
```groovy
spicyECSService(
// ... other params ...
clusterName: "my-ecs-cluster",
vpcId: "vpc-12345678",
vpcCidrBlock: "10.0.0.0/16",
availabilityZones: "ca-central-1a,ca-central-1b,ca-central-1c",
privateSubnetIds: "subnet-aaa,subnet-bbb,subnet-ccc",
)
```
### Blue/Green Deployment with Instant Rollback
```groovy
@Library(["spicy-automation@main"]) _
spicyECSService(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-api-prod",
serviceName: "my-api",
clusterName: "my-ecs-cluster-prod",
vpcId: "vpc-12345678",
vpcCidrBlock: "10.0.0.0/16",
availabilityZones: "ca-central-1a,ca-central-1b",
privateSubnetIds: "subnet-aaa,subnet-bbb",
image: "nexus.kodeniks.com/docker-hosted/my-api:latest",
containerPort: 3000,
// Enable Blue/Green
blueGreen: true,
activeHostname: "api.example.com",
inactiveHostname: "inactive-api.example.com",
// ALB routing - listener ARN auto-imports from ${clusterName}-internet-facing-https-listener
priority: 100,
useExternalALB: true,
// externalListenerArn auto-imports when useExternalALB=true
// Test before swap
blueGreenTest: { args, buildInfo ->
sh "curl -f https://${buildInfo.inactiveHostname}/health"
},
// Test after swap
smokeTest: { args, buildInfo ->
sh "curl -f https://${buildInfo.activeHostname}/health"
},
ownerTag: "Platform",
productTag: "myproduct",
componentTag: "api",
environment: "prod"
)
```
### Instant Rollback (30 seconds)
```groovy
@Library(["spicy-automation@main"]) _
spicyRollback(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-api-prod",
serviceName: "my-api",
// ... same params as deploy ...
)
```
## Documentation
| Document | Description |
| ------------------------------------------------------ | ---------------------------------------------- |
| [VPC Guide](docs/VPC.md) | Complete VPC deployment guide with all options |
| [ECS Cluster Guide](docs/ECS_CLUSTER.md) | ECS cluster with Spot, Capacity Providers |
| [ECS Service Guide](docs/ECS_SERVICE.md) | ECS service with mixed EC2/Fargate strategy |
| [Persistent ALB](docs/PERSISTENT_ALB.md) | Persistent ALB pattern (1:1 with service) |
| [Cost Optimization](docs/COST_OPTIMIZATION_TESTING.md) | Cost optimization for testing environments |
| [CDK Synth Examples](docs/CDK_SYNTH_EXAMPLES.md) | Complete CDK synth command examples |
| [Jenkins Utilities](docs/JENKINS_UTILITIES.md) | All available Jenkins utility functions |
| [Accounts Configuration](docs/ACCOUNTS.md) | Multi-account setup guide |
| [Local Development](docs/DEVELOPMENT.md) | Running CDK locally |
| [NPM Example](docs/JENKINSFILE_EXAMPLE_NPM.md) | Example Jenkinsfile for NPM publishing |
## Features
### Infrastructure (CDK)
- **SpicyVpc**: Multi-AZ VPC with public/private subnets, NAT gateways, NACLs, VPC endpoints
- **SpicyEcsCluster**: ECS cluster with EC2 Capacity Providers, Mixed Instances Policy for Spot, ALBs
- **SpicyEcsService**: ECS service with mixed capacity strategy, auto-scaling, circuit breaker
### Blue/Green Deployments
- **Zero-downtime releases** with hostname-based routing
- **Instant rollback** (~30 seconds) via hostname swap
- **Test before swap** with `blueGreenTest` hook
- **Rollback window** - old version kept for 2+ hours
### Pipeline Hooks
- **buildCommand**: Custom build logic
- **onPostBuild**: Unit tests, linting, coverage
- **onPreDeploy**: Setup, test preparation
- **blueGreenTest**: Integration tests on inactive stack
- **onPostDeploy**: Cleanup, notifications
- **smokeTest**: Post-deployment verification
### Jenkins Pipelines
- **spicyVPC**: Deploy VPCs
- **spicyECSCluster**: Deploy ECS clusters with Spot support
- **spicyECSService**: Deploy ECS services with EC2 + Fargate burst, blue/green
- **spicyRollback**: Instant rollback for blue/green deployments
- **buildAndPushDockerImage**: Build and push Docker images to Nexus
## Jenkins Setup
### 1. Configure Global Library
In Jenkins → **Manage Jenkins****Configure System****Global Pipeline Libraries**:
| Setting | Value |
| ------------------ | ------------------------------------------------ |
| Name | `spicy-automation` |
| Default version | `main` |
| Retrieval method | Modern SCM → Git |
| Project Repository | `git@git.kodeniks.com:CORP/spicy-automation.git` |
| Library Path | `jenkins/` |
### 2. Configure Credentials
| Credential ID | Type | Description |
| --------------------------- | ----------------- | --------------------------------- |
| `aws-credentials` | Username/Password | AWS Access Key ID / Secret |
| `kodeniks-gitea-token` | Secret text | Gitea personal access token |
| `kodeniks-nexus-repository` | Username/Password | Nexus Docker registry credentials |
## Project Structure
```
spicy-automation/
├── bin/spicy-cdk.ts # CDK app entry point
├── lib/
│ ├── constructs/ # Reusable CDK constructs
│ │ ├── spicy-vpc.ts # VPC construct
│ │ ├── spicy-ecs-cluster.ts # ECS cluster construct
│ │ └── spicy-ecs-service.ts # ECS service construct
│ └── stacks/ # CDK stacks
│ ├── spicy-vpc-stack.ts
│ ├── spicy-ecs-cluster-stack.ts
│ └── spicy-ecs-service-stack.ts
├── vars/ # Jenkins shared library
│ ├── spicyVPC.groovy # VPC pipeline
│ ├── spicyECSCluster.groovy # ECS cluster pipeline
│ ├── spicyECSService.groovy # ECS service pipeline
│ ├── buildAndPushDockerImage.groovy # Docker build pipeline
│ ├── cdkUtils.groovy # CDK commands
│ ├── dockerUtils.groovy # Docker/Nexus utilities
│ ├── gitUtils.groovy # Git utilities
│ ├── giteaUtils.groovy # Commit status updates
│ └── accounts.groovy # Account configurations
├── docs/ # Documentation
├── test/ # Jest tests
└── Dockerfile # Jenkins agent image
```
## Useful Commands
```bash
# No build step required - runs directly with ts-node!
npx cdk synth -c stackType=vpc -c stackName=my-vpc ...
# Or use pnpm scripts
pnpm run test # Run Jest tests
pnpm run build # Compile TypeScript (optional)
```
## Migration from spicy-automation-legacy
| Feature | spicy-automation-legacy | spicy-automation |
| --------------- | ----------------------- | ---------------- |
| Infrastructure | CloudFormation YAML | TypeScript CDK |
| Provisioning | Ansible | CDK CLI |
| Testing | None | Jest |
| Type Safety | None | Full TypeScript |
| Docker Registry | AWS ECR | Nexus |
CloudFormation outputs are identical, so existing stacks referencing VPC exports continue to work.