--- 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: regionName: awsCommand: lambda awsSubCommand: update-function-code awsArguments: >- --function-name --zip-file fileb://$(Pipeline.Workspace)/lambda-package/$(Build.BuildNumber).zip displayName: "Deploy — update function code" - task: AWSCLI@1 inputs: awsCredentials: regionName: awsCommand: lambda awsSubCommand: wait awsArguments: function-updated --function-name displayName: "Deploy — wait for update" - task: AWSCLI@1 inputs: awsCredentials: regionName: awsCommand: lambda awsSubCommand: publish-version awsArguments: --function-name displayName: "Deploy — publish version" - script: | VERSION=$(aws lambda list-versions-by-function \ --function-name \ --query "Versions[-1].Version" \ --output text) aws lambda update-alias \ --function-name \ --name \ --function-version "$VERSION" displayName: "Deploy — update alias" env: AWS_DEFAULT_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