Skip to content

Comments

feat(infra): migrate to standalone keyfunder image#7721

Merged
paulbalaji merged 3 commits intomainfrom
pbio/keyfunder-infra-migration
Jan 28, 2026
Merged

feat(infra): migrate to standalone keyfunder image#7721
paulbalaji merged 3 commits intomainfrom
pbio/keyfunder-infra-migration

Conversation

@paulbalaji
Copy link
Collaborator

@paulbalaji paulbalaji commented Jan 7, 2026

Summary

Migrates the keyfunder Kubernetes deployment from the monorepo image to the standalone @hyperlane-xyz/keyfunder package, deleting 1,207 lines of legacy code.

Motivation

With the standalone keyfunder package in #7720, we can now:

  • Deploy keyfunder independently of the monorepo release cycle
  • Use smaller, purpose-built Docker images
  • Simplify configuration via YAML instead of TypeScript
  • Align with the rebalancer/warp-monitor deployment patterns

Architecture Change

┌─────────────────────────────────────────────────────────────────────┐
│ BEFORE                                                              │
├─────────────────────────────────────────────────────────────────────┤
│ Monorepo Image → fund-keys-from-deployer.ts (1,207 lines)           │
│ ├─ GCP SDK for secrets                                              │
│ ├─ Addresses via ExternalSecrets                                    │
│ └─ Tightly coupled to infra context/environment enums               │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│ AFTER                                                               │
├─────────────────────────────────────────────────────────────────────┤
│ Standalone Image (hyperlane-keyfunder)                              │
│ ├─ YAML ConfigMap (generated from funding.ts)                       │
│ ├─ HYP_KEY + RPC_URL_* via ExternalSecrets                          │
│ └─ Addresses resolved internally via registry                       │
└─────────────────────────────────────────────────────────────────────┘

Changes

Deleted

  • scripts/funding/fund-keys-from-deployer.ts (1,207 lines) - replaced by standalone service

Helm Chart Updates (helm/key-funder/)

File Change
cron-job.yaml Uses standalone image, mounts ConfigMap
configmap.yaml New - stores keyfunder YAML
env-var-external-secret.yaml Injects HYP_KEY and RPC_URL_*
addresses-external-secret.yaml Deleted - addresses resolved via registry

Infrastructure Code

File Change
docker.ts Added KEYFUNDER to DockerImageRepos
key-funder.ts KeyFunderHelmManager generates YAML config from env context
deploy-key-funder.ts Passes registry commit for versioned REGISTRY_URI
funding.ts configs Reference DockerImageRepos.KEYFUNDER

ExternalSecrets Pattern

Secrets are fetched from GCP Secret Manager and injected as environment variables:

HYP_KEY: <from hyperlane-{env}-key-deployer>
RPC_URL_ETHEREUM: <first URL from {env}-rpc-endpoints-ethereum>
RPC_URL_ARBITRUM: <first URL from {env}-rpc-endpoints-arbitrum>
...

Testing

pnpm -C typescript/infra build
# Then deploy via: pnpm -C typescript/infra run deploy-key-funder

Dependencies

Summary by CodeRabbit

  • Infrastructure Updates

    • Key Funder deployment refactored to use ConfigMap-based configuration and env-driven settings; ExternalSecret removed.
    • Image registry and image-name handling improved; image references and tags updated.
  • New Features

    • Added a default sweep address for funding operations.
    • Added package export metadata for Keyfunder publishing.
  • Documentation

    • Updated deployment scripts and configuration values to reflect new deployment patterns.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 7, 2026

⚠️ No Changeset found

