diff --git a/README.md b/README.md index 63d8d37..755d459 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Shared actions for Forgejo CI/CD pipelines. | [aikido-full-scan](aikido-full-scan) | Aikido full scan | | [aikido-pr-scan](aikido-pr-scan) | Aikido PR scan | | [aws-configure](aws-configure) | Authenticate with AWS via OIDC | +| [aws-lambda-alias-update](aws-lambda-alias-update) | Update Aliases of Lambda Functions to a new Version | +| [aws-lambda-wait-for-provisioned-concurrency](aws-lambda-wait-for-provisioned-concurrency) | Wait until the Provisioned Concurrency is Ready for Lambda Functions | | [cache](cache) | Cache files between workflow runs | | [checkout](checkout) | Action for checking out a repository | | [download-artifact](download-artifact) | Download Forgejo Actions artifacts by name or pattern | @@ -16,18 +18,18 @@ Shared actions for Forgejo CI/CD pipelines. | [i18n-sync](i18n-sync) | Fetch translations from i18n.schmalz.com and open a pull request | | [inject-content](inject-content) | Inject content into a file by appending or overwriting | | [maven-build](maven-build) | Action for building and validating Maven projects | -| [pnpm-build](pnpm-build) | Action for building and validating with PNPM | | [playwright-merge](playwright-merge) | Merge Playwright shard blob reports and publish consolidated reports | | [playwright-run](playwright-run) | Run Playwright tests for one shard and upload its blob report | +| [pnpm-build](pnpm-build) | Action for building and validating with PNPM | | [publish-npm-package](publish-npm-package) | Publish a PNPM package to JFrog Artifactory | | [publish-rust-crate](publish-rust-crate) | Publish a Rust crate to JFrog Artifactory | | [publish-static-contents](publish-static-contents) | Syncs frontend assets to S3 and invalidates a CloudFront distribution | | [rust-build](rust-build) | Set up Rust toolchain, run checks, and build via the project's build.sh | | [terraform-apply](terraform-apply) | Apply Terraform configuration files using the official Terraform CLI | +| [terraform-plan](terraform-plan) | Preview Terraform infrastructure changes (create, update, delete, replace) without applying them | | [terraform-validate](terraform-validate) | Validate Terraform configuration files using the official Terraform CLI | | [upload-artifact](upload-artifact) | Upload files as a Forgejo Actions artifact | | [vacuum-lint](vacuum-lint) | Validate and lint OpenAPI specifications using Vacuum | -| [terraform-plan](terraform-plan) | Preview Terraform infrastructure changes (create, update, delete, replace) without applying them | ## Security diff --git a/aws-lambda-alias-update/README.md b/aws-lambda-alias-update/README.md new file mode 100644 index 0000000..26d2647 --- /dev/null +++ b/aws-lambda-alias-update/README.md @@ -0,0 +1,84 @@ +# aws-lambda-alias-update + +Composite action that updates Lambda function aliases from a Terraform output. Iterates over the `lambda_alias_updates` Terraform output and calls `aws lambda update-alias` for each entry. + +**Example `lambda-alias-updates` input:** + +```json +[ + "{\"alias_name\": \"live\", \"function_name\": \"my-get-product\", \"version\": \"42\"}", + "{\"alias_name\": \"live\", \"function_name\": \"my-get-category\", \"version\": \"7\"}" +] +``` + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `lambda-alias-updates` | Yes | — | JSON array of Lambda alias update objects (Terraform output: `lambda_alias_updates`). Each element is a JSON-encoded string with `alias_name`, `function_name`, and `version`. | + +## Usage + +```yaml +- name: Update Lambda Aliases + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-alias-update@aws-lambda-alias-update-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Terraform Setup + +- Add the following content to the project +- Add all Lambda Modules to the `provisioned_lambda_modules` list for which the Function Alias and/or Provisioned Concurrency should be updated + +**`output.tf`** +```tf +locals { + // List of Lambda Modules that have provisioned concurrency configured. + // Required to update the aliases of these functions after deployment. + provisioned_lambda_modules = [ + module.lambda_get_category, + module.lambda_product_get_full_slug, + module.lambda_get_product, + ] +} + +// Output which allows Updates of Lambda Alias and Provisioned Concurrency +output "lambda_alias_updates" { + value = concat([for module in local.provisioned_lambda_modules : "{\"alias_name\": \"${module.lambda_alias_name}\", \"function_name\": \"${module.lambda_name}\", \"version\": \"${module.lambda_version}\" }"]) +} + +``` + +## Example Usage with other Shared Actions + +```yml +jobs: + deploy-stage: + name: Build and Deploy to Stage + runs-on: stackit-ubuntu-22 + steps: + - name: Apply Terraform + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/terraform-apply@terraform-apply-v1 + id: tf-apply + with: + terraform-version: 1.14.9 + workspace: stage + var-file: stage.tfvars + jfrog-token: ${{ secrets.JFROG_TOKEN }} + + - name: Update Lambda Aliases + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-alias-update@aws-lambda-alias-update-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} + + - name: Wait for Lambda Provisioned Concurrency + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-wait-for-provisioned-concurrency@aws-lambda-wait-for-provisioned-concurrency-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Notes + +- Expects the `lambda-alias-updates` input to be the raw `lambda_alias_updates` output from the `terraform-apply` action. +- Requires AWS credentials to be configured in the job before this step runs. diff --git a/aws-lambda-alias-update/action.yml b/aws-lambda-alias-update/action.yml new file mode 100644 index 0000000..42f632f --- /dev/null +++ b/aws-lambda-alias-update/action.yml @@ -0,0 +1,49 @@ +name: "AWS Lambda - Update Alias" +description: > + Updates Lambda function aliases from a Terraform output. + Iterates over the lambda_alias_updates Terraform output and calls + aws lambda update-alias for each entry. + +inputs: + lambda-alias-updates: + description: > + JSON array of Lambda alias update objects (Terraform output: lambda_alias_updates). + Each element is a JSON-encoded string with alias_name, function_name, and version. + required: true + +runs: + using: "composite" + steps: + - name: Install AWS CLI + shell: bash + run: | + if ! command -v aws &> /dev/null; then + curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip + unzip -q /tmp/awscliv2.zip -d /tmp + sudo /tmp/aws/install + rm -rf /tmp/awscliv2.zip /tmp/aws + fi + + - name: Install jq if missing + shell: bash + run: | + set -euo pipefail + command -v jq >/dev/null 2>&1 || sudo apt-get install -y --no-install-recommends jq + + - name: Update Lambda Aliases + shell: bash + env: + LAMBDA_ALIAS_UPDATES: ${{ inputs.lambda-alias-updates }} + run: | + echo "$LAMBDA_ALIAS_UPDATES" | jq -c '.[] | fromjson' | while IFS= read -r entry; do + alias_name=$(echo "$entry" | jq -r '.alias_name') + function_name=$(echo "$entry" | jq -r '.function_name') + version=$(echo "$entry" | jq -r '.version') + echo "Updating alias '$alias_name' for '$function_name' to version '$version'" + aws lambda update-alias \ + --no-cli-pager \ + --name "$alias_name" \ + --function-name "$function_name" \ + --function-version "$version" + echo "Updated alias '$alias_name' for '$function_name' to version '$version'" + done diff --git a/aws-lambda-wait-for-provisioned-concurrency/README.md b/aws-lambda-wait-for-provisioned-concurrency/README.md new file mode 100644 index 0000000..2efbbc3 --- /dev/null +++ b/aws-lambda-wait-for-provisioned-concurrency/README.md @@ -0,0 +1,86 @@ +# aws-lambda-wait-for-provisioned-concurrency + +Composite action that waits for provisioned concurrency to reach `READY` status for all Lambda functions listed in the Terraform `lambda_alias_updates` output. Iterates over the `lambda_alias_updates` Terraform output and polls `aws lambda get-provisioned-concurrency-config` for each entry until the status is `READY` or `FAILED`. + +**Example `lambda-alias-updates` input:** + +```json +[ + "{\"alias_name\": \"live\", \"function_name\": \"my-get-product\", \"version\": \"42\"}", + "{\"alias_name\": \"live\", \"function_name\": \"my-get-category\", \"version\": \"7\"}" +] +``` + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `lambda-alias-updates` | Yes | — | JSON array of Lambda alias update objects (Terraform output: `lambda_alias_updates`). Each element is a JSON-encoded string with `alias_name`, `function_name`, and `version`. | + +## Usage + +```yaml +- name: Wait for Lambda Provisioned Concurrency + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-wait-for-provisioned-concurrency@aws-lambda-wait-for-provisioned-concurrency-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Terraform Setup + +- Add the following content to the project +- Add all Lambda Modules to the `provisioned_lambda_modules` list for which the Function Alias and/or Provisioned Concurrency should be updated + +**`output.tf`** +```tf +locals { + // List of Lambda Modules that have provisioned concurrency configured. + // Required to update the aliases of these functions after deployment. + provisioned_lambda_modules = [ + module.lambda_get_category, + module.lambda_product_get_full_slug, + module.lambda_get_product, + ] +} + +// Output which allows Updates of Lambda Alias and Provisioned Concurrency +output "lambda_alias_updates" { + value = concat([for module in local.provisioned_lambda_modules : "{\"alias_name\": \"${module.lambda_alias_name}\", \"function_name\": \"${module.lambda_name}\", \"version\": \"${module.lambda_version}\" }"]) +} + +``` + +## Example Usage with other Shared Actions + +```yml +jobs: + deploy-stage: + name: Build and Deploy to Stage + runs-on: stackit-ubuntu-22 + steps: + - name: Apply Terraform + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/terraform-apply@terraform-apply-v1 + id: tf-apply + with: + terraform-version: 1.14.9 + workspace: stage + var-file: stage.tfvars + jfrog-token: ${{ secrets.JFROG_TOKEN }} + + - name: Update Lambda Aliases + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-alias-update@aws-lambda-alias-update-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} + + - name: Wait for Lambda Provisioned Concurrency + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-wait-for-provisioned-concurrency@aws-lambda-wait-for-provisioned-concurrency-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Notes + +- Expects the `lambda-alias-updates` input to be the raw `lambda_alias_updates` output from the `terraform-apply` action. +- Functions without provisioned concurrency configured are skipped automatically. +- If provisioned concurrency reaches `FAILED` status, the action logs a warning and continues without failing the workflow. +- Requires AWS credentials to be configured in the job before this step runs. diff --git a/aws-lambda-wait-for-provisioned-concurrency/action.yml b/aws-lambda-wait-for-provisioned-concurrency/action.yml new file mode 100644 index 0000000..690e6c3 --- /dev/null +++ b/aws-lambda-wait-for-provisioned-concurrency/action.yml @@ -0,0 +1,64 @@ +name: "AWS Lambda - Wait for Provisioned Concurrency" +description: > + Waits for provisioned concurrency to reach READY status for all Lambda + functions listed in the Terraform lambda_alias_updates output. + +inputs: + lambda-alias-updates: + description: > + JSON array of Lambda alias update objects (Terraform output: lambda_alias_updates). + Each element is a JSON-encoded string with alias_name, function_name, and version. + required: true + +runs: + using: "composite" + steps: + - name: Install AWS CLI + shell: bash + run: | + if ! command -v aws &> /dev/null; then + curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip + unzip -q /tmp/awscliv2.zip -d /tmp + sudo /tmp/aws/install + rm -rf /tmp/awscliv2.zip /tmp/aws + fi + + - name: Install jq if missing + shell: bash + run: | + set -euo pipefail + command -v jq >/dev/null 2>&1 || sudo apt-get install -y --no-install-recommends jq + + - name: Wait for Lambda Provisioned Concurrency + shell: bash + env: + LAMBDA_ALIAS_UPDATES: ${{ inputs.lambda-alias-updates }} + run: | + echo "$LAMBDA_ALIAS_UPDATES" | jq -c '.[] | fromjson' | while IFS= read -r entry; do + function_name=$(echo "$entry" | jq -r '.function_name') + alias_name=$(echo "$entry" | jq -r '.alias_name') + if aws lambda get-provisioned-concurrency-config \ + --no-cli-pager \ + --function-name "$function_name" \ + --qualifier "$alias_name" >/dev/null 2>&1; then + echo "Provisioned concurrency found, waiting for READY status... ($function_name:$alias_name)" + while true; do + STATUS=$(aws lambda get-provisioned-concurrency-config \ + --no-cli-pager \ + --function-name "$function_name" \ + --qualifier "$alias_name" \ + --query 'Status' \ + --output text 2>/dev/null || echo "FAILED") + echo "Current status: $STATUS ($function_name:$alias_name)" + if [[ "$STATUS" == "READY" ]]; then + echo "Provisioned Concurrency - Ready ($function_name:$alias_name)" + break + elif [[ "$STATUS" == "FAILED" ]]; then + echo "Provisioned concurrency failed, continuing anyway ($function_name:$alias_name)" + break + fi + done + else + echo "No provisioned concurrency configured, skipping wait ($function_name:$alias_name)" + fi + done