Appearance
Connecting GitHub
pipeline.source: github builds from a GitHub repository, and a private one is reached through an AWS CodeConnections connection. Setting one up is four steps, two of which have a wrong answer that produces a working-looking connection and a failing build.
This is the procedure for both an organization and a personal account. They differ in one field.
What has to be true
Three things, and Keel can verify only the first:
- A connection exists and is
AVAILABLE, recorded at/keel/connections/github/{owner}. - That connection is bound to a GitHub App installation which can see the repository. Not to a GitHub user — see below.
- The account has a GitHub source credential naming that connection. This is what CodeBuild reads when it creates a build project.
keel auth connect github {owner} does 1 and 3. Step 2 happens in a browser and is the one that goes wrong.
The owner comes from keel.yml
Keel derives it from pipeline.repo:
yaml
pipeline:
source: github
repo: devtide-llc/keel-test # owner is "devtide-llc"
branch: mainThat owner names the connection (keel-devtide-llc) and keys the SSM parameter. It is a label, not a boundary. CreateConnection takes only a name and a provider type — AWS is never told which organization you meant, and nothing constrains where the App is installed. A personal repo works the same way with repo: {username}/{repo}.
Procedure
1. Install the App where the repository is
Do this first. It removes the step where the wrong answer is easiest to give.
- Organization: https://github.com/apps/aws-connector-for-github → Install → choose the organization → All repositories or select the ones Keel may clone. Verify at
https://github.com/organizations/{org}/settings/installations. - Personal account: the same page, choosing your own account. Verify at https://github.com/settings/installations.
If you have installations you do not want used, remove them now. The AWS console lists installations by opaque numeric ID rather than by account name, so the reliable way to pick the right one is for it to be the only one.
2. Create the connection
bash
keel auth connect github {owner}It creates the connection PENDING, records the ARN in SSM, prints a console URL and waits. An existing connection is reused rather than duplicated.
3. Authorize, in the browser
Open the printed URL, choose the connection, and select Update pending connection. Two screens follow and only the second one decides anything:
github.com/login/oauth/authorize — "AWS Connector for GitHub wants access to your GitHub account", verifying your GitHub identity. There is no organization option here and that is correct: identities are personal. Click Authorize.
Back in the AWS console — "GitHub connection settings". This is the decision:
App Installation - optional
Install GitHub App to connect as a bot. Alternatively, leave it blank to
connect as a GitHub user, which can be used in AWS CodeBuild projects.Choose the installation. Do not leave it blank. The field is marked optional and the help text says a blank one works with CodeBuild; in practice a user-bound connection reaches AVAILABLE and then fails every CreateProject. If the picker is empty, use Install a new app — GitHub then shows an account picker, and that is where you choose the organization rather than your personal account.
Then Connect.
4. Apply
bash
keel up --env {env}keel auth connect has already registered the account's GitHub source credential, so nothing else is needed.
Verifying, and what Keel cannot tell you
AVAILABLE means an installation is bound. It does not say which one. No CodeConnections API returns the install target — not GetConnection, and not CreateRepositoryLink, which accepts an owner and repository as plain strings and does no reachability check at all. So Keel reports the status it can read and names where you check the rest:
bash
# the connection Keel will use
aws ssm get-parameter --name /keel/connections/github/{owner} \
--query Parameter.Value --output text
# the account's source credential — CodeBuild reads this, not the project
aws codebuild list-source-credentialsThe installation itself is only visible on GitHub, at the organization's or your own installations page.
When it goes wrong
OAuthProviderException: User is not authorized to access connection {arn}
Raised by CreateProject during keel up. The message names the connection and is usually not about the connection — which is what makes it expensive. Check in this order:
- The account's source credential.
aws codebuild list-source-credentialsshould return aGITHUBentry. Absent, re-runkeel auth connect github {owner}, which registers it, or:bashaws codebuild import-source-credentials --server-type GITHUB \ --auth-type CODECONNECTIONS --token {connection-arn} - Whether the connection is bound to a user rather than an installation. Not readable from AWS. If the App Installation field was left blank in step 3, delete the connection, delete
/keel/connections/github/{owner}, and redo steps 2–3. - Whether the installation can see the repository — the organization's installations page, Repository access.
A stale keel-admin policy is worth ruling out once, and rarely the answer:
bash
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::{account}:role/keel-admin \
--action-names codestar-connections:PassConnection \
--resource-arns {connection-arn} --query 'EvaluationResults[0].EvalDecision'implicitDeny means re-run keel auth setup, which rewrites the policies.
The build creates and then fails to clone
The project exists, so the credential is right; the installation cannot see the repository. Check Repository access on the installation.
keel auth connect says the connection already exists and exits
Reuse rather than repair, by design — but it does re-register the account credential on every run, so it is the right thing to try first. If the connection itself is wrong, delete it and the SSM parameter before re-running:
bash
aws codeconnections delete-connection --connection-arn {arn}
aws ssm delete-parameter --name /keel/connections/github/{owner}Why CodeBuild works this way
Worth knowing, because the obvious design is the wrong one and reads as correct.
A CodeBuild project can carry a per-source auth block naming a connection, and CODECONNECTIONS is a valid type there. It does not work: CreateProject fails with the OAuthProviderException above while the connection, the caller's PassConnection, the service role's UseConnection and the App installation are all correct. Established by creating one project twice with the same service role, differing only in that block — without it the project is created, with it the call fails.
What CodeBuild reads is ImportSourceCredentials: one credential per account, per region, per server type. Keel writes it from keel auth connect rather than from an application's stack, because two applications in one account would otherwise contend for a single resource and either one's keel destroy would take the other's builds with it — the same reason the account-wide DynamoDB tables are not in the stack.
The consequence to keep in view: that credential is account-wide, so connecting a second owner overwrites it. One GitHub account or organization per AWS account and region, for now.
No connection at all
A public repository clones without one, and keel up says so rather than failing. pipeline.source: codecommit avoids GitHub entirely — keel up creates the repository and keel deploy pushes to it — which is also the quickest way to get an environment up while a connection problem is being sorted out.