Skip to content

feat(github-app): use ssm manifest for extra apps - #5282

Merged
guicaulada merged 2 commits into
mainfrom
gc/feat/github-apps-manifest
Sep 8, 2026
Merged

feat(github-app): use ssm manifest for extra apps#5282
guicaulada merged 2 commits into
mainfrom
gc/feat/github-apps-manifest

Conversation

@guicaulada

@guicaulada guicaulada commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Description

Follow-up to #5269, as promised in the #5038 review (items 1, 3, 4, and 5). We run this design in production.

  • Deliver additional GitHub App credentials via an SSM manifest parameter instead of colon-joined parameter names in the lambda environment. Lambda's total environment limit is 4 KB, which the colon-joined lists hit at roughly 15–20 apps with typical parameter paths; the manifest keeps the environment constant regardless of app count (Intelligent-Tiering covers manifests beyond the 4 KB standard parameter tier).
  • Removes the positional list alignment between id/key/installation-id parameter names, which could silently shift installation ids across apps if the lists drifted.
  • Rate-limit metric reads app ids from already-loaded credentials (getLoadedAppId) instead of re-reading SSM per app index; out-of-range indexes no longer throw inside the swallowed catch.
  • Documents that additional apps must be installed on the same orgs/repos as the primary app, in a new "Distributing load across multiple GitHub Apps" section of the rate-limits guide.

Internal contract only: Terraform and the lambdas deploy together, so the env transport change is invisible to module users. additional_github_apps is unchanged.

Test Plan

  • control-plane: 346 tests passed, including rewritten manifest-based credential loading tests.
  • terraform fmt/validate clean on root, runners, multi-runner, ssm; terraform test in modules/runners passes.
  • ESLint + Prettier clean; READMEs regenerated with terraform-docs.

Related Issues

Follow-up to #5269 / #5038.

@guicaulada
guicaulada requested review from a team as code owners August 19, 2026 18:01
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Brend-Smits
Brend-Smits previously approved these changes Sep 8, 2026

@Brend-Smits Brend-Smits left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed and dev-deployed on a sandbox multi-runner stack. The env→manifest transport works end-to-end: scale-up/scale-down load credentials via the new gh-auth path with no errors, a runner scaled up and self-terminated cleanly.

