Skip to content

Commit a4df9d5

Browse files
committed
feat: custom_tarball param
1 parent 635beb6 commit a4df9d5

10 files changed

Lines changed: 180 additions & 60 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## Next Release
4+
5+
- Adds `custom_tarball` parameter, allowing you to bundle your distributable assets however you'd like
6+
- Optimizes how asset URL selection occurs when downloading assets to generate checksums for
7+
38
## v3.1.0 (2025-12-26)
49

510
- Adds `skip_checksum` parameter which skips uploading the checksum file for all release assets to the latest release. Useful if you generate your own checksums or already had a checksum file since we cannot overwrite an existing checksum file without deleting the previous one

README.md

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,43 @@ When you cut a new release when using this GitHub Action, Homebrew Releaser will
3333

3434
After you release a project on GitHub, Homebrew Releaser can publish that release to a personal Homebrew tap by updating the project description, version, tar archive url, license, checksum, installation and testing command, and any other required info so you don't have to. You can check the [Homebrew documentation on taps](https://docs.brew.sh/How-to-Create-and-Maintain-a-Tap) and the [formula cookbook](https://docs.brew.sh/Formula-Cookbook) for more details on setting up a Homebrew formula or tap.
3535

36+
#### Minimal Setup
37+
38+
The following is the bare minimum set of parameters required to run Homebrew Releaser (some defaults are assumed):
39+
40+
```yml
41+
# .github/workflows/release.yml
42+
# Start Homebrew Releaser when a new GitHub release is created
43+
on:
44+
release:
45+
types: [published]
46+
47+
jobs:
48+
homebrew-releaser:
49+
runs-on: ubuntu-latest
50+
name: homebrew-releaser
51+
steps:
52+
- name: Release project to Homebrew tap
53+
uses: Justintime50/homebrew-releaser@v3
54+
with:
55+
# The name of the homebrew tap to publish your formula to as it appears on GitHub (Homebrew taps must start with `homebrew-`).
56+
# Required - strings
57+
homebrew_owner: Justintime50
58+
homebrew_tap: homebrew-formulas
59+
60+
# The Personal Access Token (saved as a repo secret) that has `repo` permissions for the repo running the action AND Homebrew tap you want to release to.
61+
# Required - string
62+
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
63+
64+
# Install command for your formula.
65+
# Required - string
66+
install: 'bin.install "src/my-script.sh" => "my-script"'
67+
```
68+
69+
#### Complete List of Parameters
70+
71+
The following is the complete list of parameters that are usable with Homebrew Releaser:
72+
3673
```yml
3774
# .github/workflows/release.yml
3875
# Start Homebrew Releaser when a new GitHub release is created
@@ -109,7 +146,7 @@ jobs:
109146

110147
# Adds URL and checksum targets for different OS and architecture pairs. Using this option assumes
111148
# a tar archive exists on your GitHub repo with the following URL pattern (this cannot be customized):
112-
# https://github.com/{GITHUB_OWNER}/{REPO_NAME}/releases/download/{TAG}/{REPO_NAME}-{VERSION}-{OPERATING_SYSTEM}-{ARCHITECTURE}.tar.gz'
149+
# https://github.com/{github_owner}/{repo_name}/releases/download/{tag}/{repo_name}-{version}-{operating_system}-{architecture}.tar.gz'
113150
# Darwin AMD pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/myrepo-1.2.0-darwin-amd64.tar.gz
114151
# Linux ARM pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/myrepo-1.2.0-linux-arm64.tar.gz
115152
# Optional - booleans
@@ -118,6 +155,13 @@ jobs:
118155
target_linux_amd64: true
119156
target_linux_arm64: false
120157

158+
# Use a custom tarball on your release instead of the auto generated or templated arch URLs listed above.
159+
# NOTE: Although you can use whatever packaging and naming conventions you want, Homebrew Releaser will look
160+
# for your tarball at the following URL: https://github.com/{user}/{repo}/releases/download/{release_name}/{custom_tarball}.tar.gz
161+
# Custom tarball pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/v1.2.0.tar.gz
162+
# Optional - string
163+
custom_tarball: v1.2.0
164+
121165
# Update your homebrew tap's README with a table of all projects in the tap.
122166
# This is done by pulling the information from all your formula.rb files - eg:
123167
#
@@ -149,7 +193,7 @@ jobs:
149193
debug: false
150194
```
151195
152-
#### Python
196+
#### Python Formula
153197
154198
To release a Python package using Homebrew Releaser, one may setup their workflow like so:
155199

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ inputs:
6161
target_linux_arm64:
6262
description: 'Add a custom URL/checksum target for ARM64 Linux builds.'
6363
required: false
64+
custom_tarball:
65+
description: 'Use a custom tarball on your release instead of the auto generated or templated arch URLs listed above.'
66+
required: false
6467
update_readme_table:
6568
description: "Update your homebrew tap's README with a table of all projects in the tap."
6669
required: false
@@ -95,6 +98,7 @@ runs:
9598
- ${{ inputs.target_darwin_arm64 }}
9699
- ${{ inputs.target_linux_amd64 }}
97100
- ${{ inputs.target_linux_arm64 }}
101+
- ${{ inputs.custom_tarball }}
98102
- ${{ inputs.update_readme_table }}
99103
- ${{ inputs.skip_commit }}
100104
- ${{ inputs.skip_checksum }}

docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ services:
2727
- INPUT_TARGET_DARWIN_ARM64=
2828
- INPUT_TARGET_LINUX_AMD64=
2929
- INPUT_TARGET_LINUX_ARM64=
30+
- INPUT_CUSTOM_TARBALL=
3031
- INPUT_SKIP_CHECKSUM=

homebrew_releaser/app.py

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from homebrew_releaser.constants import (
1212
CHECKSUM_FILE,
1313
CUSTOM_REQUIRE,
14+
CUSTOM_TARBALL,
1415
DOWNLOAD_STRATEGY,
1516
FORMULA_INCLUDES,
1617
GITHUB_OWNER,
@@ -115,16 +116,16 @@ def run_github_action():
115116
if repository["private"]:
116117
logger.debug("Repository is private. Using auto-generated release tarball and zipball REST API endpoints.")
117118
archive_base_url = f"{GITHUB_BASE_URL}/repos/{GITHUB_OWNER}/{GITHUB_REPO}"
118-
auto_generated_release_tar = f"{archive_base_url}/tarball/{version}"
119-
auto_generated_release_zip = f"{archive_base_url}/zipball/{version}"
119+
auto_generated_release_tar_url = f"{archive_base_url}/tarball/{version}"
120+
auto_generated_release_zip_url = f"{archive_base_url}/zipball/{version}"
120121
else:
121122
logger.debug("Repository is public. Using auto-generated release tarball and zipball public URLs.")
122123
archive_base_url = f"https://github.com/{GITHUB_OWNER}/{GITHUB_REPO}/archive/refs/tags/{version}"
123-
auto_generated_release_tar = f"{archive_base_url}.tar.gz"
124-
auto_generated_release_zip = f"{archive_base_url}.zip"
124+
auto_generated_release_tar_url = f"{archive_base_url}.tar.gz"
125+
auto_generated_release_zip_url = f"{archive_base_url}.zip"
125126

126-
archive_urls.append(auto_generated_release_tar)
127-
archive_urls.append(auto_generated_release_zip)
127+
archive_urls.append(auto_generated_release_tar_url)
128+
archive_urls.append(auto_generated_release_zip_url)
128129

129130
target_browser_download_base_url = (
130131
f"https://github.com/{GITHUB_OWNER}/{GITHUB_REPO}/releases/download/{version}/{GITHUB_REPO}-{version_no_v}"
@@ -138,38 +139,42 @@ def run_github_action():
138139
if TARGET_LINUX_ARM64:
139140
archive_urls.append(f"{target_browser_download_base_url}-linux-arm64.tar.gz")
140141

142+
custom_tarball_url = None
143+
if CUSTOM_TARBALL:
144+
custom_tarball_url = (
145+
f"https://github.com/{GITHUB_OWNER}/{GITHUB_REPO}/releases/download/{version}/{CUSTOM_TARBALL}.tar.gz"
146+
)
147+
logger.debug(
148+
f"Using the following custom tarball URL instead of auto-generated tarball URL: {custom_tarball_url}"
149+
)
150+
archive_urls.append(custom_tarball_url)
151+
141152
checksums = []
142153
for archive_url in archive_urls:
143-
if not assets:
144-
assets = [0] # Populate `assets` so that if we don't have any, we can use the auto generated checksums
145-
for asset in assets:
146-
# Download the asset url so private repos work but use the brower URL for name and path in formula
147-
if archive_url == auto_generated_release_tar or archive_url == auto_generated_release_zip:
148-
download_url = archive_url
149-
else:
150-
download_url = asset["url"]
151-
152-
if (
153-
archive_url == auto_generated_release_tar
154-
or archive_url == auto_generated_release_zip
155-
or archive_url == asset["browser_download_url"]
156-
):
157-
# For REST API requests, we should not stream archive file, but it is fine for browser URLs
158-
stream = False if archive_url.find("api.github.com") != -1 else True
159-
downloaded_filename = _download_archive(download_url, stream)
160-
checksum = calculate_checksum(downloaded_filename)
161-
archive_filename = get_filename_from_path(archive_url)
162-
archive_checksum_entries += f"{checksum} {archive_filename}\n"
163-
checksums.append(
164-
{
165-
archive_filename: {
166-
"checksum": checksum,
167-
"url": archive_url,
168-
}
169-
},
170-
)
171-
# We break here so we don't include duplicate checksums for the auto generated URLs
172-
break
154+
if repository["private"]:
155+
# For private repos, use asset["url"] if available, otherwise use archive_url
156+
matching_asset = next(
157+
(asset for asset in assets if asset and asset.get("browser_download_url") == archive_url), None
158+
)
159+
download_url = matching_asset["url"] if matching_asset else archive_url
160+
stream = False
161+
else:
162+
# For public repos, always use browser URLs
163+
download_url = archive_url
164+
stream = True
165+
166+
downloaded_filename = _download_archive(download_url, stream)
167+
checksum = calculate_checksum(downloaded_filename)
168+
archive_filename = get_filename_from_path(archive_url)
169+
archive_checksum_entries += f"{checksum} {archive_filename}\n"
170+
checksums.append(
171+
{
172+
archive_filename: {
173+
"checksum": checksum,
174+
"url": archive_url,
175+
}
176+
}
177+
)
173178

174179
write_file(CHECKSUM_FILE, archive_checksum_entries)
175180

@@ -180,7 +185,7 @@ def run_github_action():
180185
repository,
181186
checksums,
182187
INSTALL,
183-
auto_generated_release_tar,
188+
custom_tarball_url or auto_generated_release_tar_url,
184189
DEPENDS_ON,
185190
TEST,
186191
DOWNLOAD_STRATEGY,

homebrew_releaser/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,4 @@
5858
TARGET_LINUX_ARM64 = (
5959
os.getenv("INPUT_TARGET_LINUX_ARM64", False) if os.getenv("INPUT_TARGET_LINUX_ARM64") != "false" else False
6060
) # Must check for string `false` since GitHub Actions passes the bool as a string
61+
CUSTOM_TARBALL = os.getenv("INPUT_CUSTOM_TARBALL")

homebrew_releaser/formula.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from homebrew_releaser.constants import (
1212
ARTICLES,
13+
CUSTOM_TARBALL,
1314
LOGGER_NAME,
1415
MAX_DESC_FIELD_LENGTH,
1516
TARGET_DARWIN_AMD64,
@@ -90,23 +91,29 @@ def generate_formula_data(
9091
for index, checksum in enumerate(checksums):
9192
checksum_filename = next(iter(checksum))
9293
checksum_url = checksum[checksum_filename]["url"] # type: ignore
94+
checksum_value = checksum[checksum_filename]["checksum"] # type: ignore
9395

94-
# Autogenerated tar URL is the first one
96+
# Autogenerated tar URL is always the first entry
9597
if index == 0:
96-
autogenerated_tar_checksum = checksum[checksum_filename]["checksum"] # type: ignore
98+
tar_url_checksum = checksum_value # type: ignore
99+
continue
100+
101+
# If using a custom tarball, replace the tar_url_checksum with that one
102+
if CUSTOM_TARBALL and re.search(rf".*/download/[^/]+/{re.escape(CUSTOM_TARBALL)}\.tar\.gz$", checksum_url):
103+
tar_url_checksum = checksum_value # type: ignore
97104

98105
if checksum_url.endswith("darwin-amd64.tar.gz") and TARGET_DARWIN_AMD64:
99106
darwin_amd64_url = checksum_url
100-
darwin_amd64_checksum = checksum[checksum_filename]["checksum"] # type: ignore
107+
darwin_amd64_checksum = checksum_value # type: ignore
101108
elif checksum_url.endswith("darwin-arm64.tar.gz") and TARGET_DARWIN_ARM64:
102109
darwin_arm64_url = checksum_url
103-
darwin_arm64_checksum = checksum[checksum_filename]["checksum"] # type: ignore
110+
darwin_arm64_checksum = checksum_value # type: ignore
104111
elif checksum_url.endswith("linux-amd64.tar.gz") and TARGET_LINUX_AMD64:
105112
linux_amd64_url = checksum_url
106-
linux_amd64_checksum = checksum[checksum_filename]["checksum"] # type: ignore
113+
linux_amd64_checksum = checksum_value # type: ignore
107114
elif checksum_url.endswith("linux-arm64.tar.gz") and TARGET_LINUX_ARM64:
108115
linux_arm64_url = checksum_url
109-
linux_arm64_checksum = checksum[checksum_filename]["checksum"] # type: ignore
116+
linux_arm64_checksum = checksum_value # type: ignore
110117

111118
# We set these so we can properly space items only if both are present
112119
darwin_amd_and_arm = darwin_amd64_url and darwin_arm64_url
@@ -134,7 +141,7 @@ class {{class_name}} < Formula
134141
{{# version}}
135142
version "{{version}}"
136143
{{/ version}}
137-
sha256 "{{autogenerated_tar_checksum}}"
144+
sha256 "{{tar_url_checksum}}"
138145
{{# license_type}}
139146
license "{{license_type}}"
140147
{{/ license_type}}
@@ -204,7 +211,7 @@ def install
204211
"owner": owner,
205212
"repo_name": repo_name,
206213
"tar_url": tar_url,
207-
"autogenerated_tar_checksum": autogenerated_tar_checksum,
214+
"tar_url_checksum": tar_url_checksum,
208215
"license_type": license_type,
209216
"dependencies": dependencies_list,
210217
"install_instructions": _match_indent_of(template, "install_instructions", install),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# typed: true
2+
# frozen_string_literal: true
3+
4+
# This file was generated by Homebrew Releaser. DO NOT EDIT.
5+
class TestGenerateFormulaCustomTarball < Formula
6+
desc "Release scripts, binaries, and executables to github"
7+
homepage "https://github.com/Justintime50/test-generate-formula-custom-tarball"
8+
url "https://github.com/Justintime50/test-generate-formula-custom-tarball/download/v0.1.0/custom_tarball.tar.gz"
9+
sha256 "0000000000000000000000000000000000000000000000000000000000000000"
10+
license "MIT"
11+
12+
def install
13+
bin.install "src/secure-browser-kiosk.sh" => "secure-browser-kiosk"
14+
end
15+
end

0 commit comments

Comments
 (0)