Skip to content

Commit 17466a1

Browse files
authored
Merge pull request #510 from desktop/gcm
Bundle GCM on macOS and Linux
2 parents 1074931 + 561c2d2 commit 17466a1

File tree

8 files changed

+227
-24
lines changed

8 files changed

+227
-24
lines changed

dependencies.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,31 @@
5858
"checksum": "94435072f6b3a6f9064b277760c8340e432b5ede0db8205d369468b9be52c6b6"
5959
}
6060
]
61+
},
62+
"git-credential-manager": {
63+
"version": "2.5.0",
64+
"files": [
65+
{
66+
"name": "gcm-linux_amd64.2.5.0.tar.gz",
67+
"platform": "linux",
68+
"arch": "amd64",
69+
"url": "https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.5.0/gcm-linux_amd64.2.5.0.tar.gz",
70+
"checksum": "3adb86ab82111c94a22256980efd01a064ed9a06b882b138ab631ba6996d5752"
71+
},
72+
{
73+
"name": "gcm-osx-arm64-2.5.0.tar.gz",
74+
"platform": "darwin",
75+
"arch": "arm64",
76+
"url": "https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.5.0/gcm-osx-arm64-2.5.0.tar.gz",
77+
"checksum": "e3960aa72784ffb6e94294e1de14f0f5e96b6632854712ef4fa8837496032831"
78+
},
79+
{
80+
"name": "gcm-osx-x64-2.5.0.tar.gz",
81+
"platform": "darwin",
82+
"arch": "amd64",
83+
"url": "https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.5.0/gcm-osx-x64-2.5.0.tar.gz",
84+
"checksum": "4c7087492310a641318d0ab79de3554ea07de599431b5ac1bd0d43efbf4fa7f7"
85+
}
86+
]
6187
}
6288
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"check": "tsc",
66
"update-git": "ts-node script/update-git.ts",
77
"update-git-lfs": "ts-node script/update-git-lfs.ts && npm run prettier-fix",
8+
"update-git-credential-manager": "ts-node script/update-git-credential-manager.ts && npm run prettier-fix",
89
"generate-release-notes": "ts-node script/generate-release-notes.ts",
910
"prettier": "prettier -l \"**/*.y{,a}ml\" \"**/*.{js,ts,json}\"",
1011
"prettier-fix": "prettier --write \"**/*.y{,a}ml\" \"**/*.{js,ts,json}\""

script/build-macos.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,40 @@ else
9999
echo "-- Skipped bundling Git LFS (set GIT_LFS_VERSION to include it in the bundle)"
100100
fi
101101

102+
GCM_VERSION="$(jq --raw-output '.["git-credential-manager"].version[1:]' dependencies.json)"
103+
GCM_CHECKSUM="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .checksum" dependencies.json)"
104+
GCM_URL="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$GOARCH\" and .platform == \"darwin\") | .url" dependencies.json)"
105+
106+
if [[ "$GCM_VERSION" && "$GCM_URL" ]]; then
107+
echo "-- Bundling GCM"
108+
GCM_FILE=git-credential-manager.tar.gz
109+
echo "-- Downloading from $GCM_URL"
110+
curl -sL -o $GCM_FILE "$GCM_URL"
111+
COMPUTED_SHA256=$(compute_checksum $GCM_FILE)
112+
if [ "$COMPUTED_SHA256" = "$GCM_CHECKSUM" ]; then
113+
echo "GCM: checksums match"
114+
SUBFOLDER="$DESTINATION/libexec/git-core"
115+
tar -xvkf $GCM_FILE -C "$SUBFOLDER"
116+
117+
if [[ ! -f "$SUBFOLDER/git-credential-manager" ]]; then
118+
echo "After extracting GCM the file was not found under libexec/git-core/"
119+
echo "aborting..."
120+
exit 1
121+
fi
122+
chmod +x "$SUBFOLDER/git-credential-manager"
123+
else
124+
echo "GCM: expected checksum $GCM_CHECKSUM but got $COMPUTED_SHA256"
125+
echo "aborting..."
126+
exit 1
127+
fi
128+
else
129+
if [ -z "$GCM_URL" ]; then
130+
echo "-- No download URL for GCM on macOS/$GOARCH, skipping bundling"
131+
else
132+
echo "-- Skipped bundling GCM (set GCM_VERSION to include it in the bundle)"
133+
fi
134+
fi
135+
102136
echo "-- Removing server-side programs"
103137
rm "$DESTINATION/bin/git-cvsserver"
104138
rm "$DESTINATION/bin/git-receive-pack"

