Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/actions/update-aws-app-runner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Update AWS App Runner GitHub Action

## Overview

This GitHub action deploys a new image to an AWS App Runner service by triggering a manual deployment via the AWS CLI.

It starts the deployment and optionally waits for the service to reach a `RUNNING` state, polling every 15 seconds with a 10-minute timeout.

## Inputs

- `service_arn` - Required. The ARN of the App Runner service to deploy.
- `wait_for_deployment` - Optional. Whether to wait for the deployment to complete. Defaults to `'true'`.
Polls every 15 seconds and times out after 10 minutes.
- `aws_access_key_id` - Optional. AWS access key ID for credentials.
If this is NOT provided, the action will NOT set up AWS credentials; it is assumed they are already set up.
- `aws_secret_access_key` - Optional. AWS secret access key for credentials.
If this is NOT provided, the action will NOT set up AWS credentials; it is assumed they are already set up.
- `aws_default_region` - Optional. AWS default region for credentials.
If this is NOT provided, the action will NOT set up AWS credentials; it is assumed they are already set up.

## Example Usage

```yml
uses: generalui/github-workflow-accelerators/.github/actions/update-aws-app-runner@1.0.0-update-aws-app-runner
with:
service_arn: arn:aws:apprunner:us-east-1:123456789012:service/my-service/abc123def456
wait_for_deployment: 'true'
```

This will trigger a deployment on the App Runner service and wait for it to reach a `RUNNING` state.

## How it Works

The action runs the following steps:

1. Checks if AWS credentials need to be configured
1. Configures AWS credentials if provided
1. Calls `aws apprunner start-deployment` with the provided service ARN
1. If `wait_for_deployment` is `'true'`, polls `aws apprunner describe-service` every 15 seconds until the service status is `RUNNING`
1. Exits non-zero if the deployment fails or the 10-minute timeout is reached

## Notes

- Requires AWS credentials configured either via inputs or already present in the environment
- Requires the AWS CLI and `jq` to be installed on the runner
- The deploying IAM principal must have `apprunner:StartDeployment` and `apprunner:DescribeService` permissions
56 changes: 56 additions & 0 deletions .github/actions/update-aws-app-runner/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Update App Runner

description: Deploy a new image to an AWS App Runner service by triggering a manual deployment

inputs:
aws_access_key_id:
description: The AWS access key ID to use. If this is NOT provided, the action will NOT set up AWS credentials; it is assumed they are already set up.
required: false
default: ''
aws_secret_access_key:
description: The AWS secret access key to use. If this is NOT provided, the action will NOT set up AWS credentials; it is assumed they are already set up.
required: false
default: ''
aws_default_region:
description: The AWS region to use. If this is NOT provided, the action will NOT set up AWS credentials; it is assumed they are already set up.
required: false
default: ''
service_arn:
description: The ARN of the App Runner service to deploy.
required: true
wait_for_deployment:
description: Whether to wait for the deployment to complete (polls every 15s, times out after 10 minutes).
required: false
default: 'true'

runs:
using: composite
steps:
- name: Should configure AWS
run: |
configure=true
if [[ -z "${{ inputs.aws_access_key_id }}" || -z "${{ inputs.aws_secret_access_key }}" || -z "${{ inputs.aws_default_region }}" ]]; then
configure=false
fi
echo "configure=${configure}" >> $GITHUB_OUTPUT

echo "::group::Should Configure AWS Credentials"
echo 'configure: '${configure}
echo "::endgroup::"
shell: bash
id: should_configure_aws

- name: Configure AWS credentials
if: steps.should_configure_aws.outputs.configure == 'true'
uses: generalui/github-workflow-accelerators/.github/actions/configure-aws@1.0.0-configure-aws
with:
aws_access_key_id: ${{ inputs.aws_access_key_id }}
aws_secret_access_key: ${{ inputs.aws_secret_access_key }}
aws_default_region: ${{ inputs.aws_default_region }}

