---
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
