Skip to content

Commit b24afdc

Browse files
committed
infra: extend attestation preflight to all image-deploy scripts
Factor a verifyImagesAndConfirm helper into src/utils/attestation.ts and wire it into every infra deploy script that deploys an image from config/docker.ts: - agents (unchanged call site, now uses helper) - key-funder (unchanged call site, now uses helper) - rebalancer (NODE_SERVICES) - warp-monitor (NODE_SERVICES) - check-warp-deploy (MONOREPO, cronjob) - fee-quoting (FEE_QUOTING) Each script now shows build age for its deploy image and prompts before Helm, with a bold red banner + flipped default on verify fail.
1 parent d3510a6 commit b24afdc

7 files changed

Lines changed: 67 additions & 36 deletions

File tree

typescript/infra/scripts/agents/deploy-agents.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { execSync } from 'child_process';
55
import { DockerImageRepos } from '../../config/docker.js';
66
import { createAgentKeysIfNotExistsWithPrompt } from '../../src/agents/key-utils.js';
77
import { RootAgentConfig } from '../../src/config/agent/agent.js';
8-
import { preflightVerifyImages } from '../../src/utils/attestation.js';
8+
import { verifyImagesAndConfirm } from '../../src/utils/attestation.js';
99
import {
1010
checkAgentImageExists,
1111
checkMonorepoImageExists,
@@ -115,25 +115,7 @@ async function verifyAgentAttestationsWithPrompt(agentConfig: RootAgentConfig) {
115115
tag,
116116
}));
117117

118-
if (refs.length === 0) return;
119-
120-
console.log(chalk.grey.italic('Verifying image attestations...'));
121-
const { allVerified } = await preflightVerifyImages(refs);
122-
123-
const message = allVerified
124-
? 'All attestations verified. Continue with deploy?'
125-
: chalk.red.bold(
126-
'One or more images FAILED attestation verify. Continue with deploy anyway?',
127-
);
128-
129-
const shouldContinue = await confirm({
130-
message,
131-
default: allVerified,
132-
});
133-
if (!shouldContinue) {
134-
console.log(chalk.red.bold('Exiting...'));
135-
process.exit(1);
136-
}
118+
await verifyImagesAndConfirm(refs);
137119
}
138120

139121
async function main() {

typescript/infra/scripts/check/deploy-check-warp-deploy.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Contexts } from '../../config/contexts.js';
22
import { CheckWarpDeployHelmManager } from '../../src/check-warp-deploy/helm.js';
3+
import { verifyImagesAndConfirm } from '../../src/utils/attestation.js';
34
import { HelmCommand } from '../../src/utils/helm.js';
45
import { assertCorrectKubeContext } from '../agent-utils.js';
56
import { getConfigsBasedOnArgs } from '../core-utils.js';
@@ -18,6 +19,14 @@ async function main() {
1819
throw new Error('No checkWarpDeployConfig found');
1920
}
2021

22+
await verifyImagesAndConfirm([
23+
{
24+
component: 'check-warp-deploy',
25+
image: manager.config.docker.repo,
26+
tag: manager.config.docker.tag,
27+
},
28+
]);
29+
2130
await manager.runHelmCommand(HelmCommand.InstallOrUpgrade);
2231
}
2332

typescript/infra/scripts/fee-quoting/deploy-fee-quoting.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import {
55
rootLogger,
66
} from '@hyperlane-xyz/utils';
77