- name: Update App Runner
env:
SERVICE_ARN: ${{ inputs.service_arn }}
WAIT_FOR_DEPLOYMENT: ${{ inputs.wait_for_deployment }}
run: ${{ github.action_path }}/scripts/update_app_runner.sh
shell: bash
4 changes: 4 additions & 0 deletions .github/actions/update-aws-app-runner/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "update-aws-app-runner",
"version": "1.0.0"
}
86 changes: 86 additions & 0 deletions .github/actions/update-aws-app-runner/scripts/update_app_runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env bash

update_app_runner() {
# Defined some useful colors for echo outputs.
# Use blue for informational.
local blue="\033[1;34m"
# Use green for success informational.
local green="\033[1;32m"
# Use red for error informational and extreme actions.
local red="\033[1;31m"
# No Color (used to stop or reset a color).
local nc='\033[0m'

local service_arn="${SERVICE_ARN}"
local wait_for_deployment="${WAIT_FOR_DEPLOYMENT:-true}"
local usage_only=false

# Function to display script usage
usage() {
usage_only=true
echo >&2 -e "${blue}Running this script will trigger a manual deployment on the passed App Runner service.${nc}"
echo >&2 -e "${blue}Usage: $0 [OPTIONS]${nc}"
echo ""
echo >&2 -e "${blue}Options:${nc}"
echo >&2 -e "${blue} -h, --help Display this message${nc}"
}

while [ $# -gt 0 ]; do
case $1 in
-h | --help)
usage
;;
esac
shift
done

if [ "$usage_only" = false ]; then
if [ -z "$service_arn" ]; then
echo >&2 -e "${red}SERVICE_ARN is required but was not set.${nc}"
exit 1
fi

echo >&2 -e "${blue}Starting deployment for App Runner service: ${service_arn}${nc}"

local operation_id=""
operation_id=$(aws apprunner start-deployment --service-arn "$service_arn" | jq -r '.OperationId')

if [ -z "$operation_id" ]; then
echo >&2 -e "${red}Failed to start App Runner deployment.${nc}"
exit 1
fi

echo >&2 -e "${green}Deployment started. Operation ID: ${operation_id}${nc}"

if [ "$wait_for_deployment" = "true" ]; then
echo >&2 -e "${blue}Waiting for deployment to complete (polling every 15s, timeout 10min)...${nc}"

local max_attempts=40 # 40 * 15s = 600s = 10 minutes
local attempts=0

while [ "$attempts" -lt "$max_attempts" ]; do
local status=""
status=$(aws apprunner describe-service --service-arn "$service_arn" | jq -r '.Service.Status')

echo >&2 -e "${blue}Status: ${status} (attempt $((attempts + 1))/${max_attempts})${nc}"

if [ "$status" = "RUNNING" ]; then
echo >&2 -e "${green}Deployment completed successfully.${nc}"
return 0
elif [[ "$status" == *"FAILED"* ]] || [ "$status" = "DELETED" ]; then
echo >&2 -e "${red}Deployment failed with status: ${status}${nc}"
exit 1
fi

sleep 15
attempts=$((attempts + 1))
done

echo >&2 -e "${red}Timeout: deployment did not complete within 10 minutes.${nc}"
exit 1
fi
fi
}

# Main script execution
update_app_runner "$@"
6 changes: 6 additions & 0 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ jobs:
contains(steps.changed-actions.outputs.all_changed_files, 'tests/unit/update-aws-ecs')
run: bats --verbose-run tests/unit/update-aws-ecs/

- name: Test - update-aws-app-runner
if: >
contains(steps.changed-actions.outputs.all_changed_files, '.github/actions/update-aws-app-runner') ||
contains(steps.changed-actions.outputs.all_changed_files, 'tests/unit/update-aws-app-runner')
run: bats --verbose-run tests/unit/update-aws-app-runner/

- name: Test - update-aws-lambda
if: >
contains(steps.changed-actions.outputs.all_changed_files, '.github/actions/update-aws-lambda') ||
Expand Down
Loading
Loading