script/build-ubuntu.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ GIT_LFS_VERSION="$(jq --raw-output '.["git-lfs"].version[1:]' dependencies.json)
5555
GIT_LFS_CHECKSUM="$(jq --raw-output ".\"git-lfs\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .checksum" dependencies.json)"
5656
GIT_LFS_FILENAME="$(jq --raw-output ".\"git-lfs\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .name" dependencies.json)"
5757

58+
GCM_VERSION="$(jq --raw-output '.["git-credential-manager"].version[1:]' dependencies.json)"
59+
GCM_CHECKSUM="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .checksum" dependencies.json)"
60+
GCM_URL="$(jq --raw-output ".\"git-credential-manager\".files[] | select(.arch == \"$DEPENDENCY_ARCH\" and .platform == \"linux\") | .url" dependencies.json)"
61+
5862
# shellcheck source=script/compute-checksum.sh
5963
source "$CURRENT_DIR/compute-checksum.sh"
6064
# shellcheck source=script/check-static-linking.sh
@@ -120,6 +124,34 @@ else
120124
echo "-- Skipped bundling Git LFS (set GIT_LFS_VERSION to include it in the bundle)"
121125
fi
122126

127+
if [[ "$GCM_VERSION" && "$GCM_URL" ]]; then
128+
echo "-- Bundling GCM"
129+
GCM_FILE=git-credential-manager.tar.gz
130+
echo "-- Downloading from $GCM_URL"
131+
curl -sL -o $GCM_FILE "$GCM_URL"
132+
COMPUTED_SHA256=$(compute_checksum $GCM_FILE)
133+
if [ "$COMPUTED_SHA256" = "$GCM_CHECKSUM" ]; then
134+
echo "GCM: checksums match"
135+
SUBFOLDER="$DESTINATION/libexec/git-core"
136+
tar -xvkf $GCM_FILE -C "$SUBFOLDER"
137+
138+
if [[ ! -f "$SUBFOLDER/git-credential-manager" ]]; then
139+
echo "After extracting GCM the file was not found under libexec/git-core/"
140+
echo "aborting..."
141+
exit 1
142+
fi
143+
else
144+
echo "GCM: expected checksum $GCM_CHECKSUM but got $COMPUTED_SHA256"
145+
echo "aborting..."
146+
exit 1
147+
fi
148+
else
149+
if [ -z "$GCM_URL" ]; then
150+
echo "-- No download URL for GCM on Linux/$DEPENDENCY_ARCH, skipping bundling"
151+
else
152+
echo "-- Skipped bundling GCM (set GCM_VERSION to include it in the bundle)"
153+
fi
154+
fi
123155

124156
(
125157
# download CA bundle and write straight to temp folder

script/fetch-asset-checksum.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createHash } from 'crypto'
2+
3+
export async function fetchAssetChecksum(uri: string) {
4+
const hs = createHash('sha256')
5+
6+
const headers = {
7+
'User-Agent': 'dugite-native',
8+
accept: 'application/octet-stream',
9+
}
10+
11+
await fetch(uri, { headers })
12+
.then(x =>
13+
x.ok
14+
? Promise.resolve(x)
15+
: Promise.reject(new Error(`Server responded with ${x.status}`))
16+
)
17+
.then(x => x.arrayBuffer())
18+
.then(x => hs.end(Buffer.from(x)))
19+
20+
return hs.digest('hex')
21+
}

