Manage GitHub resources like repositories, teams, members, integrations and workflows with the AWS CDK as Custom Resources in CloudFormation with cdk-github.
You configure the endpoint, method and parameters documented by @octokit/rest and AWS CloudFormation runs them anytime you create, update (if you changed the custom resource), or delete stacks. When CloudFormation sends a lifecycle event notification, then your custom resource sends the request to the GitHub REST API.
TypeScript
npm install @pepperize/cdk-githubor
yarn add @pepperize/cdk-githubPython
pip install pepperize.cdk-githubC#
dotnet add package Pepperize.CDK.Github
Java
<dependency>
<groupId>com.pepperize</groupId>
<artifactId>cdk-github</artifactId>
<version>${cdkGithub.version}</version>
</dependency>Contributions of all kinds are welcome 🚀 Check out our contributor's guide.
For a quick start, fork and check out a development environment:
git clone git@github.com:pepperize/cdk-github
cd cdk-github
# install dependencies
yarn
# build with projen
yarn buildCreate an AWS Secrets Manager secret
{ "appId": "123456", "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nExample==\n-----END RSA PRIVATE KEY-----", "installationId": "12345678" }Add @pepperize/cdk-github to your project dependencies
yarn add @pepperize/cdk-github
Add your
main.tsconstapp=newApp();conststack=newStack(app,"GithubCustomResources");
Just for simplicity, it's up to you how to organize your app 😉
Import your secret
constsecret=secrets_manager.Secret.fromSecretNameV2(stack,"Auth","cdk-github/github-token");
Configure GitHub App authenticate as an installation
constauthOptions=AuthOptions.appAuth(secret);
Add your first GitHub Custom Resource with the AWS CDK
newGithubCustomResource(stack,"GithubRepo",{onCreate: {// 👇The endpoint of the GitHub API.endpoint: "repos",// 👇The method of the GitHub API.method: "createInOrg",// https://octokit.github.io/rest.js/v19/#repos-create-in-orgparameters: {// 👇The request parameters to send.org: "pepperize",name: "cdk-github",},// 👇The object keys from the GitHub API response to return to CFN.outputPaths: ["id","full_name"],// 👇This becomes the CFN Physical ID visible in the Console.physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("full_name"),// 👇Don't throw an error if message matching this regex.ignoreErrorCodesMatching: "name already exists on this account",},// 👇The implemented authentication strategy.authOptions: AuthOptions.appAuth(secret),});
Deploy your first GitHub Custom Resource
npx cdk deploy
Configure the AWS SecretsManager Secret with the AuthOptions that will be passed to octokit.auth. i.e. as an installation:
{
"appId": "123456",
"privateKey": "-----BEGIN RSA PRIVATE KEY-----\nExample==\n-----END RSA PRIVATE KEY-----",
"installationId": "12345678"
}Lookup the secret in your AWS CDK app:
// 👇Lookup your secret containing the AuthOptionsconstsecret=secrets_manager.Secret.fromSecretNameV2(stack,"Auth","cdk-github/github-token");// 👇This will send the secret arn to the custom resource handlerconstauthOptions=AuthOptions.appAuth(secret);The custom resource handler will configure octokit.js with the createAppAuth:
constgetSecretValueResponse=awaitSSM.getSecretValue({SecretId: secret}).promise();constoctokitOptions: OctokitOptions={authStrategy: createAppAuth,auth: (auth=JSON.parse(getSecretValueResponse.SecretString)),};Supported through @octokit/auth-app
Just add your PAT to an SSM StringParameter
// 👇Lookup your parameter containing the TOKENconstparameter=ssm.StringParameter.fromStringParameterName(stack,"Auth","cdk-github/github-token");// 👇This will send the parameter arn to the custom resource handlerconstauthOptions=AuthOptions.tokenAuth(parameter);Supported through @octokit/auth-token
// 👇This will configure octokit without authenticationconstauthOptions=AuthOptions.unauthenticated();@octokit/plugin-rest-endpoint-methods
constauth=secrets_manager.Secret.fromSecretNameV2(stack,"Auth","cdk-github/github-token");constrepo=newGithubCustomResource(stack,"GithubRepo",{onCreate: {// https://octokit.github.io/rest.js/v19/#repos-create-in-orgendpoint: "repos",method: "createInOrg",parameters: {org: "pepperize",name: "cdk-github",},outputPaths: ["id","full_name"],physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("full_name"),ignoreErrorCodesMatching: "name already exists on this account",},onUpdate: {// https://octokit.github.io/rest.js/v19#repos-getendpoint: "repos",method: "get",parameters: {owner: "pepperize",repo: "cdk-github",},outputPaths: ["id","full_name"],physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("full_name"),},onDelete: {// https://octokit.github.io/rest.js/v19#repos-deleteendpoint: "repos",method: "delete",parameters: {owner: "pepperize",repo: "cdk-github",},outputPaths: [],},authOptions: AuthOptions.appAuth(auth),});// 👇 This will return the created repository id as a CDK Tokenrepo.getAtt("id");Manages an environment secret. Will fetch the source AWS SecretsManager secret and encrypt it to store in GitHub.
// 👇The GitHub API authentication secretconstauth=secrets_manager.Secret.fromSecretNameV2(scope,"Auth","cdk-github/github-token");// 👇The AWS SecretsManager Secret to configure as GitHub Action secret.constsecret=secrets_manager.Secret.fromSecretNameV2(scope,"Secret","any-secret/example");newGithubActionsSecretEnvironment(scope,"GithubRepo",{// 👇The repository id, which you may lookup from the page source or via a custom resourcerepositoryId: "558989134",environmentName: "production",// 👇The name of the created GitHub secretsecretName: "example",// 👇The source AWS SecretsManager secret and JSON field to usesource: GithubActionsSecret.fromSecretsManager(secret,"some-json-field"),authOptions: AuthOptions.appAuth(auth),// 👇Whether to delete or retain the GitHub secret on resource removalremovalPolicy: RemovalPolicy.DESTROY,});You may retrieve the
repository_idfrom the GitHub Repository page source's meta tag i.e.<meta name="octolytics-dimension-repository_id" content="558989134">or from anotherGithubCustomResourceviagetAtt().
See GitHub Developer Guide, API Reference
Manage an GitHib Actions organization secret. Will fetch the source AWS SecretsManager secret and encrypt it to store in GitHub.
// 👇The GitHub API authentication secretconstauth=secrets_manager.Secret.fromSecretNameV2(scope,"Auth","cdk-github/github-token");// 👇The AWS SecretsManager Secret to configure as GitHub Action secret.constsecret=secrets_manager.Secret.fromSecretNameV2(scope,"Secret","any-secret/example");newGithubActionsSecretOrganization(scope,"GithubRepo",{organizationName: "pepperize",// 👇The name of the created GitHub secretsecretName: "example",// 👇The source AWS SecretsManager secret and JSON field to usesource: GithubActionsSecret.fromSecretsManager(secret,"some-json-field"),visibility: Visibility.ALL,authOptions: AuthOptions.appAuth(auth),// 👇Whether to delete or retain the GitHub secret on resource removalremovalPolicy: RemovalPolicy.DESTROY,});See GitHub Developer Guide, API Reference
Manage an GitHib Actions Repository secret. Will fetch the source AWS SecretsManager secret and encrypt it to store in GitHub.
// 👇The GitHub API authentication secretconstauth=secrets_manager.Secret.fromSecretNameV2(scope,"Auth","cdk-github/github-token");// 👇The AWS SecretsManager Secret to configure as GitHub Action secret.constsecret=secrets_manager.Secret.fromSecretNameV2(scope,"Secret","any-secret/example");newGithubActionsSecretRepository(scope,"GithubRepo",{owner: "pepperize",repositoryName: "cdk-github",// 👇The name of the created GitHub secretsecretName: "example",// 👇The source AWS SecretsManager secret and JSON field to usesource: GithubActionsSecret.fromSecretsManager(secret,"some-json-field"),authOptions: AuthOptions.appAuth(auth),// 👇Whether to delete or retain the GitHub secret on resource removalremovalPolicy: RemovalPolicy.DESTROY,});