-
-
Notifications
You must be signed in to change notification settings - Fork 443
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Tech] Download helper binaries instead of storing them in the repo (#…
…3849) * Download helper binaries instead of storing them in the repo * Download binaries for both x86_64 and arm64 * Use GitHub Releases instead of Actions runs * Simplify electron-builder config a bit We can simply tell it to unpack everything in the `bin` folder, since we already only include the binaries we need We can also use glob patters for the `files` option to include binaries for all architectures. Ideally we should figure out a way to only include the files for the arch we're building, but I don't think EB has an option for that * Fall back to x86_64 binaries if arch-specific one doesn't exist
- Loading branch information
Showing
20 changed files
with
302 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
#!/bin/bash | ||
pnpm i | ||
pnpm download-helper-binaries |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
import { createWriteStream } from 'fs' | ||
import { chmod, stat, mkdir, readFile, writeFile } from 'fs/promises' | ||
import { dirname, join } from 'path' | ||
import { Readable } from 'stream' | ||
import { finished } from 'stream/promises' | ||
|
||
type SupportedPlatform = 'win32' | 'darwin' | 'linux' | ||
type DownloadedBinary = 'legendary' | 'gogdl' | 'nile' | ||
|
||
const RELEASE_TAGS = { | ||
legendary: '0.20.35', | ||
gogdl: 'v1.1.1', | ||
nile: 'v1.1.0' | ||
} as const satisfies Record<DownloadedBinary, string> | ||
|
||
const pathExists = async (path: string): Promise<boolean> => | ||
stat(path).then( | ||
() => true, | ||
() => false | ||
) | ||
|
||
async function downloadFile(url: string, dst: string) { | ||
const response = await fetch(url, { | ||
headers: { | ||
'User-Agent': 'HeroicBinaryUpdater/1.0' | ||
} | ||
}) | ||
await mkdir(dirname(dst), { recursive: true }) | ||
const fileStream = createWriteStream(dst, { flags: 'w' }) | ||
await finished(Readable.fromWeb(response.body).pipe(fileStream)) | ||
} | ||
|
||
async function downloadAsset( | ||
binaryName: string, | ||
repo: string, | ||
tag_name: string, | ||
arch: string, | ||
platform: SupportedPlatform, | ||
filename: string | ||
) { | ||
const url = `https://github.com/${repo}/releases/download/${tag_name}/${filename}` | ||
console.log('Downloading', binaryName, 'for', platform, arch, 'from', url) | ||
|
||
const exeFilename = binaryName + (platform === 'win32' ? '.exe' : '') | ||
const exePath = join('public', 'bin', arch, platform, exeFilename) | ||
await downloadFile(url, exePath) | ||
|
||
console.log('Done downloading', binaryName, 'for', platform, arch) | ||
|
||
if (platform !== 'win32') { | ||
await chmod(exePath, '755') | ||
} | ||
} | ||
|
||
/** | ||
* Downloads assets uploaded to a GitHub release | ||
* @param binaryName The binary which was built & uploaded. Also used to get the final folder path | ||
* @param repo The repo to download from | ||
* @param tagName The GitHub Release tag which produced the binaries | ||
* @param assetNames The name(s) of the assets which were uploaded, mapped to platforms | ||
*/ | ||
async function downloadGithubAssets( | ||
binaryName: string, | ||
repo: string, | ||
tagName: string, | ||
assetNames: Record< | ||
'x64' | 'arm64', | ||
Partial<Record<SupportedPlatform, string>> | ||
> | ||
) { | ||
const downloadPromises = Object.entries(assetNames).map( | ||
async ([arch, platformFilenameMap]) => | ||
Promise.all( | ||
Object.entries(platformFilenameMap).map(([platform, filename]) => { | ||
if (!filename) return | ||
return downloadAsset( | ||
binaryName, | ||
repo, | ||
tagName, | ||
arch, | ||
platform as keyof typeof platformFilenameMap, | ||
filename | ||
) | ||
}) | ||
) | ||
) | ||
|
||
return Promise.all(downloadPromises) | ||
} | ||
|
||
async function downloadLegendary() { | ||
return downloadGithubAssets( | ||
'legendary', | ||
'Heroic-Games-Launcher/legendary', | ||
RELEASE_TAGS['legendary'], | ||
{ | ||
x64: { | ||
linux: 'legendary_linux_x86_64', | ||
darwin: 'legendary_macOS_x86_64', | ||
win32: 'legendary_windows_x86_64.exe' | ||
}, | ||
arm64: { | ||
darwin: 'legendary_macOS_arm64' | ||
} | ||
} | ||
) | ||
} | ||
|
||
async function downloadGogdl() { | ||
return downloadGithubAssets( | ||
'gogdl', | ||
'Heroic-Games-Launcher/heroic-gogdl', | ||
RELEASE_TAGS['gogdl'], | ||
{ | ||
x64: { | ||
linux: 'gogdl_linux_x86_64', | ||
darwin: 'gogdl_macOS_x86_64', | ||
win32: 'gogdl_windows_x86_64.exe' | ||
}, | ||
arm64: { | ||
darwin: 'gogdl_macOS_arm64' | ||
} | ||
} | ||
) | ||
} | ||
|
||
async function downloadNile() { | ||
return downloadGithubAssets('nile', 'imLinguin/nile', RELEASE_TAGS['nile'], { | ||
x64: { | ||
linux: 'nile_linux_x86_64', | ||
darwin: 'nile_macOS_x86_64', | ||
win32: 'nile_windows_x86_64.exe' | ||
}, | ||
arm64: { | ||
darwin: 'nile_macOS_arm64' | ||
} | ||
}) | ||
} | ||
|
||
/** | ||
* Finds out which binaries need to be downloaded by comparing | ||
* `public/bin/.release_tags` to RELEASE_TAGS | ||
*/ | ||
async function compareDownloadedTags(): Promise<DownloadedBinary[]> { | ||
const storedTagsText = await readFile( | ||
'public/bin/.release_tags', | ||
'utf-8' | ||
).catch(() => '{}') | ||
let storedTagsParsed: Partial<Record<DownloadedBinary, string>> | ||
try { | ||
storedTagsParsed = JSON.parse(storedTagsText) | ||
} catch { | ||
return ['legendary', 'gogdl', 'nile'] | ||
} | ||
const binariesToDownload: DownloadedBinary[] = [] | ||
for (const [runner, currentTag] of Object.entries(RELEASE_TAGS)) { | ||
if (storedTagsParsed[runner] !== currentTag) | ||
binariesToDownload.push(runner as keyof typeof RELEASE_TAGS) | ||
} | ||
return binariesToDownload | ||
} | ||
|
||
async function storeDownloadedTags() { | ||
await writeFile('public/bin/.release_tags', JSON.stringify(RELEASE_TAGS)) | ||
} | ||
|
||
async function main() { | ||
if (!(await pathExists('public/bin'))) { | ||
console.error('public/bin not found, are you in the source root?') | ||
return | ||
} | ||
|
||
const binariesToDownload = await compareDownloadedTags() | ||
if (!binariesToDownload.length) { | ||
console.log('Nothing to download, binaries are up-to-date') | ||
return | ||
} | ||
|
||
console.log('Downloading:', binariesToDownload) | ||
const promisesToAwait: Promise<unknown>[] = [] | ||
|
||
if (binariesToDownload.includes('legendary')) | ||
promisesToAwait.push(downloadLegendary()) | ||
if (binariesToDownload.includes('gogdl')) | ||
promisesToAwait.push(downloadGogdl()) | ||
if (binariesToDownload.includes('nile')) promisesToAwait.push(downloadNile()) | ||
|
||
await Promise.all(promisesToAwait) | ||
|
||
await storeDownloadedTags() | ||
} | ||
|
||
void main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.