Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- .woodpecker.yaml: image paths -> library/autojanet-{agent,dispatcher}
- .woodpecker.yaml: secret names RS_HARBOR_USER / RS_HARBOR_PASS (global)
- container/Dockerfile: restore COPY skills/, skills/ populated from opencode config
- skills/: 84 opencode skills bundled into image
- k8s/manifests: update image refs to library/
158 lines
5.1 KiB
Markdown
158 lines
5.1 KiB
Markdown
---
|
|
name: azure-pipeline-lambda
|
|
description: Extends azure-devops-pipeline for AWS Lambda deployments. Handles zip and container packaging, OIDC credentials, function update and alias promotion. Always load azure-devops-pipeline first.
|
|
---
|
|
|
|
## What I add
|
|
|
|
Type-specific steps for AWS Lambda pipelines. Merge these into the skeleton from `azure-devops-pipeline`.
|
|
|
|
## Additional required inputs — ask the user
|
|
|
|
1. **Function name** — the Lambda function name in AWS
|
|
2. **AWS region** — e.g. `us-east-1`
|
|
3. **AWS service connection name** — the ADO AWS OIDC service connection name
|
|
4. **Packaging method** — `zip` | `container`
|
|
5. **Deployment method** — `aws-cli` | `SAM` | `CDK`
|
|
6. **Runtime** — `python3.x` | `nodejs20.x` | other (for linting tool selection)
|
|
7. **Alias to update** — e.g. `nonprod` or `prod` (matches target tier)
|
|
|
|
## Lint stage steps
|
|
|
|
### Python runtime
|
|
```yaml
|
|
- script: pip install pylint && pylint src/ --fail-under=7
|
|
displayName: "Lint — pylint"
|
|
- script: |
|
|
pip install cfn-lint
|
|
cfn-lint template.yaml 2>/dev/null || true
|
|
displayName: "Lint — cfn-lint (CloudFormation, if present)"
|
|
continueOnError: true
|
|
```
|
|
|
|
### Node runtime
|
|
```yaml
|
|
- script: npm ci && npx eslint src/
|
|
displayName: "Lint — eslint"
|
|
```
|
|
|
|
## Security scan stage steps
|
|
|
|
### Python runtime
|
|
```yaml
|
|
- script: |
|
|
pip install pip-audit
|
|
pip-audit -r requirements.txt --output json > pip-audit-results.json
|
|
displayName: "Security scan — pip-audit"
|
|
- task: PublishBuildArtifacts@1
|
|
inputs:
|
|
pathToPublish: pip-audit-results.json
|
|
artifactName: security-scan
|
|
displayName: "Publish scan results"
|
|
```
|
|
|
|
### Node runtime
|
|
```yaml
|
|
- script: |
|
|
npm audit --json > npm-audit-results.json || true
|
|
npm audit --audit-level=high
|
|
displayName: "Security scan — npm audit"
|
|
- task: PublishBuildArtifacts@1
|
|
inputs:
|
|
pathToPublish: npm-audit-results.json
|
|
artifactName: security-scan
|
|
displayName: "Publish scan results"
|
|
```
|
|
|
|
## Build stage steps (zip packaging)
|
|
|
|
```yaml
|
|
- script: |
|
|
mkdir -p package
|
|
# Python: install deps into package dir
|
|
pip install -r requirements.txt -t ./package
|
|
# Copy handler (adjust filename as needed)
|
|
cp *.py ./package/
|
|
# Remove dev/test artifacts
|
|
find ./package -name "*.pyc" -delete
|
|
find ./package -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
|
find ./package -name "*.dist-info" -type d -exec rm -rf {} + 2>/dev/null || true
|
|
cd package && zip -r ../$(Build.BuildNumber).zip .
|
|
displayName: "Package Lambda — zip (Python)"
|
|
- task: PublishBuildArtifacts@1
|
|
inputs:
|
|
pathToPublish: $(Build.BuildNumber).zip
|
|
artifactName: lambda-package
|
|
displayName: "Publish Lambda artifact"
|
|
```
|
|
|
|
For Node runtime, replace the pip install/cp lines with:
|
|
```yaml
|
|
- script: |
|
|
npm ci --omit=dev
|
|
zip -r $(Build.BuildNumber).zip . \
|
|
--exclude "*.git*" \
|
|
--exclude "*node_modules/.cache*" \
|
|
--exclude "*test*" \
|
|
--exclude "*.spec.*" \
|
|
--exclude "*.test.*"
|
|
displayName: "Package Lambda — zip (Node)"
|
|
```
|
|
|
|
## Build stage steps (container packaging)
|
|
|
|
Use the full `azure-pipeline-docker` steps for the container build. Reference the resulting image URI in the Lambda deploy step by passing `--image-uri` instead of `--zip-file`.
|
|
|
|
## Deploy stage steps (aws-cli method)
|
|
|
|
```yaml
|
|
- task: AWSCLI@1
|
|
inputs:
|
|
awsCredentials: <aws-service-connection-name>
|
|
regionName: <aws-region>
|
|
awsCommand: lambda
|
|
awsSubCommand: update-function-code
|
|
awsArguments: >-
|
|
--function-name <function-name>
|
|
--zip-file fileb://$(Pipeline.Workspace)/lambda-package/$(Build.BuildNumber).zip
|
|
displayName: "Deploy — update function code"
|
|
|
|
- task: AWSCLI@1
|
|
inputs:
|
|
awsCredentials: <aws-service-connection-name>
|
|
regionName: <aws-region>
|
|
awsCommand: lambda
|
|
awsSubCommand: wait
|
|
awsArguments: function-updated --function-name <function-name>
|
|
displayName: "Deploy — wait for update"
|
|
|
|
- task: AWSCLI@1
|
|
inputs:
|
|
awsCredentials: <aws-service-connection-name>
|
|
regionName: <aws-region>
|
|
awsCommand: lambda
|
|
awsSubCommand: publish-version
|
|
awsArguments: --function-name <function-name>
|
|
displayName: "Deploy — publish version"
|
|
|
|
- script: |
|
|
VERSION=$(aws lambda list-versions-by-function \
|
|
--function-name <function-name> \
|
|
--query "Versions[-1].Version" \
|
|
--output text)
|
|
aws lambda update-alias \
|
|
--function-name <function-name> \
|
|
--name <alias-name> \
|
|
--function-version "$VERSION"
|
|
displayName: "Deploy — update alias"
|
|
env:
|
|
AWS_DEFAULT_REGION: <aws-region>
|
|
```
|
|
|
|
## Hard rules for Lambda
|
|
|
|
- Always use OIDC service connection — never hardcode `AWS_ACCESS_KEY_ID` or `AWS_SECRET_ACCESS_KEY` in the pipeline YAML
|
|
- Always wait for `function-updated` before publishing version — skipping this causes race conditions
|
|
- Always update alias after publishing version — direct function invocation without alias is not acceptable
|
|
- Zip packaging: always exclude `.git`, `__pycache__`, `*.pyc`, `node_modules/.cache`, test files
|
|
- Shell variable expansion in AWSCLI task `awsArguments` requires `>-` (block scalar) not `>` to avoid newline issues
|