script/lib/dependencies.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,33 @@ export function updateGitLfsDependencies(
8686

8787
fs.writeFileSync(dependenciesPath, newDepedenciesText, 'utf8')
8888
}
89+
90+
export function updateGitCredentialManagerDependencies(
91+
version: string,
92+
files: Array<{
93+
platform: string
94+
arch: string
95+
name: string
96+
checksum: string
97+
}>
98+
) {
99+
const dependenciesPath = path.resolve(
100+
__dirname,
101+
'..',
102+
'..',
103+
'dependencies.json'
104+
)
105+
const dependenciesText = fs.readFileSync(dependenciesPath, 'utf8')
106+
const dependencies = JSON.parse(dependenciesText)
107+
108+
const gcm = {
109+
version: version,
110+
files: files,
111+
}
112+
113+
const updatedDependencies = { ...dependencies, 'git-credential-manager': gcm }
114+
115+
const newDepedenciesText = JSON.stringify(updatedDependencies, null, 2)
116+
117+
fs.writeFileSync(dependenciesPath, newDepedenciesText, 'utf8')
118+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { Octokit } from '@octokit/rest'
2+
import { updateGitCredentialManagerDependencies } from './lib/dependencies'
3+
import { fetchAssetChecksum } from './fetch-asset-checksum'
4+
5+
process.on('unhandledRejection', reason => {
6+
console.error(reason)
7+
})
8+
9+
async function run(): Promise<boolean> {
10+
const token = process.env.GITHUB_ACCESS_TOKEN
11+
if (token == null) {
12+
console.log(`🔴 No GITHUB_ACCESS_TOKEN environment variable set`)
13+
return false
14+
}
15+
16+
const octokit = new Octokit({ auth: `token ${token}` })
17+
18+
const user = await octokit.users.getAuthenticated({})
19+
const me = user.data.login
20+
21+
console.log(`✅ Token found for ${me}`)
22+
23+
const owner = 'git-ecosystem'
24+
const repo = 'git-credential-manager'
25+
26+
const release = await octokit.repos.getLatestRelease({ owner, repo })
27+
28+
const { tag_name, id } = release.data
29+
const version = tag_name.replace(/^v/, '')
30+
31+
console.log(`✅ Newest git-credential-manager release '${version}'`)
32+
33+
const assets = await octokit.repos.listReleaseAssets({
34+
owner,
35+
repo,
36+
release_id: id,
37+
})
38+
39+
const fileTemplates = [
40+
{
41+
name: `gcm-linux_amd64.${version}.tar.gz`,
42+
platform: 'linux',
43+
arch: 'amd64',
44+
},
45+
{
46+
name: `gcm-osx-arm64-${version}.tar.gz`,
47+
platform: 'darwin',
48+
arch: 'arm64',
49+
},
50+
{
51+
name: `gcm-osx-x64-${version}.tar.gz`,
52+
platform: 'darwin',
53+
arch: 'amd64',
54+
},
55+
]
56+
57+
const files = []
58+
59+
for (const ft of fileTemplates) {
60+
const asset = assets.data.find(a => a.name === ft.name)
61+
62+
if (!asset) {
63+
throw new Error(`Could not find asset for file: ${ft.name}`)
64+
}
65+
66+
const url = asset.browser_download_url
67+
console.log(`⏳ Fetching checksum for ${ft.name}`)
68+
const checksum = await fetchAssetChecksum(url)
69+
console.log(`🔑 ${checksum}`)
70+
files.push({ ...ft, url, checksum })
71+
}
72+
73+
updateGitCredentialManagerDependencies(version, files)
74+
75+
console.log(
76+
`✅ Updated dependencies metadata to Git credential manager '${version}'`
77+
)
78+
return true
79+
}
80+
81+
run().then(success => process.exit(success ? 0 : 1))

script/update-git.ts

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import path from 'path'
2-
import crypto from 'crypto'
32
import ChildProcess from 'child_process'
43
import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'
54
import semver from 'semver'
65
import { updateGitDependencies } from './lib/dependencies'
76
import yargs from 'yargs'
8-
import fetch from 'node-fetch'
7+
import { fetchAssetChecksum } from './fetch-asset-checksum'
98

109
process.on('unhandledRejection', reason => {
1110
console.log(reason)
@@ -72,27 +71,6 @@ async function getLatestStableRelease() {
7271
return latestTag.toString()
7372
}
7473

75-
async function calculateAssetChecksum(uri: string) {
76-
return new Promise<string>((resolve, reject) => {
77-
const hs = crypto.createHash('sha256', { encoding: 'hex' })
78-
hs.on('finish', () => resolve(hs.read()))
79-
80-
const headers: Record<string, string> = {
81-
'User-Agent': 'dugite-native',
82-
accept: 'application/octet-stream',
83-
}
84-
85-
fetch(uri, { headers })
86-
.then(x =>
87-
x.ok
88-
? Promise.resolve(x)
89-
: Promise.reject(new Error(`Server responded with ${x.status}`))
90-
)
91-
.then(x => x.buffer())
92-
.then(x => hs.end(x))
93-
})
94-
}
95-
9674
async function getPackageDetails(
9775
assets: ReleaseAssets,
9876
body: string,
@@ -119,7 +97,7 @@ async function getPackageDetails(
11997
let checksum: string
12098
if (match == null || match.length !== 2) {
12199
console.log(`🔴 No checksum for ${archValue} in release notes body`)
122-
checksum = await calculateAssetChecksum(minGitFile.browser_download_url)
100+
checksum = await fetchAssetChecksum(minGitFile.browser_download_url)
123101
console.log(`✅ Calculated checksum for ${archValue} from downloaded asset`)
124102
} else {
125103
console.log(`✅ Got checksum for ${archValue} from release notes body`)

0 commit comments

Comments
 (0)