Latest commit: 491ee77

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@paulbalaji paulbalaji marked this pull request as draft January 7, 2026 17:26
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch 3 times, most recently from c68a7d6 to 38e44d7 Compare January 7, 2026 17:49
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch 3 times, most recently from b73e5cb to 3e28521 Compare January 7, 2026 18:41
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-package branch from 1b8c30e to 86722d9 Compare January 7, 2026 18:46
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from 3e28521 to ab54729 Compare January 7, 2026 18:47
@paulbalaji paulbalaji changed the title feat(infra): migrate to standalone keyfunder package feat(infra): migrate to standalone keyfunder image Jan 7, 2026
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from ab54729 to fda02b8 Compare January 7, 2026 18:56
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch 2 times, most recently from 4fdbf68 to 0924019 Compare January 7, 2026 19:08
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from 0924019 to 74ae37a Compare January 12, 2026 15:25
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-package branch from d7cf85d to affd9b6 Compare January 12, 2026 15:38
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from 74ae37a to daa7907 Compare January 12, 2026 15:42
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-package branch from affd9b6 to c18278d Compare January 12, 2026 15:45
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from daa7907 to 35d0a0a Compare January 12, 2026 15:46
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-package branch from c18278d to d5cc001 Compare January 12, 2026 15:49
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from 35d0a0a to 024a26d Compare January 12, 2026 15:50
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch 3 times, most recently from 5f12aae to f65320b Compare January 27, 2026 16:07
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-package branch from 0897652 to b1572fb Compare January 27, 2026 16:21
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from f65320b to 992f37b Compare January 27, 2026 16:22
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-package branch from 38cbb55 to d3e450c Compare January 28, 2026 15:56
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from 542cd49 to 6d88f89 Compare January 28, 2026 16:05
Base automatically changed from pbio/keyfunder-package to main January 28, 2026 17:27
@paulbalaji paulbalaji force-pushed the pbio/keyfunder-infra-migration branch from 6d88f89 to b29a170 Compare January 28, 2026 17:37
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Warning

Rate limit exceeded

@paulbalaji has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 3 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Refactors Docker image naming/lookup into typed structures, adds registry-commit awareness to KeyFunder deployment, replaces address ExternalSecret with a ConfigMap-backed KeyFunder config, removes the long funder orchestration script, and updates Helm templates and infra scripts to use the new key-funder image and registry flow.

Changes

Cohort / File(s) Summary
Docker configuration
typescript/infra/config/docker.ts
Added DockerImageNames, DockerImageReposType, computed DockerImageRepos, and updated tag typing/entries (new KEY_FUNDER name).
Environment configs
typescript/infra/config/environments/...
typescrip t/infra/config/environments/mainnet3/funding.ts, .../testnet4/funding.ts
Switched keyFunderConfig.docker.repo from MONOREPO to KEY_FUNDER; updated chainsToSkip in mainnet3.
Helm templates — removed ExternalSecret
typescript/infra/helm/key-funder/templates/addresses-external-secret.yaml
Deleted ExternalSecret template that produced per-context remoteRefs for addresses.
Helm templates — ConfigMap + CronJob changes
typescript/infra/helm/key-funder/templates/configmap.yaml, .../cron-job.yaml
Added ConfigMap template key-funder-config; refactored CronJob to mount ConfigMap, set env vars (REGISTRY_URI, SKIP_IGP_CLAIM, PROMETHEUS_PUSH_GATEWAY), removed hardcoded command and secret volume.
Helm templates — external secret rework
typescript/infra/helm/key-funder/templates/env-var-external-secret.yaml
Replaced many per-network GCP overrides with single HYP_KEY and RPC_URL_* entries; switched secretKey from deployer_key to funder_key.
Helm values
typescript/infra/helm/key-funder/values.yaml
Image repo updated to key-funder image; removed legacy fields; added registryUri, keyfunderConfig, skipIgpClaim, prometheusPushGateway.
Removed funding orchestration
typescript/infra/scripts/funding/fund-keys-from-deployer.ts
Deleted the entire 1,238-line script and its ContextFunder/funding logic.
Deploy script registry flow
typescript/infra/scripts/funding/deploy-key-funder.ts
Reads .registryrc, prompts for override, validates registry commit, uses checkKeyfunderImageExists and passes registryCommit to KeyFunderHelmManager.forEnvironment.
KeyFunder Helm manager
typescript/infra/src/funding/key-funder.ts
KeyFunderHelmManager now accepts registryCommit (factory + constructor), computes registryUri, generates YAML-config for roles/chains (balances, IGP, sweep), adds RC discount logic and helper methods, and emits keyfunderConfig in helmValues.
Utils and config tweaks
typescript/infra/src/utils/gcloud.ts, typescript/infra/src/utils/rpcUrls.ts, typescript/infra/src/config/funding.ts
Added checkKeyfunderImageExists, checkWarpMonitorImageExists, checkRebalancerImageExists; updated call sites to supply registryCommit where needed; added DEFAULT_SWEEP_ADDRESS constant.
Package metadata
typescript/infra/package.json, typescript/keyfunder/package.json
Added @hyperlane-xyz/keyfunder workspace dep to infra; added package export/type/files entries for keyfunder package.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Dev as Deploy script
participant Reg as Registry (.registryrc / GCR)
participant HelmMgr as KeyFunderHelmManager
participant GCloud as gcloud-utils (image checks)
participant K8s as Kubernetes (Helm deploy / ConfigMap & CronJob)
Dev->>Reg: read .registryrc (default commit)
Dev->>Dev: prompt override -> validateRegistryCommit
Dev->>GCloud: checkKeyfunderImageExists(tag, registryCommit)
GCloud-->>Dev: image exists?
Dev->>HelmMgr: KeyFunderHelmManager.forEnvironment(env, registryCommit)
HelmMgr->>HelmMgr: generate keyfunder YAML (roles/chains, balances, registryUri)
Dev->>K8s: helm deploy (values include keyfunderConfig via ConfigMap)
K8s-->>K8s: create ConfigMap + update CronJob (env + mounts)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • yorhodes
  • ltyu
  • tkporter
  • Mo-Hussain
  • Xaroz

