Skip to content

Commit

Permalink
Merge pull request #510 from desktop/gcm
Browse files Browse the repository at this point in the history
Bundle GCM on macOS and Linux
  • Loading branch information
niik authored May 28, 2024
2 parents 1074931 + 561c2d2 commit 17466a1
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 24 deletions.
26 changes: 26 additions & 0 deletions dependencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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}\""
Expand Down
34 changes: 34 additions & 0 deletions script/build-macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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_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
chmod +x "$SUBFOLDER/git-credential-manager"
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"
Expand Down
32 changes: 32 additions & 0 deletions script/build-ubuntu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ 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_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
Expand Down Expand Up @@ -120,6 +124,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
Expand Down
21 changes: 21 additions & 0 deletions script/fetch-asset-checksum.ts
Original file line number Diff line number Diff line change
@@ -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')
}
30 changes: 30 additions & 0 deletions script/lib/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
81 changes: 81 additions & 0 deletions script/update-git-credential-manager.ts
Original file line number Diff line number Diff line change
@@ -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<boolean> {
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))
26 changes: 2 additions & 24 deletions script/update-git.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
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 => {
console.log(reason)
Expand Down Expand Up @@ -72,27 +71,6 @@ async function getLatestStableRelease() {
return latestTag.toString()
}

async function calculateAssetChecksum(uri: string) {
return new Promise<string>((resolve, reject) => {
const hs = crypto.createHash('sha256', { encoding: 'hex' })
hs.on('finish', () => resolve(hs.read()))

const headers: Record<string, string> = {
'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,
Expand All @@ -119,7 +97,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`)
Expand Down

0 comments on commit 17466a1

Please sign in to comment.