Skip to content

Commit

Permalink
fix: use tag name instead of version when resolving GitHub files
Browse files Browse the repository at this point in the history
Modify the GitHubProvider to provide the tag name of the latest
release as apart of its UpdateInfo (which is now encapsulated in the
GithubUpdateInfo interface) so that it uses that same tag name later
when it resolves the files to download.

fix /issues/6076
  • Loading branch information
wardellbagby committed Jul 31, 2021
1 parent 6c0350f commit 094593b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 17 deletions.
38 changes: 22 additions & 16 deletions packages/electron-updater/src/providers/GitHubProvider.ts
Expand Up @@ -6,8 +6,11 @@ import { ResolvedUpdateFileInfo } from "../main"
import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util"
import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider"

const hrefRegExp = /\/tag\/v?([^/]+)$/
const hrefRegExp = /\/tag\/([^/]+)$/

interface GithubUpdateInfo extends UpdateInfo {
tag: string
}
export abstract class BaseGitHubProvider<T extends UpdateInfo> extends Provider<T> {
// so, we don't need to parse port (because node http doesn't support host as url does)
protected readonly baseUrl: URL
Expand All @@ -32,12 +35,12 @@ export abstract class BaseGitHubProvider<T extends UpdateInfo> extends Provider<
}
}

export class GitHubProvider extends BaseGitHubProvider<UpdateInfo> {
export class GitHubProvider extends BaseGitHubProvider<GithubUpdateInfo> {
constructor(protected readonly options: GithubOptions, private readonly updater: AppUpdater, runtimeOptions: ProviderRuntimeOptions) {
super(options, "github.com", runtimeOptions)
}

async getLatestVersion(): Promise<UpdateInfo> {
async getLatestVersion(): Promise<GithubUpdateInfo> {
const cancellationToken = new CancellationToken()

const feedXml: string = (await this.httpRequest(
Expand All @@ -51,16 +54,16 @@ export class GitHubProvider extends BaseGitHubProvider<UpdateInfo> {
const feed = parseXml(feedXml)
// noinspection TypeScriptValidateJSTypes
let latestRelease = feed.element("entry", false, `No published versions on GitHub`)
let version: string | null
let tag: string | null
try {
if (this.updater.allowPrerelease) {
// noinspection TypeScriptValidateJSTypes
version = hrefRegExp.exec(latestRelease.element("link").attribute("href"))![1]
tag = hrefRegExp.exec(latestRelease.element("link").attribute("href"))![1]
} else {
version = await this.getLatestVersionString(cancellationToken)
tag = await this.getLatestTagName(cancellationToken)
for (const element of feed.getElements("entry")) {
// noinspection TypeScriptValidateJSTypes
if (hrefRegExp.exec(element.element("link").attribute("href"))![1] === version) {
if (hrefRegExp.exec(element.element("link").attribute("href"))![1] === tag) {
latestRelease = element
break
}
Expand All @@ -70,12 +73,12 @@ export class GitHubProvider extends BaseGitHubProvider<UpdateInfo> {
throw newError(`Cannot parse releases feed: ${e.stack || e.message},\nXML:\n${feedXml}`, "ERR_UPDATER_INVALID_RELEASE_FEED")
}

if (version == null) {
if (tag == null) {
throw newError(`No published versions on GitHub`, "ERR_UPDATER_NO_PUBLISHED_VERSIONS")
}

const channelFile = getChannelFilename(this.getDefaultChannelName())
const channelFileUrl = newUrlFromBase(this.getBaseDownloadPath(version, channelFile), this.baseUrl)
const channelFileUrl = newUrlFromBase(this.getBaseDownloadPath(tag, channelFile), this.baseUrl)
const requestOptions = this.createRequestOptions(channelFileUrl)
let rawData: string
try {
Expand All @@ -95,10 +98,13 @@ export class GitHubProvider extends BaseGitHubProvider<UpdateInfo> {
if (result.releaseNotes == null) {
result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease)
}
return result
return {
tag: tag,
...result,
}
}

private async getLatestVersionString(cancellationToken: CancellationToken): Promise<string | null> {
private async getLatestTagName(cancellationToken: CancellationToken): Promise<string | null> {
const options = this.options
// do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise
const url =
Expand All @@ -112,7 +118,7 @@ export class GitHubProvider extends BaseGitHubProvider<UpdateInfo> {
}

const releaseInfo: GithubReleaseInfo = JSON.parse(rawData)
return releaseInfo.tag_name.startsWith("v") ? releaseInfo.tag_name.substring(1) : releaseInfo.tag_name
return releaseInfo.tag_name
} catch (e) {
throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND")
}
Expand All @@ -122,13 +128,13 @@ export class GitHubProvider extends BaseGitHubProvider<UpdateInfo> {
return `/${this.options.owner}/${this.options.repo}/releases`
}

resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {
resolveFiles(updateInfo: GithubUpdateInfo): Array<ResolvedUpdateFileInfo> {
// still replace space to - due to backward compatibility
return resolveFiles(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.version, p.replace(/ /g, "-")))
return resolveFiles(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, "-")))
}

private getBaseDownloadPath(version: string, fileName: string): string {
return `${this.basePath}/download/${this.options.vPrefixedTagName === false ? "" : "v"}${version}/${fileName}`
private getBaseDownloadPath(tag: string, fileName: string): string {
return `${this.basePath}/download/${tag}/${fileName}`
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/electron-updater/src/providers/Provider.ts
Expand Up @@ -55,7 +55,7 @@ export abstract class Provider<T extends UpdateInfo> {

abstract getLatestVersion(): Promise<T>

abstract resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo>
abstract resolveFiles(updateInfo: T): Array<ResolvedUpdateFileInfo>

/**
* Method to perform API request only to resolve update info, but not to download update.
Expand Down
7 changes: 7 additions & 0 deletions test/snapshots/updater/nsisUpdaterTest.js.snap
Expand Up @@ -107,6 +107,7 @@ Object {
],
"releaseName": "v1.5.2-beta.3",
"releaseNotes": "",
"tag": "v1.5.2-beta.3",
"version": "1.5.2-beta.3",
}
`;
Expand Down Expand Up @@ -160,6 +161,7 @@ Object {
],
"releaseName": "1.1.0",
"releaseNotes": "",
"tag": "v1.1.0",
"version": "1.1.0",
}
`;
Expand All @@ -174,6 +176,7 @@ Object {
],
"releaseName": "1.1.0",
"releaseNotes": "",
"tag": "v1.1.0",
"version": "1.1.0",
}
`;
Expand Down Expand Up @@ -205,6 +208,7 @@ Object {
"version": "1.5.0",
},
],
"tag": "v1.5.2-beta.3",
"version": "1.5.2-beta.3",
}
`;
Expand All @@ -228,6 +232,7 @@ Object {
"version": "1.5.0",
},
],
"tag": "v1.5.2-beta.3",
"version": "1.5.2-beta.3",
}
`;
Expand Down Expand Up @@ -259,6 +264,7 @@ Object {
"version": "1.5.0",
},
],
"tag": "v1.5.2-beta.3",
"version": "1.5.2-beta.3",
}
`;
Expand Down Expand Up @@ -418,6 +424,7 @@ Object {
],
"releaseName": "1.1.0",
"releaseNotes": "",
"tag": "v1.1.0",
"version": "1.1.0",
}
`;
Expand Down

0 comments on commit 094593b

Please sign in to comment.