Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ti-infinite/GSMInfrastructure/llms.txt

Use this file to discover all available pages before exploring further.

The deploy-scheduler.yml workflow deploys the GSM EventBridge Scheduler CloudFormation stack, which manages automated start and stop schedules for the ECS services and their underlying EC2 instance. Like the infrastructure workflow, it uses GitHub OIDC to assume an AWS IAM role without static credentials. The scheduler stack controls cost by spinning down all ECS tasks and stopping the EC2 instance outside of business hours, then bringing everything back up on the configured cron expressions.

Triggers

The workflow fires on two events:
  • Push to the develop, quality, or main branches, but only when devops/scheduler/template.yml is modified. Unrelated commits do not trigger a re-deploy.
  • workflow_dispatch — allows manual execution from the GitHub Actions UI with an explicit environment input.
TriggerBranch / PathResolved environment
Pushdevelop / devops/scheduler/template.ymldev
Pushquality / devops/scheduler/template.ymlqa
Pushmain / devops/scheduler/template.ymlprod
workflow_dispatchAnyValue chosen in the input (default: dev)

Environment Variable

VariableValue
AWS_REGIONus-east-1

Jobs

determine-env

Both jobs only execute when vars.WORKFLOW_SCHEDULER_ENABLED == 'true'. Setting this variable to any other value disables the scheduler workflow without deleting it, which is useful during initial environment setup.
  • Condition: vars.WORKFLOW_SCHEDULER_ENABLED == 'true'
  • Runner: ubuntu-latest
  • Purpose: Maps the triggering branch to a target environment string and exposes it as the environment job output.
  • Logic: workflow_dispatch uses the manually supplied input. Push events map mainprod, qualityqa, developdev (unknown branches fall back to dev).
Outputs:
Output keyDescription
environmentResolved environment string (dev, qa, or prod)

deploy

  • Condition: vars.WORKFLOW_SCHEDULER_ENABLED == 'true'
  • Needs: determine-env
  • Runner: ubuntu-latest
  • GitHub Environment: infra-{env} (e.g. infra-dev)
  • Permissions:
PermissionLevelReason
id-tokenwriteRequired to request the OIDC JWT for AWS role assumption
contentsreadRequired to check out the repository

Deploy Job Steps

- name: Checkout code
  uses: actions/checkout@v4
Checks out the repository so the scheduler template is available on the runner.
- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }}
    aws-region: ${{ env.AWS_REGION }}
Exchanges the GitHub OIDC token for temporary AWS credentials by assuming the AWS_INFRA_ROLE_ARN role. The same base role used by the infrastructure workflow is reused here.
- name: Deploy CloudFormation Stack
  uses: aws-actions/aws-cloudformation-github-deploy@v1.2.0
  with:
    name: "${{ needs.determine-env.outputs.environment }}-${{ vars.APP_NAME }}-scheduler-stack"
    template: devops/scheduler/template.yml
    capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM
    region: ${{ env.AWS_REGION }}
    no-fail-on-empty-changeset: "1"
Creates or updates the scheduler CloudFormation stack. no-fail-on-empty-changeset: "1" prevents pipeline failures when the schedule expressions have not changed.Stack name pattern: {env}-{appName}-scheduler-stack (e.g. dev-gsmapplication-scheduler-stack)

Parameter Overrides

All CloudFormation parameters for the scheduler stack are sourced from repository variables:
CloudFormation ParameterRepository VariableDescription
Environmentdetermine-env outputTarget environment (dev / qa / prod)
AppNamevars.APP_NAMEApplication name used in resource naming
EC2InstanceIdvars.EC2_INSTANCE_IDID of the EC2 instance to start/stop
EIPAllocationIdvars.EC2_ELASTIC_IP_IDAllocation ID of the Elastic IP to associate/disassociate
ECSClusterNamevars.ECS_CLUSTERName of the ECS cluster containing the services
GatewayServiceNamevars.GATEWAY_SERVICE_NAMEECS service name for the gateway container
AuthServiceNamevars.AUTH_SERVICE_NAMEECS service name for the auth container
ApplicationServiceNamevars.APPLICATION_SERVICE_NAMEECS service name for the application container
OperationsServiceNamevars.OPERATIONS_SERVICE_NAMEECS service name for the operations container
SchedulerStartExpressionvars.SCHEDULER_START_EXPRESSIONEventBridge cron/rate expression for the start schedule
SchedulerStopExpressionvars.SCHEDULER_STOP_EXPRESSIONEventBridge cron/rate expression for the stop schedule

Required Repository Variables

