Skip to content

Commit dc81221

Browse files
authored
getAccountId should also check config.account_id (#10520)
* move config.account_id check into getAccountId * add regression test for dry-run with container image uris * changeset
1 parent 3c15bbb commit dc81221

File tree

8 files changed

+63
-26
lines changed

8 files changed

+63
-26
lines changed

.changeset/short-monkeys-cough.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: wrangler deploy dry run should not require you to be logged in
6+
7+
Fixes a bug where if you had a container where the image was an image registry link, dry run would require you to be logged in.
8+
Also fixes a bug where container deployments were not respecting `account_id` set in Wrangler config.

packages/wrangler/src/__tests__/containers/deploy.test.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,25 +1508,20 @@ describe("wrangler deploy with containers dry run", () => {
15081508
const cliStd = mockCLIOutput();
15091509
beforeEach(() => {
15101510
clearCachedAccount();
1511+
expect(process.env.CLOUDFLARE_API_TOKEN).toBeUndefined();
15111512
});
15121513

15131514
afterEach(() => {
15141515
vi.unstubAllEnvs();
15151516
});
15161517

15171518
it("builds the image without pushing", async () => {
1518-
// Reduced mock chain for dry run (no delete, modified push)
1519+
// Reduced mock chain for dry run (no delete, push)
15191520
vi.mocked(spawn)
15201521
.mockImplementationOnce(mockDockerInfo())
15211522
.mockImplementationOnce(
15221523
mockDockerBuild("my-container", "worker", "FROM scratch", process.cwd())
1523-
)
1524-
.mockImplementationOnce(
1525-
mockDockerImageInspectDigests("my-container", "worker")
1526-
)
1527-
.mockImplementationOnce(mockDockerLogin("mockpassword"))
1528-
.mockImplementationOnce(mockDockerPush("my-container", "worker"));
1529-
1524+
);
15301525
vi.stubEnv("WRANGLER_DOCKER_BIN", "/usr/bin/docker");
15311526
fs.writeFileSync("./Dockerfile", "FROM scratch");
15321527
fs.writeFileSync(
@@ -1550,6 +1545,30 @@ describe("wrangler deploy with containers dry run", () => {
15501545
`);
15511546
expect(cliStd.stdout).toMatchInlineSnapshot(`""`);
15521547
});
1548+
1549+
it("builds the image without pushing", async () => {
1550+
// No docker mocks at all
1551+
1552+
fs.writeFileSync(
1553+
"index.js",
1554+
`export class ExampleDurableObject {}; export default{};`
1555+
);
1556+
writeWranglerConfig({
1557+
...DEFAULT_DURABLE_OBJECTS,
1558+
containers: [DEFAULT_CONTAINER_FROM_REGISTRY],
1559+
});
1560+
1561+
await runWrangler("deploy --dry-run index.js");
1562+
expect(std.out).toMatchInlineSnapshot(`
1563+
"Total Upload: xx KiB / gzip: xx KiB
1564+
Your Worker has access to the following bindings:
1565+
Binding Resource
1566+
env.EXAMPLE_DO_BINDING (ExampleDurableObject) Durable Object
1567+
1568+
--dry-run: exiting now."
1569+
`);
1570+
expect(cliStd.stdout).toMatchInlineSnapshot(`""`);
1571+
});
15531572
});
15541573

15551574
// Docker mock factory

packages/wrangler/src/cloudchamber/apply.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ export async function apply(
356356
`${config.name}-${appConfigNoDefaults.class_name}`
357357
];
358358

359-
const accountId = config.account_id || (await getAccountId(config));
359+
const accountId = await getAccountId(config);
360360
const appConfig = containerAppToCreateApplication(
361361
accountId,
362362
appConfigNoDefaults,

packages/wrangler/src/cloudchamber/build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ export async function pushCommand(
280280
) {
281281
try {
282282
await dockerLoginManagedRegistry(args.pathToDocker);
283-
const accountId = config.account_id || (await getAccountId(config));
283+
const accountId = await getAccountId(config);
284284
const newTag = getCloudflareRegistryWithAccountNamespace(
285285
accountId,
286286
args.TAG

packages/wrangler/src/cloudchamber/images/images.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ async function handleDeleteImageCommand(
8989

9090
const digest = await promiseSpinner(
9191
getCreds().then(async (creds) => {
92-
const accountId = config.account_id || (await getAccountId(config));
92+
const accountId = await getAccountId(config);
9393
const url = new URL(`https://${getCloudflareContainerRegistry()}`);
9494
const baseUrl = `${url.protocol}//${url.host}`;
9595
const [image, tag] = args.image.split(":");
@@ -126,7 +126,7 @@ async function handleListImagesCommand(
126126
getCreds().then(async (creds) => {
127127
const repos = await listReposWithTags(creds);
128128
const processed: Repository[] = [];
129-
const accountId = config.account_id || (await getAccountId(config));
129+
const accountId = await getAccountId(config);
130130
const accountIdPrefix = new RegExp(`^${accountId}/`);
131131
const filter = new RegExp(args.filter ?? "");
132132
for (const [repo, tags] of Object.entries(repos)) {

packages/wrangler/src/containers/config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const getNormalizedContainerOptions = async (
2525
args: {
2626
/** set by args.containersRollout */
2727
containersRollout?: "gradual" | "immediate";
28+
dryRun?: boolean;
2829
}
2930
): Promise<ContainerNormalizedConfig[]> => {
3031
if (!config.containers || config.containers.length === 0) {
@@ -145,11 +146,12 @@ export const getNormalizedContainerOptions = async (
145146
image_vars: container.image_vars,
146147
});
147148
} else {
148-
const accountId = await getAccountId(config);
149149
normalizedContainers.push({
150150
...shared,
151151
...instanceTypeOrLimits,
152-
image_uri: resolveImageName(accountId, container.image), // if it is not a dockerfile, it must be an image uri or have thrown an error
152+
image_uri: args.dryRun
153+
? container.image
154+
: resolveImageName(await getAccountId(config), container.image), // if it is not a dockerfile, it must be an image uri or have thrown an error
153155
});
154156
}
155157
}

packages/wrangler/src/secrets-store/commands.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export const secretsStoreStoreCreateCommand = createCommand({
7777
let store: { id: string };
7878
logger.log(`🔐 Creating store... (Name: ${args.name})`);
7979
if (args.remote) {
80-
const accountId = config.account_id || (await getAccountId(config));
80+
const accountId = await getAccountId(config);
8181
store = await createStore(config, accountId, { name: args.name });
8282
} else {
8383
throw new UserError(
@@ -112,7 +112,7 @@ export const secretsStoreStoreDeleteCommand = createCommand({
112112
async handler(args, { config }) {
113113
logger.log(`🔐 Deleting store... (Name: ${args.storeId})`);
114114
if (args.remote) {
115-
const accountId = config.account_id || (await getAccountId(config));
115+
const accountId = await getAccountId(config);
116116
await deleteStore(config, accountId, args.storeId);
117117
} else {
118118
throw new UserError(
@@ -158,7 +158,7 @@ export const secretsStoreStoreListCommand = createCommand({
158158

159159
let stores: Store[];
160160
if (args.remote) {
161-
const accountId = config.account_id || (await getAccountId(config));
161+
const accountId = await getAccountId(config);
162162
stores = await listStores(config, accountId, urlParams);
163163
} else {
164164
throw new UserError(
@@ -235,7 +235,7 @@ export const secretsStoreSecretListCommand = createCommand({
235235

236236
let secrets: Secret[];
237237
if (args.remote) {
238-
const accountId = config.account_id || (await getAccountId(config));
238+
const accountId = await getAccountId(config);
239239
secrets = await listSecrets(config, accountId, args.storeId, urlParams);
240240
} else {
241241
secrets = (
@@ -313,7 +313,7 @@ export const secretsStoreSecretGetCommand = createCommand({
313313

314314
let secret: Secret;
315315
if (args.remote) {
316-
const accountId = config.account_id || (await getAccountId(config));
316+
const accountId = await getAccountId(config);
317317
secret = await getSecret(config, accountId, args.storeId, args.secretId);
318318
} else {
319319
const name = await usingLocalSecretsStoreSecretAPI(
@@ -421,7 +421,7 @@ export const secretsStoreSecretCreateCommand = createCommand({
421421

422422
let secrets: Secret[];
423423
if (args.remote) {
424-
const accountId = config.account_id || (await getAccountId(config));
424+
const accountId = await getAccountId(config);
425425
secrets = await createSecret(config, accountId, args.storeId, {
426426
name: args.name,
427427
value: secretValue,
@@ -548,7 +548,7 @@ export const secretsStoreSecretUpdateCommand = createCommand({
548548

549549
let secret: Secret;
550550
if (args.remote) {
551-
const accountId = config.account_id || (await getAccountId(config));
551+
const accountId = await getAccountId(config);
552552
secret = await updateSecret(
553553
config,
554554
accountId,
@@ -632,7 +632,7 @@ export const secretsStoreSecretDeleteCommand = createCommand({
632632
logger.log(`🔐 Deleting secret... (ID: ${args.secretId})`);
633633

634634
if (args.remote) {
635-
const accountId = config.account_id || (await getAccountId(config));
635+
const accountId = await getAccountId(config);
636636
await deleteSecret(config, accountId, args.storeId, args.secretId);
637637
} else {
638638
await usingLocalSecretsStoreSecretAPI(
@@ -698,7 +698,7 @@ export const secretsStoreSecretDuplicateCommand = createCommand({
698698

699699
let duplicatedSecret: Secret;
700700
if (args.remote) {
701-
const accountId = config.account_id || (await getAccountId(config));
701+
const accountId = await getAccountId(config);
702702
duplicatedSecret = await duplicateSecret(
703703
config,
704704
accountId,

packages/wrangler/src/user/user.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,16 +1210,24 @@ export function listScopes(message = "💁 Available scopes:"): void {
12101210
// TODO: maybe a good idea to show usage here
12111211
}
12121212

1213+
/**
1214+
*
1215+
* Returns account_id preferentially from config.account_id > CLOUDFLARE_ACCOUNT_ID env var > cache > or user selection.
1216+
*/
12131217
export async function getAccountId(
1214-
complianceConfig: ComplianceConfig
1218+
config: ComplianceConfig & { account_id?: string }
12151219
): Promise<string> {
1220+
// TODO: v5 we should prioritise the env var instead of the config value here, for consistency
1221+
if (config.account_id) {
1222+
return config.account_id;
1223+
}
12161224
// check if we have a cached value
12171225
const cachedAccount = getAccountFromCache();
12181226
if (cachedAccount && !getCloudflareAccountIdFromEnv()) {
12191227
return cachedAccount.id;
12201228
}
12211229

1222-
const accounts = await getAccountChoices(complianceConfig);
1230+
const accounts = await getAccountChoices(config);
12231231
if (accounts.length === 1) {
12241232
saveAccountToCache({ id: accounts[0].id, name: accounts[0].name });
12251233
return accounts[0].id;
@@ -1272,7 +1280,7 @@ export async function requireAuth(
12721280
throw new UserError("Did not login, quitting...");
12731281
}
12741282
}
1275-
const accountId = config.account_id || (await getAccountId(config));
1283+
const accountId = await getAccountId(config);
12761284
if (!accountId) {
12771285
throw new UserError("No account id found, quitting...");
12781286
}

0 commit comments

Comments
 (0)