Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/target-commitish-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"electron-publish": minor
"builder-util-runtime": minor
---

feat(electron-publish): add targetCommitish support for GitHub releases

Allow specifying branch or commit for release creation via config, EP_TARGET_COMMITISH or GITHUB_SHA env vars
7 changes: 7 additions & 0 deletions packages/app-builder-lib/scheme.json
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,13 @@
"description": "If defined, sets the prefix of the tag name that comes before the semver number.\ne.g. \"v\" in \"v1.2.3\" or \"test\" of \"test1.2.3\".\nOverrides `vPrefixedTagName`",
"type": "string"
},
"targetCommitish": {
"description": "The branch or commit to create the release from.\nBy default, GitHub creates the release tag on the default branch (e.g. `main`).\nUse this to target a specific branch (e.g. `development`) or commit SHA.\n\nCan be set via `EP_TARGET_COMMITISH` env var, or `GITHUB_SHA` in GitHub Actions (current commit).",
"type": [
"null",
"string"
]
},
"timeout": {
"default": 120000,
"description": "Request timeout in milliseconds. (Default is 2 minutes; O is ignored)",
Expand Down
9 changes: 1 addition & 8 deletions packages/app-builder-lib/src/toolsets/linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,7 @@ export async function getAppImageTools(targetArch: Arch) {

artifactPath = path.resolve(artifactPath)

const runtimeArch =
targetArch === Arch.armv7l
? "arm32"
: targetArch === Arch.arm64
? "arm64"
: targetArch === Arch.ia32
? "ia32"
: "x64"
const runtimeArch = targetArch === Arch.armv7l ? "arm32" : targetArch === Arch.arm64 ? "arm64" : targetArch === Arch.ia32 ? "ia32" : "x64"

return {
mksquashfs: path.join(artifactPath, "mksquashfs"),
Expand Down
9 changes: 9 additions & 0 deletions packages/builder-util-runtime/src/publishOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ export interface GithubOptions extends PublishConfiguration {
* @default draft
*/
releaseType?: "draft" | "prerelease" | "release" | null

/**
* The branch or commit to create the release from.
* By default, GitHub creates the release tag on the default branch (e.g. `main`).
* Use this to target a specific branch (e.g. `development`) or commit SHA.
*
* Can be set via `EP_TARGET_COMMITISH` env var, or `GITHUB_SHA` in GitHub Actions (current commit).
*/
readonly targetCommitish?: string | null
}

/** @private */
Expand Down
14 changes: 12 additions & 2 deletions packages/electron-publish/src/gitHubPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ interface Asset {

export class GitHubPublisher extends HttpPublisher {
private readonly tag: string
private readonly targetCommitish: string | undefined
readonly _release = new Lazy(() => (this.token === "__test__" ? Promise.resolve(null as any) : this.getOrCreateRelease()))

private readonly token: string
Expand Down Expand Up @@ -67,6 +68,11 @@ export class GitHubPublisher extends HttpPublisher {

this.tag = githubTagPrefix(info) + version

this.targetCommitish = info.targetCommitish ?? process.env.EP_TARGET_COMMITISH ?? process.env.GITHUB_SHA ?? undefined
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hesitant to add the default of process.env.EP_TARGET_COMMITISH ?? process.env.GITHUB_SHA since this is completely net-new functionality and likely not expected by another dev.
I consider new functionality that is extracted from env vars to be breaking changes.

I'd suggest only using info.targetCommitish and then in the tsdoc, specify an example (or recommended) value.

if (this.targetCommitish != null && this.targetCommitish.length > 0) {
log.info({ targetCommitish: this.targetCommitish }, "GitHub release target_commitish is set")
}

if (isEnvTrue(process.env.EP_DRAFT)) {
this.releaseType = "draft"
log.info({ reason: "env EP_DRAFT is set to true" }, "GitHub provider release type is set to draft")
Expand Down Expand Up @@ -230,12 +236,16 @@ export class GitHubPublisher extends HttpPublisher {
}

private createRelease() {
return this.githubRequest<Release>(`/repos/${this.info.owner}/${this.info.repo}/releases`, this.token, {
const body: Record<string, any> = {
tag_name: this.tag,
name: this.version,
draft: this.releaseType === "draft",
prerelease: this.releaseType === "prerelease",
})
}
if (this.targetCommitish != null && this.targetCommitish.length > 0) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: We can simplify this to !!this.targetCommitish?.length (or use isEmptyOrSpaces from builder-util)

body.target_commitish = this.targetCommitish
}
return this.githubRequest<Release>(`/repos/${this.info.owner}/${this.info.repo}/releases`, this.token, body)
}

// test only
Expand Down
17 changes: 17 additions & 0 deletions pages/publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ win:
- bitbucket
```

To create GitHub releases from a specific branch or commit (instead of the default branch), use `targetCommitish`:

```json
{
"build": {
"publish": {
"provider": "github",
"owner": "my-org",
"repo": "my-app",
"targetCommitish": "development"
}
}
}
```

Or via env in CI: `EP_TARGET_COMMITISH` or `GITHUB_SHA` (GitHub Actions).

You can also configure publishing using CLI arguments, for example, to force publishing snap not to Snap Store, but to GitHub: `-c.snap.publish=github`

[Custom](https://github.com/electron-userland/electron-builder/issues/3261) publish provider can be used if need.
Expand Down
94 changes: 94 additions & 0 deletions test/src/publisher/github/GitHubPublisherTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { CancellationToken, GithubOptions } from "builder-util-runtime"
import { GitHubPublisher, PublishContext } from "electron-publish"
import { beforeEach, describe, test } from "vitest"

describe("GitHub Publisher - targetCommitish", () => {
let publishContext: PublishContext

beforeEach(() => {
publishContext = {
cancellationToken: new CancellationToken(),
progress: null,
}
delete process.env.EP_TARGET_COMMITISH
delete process.env.GITHUB_SHA
delete process.env.GH_TOKEN
delete process.env.GITHUB_TOKEN
})

test("constructor accepts targetCommitish in config", ({ expect }) => {
process.env.GH_TOKEN = "test-token-for-constructor"

const publisher = new GitHubPublisher(
publishContext,
{
provider: "github",
owner: "owner",
repo: "repo",
token: "test-token",
targetCommitish: "development",
} as GithubOptions,
"1.0.0"
)

expect(publisher.toString()).toContain("owner")
expect(publisher.toString()).toContain("repo")
expect(publisher.providerName).toBe("github")
})

test("constructor accepts empty config without targetCommitish", ({ expect }) => {
process.env.GH_TOKEN = "test-token-for-constructor"

const publisher = new GitHubPublisher(
publishContext,
{
provider: "github",
owner: "owner",
repo: "repo",
token: "test-token",
} as GithubOptions,
"1.0.0"
)

expect(publisher.toString()).toContain("owner")
expect(publisher.providerName).toBe("github")
})

test("constructor resolves targetCommitish from EP_TARGET_COMMITISH when not in config", ({ expect }) => {
process.env.GH_TOKEN = "test-token"
process.env.EP_TARGET_COMMITISH = "feature-branch"

const publisher = new GitHubPublisher(
publishContext,
{
provider: "github",
owner: "owner",
repo: "repo",
token: "test-token",
} as GithubOptions,
"1.0.0"
)

expect(publisher.toString()).toContain("owner")
expect(publisher.providerName).toBe("github")
})

test("constructor resolves targetCommitish from GITHUB_SHA when EP_TARGET_COMMITISH and config not set", ({ expect }) => {
process.env.GH_TOKEN = "test-token"
process.env.GITHUB_SHA = "abc123def456"

const publisher = new GitHubPublisher(
publishContext,
{
provider: "github",
owner: "owner",
repo: "repo",
token: "test-token",
} as GithubOptions,
"1.0.0"
)

expect(publisher.toString()).toContain("owner")
expect(publisher.providerName).toBe("github")
})
})
Loading