Skip to content

Commit

Permalink
fix(electron-updater): use tag name instead of version when resolving…
Browse files Browse the repository at this point in the history
… GitHub files (#6117)
  • Loading branch information
wardellbagby committed Aug 1, 2021
1 parent 6c0350f commit dcf03a6
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 17 deletions.
5 changes: 5 additions & 0 deletions empty-ties-argue.md
@@ -0,0 +1,5 @@
---
"electron-updater": patch
---

fix: use git remote's tag name instead of v-prefixed version string when resolving GitHub releases
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 dcf03a6

Please sign in to comment.