autojanet/skills/azure-pipeline-lambda/SKILL.md
Zoë cc74ad0bd0
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: use library/ Harbor project, add skills, fix pipeline secrets
- .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/
2026-05-30 15:43:14 -07:00

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