From 179d8691ece8a9cd835c23ecd78a2ee94b89b894 Mon Sep 17 00:00:00 2001 From: Gabriel Cousin <7649529+GabrielCousin@users.noreply.github.com> Date: Mon, 28 Apr 2025 10:10:53 +0200 Subject: [PATCH 1/6] refactor: replace request-sync with axios --- package.json | 3 +- src/extension.ts | 4 +- src/lib/ggshield-configuration-utils.ts | 6 +- src/lib/ggshield-resolver-utils.ts | 45 ++-- .../lib/ggshield-configuration-utils.test.ts | 4 +- .../suite/lib/ggshield-resolver-utils.test.ts | 12 +- yarn.lock | 247 +++--------------- 7 files changed, 78 insertions(+), 243 deletions(-) diff --git a/package.json b/package.json index 7a29f48..2233b90 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,6 @@ "@types/node": "20.2.5", "@types/simple-mock": "^0.8.6", "@types/tar": "^6.1.13", - "@types/unzipper": "^0.10.10", "@types/vscode": "^1.81.0", "@typescript-eslint/eslint-plugin": "^5.59.8", "@typescript-eslint/parser": "^5.59.8", @@ -169,7 +168,7 @@ }, "dependencies": { "adm-zip": "^0.5.16", - "sync-request": "^6.1.0", + "axios": "^1.9.0", "tar": "^7.4.3" } } diff --git a/src/extension.ts b/src/extension.ts index bddbc41..c7c6c77 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -69,9 +69,9 @@ function registerOpenViewsCommands( ); } -export function activate(context: ExtensionContext) { +export async function activate(context: ExtensionContext) { const outputChannel = window.createOutputChannel("GitGuardian"); - let configuration = getConfiguration(context, outputChannel); + let configuration = await getConfiguration(context, outputChannel); const ggshieldResolver = new GGShieldResolver( outputChannel, diff --git a/src/lib/ggshield-configuration-utils.ts b/src/lib/ggshield-configuration-utils.ts index 0359f14..52260f9 100644 --- a/src/lib/ggshield-configuration-utils.ts +++ b/src/lib/ggshield-configuration-utils.ts @@ -7,17 +7,17 @@ import { getGGShield } from "./ggshield-resolver-utils"; * Retrieve configuration from settings * @returns {GGShieldConfiguration} from the extension settings */ -export function getConfiguration( +export async function getConfiguration( context: ExtensionContext, outputChannel: OutputChannel -): GGShieldConfiguration { +): Promise { const config = workspace.getConfiguration("gitguardian"); const ggshieldPath: string | undefined = config.get("GGShieldPath"); const apiUrl: string | undefined = config.get("apiUrl"); const allowSelfSigned: boolean = config.get("allowSelfSigned", false); - const pathToGGShield: string = getGGShield( + const pathToGGShield: string = await getGGShield( os.platform(), os.arch(), context, diff --git a/src/lib/ggshield-resolver-utils.ts b/src/lib/ggshield-resolver-utils.ts index 4daef42..7eec8d8 100644 --- a/src/lib/ggshield-resolver-utils.ts +++ b/src/lib/ggshield-resolver-utils.ts @@ -1,9 +1,16 @@ import * as path from "path"; import * as fs from "fs"; import * as tar from "tar"; +import axios, { AxiosRequestConfig} from "axios"; + const AdmZip = require("adm-zip"); import { ExtensionContext, OutputChannel } from "vscode"; +const defaultRequestConfig = { + headers: { "User-Agent": "GitGuardian-VSCode-Extension" }, + timeout: 30_000 +} satisfies AxiosRequestConfig; + /** * Get the absolute path to GGShield binary. If it doesn't exist, it will be installed. * @param platform The platform of the user @@ -12,12 +19,12 @@ import { ExtensionContext, OutputChannel } from "vscode"; * @param outputChannel The output channel to use * @returns The absolute path to the GGShield binary */ -export function getGGShield( +export async function getGGShield( platform: NodeJS.Platform, arch: string, context: ExtensionContext, outputChannel: OutputChannel -): string { +): Promise { const version = fs .readFileSync(path.join(context.extensionPath, "ggshield_version"), "utf8") .trim(); @@ -47,7 +54,7 @@ export function getGGShield( } fs.mkdirSync(ggshieldFolder); // install GGShield - installGGShield(platform, arch, ggshieldFolder, version); + await installGGShield(platform, arch, ggshieldFolder, version); outputChannel.appendLine( `Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.` ); @@ -59,14 +66,16 @@ export function getGGShield( * Get the latest version of GGShield * @returns The latest version of GGShield */ -export function getGGShieldLatestVersion(): string { - const response = require("sync-request")( - "GET", +export async function getGGShieldLatestVersion(): Promise { + const { data } = await axios.get<{tag_name?: string}>( "https://api.github.com/repos/GitGuardian/ggshield/releases/latest", - { headers: { "User-Agent": "GitGuardian-VSCode-Extension" } } + { + ...defaultRequestConfig, + responseEncoding: 'utf8' + } ); - const data = JSON.parse(response.getBody("utf8")); - return data.tag_name?.replace(/^v/, ""); + + return data.tag_name?.replace(/^v/, "") ?? ""; } /** @@ -119,12 +128,12 @@ export function computeGGShieldFolderName( * @param ggshieldFolder The folder of the GGShield binary * @param version The version of GGShield */ -export function installGGShield( +export async function installGGShield( platform: NodeJS.Platform, arch: string, ggshieldFolder: string, version: string -): void { +): Promise { let extension: string = ""; switch (platform) { case "win32": @@ -144,7 +153,7 @@ export function installGGShield( version )}.${extension}`; const downloadUrl: string = `https://github.com/GitGuardian/ggshield/releases/download/v${version}/${fileName}`; - downloadGGShieldFromGitHub(fileName, downloadUrl, ggshieldFolder); + await downloadGGShieldFromGitHub(fileName, downloadUrl, ggshieldFolder); extractGGShieldBinary(path.join(ggshieldFolder, fileName), ggshieldFolder); } @@ -177,16 +186,18 @@ export function extractGGShieldBinary( * @param downloadUrl The URL of the GGShield binary * @param ggshieldFolder The folder of the GGShield binary */ -function downloadGGShieldFromGitHub( +async function downloadGGShieldFromGitHub( fileName: string, downloadUrl: string, ggshieldFolder: string -): void { +): Promise { console.log(`Downloading GGShield from ${downloadUrl}`); - const response = require("sync-request")("GET", downloadUrl, { - headers: { "User-Agent": "GitGuardian-VSCode-Extension" }, + const { data } = await axios.get(downloadUrl, { + ...defaultRequestConfig, + responseType: 'arraybuffer' }); - fs.writeFileSync(path.join(ggshieldFolder, fileName), response.getBody()); + + fs.writeFileSync(path.join(ggshieldFolder, fileName), data); console.log( `GGShield archive downloaded to ${path.join(ggshieldFolder, fileName)}` ); diff --git a/src/test/suite/lib/ggshield-configuration-utils.test.ts b/src/test/suite/lib/ggshield-configuration-utils.test.ts index 614d4ce..ba708e0 100644 --- a/src/test/suite/lib/ggshield-configuration-utils.test.ts +++ b/src/test/suite/lib/ggshield-configuration-utils.test.ts @@ -27,7 +27,7 @@ suite("getConfiguration", () => { simple.restore(); }); - test("Vscode settings are correctly read", () => { + test("Vscode settings are correctly read", async () => { const context = {} as ExtensionContext; const outputChannel = window.createOutputChannel("GitGuardian"); simple.mock(context, "asAbsolutePath").returnWith(""); @@ -42,7 +42,7 @@ suite("getConfiguration", () => { } }, }); - const configuration = getConfiguration(context, outputChannel); + const configuration = await getConfiguration(context, outputChannel); // Assert both workspace.getConfiguration and GGShieldConfiguration constructor were called assert( diff --git a/src/test/suite/lib/ggshield-resolver-utils.test.ts b/src/test/suite/lib/ggshield-resolver-utils.test.ts index 17f0a41..6cb302b 100644 --- a/src/test/suite/lib/ggshield-resolver-utils.test.ts +++ b/src/test/suite/lib/ggshield-resolver-utils.test.ts @@ -7,13 +7,13 @@ const AdmZip = require("adm-zip"); import * as getGGShieldUtils from "../../../lib/ggshield-resolver-utils"; import { ExtensionContext, window, OutputChannel } from "vscode"; -suite("getGGShield integration tests", () => { +suite("getGGShield integration tests", async () => { let tempDir: string; let mockContext: ExtensionContext; let outputChannel: OutputChannel = window.createOutputChannel("GitGuardian"); const platform = process.platform; const arch = process.arch; - const latestVersion = getGGShieldUtils.getGGShieldLatestVersion(); + const latestVersion = await getGGShieldUtils.getGGShieldLatestVersion(); let originalLog: (message?: any, ...optionalParams: any[]) => void; let output: string; @@ -66,7 +66,7 @@ suite("getGGShield integration tests", () => { ); }); - test("installs binary when it doesn't exist", () => { + test("installs binary when it doesn't exist", async () => { const expectedBinaryPath: string = getGGShieldUtils.computeGGShieldPath( platform, arch, @@ -75,7 +75,7 @@ suite("getGGShield integration tests", () => { ); assert(!fs.existsSync(expectedBinaryPath)); - const result = getGGShieldUtils.getGGShield( + const result = await getGGShieldUtils.getGGShield( platform, arch, mockContext, @@ -91,14 +91,14 @@ suite("getGGShield integration tests", () => { ); }); - test("updates binary when newer version set by ggshield_version file", () => { + test("updates binary when newer version set by ggshield_version file", async () => { const oldBinaryPath: string = createFakeBinary( tempDir, platform, arch, "1.0.0" ); - const result = getGGShieldUtils.getGGShield( + const result = await getGGShieldUtils.getGGShield( platform, arch, mockContext, diff --git a/yarn.lock b/yarn.lock index da38fd8..48e07f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -105,20 +105,6 @@ dependencies: "@types/node" "*" -"@types/concat-stream@^1.6.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" - integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== - dependencies: - "@types/node" "*" - -"@types/form-data@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" - integrity sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw== - dependencies: - "@types/node" "*" - "@types/glob@^8.1.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" @@ -154,21 +140,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== -"@types/node@^10.0.3": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - -"@types/node@^8.0.0": - version "8.10.66" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" - integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== - -"@types/qs@^6.2.31": - version "6.9.18" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.18.tgz#877292caa91f7c1b213032b34626505b746624c2" - integrity sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA== - "@types/semver@^7.3.12": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" @@ -187,13 +158,6 @@ "@types/node" "*" minipass "^4.0.0" -"@types/unzipper@^0.10.10": - version "0.10.10" - resolved "https://registry.yarnpkg.com/@types/unzipper/-/unzipper-0.10.10.tgz#4407f7f633db0c5cf20f05257352cb8197fb9e5a" - integrity sha512-jKJdNxhmCHTZsaKW5x0qjn6rB+gHk0w5VFbEKsw84i+RJqXZyfTmGnpjDcKqzMpjz7VVLsUBMtO5T3mVidpt0g== - dependencies: - "@types/node" "*" - "@types/vscode@^1.81.0": version "1.94.0" resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.94.0.tgz#ccd2111b6ecaba6ad4da19c2d524828fa73ae250" @@ -376,16 +340,20 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +axios@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.9.0.tgz#25534e3b72b54540077d33046f77e3b8d7081901" + integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -437,11 +405,6 @@ browser-stdout@^1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -458,14 +421,6 @@ call-bind-apply-helpers@^1.0.1: es-errors "^1.3.0" function-bind "^1.1.2" -call-bound@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" - integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== - dependencies: - call-bind-apply-helpers "^1.0.1" - get-intrinsic "^1.2.6" - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -476,11 +431,6 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caseless@^0.12.0, caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -559,16 +509,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concat-stream@^1.6.0, concat-stream@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -867,6 +807,11 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + foreground-child@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" @@ -875,16 +820,15 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" -form-data@^2.2.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.3.tgz#f9bcf87418ce748513c0c3494bb48ec270c97acc" - integrity sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ== +form-data@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" + integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" es-set-tostringtag "^2.1.0" - mime-types "^2.1.35" - safe-buffer "^5.2.1" + mime-types "^2.1.12" fs.realpath@^1.0.0: version "1.0.0" @@ -906,7 +850,7 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: +get-intrinsic@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044" integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA== @@ -922,11 +866,6 @@ get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: hasown "^2.0.2" math-intrinsics "^1.1.0" -get-port@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== - get-proto@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" @@ -1042,16 +981,6 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -http-basic@^8.1.1: - version "8.1.3" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" - integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== - dependencies: - caseless "^0.12.0" - concat-stream "^1.6.2" - http-response-object "^3.0.1" - parse-cache-control "^1.0.1" - http-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" @@ -1060,13 +989,6 @@ http-proxy-agent@^7.0.2: agent-base "^7.1.0" debug "^4.3.4" -http-response-object@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" - integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== - dependencies: - "@types/node" "^10.0.3" - https-proxy-agent@^7.0.5: version "7.0.5" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" @@ -1299,7 +1221,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.35: +mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -1401,11 +1323,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -object-inspect@^1.13.3: - version "1.13.4" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" - integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1478,11 +1395,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-cache-control@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" - integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -1526,25 +1438,16 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -promise@^8.0.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" - integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== - dependencies: - asap "~2.0.6" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -qs@^6.4.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" - integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== - dependencies: - side-channel "^1.1.0" - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -1557,7 +1460,16 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -readable-stream@^2.2.2, readable-stream@~2.3.6: +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -1570,15 +1482,6 @@ readable-stream@^2.2.2, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -1630,7 +1533,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.1.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -1669,46 +1572,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel-list@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" - integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - -side-channel-map@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" - integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - -side-channel-weakmap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" - integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - side-channel-map "^1.0.1" - -side-channel@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" - integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - side-channel-list "^1.0.0" - side-channel-map "^1.0.1" - side-channel-weakmap "^1.0.2" - signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -1826,22 +1689,6 @@ supports-color@^8.1.1: dependencies: has-flag "^4.0.0" -sync-request@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" - integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== - dependencies: - http-response-object "^3.0.1" - sync-rpc "^1.2.1" - then-request "^6.0.0" - -sync-rpc@^1.2.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" - integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== - dependencies: - get-port "^3.1.0" - tar@^7.4.3: version "7.4.3" resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" @@ -1859,23 +1706,6 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -then-request@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" - integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== - dependencies: - "@types/concat-stream" "^1.6.0" - "@types/form-data" "0.0.33" - "@types/node" "^8.0.0" - "@types/qs" "^6.2.31" - caseless "~0.12.0" - concat-stream "^1.6.0" - form-data "^2.2.0" - http-basic "^8.1.1" - http-response-object "^3.0.1" - promise "^8.0.0" - qs "^6.4.0" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -1907,11 +1737,6 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - typescript@^5.1.3: version "5.6.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" From f70132e0fc8a1ee412a26d51739442feafeac52d Mon Sep 17 00:00:00 2001 From: Gabriel Cousin <7649529+GabrielCousin@users.noreply.github.com> Date: Mon, 28 Apr 2025 10:47:04 +0200 Subject: [PATCH 2/6] feat: disable ssl checks --- src/lib/ggshield-configuration-utils.ts | 4 +++- src/lib/ggshield-resolver-utils.ts | 24 ++++++++++++++----- .../suite/lib/ggshield-resolver-utils.test.ts | 9 ++++--- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/lib/ggshield-configuration-utils.ts b/src/lib/ggshield-configuration-utils.ts index 52260f9..de4bef5 100644 --- a/src/lib/ggshield-configuration-utils.ts +++ b/src/lib/ggshield-configuration-utils.ts @@ -16,12 +16,14 @@ export async function getConfiguration( const ggshieldPath: string | undefined = config.get("GGShieldPath"); const apiUrl: string | undefined = config.get("apiUrl"); const allowSelfSigned: boolean = config.get("allowSelfSigned", false); + const ignoreSSLErrors = allowSelfSigned; const pathToGGShield: string = await getGGShield( os.platform(), os.arch(), context, - outputChannel + outputChannel, + ignoreSSLErrors ); return new GGShieldConfiguration( diff --git a/src/lib/ggshield-resolver-utils.ts b/src/lib/ggshield-resolver-utils.ts index 7eec8d8..d856603 100644 --- a/src/lib/ggshield-resolver-utils.ts +++ b/src/lib/ggshield-resolver-utils.ts @@ -2,6 +2,7 @@ import * as path from "path"; import * as fs from "fs"; import * as tar from "tar"; import axios, { AxiosRequestConfig} from "axios"; +import { Agent } from "https"; const AdmZip = require("adm-zip"); import { ExtensionContext, OutputChannel } from "vscode"; @@ -23,7 +24,8 @@ export async function getGGShield( platform: NodeJS.Platform, arch: string, context: ExtensionContext, - outputChannel: OutputChannel + outputChannel: OutputChannel, + ignoreSSLErrors: boolean ): Promise { const version = fs .readFileSync(path.join(context.extensionPath, "ggshield_version"), "utf8") @@ -54,7 +56,7 @@ export async function getGGShield( } fs.mkdirSync(ggshieldFolder); // install GGShield - await installGGShield(platform, arch, ggshieldFolder, version); + await installGGShield(platform, arch, ggshieldFolder, version, ignoreSSLErrors); outputChannel.appendLine( `Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.` ); @@ -132,7 +134,8 @@ export async function installGGShield( platform: NodeJS.Platform, arch: string, ggshieldFolder: string, - version: string + version: string, + ignoreSSLErrors: boolean, ): Promise { let extension: string = ""; switch (platform) { @@ -153,7 +156,7 @@ export async function installGGShield( version )}.${extension}`; const downloadUrl: string = `https://github.com/GitGuardian/ggshield/releases/download/v${version}/${fileName}`; - await downloadGGShieldFromGitHub(fileName, downloadUrl, ggshieldFolder); + await downloadGGShieldFromGitHub(fileName, downloadUrl, ggshieldFolder, ignoreSSLErrors); extractGGShieldBinary(path.join(ggshieldFolder, fileName), ggshieldFolder); } @@ -189,12 +192,21 @@ export function extractGGShieldBinary( async function downloadGGShieldFromGitHub( fileName: string, downloadUrl: string, - ggshieldFolder: string + ggshieldFolder: string, + ignoreSSLErrors: boolean ): Promise { console.log(`Downloading GGShield from ${downloadUrl}`); + + const instance = ignoreSSLErrors + ? new Agent({ + rejectUnauthorized: false, + }) + : undefined; + const { data } = await axios.get(downloadUrl, { ...defaultRequestConfig, - responseType: 'arraybuffer' + responseType: 'arraybuffer', + httpsAgent: instance }); fs.writeFileSync(path.join(ggshieldFolder, fileName), data); diff --git a/src/test/suite/lib/ggshield-resolver-utils.test.ts b/src/test/suite/lib/ggshield-resolver-utils.test.ts index 6cb302b..222906e 100644 --- a/src/test/suite/lib/ggshield-resolver-utils.test.ts +++ b/src/test/suite/lib/ggshield-resolver-utils.test.ts @@ -54,7 +54,8 @@ suite("getGGShield integration tests", async () => { platform, arch, mockContext, - outputChannel + outputChannel, + false ); assert.strictEqual(result, binaryPath); @@ -79,7 +80,8 @@ suite("getGGShield integration tests", async () => { platform, arch, mockContext, - outputChannel + outputChannel, + false ); assert(fs.existsSync(result)); @@ -102,7 +104,8 @@ suite("getGGShield integration tests", async () => { platform, arch, mockContext, - outputChannel + outputChannel, + false ); assert(fs.existsSync(result)); From 6dd81b5c809cae8fda6a3dc9be04fd4de8eeb020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verine=20Bonnech=C3=A8re?= Date: Mon, 28 Apr 2025 16:43:18 +0200 Subject: [PATCH 3/6] chore: remove getGGShieldLatestVersion --- .pre-commit-config.yaml | 4 +- src/lib/ggshield-resolver-utils.ts | 80 ++++++++++--------- .../suite/lib/ggshield-resolver-utils.test.ts | 76 ++++++++++-------- 3 files changed, 85 insertions(+), 75 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1239651..8870c9e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,8 +18,8 @@ repos: stages: [commit-msg] additional_dependencies: [ggcommitizen] - - repo: https://github.com/pre-commit/mirrors-prettier # to format JSON, YAML and markdown files among others - rev: v2.6.2 # Keep synchronize with .gitlab-ci.yml + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.1.0 hooks: - id: prettier diff --git a/src/lib/ggshield-resolver-utils.ts b/src/lib/ggshield-resolver-utils.ts index d856603..19272ca 100644 --- a/src/lib/ggshield-resolver-utils.ts +++ b/src/lib/ggshield-resolver-utils.ts @@ -1,7 +1,7 @@ import * as path from "path"; import * as fs from "fs"; import * as tar from "tar"; -import axios, { AxiosRequestConfig} from "axios"; +import axios, { AxiosRequestConfig } from "axios"; import { Agent } from "https"; const AdmZip = require("adm-zip"); @@ -9,9 +9,20 @@ import { ExtensionContext, OutputChannel } from "vscode"; const defaultRequestConfig = { headers: { "User-Agent": "GitGuardian-VSCode-Extension" }, - timeout: 30_000 + timeout: 30_000, } satisfies AxiosRequestConfig; +/** + * Get the version of GGShield + * @param context The extension context + * @returns The version of GGShield + */ +export function getGGShieldVersion(context: ExtensionContext): string { + return fs + .readFileSync(path.join(context.extensionPath, "ggshield_version"), "utf8") + .trim(); +} + /** * Get the absolute path to GGShield binary. If it doesn't exist, it will be installed. * @param platform The platform of the user @@ -25,27 +36,25 @@ export async function getGGShield( arch: string, context: ExtensionContext, outputChannel: OutputChannel, - ignoreSSLErrors: boolean + ignoreSSLErrors: boolean, ): Promise { - const version = fs - .readFileSync(path.join(context.extensionPath, "ggshield_version"), "utf8") - .trim(); + const version = getGGShieldVersion(context); console.log(`Latest GGShield version: ${version}`); const ggshieldFolder: string = path.join( context.extensionPath, - "ggshield-internal" + "ggshield-internal", ); const ggshieldBinaryPath: string = computeGGShieldPath( platform, arch, ggshieldFolder, - version + version, ); // if exists, return the path if (fs.existsSync(ggshieldBinaryPath)) { outputChannel.appendLine( - `Using GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.` + `Using GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`, ); console.log(`GGShield already exists at ${ggshieldBinaryPath}`); return ggshieldBinaryPath; @@ -56,30 +65,20 @@ export async function getGGShield( } fs.mkdirSync(ggshieldFolder); // install GGShield - await installGGShield(platform, arch, ggshieldFolder, version, ignoreSSLErrors); + await installGGShield( + platform, + arch, + ggshieldFolder, + version, + ignoreSSLErrors, + ); outputChannel.appendLine( - `Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.` + `Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`, ); console.log(`GGShield binary installed at ${ggshieldBinaryPath}`); return ggshieldBinaryPath; } -/** - * Get the latest version of GGShield - * @returns The latest version of GGShield - */ -export async function getGGShieldLatestVersion(): Promise { - const { data } = await axios.get<{tag_name?: string}>( - "https://api.github.com/repos/GitGuardian/ggshield/releases/latest", - { - ...defaultRequestConfig, - responseEncoding: 'utf8' - } - ); - - return data.tag_name?.replace(/^v/, "") ?? ""; -} - /** * Compute the folder name of the GGShield binary * @param platform The platform of the user @@ -90,7 +89,7 @@ export async function getGGShieldLatestVersion(): Promise { export function computeGGShieldFolderName( platform: NodeJS.Platform, arch: string, - version: string + version: string, ): string { let archString: string = ""; let platformString: string = ""; @@ -153,10 +152,15 @@ export async function installGGShield( const fileName: string = `${computeGGShieldFolderName( platform, arch, - version + version, )}.${extension}`; const downloadUrl: string = `https://github.com/GitGuardian/ggshield/releases/download/v${version}/${fileName}`; - await downloadGGShieldFromGitHub(fileName, downloadUrl, ggshieldFolder, ignoreSSLErrors); + await downloadGGShieldFromGitHub( + fileName, + downloadUrl, + ggshieldFolder, + ignoreSSLErrors, + ); extractGGShieldBinary(path.join(ggshieldFolder, fileName), ggshieldFolder); } @@ -167,7 +171,7 @@ export async function installGGShield( */ export function extractGGShieldBinary( filePath: string, - ggshieldFolder: string + ggshieldFolder: string, ): void { if (filePath.endsWith(".tar.gz")) { tar.x({ @@ -193,25 +197,25 @@ async function downloadGGShieldFromGitHub( fileName: string, downloadUrl: string, ggshieldFolder: string, - ignoreSSLErrors: boolean + ignoreSSLErrors: boolean, ): Promise { console.log(`Downloading GGShield from ${downloadUrl}`); const instance = ignoreSSLErrors ? new Agent({ rejectUnauthorized: false, - }) + }) : undefined; const { data } = await axios.get(downloadUrl, { ...defaultRequestConfig, - responseType: 'arraybuffer', - httpsAgent: instance + responseType: "arraybuffer", + httpsAgent: instance, }); fs.writeFileSync(path.join(ggshieldFolder, fileName), data); console.log( - `GGShield archive downloaded to ${path.join(ggshieldFolder, fileName)}` + `GGShield archive downloaded to ${path.join(ggshieldFolder, fileName)}`, ); } @@ -226,7 +230,7 @@ export function computeGGShieldPath( platform: NodeJS.Platform, arch: string, ggshieldFolder: string, - version: string + version: string, ): string { console.log(`Platform: ${platform}; Arch: ${arch}`); let executable: string = ""; @@ -245,6 +249,6 @@ export function computeGGShieldPath( return path.join( ggshieldFolder, computeGGShieldFolderName(platform, arch, version), - executable + executable, ); } diff --git a/src/test/suite/lib/ggshield-resolver-utils.test.ts b/src/test/suite/lib/ggshield-resolver-utils.test.ts index 222906e..067a97a 100644 --- a/src/test/suite/lib/ggshield-resolver-utils.test.ts +++ b/src/test/suite/lib/ggshield-resolver-utils.test.ts @@ -10,10 +10,10 @@ import { ExtensionContext, window, OutputChannel } from "vscode"; suite("getGGShield integration tests", async () => { let tempDir: string; let mockContext: ExtensionContext; + let version: string; let outputChannel: OutputChannel = window.createOutputChannel("GitGuardian"); const platform = process.platform; const arch = process.arch; - const latestVersion = await getGGShieldUtils.getGGShieldLatestVersion(); let originalLog: (message?: any, ...optionalParams: any[]) => void; let output: string; @@ -23,10 +23,16 @@ suite("getGGShield integration tests", async () => { mockContext = { extensionPath: tempDir, } as ExtensionContext; + // copy ggshield_version file to tempDir + fs.copyFileSync( + path.join(__dirname, "..", "..", "..", "..", "ggshield_version"), + path.join(tempDir, "ggshield_version"), + ); + version = getGGShieldUtils.getGGShieldVersion(mockContext); // copying ggshield_version file to tempDir fs.copyFileSync( path.join(__dirname, "..", "..", "..", "..", "ggshield_version"), - path.join(tempDir, "ggshield_version") + path.join(tempDir, "ggshield_version"), ); output = ""; // Reset captured output before each test originalLog = console.log; // Store original console.log @@ -43,27 +49,27 @@ suite("getGGShield integration tests", async () => { } }); - test("returns existing binary path when binary exists", () => { + test("returns existing binary path when binary exists", async () => { const binaryPath: string = createFakeBinary( tempDir, platform, arch, - latestVersion + version, ); - const result = getGGShieldUtils.getGGShield( + const result = await getGGShieldUtils.getGGShield( platform, arch, mockContext, outputChannel, - false + false, ); assert.strictEqual(result, binaryPath); assert(fs.existsSync(result)); - assert(result.includes(latestVersion)); + assert(result.includes(version)); assert( !output.includes("Updated to GGShield"), - "installGGShield should not be called when binary exists" + "installGGShield should not be called when binary exists", ); }); @@ -72,7 +78,7 @@ suite("getGGShield integration tests", async () => { platform, arch, path.join(tempDir, "ggshield-internal"), - latestVersion + version, ); assert(!fs.existsSync(expectedBinaryPath)); @@ -81,15 +87,15 @@ suite("getGGShield integration tests", async () => { arch, mockContext, outputChannel, - false + false, ); assert(fs.existsSync(result)); assert.strictEqual(result, expectedBinaryPath); - assert(result.includes(latestVersion)); + assert(result.includes(version)); assert( !output.includes("Updated to GGShield"), - "installGGShield should be called once when binary doesn't exist" + "installGGShield should be called once when binary doesn't exist", ); }); @@ -98,22 +104,22 @@ suite("getGGShield integration tests", async () => { tempDir, platform, arch, - "1.0.0" + "1.0.0", ); const result = await getGGShieldUtils.getGGShield( platform, arch, mockContext, outputChannel, - false + false, ); assert(fs.existsSync(result)); - assert(result.includes(latestVersion)); + assert(result.includes(version)); assert(!fs.existsSync(oldBinaryPath)); assert( !output.includes("Updated to GGShield"), - "installGGShield should be called once when updating binary" + "installGGShield should be called once when updating binary", ); }); }); @@ -122,13 +128,13 @@ function createFakeBinary( tempDir: string, platform: NodeJS.Platform, arch: string, - version: string + version: string, ): string { const ggshieldFolder: string = path.join(tempDir, "ggshield-internal"); const binaryName: string = platform === "win32" ? "ggshield.exe" : "ggshield"; const versionFolder: string = path.join( ggshieldFolder, - `${getGGShieldUtils.computeGGShieldFolderName(platform, arch, version)}` + `${getGGShieldUtils.computeGGShieldFolderName(platform, arch, version)}`, ); const binaryPath: string = path.join(versionFolder, binaryName); fs.mkdirSync(versionFolder, { recursive: true }); @@ -146,15 +152,15 @@ suite("ggshield-resolver-utils", () => { "win32", "x64", ggshieldFolder, - version + version, ); assert.strictEqual( result, path.join( ggshieldFolder, "ggshield-1.0.0-x86_64-pc-windows-msvc", - "ggshield.exe" - ) + "ggshield.exe", + ), ); }); @@ -163,15 +169,15 @@ suite("ggshield-resolver-utils", () => { "linux", "x64", ggshieldFolder, - version + version, ); assert.strictEqual( result, path.join( ggshieldFolder, "ggshield-1.0.0-x86_64-unknown-linux-gnu", - "ggshield" - ) + "ggshield", + ), ); }); @@ -180,15 +186,15 @@ suite("ggshield-resolver-utils", () => { "darwin", "x64", ggshieldFolder, - version + version, ); assert.strictEqual( result, path.join( ggshieldFolder, "ggshield-1.0.0-x86_64-apple-darwin", - "ggshield" - ) + "ggshield", + ), ); }); @@ -197,15 +203,15 @@ suite("ggshield-resolver-utils", () => { "darwin", "arm64", ggshieldFolder, - version + version, ); assert.strictEqual( result, path.join( ggshieldFolder, "ggshield-1.0.0-arm64-apple-darwin", - "ggshield" - ) + "ggshield", + ), ); }); @@ -215,7 +221,7 @@ suite("ggshield-resolver-utils", () => { "sunos", "x64", ggshieldFolder, - version + version, ); }, /Unsupported platform/); }); @@ -226,7 +232,7 @@ suite("ggshield-resolver-utils", () => { "darwin", "mips", ggshieldFolder, - version + version, ); }, /Unsupported architecture/); }); @@ -256,7 +262,7 @@ suite("ggshield-resolver-utils", () => { cwd: tempDir, sync: true, }, - [testFileName] + [testFileName], ); // Create zip archive @@ -279,7 +285,7 @@ suite("ggshield-resolver-utils", () => { const extractedContent = fs.readFileSync( path.join(extractDir, testFileName), - "utf8" + "utf8", ); assert.strictEqual(extractedContent, testContent); }); @@ -292,7 +298,7 @@ suite("ggshield-resolver-utils", () => { const extractedContent = fs.readFileSync( path.join(extractDir, testFileName), - "utf8" + "utf8", ); assert.strictEqual(extractedContent, testContent); }); From b4ac27144f90dbd203d06f5f4f91c96d4bb5fbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verine=20Bonnech=C3=A8re?= Date: Mon, 28 Apr 2025 16:49:08 +0200 Subject: [PATCH 4/6] chore: fix flaky timeout error on activate test --- src/test/suite/extension.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts index 0a7a4e2..ed1ba18 100644 --- a/src/test/suite/extension.test.ts +++ b/src/test/suite/extension.test.ts @@ -2,9 +2,11 @@ import * as assert from "assert"; import { extensions, commands } from "vscode"; suite("activate", () => { - test("Should activate extension successfully", async () => { + test("Should activate extension successfully", async function () { + this.timeout(10000); + const ext = extensions.getExtension( - "gitguardian-secret-security.gitguardian" + "gitguardian-secret-security.gitguardian", ); await ext?.activate(); assert.ok(ext?.isActive, "Extension should be active"); @@ -25,13 +27,13 @@ suite("activate", () => { const registered = await commands.getCommands(true); const gitguardianCommands = registered.filter((command) => - command.startsWith("gitguardian") + command.startsWith("gitguardian"), ); for (const command of commandIds) { assert.ok( gitguardianCommands.includes(command), - `Command ${command} should be registered` + `Command ${command} should be registered`, ); } }); From 4bca542cd5403bef5c738fd4added60f6815e468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verine=20Bonnech=C3=A8re?= Date: Wed, 30 Apr 2025 09:23:10 +0200 Subject: [PATCH 5/6] chore: use allowSelfSigned naming instead of switching to ignoreSSLErrors --- src/lib/ggshield-configuration-utils.ts | 7 +++---- src/lib/ggshield-resolver-utils.ts | 14 +++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lib/ggshield-configuration-utils.ts b/src/lib/ggshield-configuration-utils.ts index de4bef5..f5244d0 100644 --- a/src/lib/ggshield-configuration-utils.ts +++ b/src/lib/ggshield-configuration-utils.ts @@ -9,26 +9,25 @@ import { getGGShield } from "./ggshield-resolver-utils"; */ export async function getConfiguration( context: ExtensionContext, - outputChannel: OutputChannel + outputChannel: OutputChannel, ): Promise { const config = workspace.getConfiguration("gitguardian"); const ggshieldPath: string | undefined = config.get("GGShieldPath"); const apiUrl: string | undefined = config.get("apiUrl"); const allowSelfSigned: boolean = config.get("allowSelfSigned", false); - const ignoreSSLErrors = allowSelfSigned; const pathToGGShield: string = await getGGShield( os.platform(), os.arch(), context, outputChannel, - ignoreSSLErrors + allowSelfSigned, ); return new GGShieldConfiguration( pathToGGShield, apiUrl, - allowSelfSigned || false + allowSelfSigned || false, ); } diff --git a/src/lib/ggshield-resolver-utils.ts b/src/lib/ggshield-resolver-utils.ts index 19272ca..80b6890 100644 --- a/src/lib/ggshield-resolver-utils.ts +++ b/src/lib/ggshield-resolver-utils.ts @@ -36,7 +36,7 @@ export async function getGGShield( arch: string, context: ExtensionContext, outputChannel: OutputChannel, - ignoreSSLErrors: boolean, + allowSelfSigned: boolean, ): Promise { const version = getGGShieldVersion(context); console.log(`Latest GGShield version: ${version}`); @@ -70,7 +70,7 @@ export async function getGGShield( arch, ggshieldFolder, version, - ignoreSSLErrors, + allowSelfSigned, ); outputChannel.appendLine( `Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`, @@ -134,7 +134,7 @@ export async function installGGShield( arch: string, ggshieldFolder: string, version: string, - ignoreSSLErrors: boolean, + allowSelfSigned: boolean, ): Promise { let extension: string = ""; switch (platform) { @@ -159,7 +159,7 @@ export async function installGGShield( fileName, downloadUrl, ggshieldFolder, - ignoreSSLErrors, + allowSelfSigned, ); extractGGShieldBinary(path.join(ggshieldFolder, fileName), ggshieldFolder); } @@ -197,14 +197,14 @@ async function downloadGGShieldFromGitHub( fileName: string, downloadUrl: string, ggshieldFolder: string, - ignoreSSLErrors: boolean, + allowSelfSigned: boolean, ): Promise { console.log(`Downloading GGShield from ${downloadUrl}`); - const instance = ignoreSSLErrors + const instance = allowSelfSigned ? new Agent({ rejectUnauthorized: false, - }) + }) : undefined; const { data } = await axios.get(downloadUrl, { From 613ea335d07f6ae9e446dcc9a82fd55755c6746e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verine=20Bonnech=C3=A8re?= Date: Wed, 30 Apr 2025 09:24:13 +0200 Subject: [PATCH 6/6] chore: remove duplicated lines --- src/test/suite/lib/ggshield-resolver-utils.test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/suite/lib/ggshield-resolver-utils.test.ts b/src/test/suite/lib/ggshield-resolver-utils.test.ts index 067a97a..d8b67df 100644 --- a/src/test/suite/lib/ggshield-resolver-utils.test.ts +++ b/src/test/suite/lib/ggshield-resolver-utils.test.ts @@ -29,11 +29,6 @@ suite("getGGShield integration tests", async () => { path.join(tempDir, "ggshield_version"), ); version = getGGShieldUtils.getGGShieldVersion(mockContext); - // copying ggshield_version file to tempDir - fs.copyFileSync( - path.join(__dirname, "..", "..", "..", "..", "ggshield_version"), - path.join(tempDir, "ggshield_version"), - ); output = ""; // Reset captured output before each test originalLog = console.log; // Store original console.log