Skip to content

chore(examples): integrate in CI flow with lint and build #446

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 18, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/run-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ jobs:
aws-region: eu-west-1
- name: Run integration tests
run: npm run lerna-test:e2e
- name: Test packaging
run: |
npm run lerna-package
cd examples/cdk
npm install ../../packages/**/dist/aws-lambda-powertools-*
npm run test
24 changes: 24 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,30 @@ You can run the end-to-end tests automatically on your forked project by followi
4. In the run-e2e-tests workflow page, select "Run workflow" and run it on the desired branch.

> :warning: **Don't automatically run end-to-end tests on branch push or PRs**. A malicious attacker can submit a pull request to attack your AWS account. Ideally, use a blank account without any important workload/data, and limit `AWS_ROLE_ARN_TO_ASSUME` permission to least minimum privilege.


### Examples

As part of the repo you will find an examples folder at the root. This folder contains examples (written with CDK for now) of deployable AWS Lambda functions using Powertools.

To test your updates with these examples you just have to:

1. Build your local version of *aws-lambda-powertools-typescript* npm packages with `npm run lerna-package`
1. Update their references in examples
```
cd examples/cdk
npm install ../../packages/**/dist/aws-lambda-powertools-*
```
1. Run cdk tests
```
npm run test
```
1. Deploy
```
npm run cdk deploy
```

Previous command will deploy AWS resources therefore you will need an AWS account and it might incur in some costs which should be covered by the [AWS Free Tier](https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all). If you don't have an AWS Account follow [these instructions to create one](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/).
### Conventions

Category | Convention
Expand Down
2 changes: 1 addition & 1 deletion examples/cdk/bin/cdk-app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { CdkAppStack } from '../lib/example-stack';
import { CdkAppStack } from '../src/example-stack';

const app = new cdk.App();
new CdkAppStack(app, 'CdkAppStack', {});
2 changes: 1 addition & 1 deletion examples/cdk/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/test'],
roots: ['<rootDir>/tests'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
Expand Down
24,276 changes: 7,048 additions & 17,228 deletions examples/cdk/package-lock.json

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions examples/cdk/package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
{
"name": "cdk-app",
"version": "0.1.0",
"version": "0.3.1",
"bin": {
"cdk-app": "bin/cdk-app.js"
},
"scripts": {
"build": "tsc --skipLibCheck",
"watch": "tsc -w",
"test": "jest",
"test": "npm run test:unit",
"package": "echo 'Not applicable'",
"test:unit": "npm run build && jest",
"test:e2e": "echo 'To be implemented ...'",
"cdk": "cdk"
},
"devDependencies": {
Expand All @@ -21,18 +24,19 @@
"typescript": "^4.1.3"
},
"dependencies": {
"@aws-lambda-powertools/commons": "^0.2.0",
"@aws-lambda-powertools/logger": "^0.2.0",
"@aws-lambda-powertools/metrics": "^0.2.0",
"@aws-lambda-powertools/tracer": "^0.2.0",
"@aws-lambda-powertools/commons": "^0.3.1",
"@aws-lambda-powertools/logger": "^0.3.1",
"@aws-lambda-powertools/metrics": "^0.3.1",
"@aws-lambda-powertools/tracer": "^0.3.1",
"@aws-sdk/client-sts": "^3.43.0",
"@middy/core": "^2.5.3",
"@middy/http-error-handler": "^2.5.3",
"@middy/http-json-body-parser": "^2.5.3",
"@middy/validator": "^2.5.3",
"@types/aws-lambda": "^8.10.86",
"aws-cdk-lib": "2.0.0",
"aws-sdk": "^2.1058.0",
"constructs": "^10.0.0",
"source-map-support": "^0.5.16"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const metrics = new Metrics({ namespace: namespace, serviceName: serviceName });
const logger = new Logger({ logLevel: 'INFO', serviceName: serviceName });
const tracer = new Tracer({ serviceName: serviceName });

const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => {
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context): Promise<unknown> => {
// ### Experiment with Logger
// AWS Lambda context is automatically injected by the middleware

Expand All @@ -32,7 +32,7 @@ const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: C
const metricWithItsOwnDimensions = metrics.singleMetric();
metricWithItsOwnDimensions.addDimension('InnerDimension', 'true');
metricWithItsOwnDimensions.addMetric('single-metric', MetricUnits.Percent, 50);

// ### Experiment with Tracer

// Service & Cold Start annotations will be added for you by the decorator/middleware
Expand All @@ -58,16 +58,18 @@ const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: C
tracer.setSegment(handlerSegment);
// The main segment (facade) will be closed for you at the end by the decorator/middleware
}

return res;
}
};

// We instrument the handler with the various Middy middlewares
export const handler = middy(lambdaHandler)
.use(captureLambdaHandler(tracer))
.use(logMetrics(metrics, {
captureColdStartMetric: true,
throwOnEmptyMetrics: true,
defaultDimensions: { environment: 'example', type: 'withDecorator' },
}))
.use(injectLambdaContext(logger));
.use(
logMetrics(metrics, {
captureColdStartMetric: true,
throwOnEmptyMetrics: true,
defaultDimensions: { environment: 'example', type: 'withDecorator' },
})
)
.use(injectLambdaContext(logger));
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer';
const tracer = new Tracer({ serviceName: 'tracerDisabledFn', enabled: false });

// In this example we are using the middleware pattern but the same applies also the captureLambdaHandler decorator or to manual instrumentation
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => {
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context): Promise<unknown> => {
// No tracing will be done and the commands will be ignored, this is useful for testing
tracer.putAnnotation('awsRequestId', context.awsRequestId);
tracer.putMetadata('eventPayload', event);

let res;
try {
res = { foo: 'bar' };
} catch (err) {
throw err;
}

return res;
}
};

export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ const tracer = new Tracer({ serviceName: 'tracerMiddlewareFn' });
// Alternatively, you can also set the service name using the POWERTOOLS_SERVICE_NAME environment variable
// Learn more at: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html

const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context) => {
const lambdaHandler = async (event: typeof Events.Custom.CustomEvent, context: Context): Promise<unknown> => {
// Add custom annotation & metadata
tracer.putAnnotation('awsRequestId', context.awsRequestId);
tracer.putMetadata('eventPayload', event);

let res;
try {
res = { foo: 'bar' };
} catch (err) {
throw err;
}

return res;
}
};

// We instrument the handler with the Middy middleware and the Tracer will automatically:
// * handle the lifecycle of the subsegment
// * create a ColdStart annotation to easily filter traces that have had an initialization overhead
// * create a Service annotation to easily filter traces that have a specific service name
// * captures any response, or full exceptions generated by the handler, and include them as tracing metadata
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ interface ExampleFunctionProps {
}

class ExampleFunction extends Construct {
public function: NodejsFunction;

public constructor(scope: Construct, id: string, props: ExampleFunctionProps) {
super(scope, id);
Expand All @@ -32,7 +31,7 @@ class ExampleFunction extends Construct {
onUpdate: {
service: 'Lambda',
action: 'invoke',
physicalResourceId: custom_resources.PhysicalResourceId.of(new Date().toISOString()),
physicalResourceId: custom_resources.PhysicalResourceId.of(`${functionName}-${i}`),
parameters: {
FunctionName: fn.functionName,
InvocationType: 'RequestResponse',
Expand Down
File renamed without changes.
7 changes: 0 additions & 7 deletions examples/cdk/test/cdk-app.test.ts

This file was deleted.

9 changes: 9 additions & 0 deletions examples/cdk/tests/cdk-app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import * as CdkApp from '../src/example-stack';

test('CDK code synthesize', () => {
const app = new cdk.App();
const stack = new CdkApp.CdkAppStack(app, 'MyTestStack');
Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 13);
});
45 changes: 23 additions & 22 deletions examples/cdk/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
{
"compilerOptions": {
"target": "ES2018",
"experimentalDecorators": true,
"noImplicitAny": true,
"target": "ES2020",
"module": "commonjs",
"skipLibCheck": true,
"lib": [
"es2018"
],
"declaration": true,
"outDir": "lib",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": false,
"inlineSourceMap": true,
"inlineSources": true,
"experimentalDecorators": true,
"strictPropertyInitialization": false,
"types": []
},
"exclude": [
"node_modules",
"cdk.out"
]
"moduleResolution": "node",
"resolveJsonModule": true,
"pretty": true,
"baseUrl": "src/",
"rootDirs": [ "src/" ],
"esModuleInterop": true
},
"include": [ "src/**/*" ],
"exclude": [ "./node_modules", "cdk.out"],
"watchOptions": {
"watchFile": "useFsEvents",
"watchDirectory": "useFsEvents",
"fallbackPolling": "dynamicPriority"
},
"lib": [ "es2020" ],
"types": [
"jest",
"node"
]
}
3 changes: 2 additions & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"packages": [
"packages/*"
"packages/*",
"examples/cdk"
],
"version": "0.3.1",
"npmClient": "npm",
Expand Down