Bump ChimeCDKProvision from 0bf54c9 to e69210b (#248)
#451
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CDK and SAM Deployment | |
| on: | |
| push: | |
| branches: [ "main" ] | |
| tags-ignore: | |
| - sandbox* | |
| paths-ignore: | |
| - '**.png' | |
| - '**.md' | |
| - '**.sh' | |
| - '**dependabot.yml' | |
| permissions: | |
| id-token: write # This is required for requesting the JWT | |
| contents: write # This is required for actions/checkout and tests | |
| concurrency: deploy | |
| env: | |
| # https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository | |
| # Create secrets in the repository and they will be pushed to Parameter store, these are required | |
| FB_PAGE_ACCESS_TOKEN: ${{ secrets.FB_PAGE_ACCESS_TOKEN || 'DISABLED' }} | |
| FB_PAGE_ID: ${{ vars.FB_PAGE_ID || 'DISABLED' }} | |
| QDRANT_API_KEY: ${{ secrets.QDRANT_API_KEY || 'DISABLED' }} | |
| # https://docs.github.com/en/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository | |
| # Create repository variables to override any/all of the below from the defaults | |
| # | |
| CDK_STACK_NAME: ${{ vars.CDK_STACK_NAME || 'spring-ai-square-ivr-cdk' }} | |
| STACK_NAME: ${{ vars.STACK_NAME || 'spring-ai-square-ivr' }} | |
| # The E164 Number to be used when transferring to main number | |
| TRANSFER_NUMBER: ${{ vars.TRANSFER_NUMBER || '+18004444444' }} | |
| # If you don't set an API key for square, you can still use Spring AI by itself | |
| SQUARE_API_KEY: ${{ secrets.SQUARE_API_KEY || 'DISABLED' }} | |
| # Set to PRODUCTION if you have a real Sqaure Buisness or Leave it as SANDBOX if you just have a dev account | |
| SQUARE_ENVIRONMENT: ${{ vars.SQUARE_ENVIRONMENT || 'SANDBOX' }} | |
| # You can have many locations in Square, need to set to the location you want to query inventory or employees against (required for functions to work) | |
| SQUARE_LOCATION_ID: ${{ vars.SQUARE_LOCATION_ID || 'DISABLED' }} | |
| # Which Spring AI chat provider we are using, either OPENAI or BEDROCK are supported in the chat config | |
| SPRING_AI_PROVIDER: ${{ vars.SPRING_AI_PROVIDER || 'BEDROCK' }} | |
| # The Bedrock model to use | |
| BEDROCK_MODEL: ${{ vars.BEDROCK_MODEL || 'us.amazon.nova-2-lite-v1:0' }} | |
| # https://platform.openai.com/docs/models/overview (requres model with function calling) | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY || 'set if using OpenAI' }} | |
| OPENAI_MODEL: ${{ vars.OPENAI_MODEL || 'gpt-4.1-nano' }} | |
| # Polly voices to use https://docs.aws.amazon.com/polly/latest/dg/ntts-voices-main.html | |
| VOICE_ID_EN: ${{ vars.VOICE_ID_EN || 'Joanna' }} | |
| VOICE_ID_ES: ${{ vars.VOICE_ID_ES || 'Lupe' }} | |
| VOICE_ID_DE: ${{ vars.VOICE_ID_DE || 'Vicki' }} | |
| jobs: | |
| # First we must create all the Chime resources like Voice Connectors, SIP Media Application, SIP Rules, etc. | |
| cdk-deploy: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Setup AWS Credentials | |
| id: aws-creds | |
| uses: aws-actions/configure-aws-credentials@v6 | |
| with: | |
| aws-region: us-east-1 | |
| # The full role ARN if you are using OIDC | |
| # https://github.com/aws-actions/configure-aws-credentials#oidc | |
| role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} | |
| # Set up the below secrets if you are not using OIDC and want to use regular keys (best practive is to use just role above with OIDC provider) | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| mask-aws-account-id: true | |
| - name: Add AWS_ACCOUNT_ID to Environment | |
| run: echo "AWS_ACCOUNT_ID=${{ steps.aws-creds.outputs.aws-account-id }}" >> $GITHUB_ENV | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '25' | |
| distribution: 'corretto' | |
| cache: maven | |
| - name: Install AWS CDK | |
| run: | | |
| # Install latest version of AWS CDK | |
| npm install -g aws-cdk | |
| echo "Node Version: $(node -v)" | |
| echo "CDK Version: $(cdk version)" | |
| - name: Ensure CDK is bootstraped | |
| run: | | |
| cdk bootstrap --ci=true -c accountId=${AWS_ACCOUNT_ID} aws://${AWS_ACCOUNT_ID}/us-east-1 | |
| cdk bootstrap --ci=true -c accountId=${AWS_ACCOUNT_ID} aws://${AWS_ACCOUNT_ID}/us-west-2 | |
| - name: Deploy Stack with CDK | |
| working-directory: ./ChimeCDKProvision | |
| run: | | |
| # Deploy to both regions in parallel | |
| cdk deploy -c accountId=${AWS_ACCOUNT_ID} -c stackName=${CDK_STACK_NAME} -c regionEast=us-east-1 -c regionWest=us-west-2 --concurrency=4 --all --require-approval=never --ci=true | |
| env: | |
| # SIP PBX like Asterisk with public static IP, this will configure VC to allow calls from this and send calls to it (use IP, not a hostname actually) | |
| PBX_HOSTNAME: ${{ vars.PBX_HOSTNAME }} | |
| # If you have an existing Phone number provisioned and want to point it to the SMA's that are created | |
| CHIME_PHONE_NUMBER: ${{ vars.CHIME_PHONE_NUMBER }} | |
| # Configure a VC, this is implied if either of the above is set, however it show be set to TRUE if you want a VC and are not setting Phone or PBX | |
| VOICE_CONNECTOR: ${{ vars.VOICE_CONNECTOR }} | |
| # Twilio Create SIP trunk pointing to Voice Connector | |
| TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }} | |
| TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }} | |
| TWILIO_PHONE_NUMBER_SID: ${{ secrets.TWILIO_PHONE_NUMBER_SID }} | |
| # Now deploy the app into 2 regions at the same time via SAM with matrix job | |
| sam-deploy: | |
| strategy: | |
| matrix: | |
| region: [ us-east-1, us-west-2 ] | |
| runs-on: ubuntu-latest | |
| environment: ${{ matrix.region }} | |
| needs: [cdk-deploy] | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Setup AWS Credentials | |
| id: aws-creds | |
| uses: aws-actions/configure-aws-credentials@v6 | |
| with: | |
| aws-region: ${{ matrix.region }} | |
| # The full role ARN if you are using OIDC | |
| # https://github.com/aws-actions/configure-aws-credentials#oidc | |
| role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} | |
| # Set up the below secrets if you are not using OIDC and want to use regular keys (best practive is to use just role above with OIDC provider) | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| mask-aws-account-id: true | |
| - name: Add AWS_ACCOUNT_ID to Environment | |
| run: echo "AWS_ACCOUNT_ID=${{ steps.aws-creds.outputs.aws-account-id }}" >> $GITHUB_ENV | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '25' | |
| distribution: 'corretto' | |
| cache: maven | |
| - name: Build/Install Top level Project POM | |
| run: mvn -N install -DskipTests --no-transfer-progress --quiet | |
| - name: Build/Install Needed SMA Library | |
| working-directory: ./ChimeSMALibrary | |
| run: mvn install -DskipTests --no-transfer-progress --quiet | |
| - name: Setup AWS SAM | |
| uses: aws-actions/setup-sam@v2 | |
| with: | |
| use-installer: true | |
| - name: Sync Parameters to SSM (only if changed) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| update_param_if_changed() { | |
| local name="$1" | |
| local value="$2" | |
| local description="$3" | |
| echo "Checking SSM parameter: $name" | |
| # Get current value (if it exists). Suppress error if not found. | |
| local current_value="" | |
| if current_value_json=$(aws ssm get-parameter --name "$name" --query 'Parameter.Value' --output text 2>/dev/null); then | |
| current_value="$current_value_json" | |
| fi | |
| if [[ "$current_value" == "$value" ]]; then | |
| echo "No change for $name, skipping put-parameter" | |
| else | |
| echo "Value changed for $name, updating in SSM" | |
| aws ssm put-parameter \ | |
| --name "$name" \ | |
| --description "$description" \ | |
| --type String \ | |
| --value "$value" \ | |
| --overwrite | |
| fi | |
| } | |
| update_param_if_changed "/${STACK_NAME}/SQUARE_API_KEY" \ | |
| "${SQUARE_API_KEY}" \ | |
| "Square API Key used for stack ${STACK_NAME}" | |
| update_param_if_changed "/${STACK_NAME}/OPENAI_API_KEY" \ | |
| "${OPENAI_API_KEY}" \ | |
| "OpenAI API Key used for stack ${STACK_NAME}" | |
| update_param_if_changed "/${STACK_NAME}/FB_PAGE_ACCESS_TOKEN" \ | |
| "${FB_PAGE_ACCESS_TOKEN}" \ | |
| "Facebook Access token used for stack ${STACK_NAME}" | |
| update_param_if_changed "/${STACK_NAME}/QDRANT_API_KEY" \ | |
| "${QDRANT_API_KEY}" \ | |
| "Qdrant API Key for Vector Store used for stack ${STACK_NAME}" | |
| - name: Cache SAM Build files | |
| uses: actions/cache@v5 | |
| with: | |
| path: .aws-sam | |
| key: ${{ runner.os }}-sam | |
| - name: SAM Build | |
| run: sam build | |
| - name: Does Stack Exist | |
| id: stack-exists | |
| continue-on-error: true | |
| run: aws cloudformation describe-stacks --stack-name ${STACK_NAME} > /dev/null | |
| - name: Delete PromptCreator Custom resource Logs if stack doesn't exist | |
| if: steps.stack-exists.outcome == 'failure' | |
| continue-on-error: true | |
| run: | | |
| aws logs delete-log-group --log-group-name "/aws/lambda/${STACK_NAME}-PromptCreator" | |
| - name: Delete PromptCopier Custom resource Logs if stack doesn't exist | |
| if: steps.stack-exists.outcome == 'failure' | |
| continue-on-error: true | |
| run: | | |
| aws logs delete-log-group --log-group-name "/aws/lambda/${STACK_NAME}-PromptCopier" | |
| - name: SAM Deploy | |
| run: > | |
| sam deploy --no-fail-on-empty-changeset --no-confirm-changeset | |
| --region ${{ matrix.region }} | |
| --stack-name ${STACK_NAME} | |
| --parameter-overrides | |
| SQUAREAPIKEY=/${STACK_NAME}/SQUARE_API_KEY | |
| OPENAIAPIKEY=/${STACK_NAME}/OPENAI_API_KEY | |
| QDRANTAPIKEY=/${STACK_NAME}/QDRANT_API_KEY | |
| FBPAGEACCESSTOKEN=/${STACK_NAME}/FB_PAGE_ACCESS_TOKEN | |
| FBPAGEID=${FB_PAGE_ID} | |
| SMAID=/${CDK_STACK_NAME}/SMA_ID | |
| VOICECONNECTORARN=/${CDK_STACK_NAME}/VC_ARN | |
| SQUAREENVIRONMENT=${SQUARE_ENVIRONMENT} | |
| SQUARELOCATIONID=${SQUARE_LOCATION_ID} | |
| TRANSFERNUMBER=${TRANSFER_NUMBER} | |
| OPENAIMODEL=${OPENAI_MODEL} | |
| VOICEIDEN=${VOICE_ID_EN} | |
| VOICEIDES=${VOICE_ID_ES} | |
| VOICEIDDE=${VOICE_ID_DE} | |
| SPRINGAIPROVIDER=${SPRING_AI_PROVIDER} | |
| BEDROCKMODEL=${BEDROCK_MODEL} | |
| - name: Update SMA Endpoint | |
| run: | | |
| # The SMA ID is was pushed to param store by the CDK stack | |
| SMA_ID=$(aws ssm get-parameter --name /${CDK_STACK_NAME}/SMA_ID --query Parameter.Value --output text) | |
| # Chime for some reason loses reference to lambda, so always set to dummay and then back to what it should be | |
| TARGET_ENDPOINT=arn:aws:lambda:${{ matrix.region }}:${AWS_ACCOUNT_ID}:function:${STACK_NAME}-ChimeSMA:SNAPSTART | |
| DUMMY_ENDPOINT=$(aws ssm get-parameter --name /${CDK_STACK_NAME}/LAMBDA_ARN --query Parameter.Value --output text) | |
| aws chime-sdk-voice update-sip-media-application --sip-media-application-id ${SMA_ID} --endpoints LambdaArn=${DUMMY_ENDPOINT} | |
| # Once and a while the second update will fail, likely because above update didn't complete immediately, so give a little time | |
| sleep 5 | |
| aws chime-sdk-voice update-sip-media-application --sip-media-application-id ${SMA_ID} --endpoints LambdaArn=${TARGET_ENDPOINT} | |
| # Run a couple tests to make sure the model is responding and able to make Square calls | |
| run-tests: | |
| if: ${{ vars.RUN_TESTS }} | |
| strategy: | |
| max-parallel: 1 | |
| matrix: | |
| region: [ us-west-2, us-east-1 ] | |
| runs-on: ubuntu-latest | |
| environment: "${{ matrix.region }}-tests" | |
| needs: [sam-deploy] | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Execute Tests | |
| uses: ./.github/actions/test | |
| with: | |
| region: ${{ matrix.region }} | |
| stack-name: ${{ vars.STACK_NAME || 'spring-ai-square-ivr' }} | |
| aws-role: ${{ secrets.AWS_ROLE_TO_ASSUME }} | |
| session-id: ${{ github.run_id }}-${{ github.run_attempt }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| spring-ai-model: ${{ vars.SPRING_AI_PROVIDER == 'OPENAI' && vars.OPENAI_MODEL || vars.BEDROCK_MODEL }} | |
| spring-ai-provider: ${{ vars.SPRING_AI_PROVIDER || 'BEDROCK' }} | |
| test-filter: SmokeTests | |