Skip to content

Commit 74432ed

Browse files
refactor: update checksum handling and improve download logic; add extract-zip for file extraction
1 parent e8eb12f commit 74432ed

File tree

9 files changed

+143
-32
lines changed

9 files changed

+143
-32
lines changed

artifacts/SHA256SUMS.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
cc7a6dce911bcc4778a8e8f315428dcf1f42d21a29240cbc94849ea85309ad63 cloudsqlctl.exe
1+
fba808877110583ee067cfa9d19144c42ce8d8d8675a654b17a98c5b204b5567 cloudsqlctl-setup.exe
2+
d2427408dcbed72aa00a28fdfb55325ecb5ab847d1d7e23cdb8abef900308d12 cloudsqlctl.exe

bin/cloudsqlctl.exe

221 KB
Binary file not shown.

installer/cloudsqlctl.iss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ begin
117117
begin
118118
// Copy to Common AppData
119119
ForceDirectories(ExpandConstant('{commonappdata}\CloudSQLCTL\bin'));
120-
if FileCopy(UserBin, CommonBin, False) then
120+
if CopyFile(UserBin, CommonBin, False) then
121121
begin
122122
Result := CommonBin;
123123
exit;

package-lock.json

Lines changed: 110 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
"commander": "^12.0.0",
3737
"conf": "^15.0.2",
3838
"execa": "^9.6.1",
39+
"extract-zip": "2.0.1",
3940
"fs-extra": "^11.2.0",
4041
"inquirer": "^9.2.15",
4142
"winston": "^3.11.0"
4243
},
4344
"devDependencies": {
45+
"@types/extract-zip": "2.0.0",
4446
"@types/fs-extra": "^11.0.4",
4547
"@types/inquirer": "^9.0.7",
4648
"@types/jest": "^29.5.12",

src/cli.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,13 @@ import { authCommand } from './commands/auth.js';
2121
import { setupCommand } from './commands/setup.js';
2222
import { pathsCommand } from './commands/paths.js';
2323
import { logger } from './core/logger.js';
24-
import { createRequire } from 'module';
25-
26-
const require = createRequire(import.meta.url);
27-
const pkg = require('../package.json');
2824

2925
const program = new Command();
3026

3127
program
3228
.name('cloudsqlctl')
3329
.description('CLI for managing Google Cloud SQL Auth Proxy')
34-
.version(pkg.version);
30+
.version(process.env.CLOUDSQLCTL_VERSION ?? '0.0.0');
3531

3632
program.addCommand(installCommand);
3733
program.addCommand(updateCommand);

src/commands/gcloud.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { PATHS } from '../system/paths.js';
66
import fs from 'fs-extra';
77
import path from 'path';
88
import axios from 'axios';
9-
import { execa } from 'execa';
9+
import extract from 'extract-zip';
1010

1111
// Official Google Cloud SDK download URL pattern
1212
const GCLOUD_DOWNLOAD_URL = 'https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-windows-x86_64.zip';
@@ -55,9 +55,9 @@ gcloudCommand.command('install')
5555
writer.on('error', reject);
5656
});
5757

58-
logger.info('Extracting...');
59-
// Use PowerShell to extract
60-
await execa('powershell', ['-Command', `Expand-Archive -Path "${zipPath}" -DestinationPath "${PATHS.GCLOUD_DIR}" -Force`]);
58+
logger.info('Extracting (this may take a moment)...');
59+
// Use extract-zip for faster and reliable extraction
60+
await extract(zipPath, { dir: PATHS.GCLOUD_DIR });
6161

6262
const gcloudExe = path.join(PATHS.GCLOUD_DIR, 'google-cloud-sdk', 'bin', 'gcloud.cmd');
6363

src/core/updater.ts

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,25 @@ async function verifyChecksum(filePath: string, expectedChecksum: string): Promi
3535

3636
export async function downloadProxy(version: string, targetPath: string = PATHS.PROXY_EXE) {
3737
let downloadUrl: string | undefined;
38-
let checksumUrl: string | undefined;
38+
let expectedChecksum: string | undefined;
3939

4040
try {
4141
const releaseUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${version}`;
4242
const response = await axios.get(releaseUrl);
43-
const assets = response.data.assets;
44-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
45-
const asset = assets.find((a: any) => a.name === ASSET_NAME);
46-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
47-
const checksumAsset = assets.find((a: any) => a.name === CHECKSUM_ASSET_NAME);
48-
49-
if (asset) {
50-
downloadUrl = asset.browser_download_url;
51-
}
5243

53-
if (checksumAsset) {
54-
checksumUrl = checksumAsset.browser_download_url;
55-
}
44+
// Google Cloud SQL Proxy v2 binaries are hosted on GCS
45+
downloadUrl = `https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/${version}/${ASSET_NAME}`;
46+
47+
// Extract checksum from release body
48+
const body = response.data.body;
49+
// Regex to match: | [cloud-sql-proxy.x64.exe](...) | <hash> |
50+
const checksumRegex = new RegExp(`\\| \\[${ASSET_NAME.replace(/\./g, '\\.')}\\]\\(.*?\\) \\| ([a-f0-9]{64}) \\|`);
51+
const match = body.match(checksumRegex);
5652

57-
if (!downloadUrl) {
58-
throw new Error(`Could not find asset ${ASSET_NAME} in release ${version}`);
53+
if (match && match[1]) {
54+
expectedChecksum = match[1];
55+
} else {
56+
logger.warn(`Could not extract checksum for ${ASSET_NAME} from release notes.`);
5957
}
6058

6159
logger.info(`Downloading ${ASSET_NAME} from ${downloadUrl}...`);
@@ -79,11 +77,9 @@ export async function downloadProxy(version: string, targetPath: string = PATHS.
7977

8078
logger.info('Download complete.');
8179

82-
if (checksumUrl) {
80+
if (expectedChecksum) {
8381
logger.info('Verifying checksum...');
8482
try {
85-
const checksumResponse = await axios.get(checksumUrl);
86-
const expectedChecksum = checksumResponse.data.trim().split(' ')[0];
8783
const isValid = await verifyChecksum(targetPath, expectedChecksum);
8884

8985
if (!isValid) {
@@ -96,6 +92,8 @@ export async function downloadProxy(version: string, targetPath: string = PATHS.
9692
await fs.remove(targetPath);
9793
throw err;
9894
}
95+
} else {
96+
logger.warn('Skipping checksum verification (checksum not found).');
9997
}
10098

10199
} catch (error) {

tsup.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { defineConfig } from 'tsup';
2+
import { readFileSync } from 'fs';
3+
4+
const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf-8'));
25

36
export default defineConfig({
47
entry: ['src/cli.ts'],
@@ -9,6 +12,10 @@ export default defineConfig({
912
dts: false,
1013
sourcemap: false,
1114
shims: true,
15+
splitting: false,
16+
define: {
17+
'process.env.CLOUDSQLCTL_VERSION': JSON.stringify(pkg.version),
18+
},
1219
noExternal: [/(.*)/], // Bundle everything
1320
outExtension({ format }) {
1421
return {

0 commit comments

Comments
 (0)