Skip to content

Commit 77d9ff4

Browse files
committed
updates
1 parent 9f8b37d commit 77d9ff4

File tree

15 files changed

+4769
-0
lines changed

15 files changed

+4769
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.js
2+
!jest.config.js
3+
*.d.ts
4+
node_modules
5+
6+
# CDK asset staging directory
7+
.cdk.staging
8+
cdk.out
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.ts
2+
!*.d.ts
3+
4+
# CDK asset staging directory
5+
.cdk.staging
6+
cdk.out
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Welcome to your CDK TypeScript project
2+
3+
This is a blank project for CDK development with TypeScript.
4+
5+
The `cdk.json` file tells the CDK Toolkit how to execute your app.
6+
7+
## Useful commands
8+
9+
* `npm run build` compile typescript to js
10+
* `npm run watch` watch for changes and compile
11+
* `npm run test` perform the jest unit tests
12+
* `npx cdk deploy` deploy this stack to your default AWS account/region
13+
* `npx cdk diff` compare deployed stack with current state
14+
* `npx cdk synth` emits the synthesized CloudFormation template
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import * as cdk from "aws-cdk-lib";
5+
import * as lambda from "aws-cdk-lib/aws-lambda";
6+
import * as iam from "aws-cdk-lib/aws-iam";
7+
import * as events from "aws-cdk-lib/aws-events";
8+
import * as targets from "aws-cdk-lib/aws-events-targets";
9+
import { Construct } from "constructs";
10+
import * as path from "path";
11+
12+
const repoName = "AWSDocsSdkExamplesPublic";
13+
const awsRegion = "us-west-2";
14+
15+
class CodeCommitCloneStack extends cdk.Stack {
16+
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
17+
super(scope, id, props);
18+
19+
// Initialize Lambda function
20+
const cloneLambda = this.initCloneLambda();
21+
22+
// Set up EventBridge rule to trigger Lambda on CodeCommit repository changes
23+
this.initCodeCommitTrigger(cloneLambda);
24+
}
25+
26+
private initCloneLambda(): lambda.Function {
27+
// IAM Role and Policy for Lambda to access CodeCommit
28+
const lambdaExecutionRole = new iam.Role(this, "CloneLambdaExecutionRole", {
29+
assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
30+
description: "Execution role for Lambda function to clone CodeCommit repo",
31+
managedPolicies: [
32+
iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole"),
33+
],
34+
});
35+
36+
// Grant necessary permissions to CodeCommit and S3
37+
lambdaExecutionRole.addToPolicy(
38+
new iam.PolicyStatement({
39+
actions: [
40+
"codecommit:GetRepository",
41+
"codecommit:GitPull",
42+
"codecommit:GetBranch",
43+
"codecommit:GetDifferences",
44+
"codecommit:GetFile"
45+
],
46+
resources: [`arn:aws:codecommit:${awsRegion}:${this.account}:${repoName}`],
47+
})
48+
);
49+
50+
// Grant necessary permissions to S3 bucket "codeexamplestats" for Get and Put
51+
lambdaExecutionRole.addToPolicy(
52+
new iam.PolicyStatement({
53+
actions: ["s3:GetObject", "s3:PutObject"],
54+
resources: [`arn:aws:s3:::codeexamplestats/*`], // Allow access to all objects in the bucket
55+
})
56+
);
57+
58+
// Define the Lambda function, pointing directly to the source code directory
59+
const cloneLambda = new lambda.Function(this, "CodeCommitCloneLambda", {
60+
runtime: lambda.Runtime.PYTHON_3_9,
61+
handler: "index.lambda_handler",
62+
code: lambda.Code.fromAsset(path.join(__dirname, "lambda")), // Pointing to the directory of the lambda function code
63+
environment: {
64+
REPO_NAME: repoName,
65+
},
66+
timeout: cdk.Duration.minutes(5),
67+
role: lambdaExecutionRole,
68+
});
69+
70+
return cloneLambda;
71+
}
72+
73+
private initCodeCommitTrigger(cloneLambda: lambda.Function): void {
74+
// Create EventBridge rule for CodeCommit repository updates
75+
const codeCommitRule = new events.Rule(this, "CodeCommitUpdateRule", {
76+
eventPattern: {
77+
source: ["aws.codecommit"],
78+
detailType: ["CodeCommit Repository State Change"],
79+
resources: [`arn:aws:codecommit:${awsRegion}:${this.account}:${repoName}`],
80+
detail: {
81+
event: [
82+
"referenceCreated",
83+
"referenceUpdated",
84+
"referenceDeleted"
85+
]
86+
}
87+
}
88+
});
89+
90+
// Add Lambda function as the target of the EventBridge rule
91+
codeCommitRule.addTarget(new targets.LambdaFunction(cloneLambda));
92+
}
93+
}
94+
95+
const app = new cdk.App();
96+
new CodeCommitCloneStack(app, "CodeCommitCloneStack", {
97+
env: {
98+
account: process.env.CDK_DEFAULT_ACCOUNT,
99+
region: "us-west-2", // Where codecommit is stored
100+
},
101+
});
102+
app.synth();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
# Define paths
3+
LAMBDA_DIR="lambda" # Directory where your Lambda function code is
4+
BUILD_DIR="build" # Temporary directory to install dependencies
5+
OUTPUT_ZIP="lambda_package.zip" # Final zip package
6+
7+
# Clean up any previous builds
8+
rm -rf $BUILD_DIR $OUTPUT_ZIP
9+
mkdir -p $BUILD_DIR/python
10+
11+
# Install dependencies to the build directory
12+
pip install -r $LAMBDA_DIR/requirements.txt -t $BUILD_DIR/python
13+
14+
# Copy Lambda code to the build directory
15+
cp -r $LAMBDA_DIR/* $BUILD_DIR/python
16+
17+
# Zip everything in the build directory into the output zip
18+
cd $BUILD_DIR/python && zip -r ../../$OUTPUT_ZIP . && cd ../../
19+
20+
# Clean up build directory
21+
rm -rf $BUILD_DIR
22+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"app": "npx ts-node app.ts"
3+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"fileLocations": [
3+
{
4+
"URIs": [
5+
"s3://codeexamplestats/stats.csv"
6+
]
7+
}
8+
],
9+
"globalUploadSettings": {
10+
"format": "CSV",
11+
"delimiter": ",",
12+
"textqualifier": "\"",
13+
"containsHeader": "true"
14+
}
15+
}
16+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
roots: ['<rootDir>/test'],
4+
testMatch: ['**/*.test.ts'],
5+
transform: {
6+
'^.+\\.tsx?$': 'ts-jest'
7+
}
8+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import boto3
2+
import os
3+
import tempfile
4+
from io import BytesIO, StringIO
5+
import json
6+
import csv
7+
from datetime import datetime # Import datetime module
8+
9+
def lambda_handler(event, context):
10+
# Initialize boto3 clients
11+
codecommit = boto3.client("codecommit", region_name=os.environ["AWS_REGION"])
12+
s3 = boto3.client("s3")
13+
14+
# Environment variables
15+
repo_name = os.environ.get("REPO_NAME")
16+
branch_name = os.environ.get("BRANCH_NAME", "mainline") # Default to "mainline"
17+
bucket_name = "codeexamplestats"
18+
csv_file_key = "stats.csv"
19+
20+
try:
21+
# Step 1: Retrieve the .stats file content directly from CodeCommit
22+
file_response = codecommit.get_file(
23+
repositoryName=repo_name,
24+
filePath='.stats', # Specify the path to the .stats file
25+
commitSpecifier=branch_name
26+
)
27+
28+
# Convert .stats content to valid JSON if necessary
29+
file_content = file_response['fileContent'].decode("utf-8")
30+
try:
31+
stats_data = json.loads(file_content) # Valid JSON parsing
32+
except json.JSONDecodeError:
33+
file_content = file_content.replace("'", "\"") # Replace single quotes
34+
stats_data = json.loads(file_content)
35+
36+
# Step 2: Fetch the current stats.csv file from S3
37+
existing_rows = []
38+
try:
39+
csv_obj = s3.get_object(Bucket=bucket_name, Key=csv_file_key)
40+
csv_data = csv_obj['Body'].read().decode('utf-8')
41+
csv_reader = csv.DictReader(StringIO(csv_data))
42+
existing_rows = list(csv_reader)
43+
except s3.exceptions.NoSuchKey:
44+
existing_rows = []
45+
46+
# Step 3: Append the new data from .stats file with a formatted timestamp
47+
new_row = {
48+
'sdks': stats_data['sdks'],
49+
'services': stats_data['services'],
50+
'examples': stats_data['examples'],
51+
'versions': stats_data['versions'],
52+
'snippets': stats_data['snippets'],
53+
'genai_none': stats_data['genai']['none'],
54+
'genai_some': stats_data['genai']['some'],
55+
'genai_most': stats_data['genai']['most'],
56+
'timestamp': datetime.now().strftime("%d/%m/%Y %H:%M:%S") # Formatted timestamp
57+
}
58+
existing_rows.append(new_row)
59+
60+
# Step 4: Save the updated data back to CSV and upload it to S3
61+
with StringIO() as output:
62+
# Include 'timestamp' in fieldnames to write the timestamp in the CSV
63+
writer = csv.DictWriter(output, fieldnames=new_row.keys())
64+
writer.writeheader() # Ensure we have headers
65+
writer.writerows(existing_rows)
66+
s3.put_object(Bucket=bucket_name, Key=csv_file_key, Body=output.getvalue().encode('utf-8'))
67+
68+
print("Successfully updated stats.csv in S3 with new .stats data.")
69+
70+
except Exception as e:
71+
print(f"Error occurred: {e}")
72+
return {"statusCode": 500, "body": "Failed to update stats.csv."}
73+
74+
return {"statusCode": 200, "body": "stats.csv updated successfully in S3."}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pandas
2+
numpy

0 commit comments

Comments
 (0)