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>
This commit is contained in:
2025-11-18 22:21:00 -08:00
commit 68684df471
51 changed files with 15587 additions and 0 deletions

497
docs/JENKINS_UTILITIES.md Normal file
View File

@@ -0,0 +1,497 @@
# Jenkins Utilities Reference
All available utility functions in the `spicy-automation` Jenkins shared library.
## Table of Contents
- [cdkUtils](#cdkutils) - CDK command execution
- [dockerUtils](#dockerutils) - Docker/Nexus operations
- [gitUtils](#gitutils) - Git information
- [giteaUtils](#giteautils) - Gitea commit status
- [awsUtils](#awsutils) - AWS CLI operations
- [spicyUtils](#spicyutils) - Pipeline utilities
- [accounts](#accounts) - Account configurations
- [manualApproval](#manualapproval) - Approval gates
---
## cdkUtils
Execute AWS CDK commands from Jenkins pipelines.
### `cdkUtils.deploy(Map args)`
Deploy a CDK stack.
```groovy
cdkUtils.deploy(
account: [
region: "ca-central-1",
jenkinsAwsCredentialsId: "aws-credentials",
accountId: "123456789012" // optional
],
stackName: "my-stack",
stackType: "vpc", // vpc, ecs-cluster, ecs-service
context: [ // Additional CDK context
ownerTag: "MyTeam",
productTag: "myapp"
],
workDir: "." // optional, defaults to current dir
)
```
### `cdkUtils.diff(Map args)`
Show changes between deployed and local stack.
```groovy
cdkUtils.diff(
account: account,
stackName: "my-stack",
stackType: "vpc",
context: context
)
```
### `cdkUtils.synth(Map args)`
Synthesize CloudFormation template.
```groovy
cdkUtils.synth(
account: account,
stackName: "my-stack",
stackType: "vpc",
context: context
)
```
### `cdkUtils.destroy(Map args)`
Destroy a CDK stack.
```groovy
cdkUtils.destroy(
account: account,
stackName: "my-stack",
stackType: "vpc",
context: context
)
```
### `cdkUtils.install(Map args)`
Install CDK dependencies.
```groovy
cdkUtils.install(workDir: ".")
```
### `cdkUtils.build(Map args)`
Build CDK TypeScript (optional - ts-node runs directly).
```groovy
cdkUtils.build(workDir: ".")
```
### `cdkUtils.test(Map args)`
Run CDK tests.
```groovy
cdkUtils.test(workDir: ".")
```
---
## dockerUtils
Docker operations with Nexus registry support.
**Default Configuration:**
- Registry: `nexus.kodeniks.com`
- Repository: `docker-hosted`
- Credentials: `kodeniks-nexus-repository`
### `dockerUtils.buildAndPush(Map args)`
Build and push a Docker image to Nexus.
```groovy
def imageRef = dockerUtils.buildAndPush(
imageName: "my-service", // required
dockerfile: "Dockerfile", // default: Dockerfile
context: ".", // default: .
buildArgs: [ // optional
NODE_ENV: "production",
VERSION: "1.0.0"
],
tagLatest: true, // default: true on main branch
compareWithLatest: true, // default: true, skip if unchanged
registry: "nexus.kodeniks.com", // optional override
repository: "docker-hosted", // optional override
credentialsId: "kodeniks-nexus-repository" // optional override
)
echo "Pushed: ${imageRef}"
// Output: nexus.kodeniks.com/docker-hosted/my-service:abc1234
```
### `dockerUtils.buildImage(Map args)`
Build a Docker image without pushing.
```groovy
def containerName = dockerUtils.buildImage(
imageName: "my-service",
dockerfile: "Dockerfile",
context: ".",
buildArgs: [NODE_ENV: "production"]
)
```
### `dockerUtils.tagImage(Map args)`
Tag an image for Nexus registry.
```groovy
dockerUtils.tagImage(
imageName: "my-service",
tagLatest: true // also tag as 'latest'
)
```
### `dockerUtils.pushImage(Map args)`
Push image to Nexus with smart comparison.
```groovy
def pushed = dockerUtils.pushImage(
imageName: "my-service",
tagLatest: true,
compareWithLatest: true // skip if identical to remote latest
)
if (pushed) {
echo "Image was pushed"
} else {
echo "Image unchanged, push skipped"
}
```
### `dockerUtils.pullImage(Map args)`
Pull an image from Nexus.
```groovy
def imageRef = dockerUtils.pullImage(
imageName: "my-service",
tag: "latest" // default: latest
)
```
### `dockerUtils.login(Map args)`
Login to Nexus registry.
```groovy
dockerUtils.login()
// Or with custom registry:
dockerUtils.login(registry: "other-nexus.example.com")
```
### `dockerUtils.prune()`
Clean up dangling Docker images.
```groovy
dockerUtils.prune()
```
### `dockerUtils.copyFromImage(Map args)`
Copy files from a Docker image.
```groovy
dockerUtils.copyFromImage(
imageID: "my-image:latest",
dockerPath: "/app/dist",
jenkinsPath: "./dist"
)
```
### `dockerUtils.getImageRefSHA(Map args)`
Get full image reference with SHA tag.
```groovy
def ref = dockerUtils.getImageRefSHA(imageName: "my-service")
// Returns: nexus.kodeniks.com/docker-hosted/my-service:abc1234
```
### `dockerUtils.getImageRefLatest(Map args)`
Get full image reference with latest tag.
```groovy
def ref = dockerUtils.getImageRefLatest(imageName: "my-service")
// Returns: nexus.kodeniks.com/docker-hosted/my-service:latest
```
---
## gitUtils
Git repository information.
### `gitUtils.getSHA()`
Get full commit SHA.
```groovy
def sha = gitUtils.getSHA()
// Returns: abc123def456...
```
### `gitUtils.getShortSHA()`
Get short commit SHA (7 characters).
```groovy
def shortSha = gitUtils.getShortSHA()
// Returns: abc123d
```
### `gitUtils.getBranch()`
Get current branch name.
```groovy
def branch = gitUtils.getBranch()
// Returns: main, feature/xyz, etc.
```
### `gitUtils.isMain()`
Check if on main branch.
```groovy
if (gitUtils.isMain()) {
echo "On main branch - deploying!"
}
```
### `gitUtils.getRemoteURL()`
Get Git remote URL.
```groovy
def url = gitUtils.getRemoteURL()
// Returns: git@git.kodeniks.com:CORP/my-repo.git
```
---
## giteaUtils
Update Gitea commit status.
**Default Configuration:**
- Gitea URL: `https://git.kodeniks.com`
- Credentials: `kodeniks-gitea-token`
### `giteaUtils.setSuccess(context)`
Set commit status to success.
```groovy
giteaUtils.setSuccess("build")
giteaUtils.setSuccess("deploy")
```
### `giteaUtils.setPending(context)`
Set commit status to pending.
```groovy
giteaUtils.setPending("build")
```
### `giteaUtils.setFailed(context)`
Set commit status to failed.
```groovy
giteaUtils.setFailed("build")
```
### `giteaUtils.setError(context)`
Set commit status to error.
```groovy
giteaUtils.setError("build")
```
### `giteaUtils.updateStatus(Map args)`
Update commit status with full control.
```groovy
giteaUtils.updateStatus(
context: "build",
state: "success", // success, pending, failure, error
message: "Build passed",
giteaUrl: "https://git.kodeniks.com", // optional override
credentialsId: "kodeniks-gitea-token" // optional override
)
```
---
## awsUtils
AWS CLI operations.
### `awsUtils.assumeRole(Map args)`
Assume an IAM role.
```groovy
awsUtils.assumeRole(
roleArn: "arn:aws:iam::123456789012:role/MyRole",
sessionName: "jenkins-deploy"
)
```
### `awsUtils.getCallerIdentity(Map args)`
Get current AWS identity.
```groovy
def identity = awsUtils.getCallerIdentity(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1"
)
```
### `awsUtils.describeStacks(Map args)`
Describe CloudFormation stacks.
```groovy
def stacks = awsUtils.describeStacks(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-stack"
)
```
---
## spicyUtils
Pipeline utility functions.
### `spicyUtils.stageWithFailure(name, closure)`
Run a stage that sets Gitea status on failure.
```groovy
spicyUtils.stageWithFailure("Build") {
sh "npm run build"
}
```
### `spicyUtils.withRetry(Map args, closure)`
Retry a block with exponential backoff.
```groovy
spicyUtils.withRetry(maxAttempts: 3, delay: 5) {
sh "flaky-command"
}
```
---
## accounts
Multi-account configuration management.
### `accounts.get()`
Get all account configurations.
```groovy
def allAccounts = accounts.get()
def prodAccount = allAccounts.SPICY_CA_CENRAL_1_PROD
def devAccount = allAccounts.SPICY_CA_CENRAL_1_DEV
```
### Account Object Properties
| Property | Description |
| ------------------------- | ------------------------------ |
| `accountId` | AWS Account ID |
| `region` | AWS Region |
| `jenkinsAwsCredentialsId` | Jenkins credential ID |
| `vpcStackName` | Default VPC stack name |
| `ecsClusterStackName` | Default ECS cluster stack name |
### Available Accounts
| Key | Description |
| --------------------------- | ----------------------- |
| `SPICY_CA_CENRAL_1` | Base account |
| `SPICY_CA_CENRAL_1_DEV` | Development environment |
| `SPICY_CA_CENRAL_1_SANDBOX` | Sandbox environment |
| `SPICY_CA_CENRAL_1_QA` | QA environment |
| `SPICY_CA_CENRAL_1_STAGING` | Staging environment |
| `SPICY_CA_CENRAL_1_PROD` | Production environment |
---
## manualApproval
Manual approval gates for pipelines.
### `manualApproval(Map args)`
Request manual approval before proceeding.
```groovy
manualApproval(
message: "Deploy to production?",
submitter: "admin,deployers", // optional: allowed approvers
timeout: 24, // optional: hours to wait
timeoutUnit: "HOURS" // optional: HOURS, MINUTES, DAYS
)
```
---
## spicyDefaults
Apply default pipeline configuration.
### `spicyDefaults(Map args)`
Merge defaults into pipeline arguments.
```groovy
def call(Map args) {
args = spicyDefaults(args)
// args now has default pipelineProperties, etc.
}
```
Default properties applied:
- Build discarder (keep 10 builds)
- Disable concurrent builds
- GitHub project URL (if applicable)