"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SourceWatcher = void 0;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
const path = require("path");
class SourceWatcher extends constructs_1.Construct {
    constructor(scope, id, props) {
        super(scope, id);
        const stack = aws_cdk_lib_1.Stack.of(this);
        // Each trigger will create a StringList parameter in SSM. This way the lambda can get a dynamic list based on
        // the infrastructure instead of hardcoding in the lambda itself.
        const triggersSsmPath = `/all/stacks/${stack.stackName}/triggers`;
        props.triggers.forEach(trigger => {
            new aws_cdk_lib_1.aws_ssm.StringListParameter(this, `TriggerParam_${trigger.pipelineStackName}`, {
                parameterName: `${triggersSsmPath}/${trigger.pipelineStackName}`,
                description: 'Glob patterns for file paths in the infrastructure repo which will trigger the pipeline.',
                stringListValue: trigger.triggerPatterns,
            });
        });
        // Get the secret which is used to validate the signature of the event payload
        const webhookSecret = aws_cdk_lib_1.SecretValue.secretsManager(props.gitTokenPath, { jsonField: 'webhook-secret' });
        this.lambdaFunction = new aws_cdk_lib_1.aws_lambda.Function(this, 'SourceWatcherLambda', {
            code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, './internal-lambdas/sourceWatcherLambda/src')),
            description: 'Checks if git push changed certain files and triggers pipeline(s) accordingly.',
            handler: 'index.handler',
            runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_22_X,
            timeout: aws_cdk_lib_1.Duration.minutes(1),
            environment: {
                WEBHOOK_SECRET: webhookSecret.toString(),
                TRIGGER_PARAMS_PATH: triggersSsmPath,
                GIT_REPO: props.targetRepo,
                GIT_BRANCH: props.targetBranch,
            },
        });
        // Allow lambda to read params we created specifying the trigger metadata.
        this.lambdaFunction.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
            resources: [
                aws_cdk_lib_1.Fn.sub('arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter' + triggersSsmPath + '/*'),
            ].concat(props.triggers.map(trigger => aws_cdk_lib_1.Fn.sub('arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/all/stacks/' +
                trigger.pipelineStackName +
                '/pipeline-name'))),
            actions: ['ssm:GetParameter', 'ssm:GetParameters'],
        }));
        this.lambdaFunction.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
            resources: [aws_cdk_lib_1.Fn.sub('arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter' + triggersSsmPath)],
            actions: ['ssm:GetParametersByPath'],
        }));
        this.lambdaFunction.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
            resources: ['*'],
            actions: ['codepipeline:StartPipelineExecution'],
        }));
        // The API gateway will serve an endpoint which we can hit in a github webhook to trigger the lambda
        this.api = new aws_cdk_lib_1.aws_apigateway.LambdaRestApi(this, 'SourceWatcherApi', {
            handler: this.lambdaFunction,
            proxy: true,
        });
        // Added the following code to get the WebhookLambdaArn from either a parameter store path or a stack name.  (Used to be only from stack name)
        let githubWebhookLambdaArn = '';
        if (props.webhookResourceArnParameterPath) {
            githubWebhookLambdaArn = aws_ssm_1.StringParameter.valueForStringParameter(this, props.webhookResourceArnParameterPath);
        }
        if (!githubWebhookLambdaArn && props.webhookResourceStackName) {
            githubWebhookLambdaArn = aws_cdk_lib_1.Fn.importValue(`${props.webhookResourceStackName}:LambdaArn`);
        }
        if (!githubWebhookLambdaArn) {
            throw new Error('You must provide a webhookResourceArnParameterPath or webhookResourceStackName to create a GitHub webhook.');
        }
        // Finally, create the Webhook on GitHub to route push events to the API!
        const webhookLambda = aws_cdk_lib_1.aws_lambda.Function.fromFunctionAttributes(this, 'GithubWebhookLambda', {
            functionArn: githubWebhookLambdaArn,
            skipPermissions: true,
        });
        const resourceProvider = new aws_cdk_lib_1.custom_resources.Provider(this, 'WebhookProvider', {
            onEventHandler: webhookLambda,
            logRetention: aws_cdk_lib_1.aws_logs.RetentionDays.ONE_WEEK,
        });
        const webhook = new aws_cdk_lib_1.CustomResource(this, 'GithubWebhook', {
            resourceType: 'Custom::GitHubWebhook',
            serviceToken: resourceProvider.serviceToken,
            properties: {
                Repo: props.targetRepo,
                Events: 'push',
                Endpoint: this.api.url,
            },
        });
        this.webhookId = webhook.getAtt('WebhookId').toString();
        new aws_cdk_lib_1.CfnOutput(this, 'WebhookId', {
            description: 'ID used by provider (GitHub) to identify the webhook.',
            value: this.webhookId,
        });
    }
}
exports.SourceWatcher = SourceWatcher;