8+
import { DockerImageRepos, mainnetDockerTags } from '../../config/docker.js';
89
import { FeeQuotingHelmManager } from '../../src/fee-quoting/helm.js';
10+
import { verifyImagesAndConfirm } from '../../src/utils/attestation.js';
911
import { HelmCommand } from '../../src/utils/helm.js';
1012
import {
1113
assertCorrectKubeContext,
@@ -22,6 +24,14 @@ async function main() {
2224

2325
await assertCorrectKubeContext(getEnvironmentConfig(environment));
2426

27+
await verifyImagesAndConfirm([
28+
{
29+
component: 'fee-quoting',
30+
image: DockerImageRepos.FEE_QUOTING,
31+
tag: mainnetDockerTags.feeQuoting,
32+
},
33+
]);
34+
2535
const helmManager = new FeeQuotingHelmManager(
2636
environment,
2737
registryCommit ?? 'main',

typescript/infra/scripts/funding/deploy-key-funder.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { join } from 'path';
66
import { Contexts } from '../../config/contexts.js';
77
import { DockerImageRepos } from '../../config/docker.js';
88
import { KeyFunderHelmManager } from '../../src/funding/key-funder.js';
9-
import { preflightVerifyImages } from '../../src/utils/attestation.js';
9+
import { verifyImagesAndConfirm } from '../../src/utils/attestation.js';
1010
import {
1111
checkNodeServicesImageExists,
1212
warnIfPrTag,
@@ -44,23 +44,9 @@ async function main() {
4444
process.exit(1);
4545
}
4646

47-
console.log(chalk.grey.italic('Verifying image attestation...'));
48-
const { allVerified } = await preflightVerifyImages([
47+
await verifyImagesAndConfirm([
4948
{ component: 'key-funder', image: DockerImageRepos.NODE_SERVICES, tag },
5049
]);
51-
52-
const shouldContinue = await confirm({
53-
message: allVerified
54-
? 'Attestation verified. Continue with deploy?'
55-
: chalk.red.bold(
56-
'Image FAILED attestation verify. Continue with deploy anyway?',
57-
),
58-
default: allVerified,
59-
});
60-
if (!shouldContinue) {
61-
console.log(chalk.red.bold('Exiting...'));
62-
process.exit(1);
63-
}
6450
}
6551

6652
const defaultRegistryCommit = readRegistryRc();

typescript/infra/scripts/rebalancer/deploy-rebalancer.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import {
88
rootLogger,
99
} from '@hyperlane-xyz/utils';
1010

11+
import { DockerImageRepos, mainnetDockerTags } from '../../config/docker.js';
1112
import { DeployEnvironment } from '../../src/config/deploy-environment.js';
1213
import {
1314
RebalancerHelmManager,
1415
getDeployedRebalancerWarpRouteIds,
1516
} from '../../src/rebalancer/helm.js';
17+
import { verifyImagesAndConfirm } from '../../src/utils/attestation.js';
1618
import { REBALANCER_HELM_RELEASE_PREFIX } from '../../src/utils/consts.js';
1719
import { validateRegistryCommit } from '../../src/utils/git.js';
1820
import { HelmCommand } from '../../src/utils/helm.js';
@@ -45,6 +47,14 @@ async function main() {
4547

4648
await assertCorrectKubeContext(getEnvironmentConfig(environment));
4749

50+
await verifyImagesAndConfirm([
51+
{
52+
component: 'rebalancer',
53+
image: DockerImageRepos.NODE_SERVICES,
54+
tag: mainnetDockerTags.rebalancer,
55+
},
56+
]);
57+
4858
let warpRouteIds: string[];
4959
if (warpRouteId) {
5060
warpRouteIds = [warpRouteId];

typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import {
99
} from '@hyperlane-xyz/utils';
1010

1111
import { Contexts } from '../../config/contexts.js';
12+
import { DockerImageRepos, mainnetDockerTags } from '../../config/docker.js';
1213
import { getWarpCoreConfig } from '../../config/registry.js';
14+
import { verifyImagesAndConfirm } from '../../src/utils/attestation.js';
1315
import { WARP_ROUTE_MONITOR_HELM_RELEASE_PREFIX } from '../../src/utils/consts.js';
1416
import { validateRegistryCommit } from '../../src/utils/git.js';
1517
import { HelmCommand } from '../../src/utils/helm.js';
@@ -41,6 +43,14 @@ async function main() {
4143
assertCorrectKubeContext(getEnvironmentConfig(environment)),
4244
);
4345

46+
await verifyImagesAndConfirm([
47+
{
48+
component: 'warp-monitor',
49+
image: DockerImageRepos.NODE_SERVICES,
50+
tag: mainnetDockerTags.warpMonitor,
51+
},
52+
]);
53+
4454
const envConfig = getEnvironmentConfig(environment);
4555

4656
let warpRouteIds: string[];

typescript/infra/src/utils/attestation.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { confirm } from '@inquirer/prompts';
12
import chalk from 'chalk';
23
import { execSync } from 'child_process';
34

@@ -143,3 +144,26 @@ export async function preflightVerifyImages(
143144

144145
return { allVerified, results };
145146
}
147+
148+
export async function verifyImagesAndConfirm(refs: ImageRef[]): Promise<void> {
149+
if (refs.length === 0) return;
150+
151+
console.log(chalk.grey.italic('Verifying image attestations...'));
152+
const { allVerified } = await preflightVerifyImages(refs);
153+
154+
const message = allVerified
155+
? 'All attestations verified. Continue with deploy?'
156+
: chalk.red.bold(
157+
'One or more images FAILED attestation verify. Continue with deploy anyway?',
158+
);
159+
160+
const shouldContinue = await confirm({
161+
message,
162+
default: allVerified,
163+
});
164+
165+
if (!shouldContinue) {
166+
console.log(chalk.red.bold('Exiting...'));
167+
process.exit(1);
168+
}
169+
}

0 commit comments

Comments
 (0)