Poem

A swampy change — we slim the mess,
Docker names now tidy, bless.
Registry commits we read and tell,
ConfigMaps sing where secrets fell;
Old scripts gone, new flows snug as well. 🐸✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main architectural change: migrating from monorepo to a standalone keyfunder image, which is the primary focus of this 1,207-line deletion and infrastructure refactor.
Description check ✅ Passed The description comprehensively covers all template sections: detailed summary of changes, clear motivation, architecture comparison, organized file changes, and testing instructions. All required sections are present and well-developed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pbio/keyfunder-infra-migration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@typescript/infra/src/funding/key-funder.ts`:
- Around line 56-78: helmValues constructs registryUri using
DEFAULT_GITHUB_REGISTRY and this.registryCommit which can be an empty string
causing an invalid URI; update helmValues to guard against empty/undefined
this.registryCommit (or derive registryUri only when present) and return either
registryUri undefined or omit registryUri from the returned hyperlane object
when it's falsy, ensuring downstream consumers of helmValues (e.g., code
expecting registryUri) handle the optional value; locate helmValues, the
registryCommit property, DEFAULT_GITHUB_REGISTRY constant, and
generateKeyfunderYaml to implement the conditional construction and adjust the
returned object accordingly.
🧹 Nitpick comments (6)
typescript/infra/src/config/funding.ts (1)

63-102: Solid validation schema, one edge case to be aware of.

The refinement only validates when both multipliers are provided, which means someone could set just targetMultiplier without triggerMultiplier (or vice versa). That might be fine if the keyfunder handles partial configs gracefully with defaults, but worth double-checking that downstream code doesn't assume "if one is set, both are set."

typescript/infra/src/utils/rpcUrls.ts (1)

502-505: Empty string for registryCommit - works but could be cleaner.

The comment explains why, which is good. This ties back to my earlier note about helmValues() - when registryCommit is empty, the generated registryUri will be malformed. For the refresh use case this might not matter if helmValues() isn't called, but it's a bit of a code smell to pass invalid data and rely on not using it.

Consider whether registryCommit should be optional in the type signature, with undefined explicitly meaning "not needed."

typescript/infra/scripts/funding/deploy-key-funder.ts (2)

15-18: Add error handling for missing .registryrc file, would ya?

If the .registryrc file doesn't exist in the monorepo root, this'll throw an uncaught exception that's about as helpful as a screen door on a submarine. Consider wrapping this in a try-catch or checking file existence first.

🛠️ Suggested improvement
-function readRegistryRc(): string {
-  const registryRcPath = join(getMonorepoRoot(), '.registryrc');
-  return readFileSync(registryRcPath, 'utf-8').trim();
-}
+function readRegistryRc(): string {
+  const registryRcPath = join(getMonorepoRoot(), '.registryrc');
+  try {
+    return readFileSync(registryRcPath, 'utf-8').trim();
+  } catch (error) {
+    throw new Error(
+      `Failed to read registry version from ${registryRcPath}. Ensure .registryrc exists in the monorepo root.`,
+    );
+  }
+}

54-62: Empty input could slip through like a sneaky onion.

If the user types nothing and hits enter, registryCommit becomes an empty string. While validateRegistryCommit might catch this, it'd be friendlier to validate the input isn't empty right here or use a default/required pattern in the input prompt.

🧅 Optional: Add input validation
   if (shouldOverride) {
     registryCommit = await input({
       message:
         'Enter the registry version to use (can be a commit, branch or tag):',
+      validate: (value) => value.trim() !== '' || 'Registry version cannot be empty',
     });
   }
typescript/infra/helm/key-funder/templates/env-var-external-secret.yaml (1)

23-25: Note: Only the first RPC endpoint is used per chain.

The template extracts just index ... 0 from the RPC array. If there's failover logic needed, it'd have to be handled in the keyfunder application itself rather than at the config level. Just somethin' to keep in the back of yer mind if RPC reliability becomes an issue.

typescript/infra/helm/key-funder/templates/cron-job.yaml (1)

25-42: Quote templated env values to avoid YAML parsing surprises.
REGISTRY_URI and PROMETHEUS_PUSH_GATEWAY often include ://; using | quote keeps Helm/YAML happy and avoids edge cases.

♻️ Proposed tweak
-            - name: REGISTRY_URI
-              value: {{ .Values.hyperlane.registryUri }}
+            - name: REGISTRY_URI
+              value: {{ .Values.hyperlane.registryUri | quote }}
...
             - name: PROMETHEUS_PUSH_GATEWAY
-              value: {{ .Values.hyperlane.prometheusPushGateway }}
+              value: {{ .Values.hyperlane.prometheusPushGateway | quote }}

@paulbalaji paulbalaji enabled auto-merge January 28, 2026 18:11
@paulbalaji paulbalaji disabled auto-merge January 28, 2026 18:12
@paulbalaji paulbalaji enabled auto-merge January 28, 2026 18:21
@hyper-gonk
Copy link
Contributor

hyper-gonk bot commented Jan 28, 2026

🐳 Monorepo Docker Image Built Successfully

Service Tag
📦 monorepo e8033f4-20260128-182007
Full image paths
gcr.io/abacus-labs-dev/hyperlane-monorepo:e8033f4-20260128-182007

@hyper-gonk
Copy link
Contributor

hyper-gonk bot commented Jan 28, 2026

⚙️ Node Service Docker Images Built Successfully

Service Tag
🔑 key-funder e8033f4-20260128-182006
🔍 offchain-lookup-server e8033f4-20260128-182006
♻️ rebalancer e8033f4-20260128-182006
🕵️ warp-monitor e8033f4-20260128-182006
Full image paths
gcr.io/abacus-labs-dev/hyperlane-key-funder:e8033f4-20260128-182006
gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server:e8033f4-20260128-182006
gcr.io/abacus-labs-dev/hyperlane-rebalancer:e8033f4-20260128-182006
gcr.io/abacus-labs-dev/hyperlane-warp-monitor:e8033f4-20260128-182006

@paulbalaji paulbalaji added this pull request to the merge queue Jan 28, 2026
Merged via the queue into main with commit b2b795b Jan 28, 2026
111 checks passed
@paulbalaji paulbalaji deleted the pbio/keyfunder-infra-migration branch January 28, 2026 18:40
@github-project-automation github-project-automation bot moved this from In Review to Done in Hyperlane Tasks Jan 28, 2026
@codecov
Copy link

codecov bot commented Jan 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.02%. Comparing base (2103db3) to head (e8033f4).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7721   +/-   ##
=======================================
  Coverage   77.02%   77.02%           
=======================================
  Files         117      117           
  Lines        2651     2651           
  Branches      244      244           
=======================================
  Hits         2042     2042           
  Misses        593      593           
  Partials       16       16           
Components Coverage Δ
core 87.80% <ø> (ø)
hooks 71.86% <ø> (ø)
isms 81.10% <ø> (ø)
token 86.67% <ø> (ø)
middlewares 84.98% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants