Skip to content

Commit ff46db1

Browse files
committed
feat: support finding binary using file path
TICKET: VL-4112
1 parent c038e23 commit ff46db1

File tree

4 files changed

+112
-41
lines changed

4 files changed

+112
-41
lines changed

README.md

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# install-github-release-binary
22

3-
[![Build Status]](https://github.com/EricCrosson/install-github-release-binary/actions/workflows/release.yml)
3+
[![Build Status]](https://github.com/BitGo/install-github-release-binary/actions/workflows/release.yml)
44

5-
[build status]: https://github.com/EricCrosson/install-github-release-binary/actions/workflows/release.yml/badge.svg?event=push
5+
[build status]: https://github.com/BitGo/install-github-release-binary/actions/workflows/release.yml/badge.svg?event=push
66

77
**install-github-release-binary** is an opinionated GitHub Action for adding a binary from a GitHub Release to your CI `$PATH`.
88

@@ -18,7 +18,6 @@ This action only supports installing from releases where the release:
1818

1919
- is tagged with the full `{major}.{minor}.{patch}` semantic version
2020
- contains raw binary assets (archives not supported)
21-
- assets are labeled with the binary name and [target triple] in the format `<binary name>-<target triple>`
2221

2322
You can create compatible releases with [semantic-release], using a workflow like [semantic-release-action/rust].
2423

@@ -32,35 +31,45 @@ Use this action in a step:
3231

3332
```yaml
3433
- name: Install flux-capacitor
35-
uses: EricCrosson/install-github-release-binary@v2
34+
uses: BitGo/install-github-release-binary@v2
3635
with:
37-
targets: EricCrosson/flux-capacitor@v1
36+
targets: BitGo/flux-capacitor@v1
3837
```
3938
4039
> [!NOTE]
4140
> I recommend adding an explicit step name, otherwise the step will only reference
42-
> `EricCrosson/install-github-release-binary@v2`, not your targets.
41+
> `BitGo/install-github-release-binary@v2`, not your targets.
4342

4443
Install multiple binaries:
4544

4645
```yaml
4746
- name: Install future tools
48-
uses: EricCrosson/install-github-release-binary@v2
47+
uses: BitGo/install-github-release-binary@v2
4948
with:
5049
targets: |
51-
EricCrosson/flux-capacitor@v1
52-
EricCrosson/steam-locomotive@v7.5.3
53-
EricCrosson/hoverboard@11.7.3:sha256-8a4600be96d2ec013209042458ce97a9652fcc46c1c855d0217aa42e330fc06e
50+
BitGo/flux-capacitor@v1
51+
BitGo/steam-locomotive@v7.5.3
52+
BitGo/hoverboard@11.7.3:sha256-8a4600be96d2ec013209042458ce97a9652fcc46c1c855d0217aa42e330fc06e
5453
```
5554

5655
Install a binary from a release with multiple binaries available:
5756

5857
```yaml
5958
- name: Install flux-capacitor
60-
uses: EricCrosson/install-github-release-binary@v2
59+
uses: BitGo/install-github-release-binary@v2
6160
with:
6261
targets: |
63-
EricCrosson/future-tools/flux-capacitor@v1
62+
BitGo/future-tools/flux-capacitor@v1
63+
```
64+
65+
Install a specific binary with checksum validation:
66+
67+
```yaml
68+
- name: Install argocd CLI
69+
uses: BitGo/install-github-release-binary@v2
70+
with:
71+
targets: |
72+
argoproj/argo-cd/argocd-linux-amd64@v3.1.4:sha256-7def0aa3cc9ebcd6acdddc27244e7ea4de448d872a9ab0cf6cab4b1e653841a6
6473
```
6574

6675
## Inputs
@@ -82,11 +91,11 @@ Optionally, include:
8291

8392
Examples:
8493

85-
- `EricCrosson/flux-capacitor@v1`
86-
- `EricCrosson/flux-capacitor@v1.2`
87-
- `EricCrosson/flux-capacitor@v1.2.3`
88-
- `EricCrosson/flux-capacitor@v1.2.3:sha256-ad91159c656d427ad8fe5ded2946f29f3a612c6b7a4af6129e9aa85256b7299e`
89-
- `EricCrosson/future-tools/flux-capacitor@v1`
94+
- `BitGo/flux-capacitor@v1`
95+
- `BitGo/flux-capacitor@v1.2`
96+
- `BitGo/flux-capacitor@v1.2.3`
97+
- `BitGo/flux-capacitor@v1.2.3:sha256-ad91159c656d427ad8fe5ded2946f29f3a612c6b7a4af6129e9aa85256b7299e`
98+
- `BitGo/future-tools/flux-capacitor@v1`
9099

91100
[semantic version number]: https://semver.org/
92101

dist/index.js

Lines changed: 32 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/fetch.ts

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ export async function findExactSemanticVersionTag(
122122
);
123123
}
124124

125+
// Define matching strategies for assets
126+
enum MatchingStrategy {
127+
Label,
128+
Name,
129+
}
130+
125131
type ReleaseAssetMetadata = {
126132
binaryName: Option<string>;
127133
url: string;
@@ -144,12 +150,22 @@ export async function fetchReleaseAssetMetadataFromTag(
144150
// When the binary name is provided, look for matching binary and target triple.
145151
if (isSome(binaryName)) {
146152
const targetLabel = `${binaryName.value}-${targetTriple}`;
147-
const asset = releaseMetadata.data.assets.find(
153+
154+
// First try to find asset by label (original behavior)
155+
let asset = releaseMetadata.data.assets.find(
148156
(asset) => asset.label === targetLabel,
149157
);
158+
159+
// If not found by label, try to find asset by exact name match
160+
if (asset === undefined) {
161+
asset = releaseMetadata.data.assets.find(
162+
(asset) => asset.name === binaryName.value,
163+
);
164+
}
165+
150166
if (asset === undefined) {
151167
throw new Error(
152-
`Expected to find asset in release ${slug.owner}/${slug.repository}@${tag} with label ${targetLabel}`,
168+
`Expected to find asset in release ${slug.owner}/${slug.repository}@${tag} with label ${targetLabel} or name ${binaryName.value}`,
153169
);
154170
}
155171
return {
@@ -160,27 +176,49 @@ export async function fetchReleaseAssetMetadataFromTag(
160176

161177
// When the binary name is not provided, support two use cases:
162178
// 1. There is only one binary uploaded to this release, a named binary.
163-
// 2. There is an asset label matching the target triple (with no binary name).
179+
// 2. There is an asset label or name matching the target triple (with no binary name).
164180
// In both cases, we assume that's the binary the user meant.
165181
// If there is ambiguity, exit with an error.
166-
const matchingTargetTriples = releaseMetadata.data.assets.filter(
167-
(asset) =>
168-
typeof asset.label === "string" && asset.label.endsWith(targetTriple),
169-
);
170-
if (matchingTargetTriples.length === 0) {
182+
183+
// Create an array of assets with their matching strategy
184+
const matchingAssets = releaseMetadata.data.assets
185+
.map((asset) => {
186+
if (typeof asset.label === "string" && asset.label.endsWith(targetTriple)) {
187+
return { asset, strategy: MatchingStrategy.Label };
188+
}
189+
if (typeof asset.name === "string" && asset.name.endsWith(targetTriple)) {
190+
return { asset, strategy: MatchingStrategy.Name };
191+
}
192+
return null;
193+
})
194+
.filter(Boolean);
195+
196+
if (matchingAssets.length === 0) {
171197
throw new Error(
172-
`Expected to find asset in release ${slug.owner}/${slug.repository}@${tag} with label ending in ${targetTriple}`,
198+
`Expected to find asset in release ${slug.owner}/${slug.repository}@${tag} with label or name ending in ${targetTriple}`,
173199
);
174200
}
175-
if (matchingTargetTriples.length > 1) {
201+
202+
if (matchingAssets.length > 1) {
176203
throw new Error(
177-
`Ambiguous targets: expected to find a single asset in release ${slug.owner}/${slug.repository}@${tag} matching target triple ${targetTriple}, but found ${matchingTargetTriples.length}.
204+
`Ambiguous targets: expected to find a single asset in release ${slug.owner}/${slug.repository}@${tag} matching target triple ${targetTriple}, but found ${matchingAssets.length}.
178205
179206
To resolve, specify the desired binary with the target format ${slug.owner}/${slug.repository}/<binary-name>@${tag}`,
180207
);
181208
}
182-
const asset = matchingTargetTriples.shift()!;
183-
const targetName = stripTargetTriple(asset.label!);
209+
210+
const { asset, strategy } = matchingAssets[0]!;
211+
212+
// Apply stripTargetTriple based on the matching strategy
213+
let targetName: Option<string>;
214+
if (strategy === MatchingStrategy.Label && typeof asset.label === "string") {
215+
targetName = stripTargetTriple(asset.label);
216+
} else if (typeof asset.name === "string") {
217+
targetName = stripTargetTriple(asset.name);
218+
} else {
219+
targetName = none();
220+
}
221+
184222
return {
185223
binaryName: targetName,
186224
url: asset.url,

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ async function installGitHubReleaseBinary(
7272
targetTriple,
7373
);
7474

75+
core.info(`Release asset binary name: ${releaseAsset.binaryName}`);
7576
const destinationBasename = unwrapOrDefault(
7677
releaseAsset.binaryName,
7778
targetRelease.slug.repository,
@@ -81,6 +82,7 @@ async function installGitHubReleaseBinary(
8182
destinationBasename,
8283
);
8384

85+
core.info(`Creating directory at ${destinationDirectory} if it does not exist`);
8486
fs.mkdirSync(destinationDirectory, { recursive: true });
8587

8688
// Check if file already exists and skip if ignoreExisting is true
@@ -93,6 +95,7 @@ async function installGitHubReleaseBinary(
9395
}
9496
}
9597

98+
core.info(`Downloading release asset at ${releaseAsset.url} to ${destinationFilename}.`);
9699
await tc.downloadTool(
97100
releaseAsset.url,
98101
destinationFilename,

0 commit comments

Comments
 (0)