packages/cdk/lib/github-actions-usage.ts (63 lines of code) (raw):

import type { GuStack } from '@guardian/cdk/lib/constructs/core'; import type { GuSecurityGroup } from '@guardian/cdk/lib/constructs/ec2'; import { GuLambdaFunction } from '@guardian/cdk/lib/constructs/lambda'; import { Duration } from 'aws-cdk-lib'; import type { IVpc } from 'aws-cdk-lib/aws-ec2'; import { ScheduledFargateTask } from 'aws-cdk-lib/aws-ecs-patterns'; import { Rule } from 'aws-cdk-lib/aws-events'; import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets'; import { Architecture, Runtime } from 'aws-cdk-lib/aws-lambda'; import type { DatabaseInstance } from 'aws-cdk-lib/aws-rds'; interface GithubActionsUsageProps { vpc: IVpc; db: DatabaseInstance; dbAccess: GuSecurityGroup; } export function addGithubActionsUsageLambda( scope: GuStack, props: GithubActionsUsageProps, ) { const app = 'github-actions-usage'; const { vpc, dbAccess, db } = props; const lambda = new GuLambdaFunction(scope, 'GithubActionsUsage', { app, vpc, architecture: Architecture.ARM_64, securityGroups: [dbAccess], fileName: `${app}.zip`, handler: 'index.main', environment: { DATABASE_HOSTNAME: db.dbInstanceEndpointAddress, QUERY_LOGGING: 'false', // Set this to 'true' to enable SQL query logging }, runtime: Runtime.NODEJS_20_X, timeout: Duration.minutes(10), }); // This sort of lookup is a bit fragile! // TODO pass the task in as a prop const task = scope.node.children.find( (_) => _ instanceof ScheduledFargateTask && _.taskDefinition.family.includes('GitHubRepositories'), ) as ScheduledFargateTask | undefined; if (!task) { throw new Error('Could not find the GitHubRepositories task'); } // Invoke the lambda when the GitHubRepositories task has completed successfully new Rule(scope, `${app}-lambda-trigger`, { targets: [new LambdaFunction(lambda)], enabled: true, eventPattern: { source: ['aws.ecs'], detailType: ['ECS Task State Change'], // See https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Task.html detail: { clusterArn: [task.cluster.clusterArn], taskDefinitionArn: [task.taskDefinition.taskDefinitionArn], lastStatus: ['STOPPED'], stopCode: ['EssentialContainerExited'], // The CloudQuery container is the "essential" one 'containers.exitCode': [{ numeric: ['=', 0] }], 'containers.name': [ task.taskDefinition.defaultContainer?.containerName, ], }, }, }); db.grantConnect(lambda, 'github_actions_usage'); }