This example PicoFun project demonstrates generating an AWS CDK Construct for the GitHub REST API with GitHub App authentication.
┌──────────────────────┐
│ Secrets Manager │
│ │
┌──────────────────┐ write │ picofun/githubapp/ │
│ Token Rotation │─────────────▶│ token │
│ Lambda │ │ app-credentials │
│ (every 30 min) │◀─────────────│ │
└──────────────────┘ read └──────────┬───────────┘
│ read token
▼
┌──────────────────────┐
│ API Lambdas │
│ (PicoFun-generated) │
│ │
│ Preprocessor adds │
│ Bearer token header │
└──────────┬───────────┘
│
▼
┌─────────────────────┐
│ GitHub REST API │
└─────────────────────┘
Token flow:
- A rotation Lambda runs every 30 minutes via an EventBridge schedule
- It reads the GitHub App credentials from Secrets Manager, generates a JWT, exchanges it for an installation token via the GitHub API, and writes the token back to Secrets Manager
- API Lambdas read the installation token from Secrets Manager (cached in-memory for 5 minutes) and set the
Authorization: Bearerheader via a preprocessor
- AWS CLI configured with appropriate credentials
- AWS CDK CLI
- Python 3.13+
- uv
- A GitHub App with:
- A generated private key (PEM format)
- The App ID and Installation ID
From the examples/github-app-cdk/ directory, generate the Lambda functions and CDK construct:
uv run picofun --config-file examples/github-app-cdk/picofun.toml --output-dir examples/github-app-cdk/output githubapp https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.jsonThis produces:
output/construct.py-- an L3 CDK Construct class (GithubappFunctions)output/lambdas/-- generated Lambda function filesoutput/layer/-- Lambda layer code (includes the preprocessor fromhelpers/)
cd examples/github-app-cdk
uv syncSynthesize the CloudFormation template:
uv run cdk synthDeploy:
uv run cdk deployAfter deployment, update the secrets with your GitHub App credentials:
aws secretsmanager update-secret \
--secret-id "picofun/githubapp/app-credentials" \
--secret-string "{\"private_key\": \"$(cat /path/to/your-app.pem)\", \"app_id\": \"YOUR_APP_ID\", \"installation_id\": \"YOUR_INSTALLATION_ID\"}"After configuring the secret, manually invoke the rotation Lambda to generate the first installation token:
aws lambda invoke \
--function-name $(aws cloudformation describe-stacks \
--stack-name GitHubAppLambdas \
--query 'Stacks[0].Outputs[?OutputKey==`RotationFunctionArn`].OutputValue' \
--output text) \
/dev/stdoutThe EventBridge schedule will then rotate the token every 30 minutes automatically.
The generated construct exposes a functions property (dict[str, lambda_.Function]) for wiring into Step Functions or other CDK constructs:
from output.construct import GithubappFunctions
github_api = GithubappFunctions(self, "GithubappFunctions")
# Wire a specific function into a Step Function task
get_repo_task = sfn_tasks.LambdaInvoke(
self, "GetRepo",
lambda_function=github_api.functions["get_repos_owner_repo"],
)The construct also exposes a role property for the shared IAM role.
Example event payload for getting a repository:
{
"pathParameters": {
"owner": "proactiveops",
"repo": "picofun"
}
}Invoke via the AWS CLI:
aws lambda invoke \
--function-name <function-name-from-stack-outputs> \
--payload '{"pathParameters": {"owner": "proactiveops", "repo": "picofun"}}' \
/dev/stdout