The branch is behind main and needs a rebase, the only conflicts are in modules/multi-runner/{main.tf,termination-watcher.tf} from the effective_config refactor (#5342), resolved by keeping the effective-config wiring and swapping github_app_parameters.id[0]/key_base64[0] → the new scalar shape.

LGTM once rebased.

guicaulada added a commit that referenced this pull request Sep 8, 2026
## Description

Follow-up to #5269, item 2 of the [#5038
review](#5038 (review)).
Stacked on #5282 (manifest transport); review that first.

Replaces uniform random GitHub App selection with budget-aware
selection, ported from our production fork:

- The auth module tracks the last observed `x-ratelimit-remaining` per
app, fed by `metricGitHubAppRateLimit` headers and the throttling plugin
callbacks.
- Selection picks the app with the most budget remaining; apps with no
observed state are assumed full.
- Apps that hit a secondary rate limit are skipped for 60 seconds; if
every app is cooling down, the one with the most budget is used anyway.
- Iteration starts at a random offset so concurrent cold-started lambdas
do not converge on the same app.

Uniform random kept sending ~1/N of traffic to apps that were already
exhausted. Selection state is per warm container and converges within a
few invocations; a cold container starts as before.

## Test Plan

- control-plane: 353 tests passed, including six new selection tests
(budget preference, unobserved-assumed-full, cooldown skip, all-cooling
fallback, single-app short-circuit, explicit appIndex) and a
selector-feed test for the rate-limit headers.
- ESLint + Prettier clean.

## Related Issues

Follow-up to #5269 / #5038. Depends on #5282.
guicaulada added a commit that referenced this pull request Sep 8, 2026
## Description

Follow-up to #5269, item 2 of the [#5038
review](#5038 (review)).
Stacked on #5282 (manifest transport); review that first.

Replaces uniform random GitHub App selection with budget-aware
selection, ported from our production fork:

- The auth module tracks the last observed `x-ratelimit-remaining` per
app, fed by `metricGitHubAppRateLimit` headers and the throttling plugin
callbacks.
- Selection picks the app with the most budget remaining; apps with no
observed state are assumed full.
- Apps that hit a secondary rate limit are skipped for 60 seconds; if
every app is cooling down, the one with the most budget is used anyway.
- Iteration starts at a random offset so concurrent cold-started lambdas
do not converge on the same app.

Uniform random kept sending ~1/N of traffic to apps that were already
exhausted. Selection state is per warm container and converges within a
few invocations; a cold container starts as before.

## Test Plan

- control-plane: 353 tests passed, including six new selection tests
(budget preference, unobserved-assumed-full, cooldown skip, all-cooling
fallback, single-app short-circuit, explicit appIndex) and a
selector-feed test for the rate-limit headers.
- ESLint + Prettier clean.

## Related Issues

Follow-up to #5269 / #5038. Depends on #5282.
@guicaulada
guicaulada force-pushed the gc/feat/github-apps-manifest branch 2 times, most recently from 3c4f41b to 4e0f829 Compare September 8, 2026 18:46
guicaulada added a commit that referenced this pull request Sep 8, 2026
## Description

Follow-up to #5269, item 2 of the [#5038
review](#5038 (review)).
Stacked on #5282 (manifest transport); review that first.

Replaces uniform random GitHub App selection with budget-aware
selection, ported from our production fork:

- The auth module tracks the last observed `x-ratelimit-remaining` per
app, fed by `metricGitHubAppRateLimit` headers and the throttling plugin
callbacks.
- Selection picks the app with the most budget remaining; apps with no
observed state are assumed full.
- Apps that hit a secondary rate limit are skipped for 60 seconds; if
every app is cooling down, the one with the most budget is used anyway.
- Iteration starts at a random offset so concurrent cold-started lambdas
do not converge on the same app.

Uniform random kept sending ~1/N of traffic to apps that were already
exhausted. Selection state is per warm container and converges within a
few invocations; a cold container starts as before.

## Test Plan

- control-plane: 353 tests passed, including six new selection tests
(budget preference, unobserved-assumed-full, cooldown skip, all-cooling
fallback, single-app short-circuit, explicit appIndex) and a
selector-feed test for the rate-limit headers.
- ESLint + Prettier clean.

## Related Issues

Follow-up to #5269 / #5038. Depends on #5282.
@guicaulada
guicaulada force-pushed the gc/feat/github-apps-manifest branch from 4e0f829 to 3d6681b Compare September 8, 2026 18:51
guicaulada added a commit that referenced this pull request Sep 8, 2026
## Description

Follow-up to #5269, item 2 of the [#5038
review](#5038 (review)).
Stacked on #5282 (manifest transport); review that first.

Replaces uniform random GitHub App selection with budget-aware
selection, ported from our production fork:

- The auth module tracks the last observed `x-ratelimit-remaining` per
app, fed by `metricGitHubAppRateLimit` headers and the throttling plugin
callbacks.
- Selection picks the app with the most budget remaining; apps with no
observed state are assumed full.
- Apps that hit a secondary rate limit are skipped for 60 seconds; if
every app is cooling down, the one with the most budget is used anyway.
- Iteration starts at a random offset so concurrent cold-started lambdas
do not converge on the same app.

Uniform random kept sending ~1/N of traffic to apps that were already
exhausted. Selection state is per warm container and converges within a
few invocations; a cold container starts as before.

## Test Plan

- control-plane: 353 tests passed, including six new selection tests
(budget preference, unobserved-assumed-full, cooldown skip, all-cooling
fallback, single-app short-circuit, explicit appIndex) and a
selector-feed test for the rate-limit headers.
- ESLint + Prettier clean.

## Related Issues

Follow-up to #5269 / #5038. Depends on #5282.
@guicaulada
guicaulada force-pushed the gc/feat/github-apps-manifest branch from 3d6681b to 47da986 Compare September 8, 2026 19:53
guicaulada and others added 2 commits September 8, 2026 17:02
Deliver additional GitHub App credentials to the lambdas through a
manifest SSM parameter listing the per-app credential parameter names,
instead of colon-joined parameter names in the environment. The lambda
environment size stays constant regardless of app count, avoiding the
4 KB Lambda environment limit (roughly 15-20 apps with typical paths).

The manifest also removes the positional alignment between the id, key,
and installation-id lists, which could silently shift installation ids
across apps if the lists drifted.

The rate-limit metric now reads app ids from the credentials already
loaded by the auth module instead of re-reading SSM per app index.

Document that additional apps must be installed on the same
organizations or repositories as the primary app.
@guicaulada
guicaulada force-pushed the gc/feat/github-apps-manifest branch from 47da986 to 56f938b Compare September 8, 2026 20:02
@guicaulada
guicaulada merged commit 33c3332 into main Sep 8, 2026
55 of 56 checks passed
@guicaulada
guicaulada deleted the gc/feat/github-apps-manifest branch September 8, 2026 20:06
guicaulada added a commit that referenced this pull request Sep 8, 2026
Follow-up to #5269, item 2 of the [#5038
review](#5038 (review)).
Stacked on #5282 (manifest transport); review that first.

Replaces uniform random GitHub App selection with budget-aware
selection, ported from our production fork:

- The auth module tracks the last observed `x-ratelimit-remaining` per
app, fed by `metricGitHubAppRateLimit` headers and the throttling plugin
callbacks.
- Selection picks the app with the most budget remaining; apps with no
observed state are assumed full.
- Apps that hit a secondary rate limit are skipped for 60 seconds; if
every app is cooling down, the one with the most budget is used anyway.
- Iteration starts at a random offset so concurrent cold-started lambdas
do not converge on the same app.

Uniform random kept sending ~1/N of traffic to apps that were already
exhausted. Selection state is per warm container and converges within a
few invocations; a cold container starts as before.

- control-plane: 353 tests passed, including six new selection tests
(budget preference, unobserved-assumed-full, cooldown skip, all-cooling
fallback, single-app short-circuit, explicit appIndex) and a
selector-feed test for the rate-limit headers.
- ESLint + Prettier clean.

Follow-up to #5269 / #5038. Depends on #5282.
guicaulada added a commit that referenced this pull request Sep 8, 2026
Follow-up to #5269, item 2 of the [#5038
review](#5038 (review)).
Stacked on #5282 (manifest transport); review that first.

Replaces uniform random GitHub App selection with budget-aware
selection, ported from our production fork:

- The auth module tracks the last observed `x-ratelimit-remaining` per
app, fed by `metricGitHubAppRateLimit` headers and the throttling plugin
callbacks.
- Selection picks the app with the most budget remaining; apps with no
observed state are assumed full.
- Apps that hit a secondary rate limit are skipped for 60 seconds; if
every app is cooling down, the one with the most budget is used anyway.
- Iteration starts at a random offset so concurrent cold-started lambdas
do not converge on the same app.

Uniform random kept sending ~1/N of traffic to apps that were already
exhausted. Selection state is per warm container and converges within a
few invocations; a cold container starts as before.

- control-plane: 353 tests passed, including six new selection tests
(budget preference, unobserved-assumed-full, cooldown skip, all-cooling
fallback, single-app short-circuit, explicit appIndex) and a
selector-feed test for the rate-limit headers.
- ESLint + Prettier clean.

Follow-up to #5269 / #5038. Depends on #5282.
guicaulada added a commit that referenced this pull request Sep 8, 2026
Replaces uniform random GitHub App selection with selection based on the
last observed rate-limit budget. Apps under a secondary rate-limit
cooldown are temporarily skipped, and randomized starting points spread
cold-start traffic across apps.

Uses the credential storage interface introduced on main and preserves
the selected app index throughout each operation. Includes a regression
test verifying selection from an injected credentials store without
reading SSM.

This PR targets `main` and contains only the rate-limit selection
change. The manifest prerequisite was merged separately in #5282.
Replaces #5283, which was originally merged into the parent feature
branch.

Validation: 350 control-plane tests passed; TypeScript, ESLint, and diff
whitespace checks passed. The commit is signed and verified.

Follow-up to #5269 / #5038.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants