From 432f2ddeb640708c3377fd6334c20268df38f404 Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Thu, 23 May 2024 16:38:48 +0200 Subject: [PATCH 1/5] Keep track of GCM dependency --- dependencies.json | 26 ++++++++ package.json | 1 + script/fetch-asset-checksum.ts | 21 +++++++ script/lib/dependencies.ts | 30 +++++++++ script/update-git-credential-manager.ts | 81 +++++++++++++++++++++++++ script/update-git.ts | 24 +------- 6 files changed, 161 insertions(+), 22 deletions(-) create mode 100644 script/fetch-asset-checksum.ts create mode 100644 script/update-git-credential-manager.ts diff --git a/dependencies.json b/dependencies.json index 43659c55..731a8e13 100644 --- a/dependencies.json +++ b/dependencies.json @@ -58,5 +58,31 @@ "checksum": "94435072f6b3a6f9064b277760c8340e432b5ede0db8205d369468b9be52c6b6" } ] + }, + "git-credential-manager": { + "version": "2.5.0", + "files": [ + { + "name": "gcm-linux_amd64.2.5.0.tar.gz", + "platform": "linux", + "arch": "amd64", + "url": "https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.5.0/gcm-linux_amd64.2.5.0.tar.gz", + "checksum": "3adb86ab82111c94a22256980efd01a064ed9a06b882b138ab631ba6996d5752" + }, + { + "name": "gcm-osx-arm64-2.5.0.tar.gz", + "platform": "darwin", + "arch": "arm64", + "url": "https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.5.0/gcm-osx-arm64-2.5.0.tar.gz", + "checksum": "e3960aa72784ffb6e94294e1de14f0f5e96b6632854712ef4fa8837496032831" + }, + { + "name": "gcm-osx-x64-2.5.0.tar.gz", + "platform": "darwin", + "arch": "amd64", + "url": "https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.5.0/gcm-osx-x64-2.5.0.tar.gz", + "checksum": "4c7087492310a641318d0ab79de3554ea07de599431b5ac1bd0d43efbf4fa7f7" + } + ] } } diff --git a/package.json b/package.json index 5ff45885..b56df5d2 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "check": "tsc", "update-git": "ts-node script/update-git.ts", "update-git-lfs": "ts-node script/update-git-lfs.ts && npm run prettier-fix", + "update-git-credential-manager": "ts-node script/update-git-credential-manager.ts && npm run prettier-fix", "generate-release-notes": "ts-node script/generate-release-notes.ts", "prettier": "prettier -l \"**/*.y{,a}ml\" \"**/*.{js,ts,json}\"", "prettier-fix": "prettier --write \"**/*.y{,a}ml\" \"**/*.{js,ts,json}\"" diff --git a/script/fetch-asset-checksum.ts b/script/fetch-asset-checksum.ts new file mode 100644 index 00000000..c759c71e --- /dev/null +++ b/script/fetch-asset-checksum.ts @@ -0,0 +1,21 @@ +import { createHash } from 'crypto' + +export async function fetchAssetChecksum(uri: string) { + const hs = createHash('sha256') + + const headers = { + 'User-Agent': 'dugite-native', + accept: 'application/octet-stream', + } + + await fetch(uri, { headers }) + .then(x => + x.ok + ? Promise.resolve(x) + : Promise.reject(new Error(`Server responded with ${x.status}`)) + ) + .then(x => x.arrayBuffer()) + .then(x => hs.end(Buffer.from(x))) + + return hs.digest('hex') +} diff --git a/script/lib/dependencies.ts b/script/lib/dependencies.ts index 7108ecda..7ac18cfc 100644 --- a/script/lib/dependencies.ts +++ b/script/lib/dependencies.ts @@ -86,3 +86,33 @@ export function updateGitLfsDependencies( fs.writeFileSync(dependenciesPath, newDepedenciesText, 'utf8') } + +export function updateGitCredentialManagerDependencies( + version: string, + files: Array<{ + platform: string + arch: string + name: string + checksum: string + }> +) { + const dependenciesPath = path.resolve( + __dirname, + '..', + '..', + 'dependencies.json' + ) + const dependenciesText = fs.readFileSync(dependenciesPath, 'utf8') + const dependencies = JSON.parse(dependenciesText) + + const gcm = { + version: version, + files: files, + } + + const updatedDependencies = { ...dependencies, 'git-credential-manager': gcm } + + const newDepedenciesText = JSON.stringify(updatedDependencies, null, 2) + + fs.writeFileSync(dependenciesPath, newDepedenciesText, 'utf8') +} diff --git a/script/update-git-credential-manager.ts b/script/update-git-credential-manager.ts new file mode 100644 index 00000000..4b814e84 --- /dev/null +++ b/script/update-git-credential-manager.ts @@ -0,0 +1,81 @@ +import { Octokit } from '@octokit/rest' +import { updateGitCredentialManagerDependencies } from './lib/dependencies' +import { fetchAssetChecksum } from './fetch-asset-checksum' + +process.on('unhandledRejection', reason => { + console.error(reason) +}) + +async function run(): Promise { + const token = process.env.GITHUB_ACCESS_TOKEN + if (token == null) { + console.log(`🔴 No GITHUB_ACCESS_TOKEN environment variable set`) + return false + } + + const octokit = new Octokit({ auth: `token ${token}` }) + + const user = await octokit.users.getAuthenticated({}) + const me = user.data.login + + console.log(`✅ Token found for ${me}`) + + const owner = 'git-ecosystem' + const repo = 'git-credential-manager' + + const release = await octokit.repos.getLatestRelease({ owner, repo }) + + const { tag_name, id } = release.data + const version = tag_name.replace(/^v/, '') + + console.log(`✅ Newest git-credential-manager release '${version}'`) + + const assets = await octokit.repos.listReleaseAssets({ + owner, + repo, + release_id: id, + }) + + const fileTemplates = [ + { + name: `gcm-linux_amd64.${version}.tar.gz`, + platform: 'linux', + arch: 'amd64', + }, + { + name: `gcm-osx-arm64-${version}.tar.gz`, + platform: 'darwin', + arch: 'arm64', + }, + { + name: `gcm-osx-x64-${version}.tar.gz`, + platform: 'darwin', + arch: 'amd64', + }, + ] + + const files = [] + + for (const ft of fileTemplates) { + const asset = assets.data.find(a => a.name === ft.name) + + if (!asset) { + throw new Error(`Could not find asset for file: ${ft.name}`) + } + + const url = asset.browser_download_url + console.log(`⏳ Fetching checksum for ${ft.name}`) + const checksum = await fetchAssetChecksum(url) + console.log(`🔑 ${checksum}`) + files.push({ ...ft, url, checksum }) + } + + updateGitCredentialManagerDependencies(version, files) + + console.log( + `✅ Updated dependencies metadata to Git credential manager '${version}'` + ) + return true +} + +run().then(success => process.exit(success ? 0 : 1)) diff --git a/script/update-git.ts b/script/update-git.ts index b9095951..4fba1deb 100644 --- a/script/update-git.ts +++ b/script/update-git.ts @@ -6,6 +6,7 @@ import semver from 'semver' import { updateGitDependencies } from './lib/dependencies' import yargs from 'yargs' import fetch from 'node-fetch' +import { fetchAssetChecksum } from './fetch-asset-checksum' process.on('unhandledRejection', reason => { console.log(reason) @@ -72,27 +73,6 @@ async function getLatestStableRelease() { return latestTag.toString() } -async function calculateAssetChecksum(uri: string) { - return new Promise((resolve, reject) => { - const hs = crypto.createHash('sha256', { encoding: 'hex' }) - hs.on('finish', () => resolve(hs.read())) - - const headers: Record = { - 'User-Agent': 'dugite-native', - accept: 'application/octet-stream', - } - - fetch(uri, { headers }) - .then(x => - x.ok - ? Promise.resolve(x) - : Promise.reject(new Error(`Server responded with ${x.status}`)) - ) - .then(x => x.buffer()) - .then(x => hs.end(x)) - }) -} - async function getPackageDetails( assets: ReleaseAssets, body: string, @@ -119,7 +99,7 @@ async function getPackageDetails( let checksum: string if (match == null || match.length !== 2) { console.log(`🔴 No checksum for ${archValue} in release notes body`) - checksum = await calculateAssetChecksum(minGitFile.browser_download_url) + checksum = await fetchAssetChecksum(minGitFile.browser_download_url) console.log(`✅ Calculated checksum for ${archValue} from downloaded asset`) } else { console.log(`✅ Got checksum for ${archValue} from release notes body`) From 94552db675d64161ce03742702e7050df0190b25 Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Thu, 23 May 2024 16:59:57 +0200 Subject: [PATCH 2/5] Try downloading GCM on linux/darwin --- script/build-macos.sh | 34 ++++++++++++++++++++++++++++++++++ script/build-ubuntu.sh | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/script/build-macos.sh b/script/build-macos.sh index 30e3e00a..518ef56d 100755 --- a/script/build-macos.sh +++ b/script/build-macos.sh @@ -99,6 +99,40 @@ else echo "-- Skipped bundling Git LFS (set GIT_LFS_VERSION to include it in the bundle)" fi +GCM_VERSION="$(jq --raw-output '.["git-credential-manager"].version[1:]' dependencies.json)" +GCM_CHECKSUM="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .checksum" dependencies.json)" +GCM_FILENAME="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .name" dependencies.json)" +GCM_URL="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .url" dependencies.json)" + +if [[ "$GCM_VERSION" && "$GCM_URL" ]]; then + echo "-- Bundling GCM" + GCM_FILE=git-credential-manager.tar.gz + echo "-- Downloading from $GCM_URL" + curl -sL -o $GCM_FILE "$GCM_URL" + COMPUTED_SHA256=$(compute_checksum $GCM_FILE) + if [ "$COMPUTED_SHA256" = "$GCM_CHECKSUM" ]; then + echo "GCM: checksums match" + SUBFOLDER="$DESTINATION/libexec/git-core" + tar -xvkf $GCM_FILE -C "$SUBFOLDER" + + if [[ ! -f "$SUBFOLDER/git-credential-manager" ]]; then + echo "After extracting GCM the file was not found under libexec/git-core/" + echo "aborting..." + exit 1 + fi + else + echo "GCM: expected checksum $GCM_CHECKSUM but got $COMPUTED_SHA256" + echo "aborting..." + exit 1 + fi +else + if [ -z "$GCM_URL" ]; then + echo "-- No download URL for GCM on macOS/$GOARCH, skipping bundling" + else + echo "-- Skipped bundling GCM (set GCM_VERSION to include it in the bundle)" + fi +fi + echo "-- Removing server-side programs" rm "$DESTINATION/bin/git-cvsserver" rm "$DESTINATION/bin/git-receive-pack" diff --git a/script/build-ubuntu.sh b/script/build-ubuntu.sh index 563b1270..f76786e5 100755 --- a/script/build-ubuntu.sh +++ b/script/build-ubuntu.sh @@ -55,6 +55,11 @@ GIT_LFS_VERSION="$(jq --raw-output '.["git-lfs"].version[1:]' dependencies.json) GIT_LFS_CHECKSUM="$(jq --raw-output ".\"git-lfs\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .checksum" dependencies.json)" GIT_LFS_FILENAME="$(jq --raw-output ".\"git-lfs\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .name" dependencies.json)" +GCM_VERSION="$(jq --raw-output '.["git-credential-manager"].version[1:]' dependencies.json)" +GCM_CHECKSUM="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .checksum" dependencies.json)" +GCM_FILENAME="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .name" dependencies.json)" +GCM_URL="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .url" dependencies.json)" + # shellcheck source=script/compute-checksum.sh source "$CURRENT_DIR/compute-checksum.sh" # shellcheck source=script/check-static-linking.sh @@ -120,6 +125,34 @@ else echo "-- Skipped bundling Git LFS (set GIT_LFS_VERSION to include it in the bundle)" fi +if [[ "$GCM_VERSION" && "$GCM_URL" ]]; then + echo "-- Bundling GCM" + GCM_FILE=git-credential-manager.tar.gz + echo "-- Downloading from $GCM_URL" + curl -sL -o $GCM_FILE "$GCM_URL" + COMPUTED_SHA256=$(compute_checksum $GCM_FILE) + if [ "$COMPUTED_SHA256" = "$GCM_CHECKSUM" ]; then + echo "GCM: checksums match" + SUBFOLDER="$DESTINATION/libexec/git-core" + tar -xvkf $GCM_FILE -C "$SUBFOLDER" + + if [[ ! -f "$SUBFOLDER/git-credential-manager" ]]; then + echo "After extracting GCM the file was not found under libexec/git-core/" + echo "aborting..." + exit 1 + fi + else + echo "GCM: expected checksum $GCM_CHECKSUM but got $COMPUTED_SHA256" + echo "aborting..." + exit 1 + fi +else + if [ -z "$GCM_URL" ]; then + echo "-- No download URL for GCM on Linux/$DEPENDENCY_ARCH, skipping bundling" + else + echo "-- Skipped bundling GCM (set GCM_VERSION to include it in the bundle)" + fi +fi ( # download CA bundle and write straight to temp folder From bc8e7cb84e27e2d8a7746fece0bf856fd7ac4d4a Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Thu, 23 May 2024 17:11:35 +0200 Subject: [PATCH 3/5] Update update-git.ts --- script/update-git.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/script/update-git.ts b/script/update-git.ts index 4fba1deb..bda147c4 100644 --- a/script/update-git.ts +++ b/script/update-git.ts @@ -1,11 +1,9 @@ import path from 'path' -import crypto from 'crypto' import ChildProcess from 'child_process' import { Octokit, RestEndpointMethodTypes } from '@octokit/rest' import semver from 'semver' import { updateGitDependencies } from './lib/dependencies' import yargs from 'yargs' -import fetch from 'node-fetch' import { fetchAssetChecksum } from './fetch-asset-checksum' process.on('unhandledRejection', reason => { From 482fd9541830175ca3529507cb6fd2db8838da1b Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Thu, 23 May 2024 17:16:32 +0200 Subject: [PATCH 4/5] :fire: unused --- script/build-macos.sh | 1 - script/build-ubuntu.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/script/build-macos.sh b/script/build-macos.sh index 518ef56d..308c2afd 100755 --- a/script/build-macos.sh +++ b/script/build-macos.sh @@ -101,7 +101,6 @@ fi GCM_VERSION="$(jq --raw-output '.["git-credential-manager"].version[1:]' dependencies.json)" GCM_CHECKSUM="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .checksum" dependencies.json)" -GCM_FILENAME="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .name" dependencies.json)" GCM_URL="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .url" dependencies.json)" if [[ "$GCM_VERSION" && "$GCM_URL" ]]; then diff --git a/script/build-ubuntu.sh b/script/build-ubuntu.sh index f76786e5..97bef5dd 100755 --- a/script/build-ubuntu.sh +++ b/script/build-ubuntu.sh @@ -57,7 +57,6 @@ GIT_LFS_FILENAME="$(jq --raw-output ".\"git-lfs\".files[] | select(.arch == \"$D GCM_VERSION="$(jq --raw-output '.["git-credential-manager"].version[1:]' dependencies.json)" GCM_CHECKSUM="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .checksum" dependencies.json)" -GCM_FILENAME="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .name" dependencies.json)" GCM_URL="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .url" dependencies.json)" # shellcheck source=script/compute-checksum.sh From 561c2d20183518bde09a6cfa44b08dc5c53c1530 Mon Sep 17 00:00:00 2001 From: Markus Olsson Date: Mon, 27 May 2024 10:56:33 +0200 Subject: [PATCH 5/5] Don't know why this isn't already the case --- script/build-macos.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/script/build-macos.sh b/script/build-macos.sh index 308c2afd..343267dc 100755 --- a/script/build-macos.sh +++ b/script/build-macos.sh @@ -119,6 +119,7 @@ if [[ "$GCM_VERSION" && "$GCM_URL" ]]; then echo "aborting..." exit 1 fi + chmod +x "$SUBFOLDER/git-credential-manager" else echo "GCM: expected checksum $GCM_CHECKSUM but got $COMPUTED_SHA256" echo "aborting..."