Configure these variables under Settings → Secrets and variables → Actions → Variables:
VariableDescription
WORKFLOW_SCHEDULER_ENABLEDSet to 'true' to enable this workflow; any other value skips all jobs
APP_NAMEApplication name prefix used in all CloudFormation resource names
EC2_INSTANCE_IDThe EC2 instance ID that runs the ECS tasks (e.g. i-0abc1234def56789)
EC2_ELASTIC_IP_IDAllocation ID of the Elastic IP (e.g. eipalloc-0abc1234)
ECS_CLUSTERFull name of the ECS cluster (e.g. dev-gsmapplication-cluster)
GATEWAY_SERVICE_NAMEFull ECS service name for the gateway (e.g. dev-gsmapplication-gateway-service)
AUTH_SERVICE_NAMEFull ECS service name for auth (e.g. dev-gsmapplication-auth-service)
APPLICATION_SERVICE_NAMEFull ECS service name for application (e.g. dev-gsmapplication-application-service)
OPERATIONS_SERVICE_NAMEFull ECS service name for operations (e.g. dev-gsmapplication-operations-service)
SCHEDULER_START_EXPRESSIONEventBridge cron for start (e.g. cron(0 8 ? * MON-FRI *))
SCHEDULER_STOP_EXPRESSIONEventBridge cron for stop (e.g. cron(0 20 ? * MON-FRI *))

Required Secret

SecretDescription
AWS_INFRA_ROLE_ARNARN of the IAM role to assume via OIDC (shared with the infrastructure workflow)
AWS_INFRA_ROLE_ARN must be stored as an Actions secret scoped to the infra-{env} GitHub Environment. The IAM role’s trust policy allows assumption only from the infra-* environment token claim, so the secret must live there — not at the repository level.

Full Workflow YAML

name: Deploy Scheduler
on:
  push:
    branches: ["develop", "quality", "main"]
    paths:
      - "devops/scheduler/template.yml"
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment (dev/qa/prod)'
        default: 'dev'

env:
  AWS_REGION: us-east-1

jobs:
  determine-env:
    if: ${{ vars.WORKFLOW_SCHEDULER_ENABLED == 'true' }}
    name: Determine Environment
    runs-on: ubuntu-latest
    outputs:
      environment: ${{ steps.set-env.outputs.environment }}
    steps:
      - name: Set Environment
        id: set-env
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            ENV="${{ github.event.inputs.environment }}"
          else
            BRANCH="${{ github.ref_name }}"
            if [ "$BRANCH" = "main" ]; then
              ENV="prod"
            elif [ "$BRANCH" = "quality" ]; then
              ENV="qa"
            elif [ "$BRANCH" = "develop" ]; then
              ENV="dev"
            else
              ENV="dev"
            fi
          fi
          echo "environment=$ENV" >> $GITHUB_OUTPUT
          echo "Deploying $ENV-gsmapplication-scheduler-stack"
  
  deploy:
    if: ${{ vars.WORKFLOW_SCHEDULER_ENABLED == 'true' }}
    name: Deploy Scheduler
    needs: determine-env
    runs-on: ubuntu-latest
    environment: infra-${{ needs.determine-env.outputs.environment }}
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}
      
      - name: Deploy CloudFormation Stack
        uses: aws-actions/aws-cloudformation-github-deploy@v1.2.0
        with:
          name: "${{ needs.determine-env.outputs.environment }}-${{ vars.APP_NAME }}-scheduler-stack"
          template: devops/scheduler/template.yml
          capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM
          region: ${{ env.AWS_REGION }}
          parameter-overrides: >-
            Environment="${{ needs.determine-env.outputs.environment }}",
            AppName="${{ vars.APP_NAME }}",
            EC2InstanceId="${{ vars.EC2_INSTANCE_ID }}",
            EIPAllocationId="${{ vars.EC2_ELASTIC_IP_ID }}",
            ECSClusterName="${{ vars.ECS_CLUSTER }}",
            GatewayServiceName="${{ vars.GATEWAY_SERVICE_NAME }}",
            AuthServiceName="${{ vars.AUTH_SERVICE_NAME }}",
            ApplicationServiceName="${{ vars.APPLICATION_SERVICE_NAME }}",
            OperationsServiceName="${{ vars.OPERATIONS_SERVICE_NAME }}",
            SchedulerStartExpression="${{ vars.SCHEDULER_START_EXPRESSION }}",
            SchedulerStopExpression="${{ vars.SCHEDULER_STOP_EXPRESSION }}"
          no-fail-on-empty-changeset: "1"

Build docs developers (and LLMs) love