AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Tinqs CI Orchestrator — webhook dispatch, Fargate routing, cancel support Parameters: GiteaURL: Type: String Default: https://tinqs.com GiteaToken: Type: String NoEcho: true ECSCluster: Type: String Default: tinqs-git Subnets: Type: CommaDelimitedList Description: VPC subnet IDs for Fargate tasks SecurityGroup: Type: String Description: Security group for Fargate tasks ECRBase: Type: String Default: 149751500842.dkr.ecr.eu-west-1.amazonaws.com TaskRoleArn: Type: String Default: arn:aws:iam::149751500842:role/tinqs-git-task ExecRoleArn: Type: String Default: arn:aws:iam::149751500842:role/ecsTaskExecutionRole Globals: Function: Runtime: provided.al2023 Architectures: [x86_64] Timeout: 30 MemorySize: 128 Resources: # --- API Gateway --- WebhookApi: Type: AWS::Serverless::Api Properties: Name: tinqs-ci-webhook StageName: prod # --- DynamoDB --- RunsTable: Type: AWS::DynamoDB::Table Properties: TableName: tinqs-ci-runs BillingMode: PAY_PER_REQUEST AttributeDefinitions: - AttributeName: repo AttributeType: S - AttributeName: run_id AttributeType: S KeySchema: - AttributeName: repo KeyType: HASH - AttributeName: run_id KeyType: RANGE TimeToLiveSpecification: AttributeName: ttl Enabled: true # --- Dispatcher Lambda --- DispatchFunction: Type: AWS::Serverless::Function Properties: FunctionName: tinqs-ci-dispatch Handler: bootstrap CodeUri: ../dispatch/ Description: Receives webhook, routes to Fargate or Lambda by runs-on label Timeout: 60 MemorySize: 256 Environment: Variables: GITEA_URL: !Ref GiteaURL GITEA_TOKEN: !Ref GiteaToken EXECUTOR_FUNCTION_NAME: !Ref ExecFunction ECS_CLUSTER: !Ref ECSCluster SUBNETS: !Join [",", !Ref Subnets] SECURITY_GROUP: !Ref SecurityGroup ECR_BASE: !Ref ECRBase DDB_TABLE: !Ref RunsTable TASK_ROLE_ARN: !Ref TaskRoleArn EXEC_ROLE_ARN: !Ref ExecRoleArn Policies: - LambdaInvokePolicy: FunctionName: !Ref ExecFunction - DynamoDBCrudPolicy: TableName: !Ref RunsTable - Version: '2012-10-17' Statement: - Effect: Allow Action: - ecs:RunTask - ecs:StopTask - ecs:RegisterTaskDefinition - ecs:DescribeTasks Resource: '*' - Effect: Allow Action: iam:PassRole Resource: - !Ref TaskRoleArn - !Ref ExecRoleArn Events: Webhook: Type: Api Properties: RestApiId: !Ref WebhookApi Path: /webhook Method: POST # --- Executor Lambda (deploy-only jobs) --- ExecFunction: Type: AWS::Serverless::Function Properties: FunctionName: tinqs-ci-exec Handler: bootstrap CodeUri: ../exec/ Description: Executes deploy-only workflow steps directly in Lambda Timeout: 900 MemorySize: 2048 EphemeralStorage: Size: 5120 Environment: Variables: GITEA_URL: !Ref GiteaURL GITEA_TOKEN: !Ref GiteaToken Policies: - S3CrudPolicy: BucketName: tinqs-cli-releases - S3CrudPolicy: BucketName: arikigame.com - S3CrudPolicy: BucketName: docs.tinqs.com - Version: '2012-10-17' Statement: - Effect: Allow Action: - ecs:UpdateService - ecs:DescribeServices Resource: !Sub 'arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:service/tinqs-git/*' - Effect: Allow Action: - cloudfront:CreateInvalidation Resource: '*' # --- Cleanup Cron (every 5 min) --- CleanupRule: Type: AWS::Events::Rule Properties: Name: tinqs-ci-cleanup ScheduleExpression: 'rate(5 minutes)' State: ENABLED Targets: - Id: cleanup Arn: !GetAtt DispatchFunction.Arn Input: '{"body":"{\"action\":\"cleanup\"}","headers":{}}' CleanupPermission: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref DispatchFunction Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: !GetAtt CleanupRule.Arn # --- Log Group --- CILogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: /ecs/tinqs-ci RetentionInDays: 14 Outputs: WebhookURL: Description: Configure this as Gitea system webhook Value: !Sub 'https://${WebhookApi}.execute-api.${AWS::Region}.amazonaws.com/prod/webhook' DispatchArn: Value: !GetAtt DispatchFunction.Arn ExecArn: Value: !GetAtt ExecFunction.Arn RunsTable: Value: !Ref RunsTable