|
1 | 1 | import type { Octokit } from "./octokit"; |
2 | 2 | import { isEqual, isSome, none, Option, some } from "./option"; |
3 | 3 | import { stripTargetTriple } from "./platform"; |
| 4 | +import type { TargetDuple } from "./types"; |
4 | 5 |
|
5 | 6 | import { |
6 | 7 | isExactSemanticVersion, |
@@ -127,62 +128,104 @@ type ReleaseAssetMetadata = { |
127 | 128 | url: string; |
128 | 129 | }; |
129 | 130 |
|
130 | | -export async function fetchReleaseAssetMetadataFromTag( |
131 | | - octokit: Octokit, |
| 131 | +/** |
| 132 | + * Type for GitHub release metadata required by our function |
| 133 | + */ |
| 134 | +export type ReleaseMetadataResponse = { |
| 135 | + data: { |
| 136 | + assets: Array<{ |
| 137 | + label?: string | null; |
| 138 | + url: string; |
| 139 | + // Other fields may exist but we don't use them |
| 140 | + }>; |
| 141 | + }; |
| 142 | +}; |
| 143 | + |
| 144 | +/** |
| 145 | + * Extract matching asset metadata from release assets based on target platform format |
| 146 | + */ |
| 147 | +export function findMatchingReleaseAssetMetadata( |
| 148 | + releaseMetadata: ReleaseMetadataResponse, |
132 | 149 | slug: RepositorySlug, |
133 | 150 | binaryName: Option<BinaryName>, |
134 | 151 | tag: ExactSemanticVersion, |
135 | 152 | targetTriple: TargetTriple, |
136 | | -): Promise<ReleaseAssetMetadata> { |
137 | | - // Maintainer's note: this impure function call makes this function difficult to test. |
138 | | - const releaseMetadata = await octokit.rest.repos.getReleaseByTag({ |
139 | | - owner: slug.owner, |
140 | | - repo: slug.repository, |
141 | | - tag, |
142 | | - }); |
143 | | - |
144 | | - // When the binary name is provided, look for matching binary and target triple. |
| 153 | + targetDuple: TargetDuple, |
| 154 | +): ReleaseAssetMetadata { |
| 155 | + // When the binary name is provided, look for matching binary with target triple or target duple |
145 | 156 | if (isSome(binaryName)) { |
146 | | - const targetLabel = `${binaryName.value}-${targetTriple}`; |
| 157 | + const targetLabelTraditional = `${binaryName.value}-${targetTriple}`; |
| 158 | + const targetLabelDuple = `${binaryName.value}-${targetDuple}`; |
| 159 | + |
147 | 160 | const asset = releaseMetadata.data.assets.find( |
148 | | - (asset) => asset.label === targetLabel, |
| 161 | + (asset) => |
| 162 | + typeof asset.label === "string" && |
| 163 | + (asset.label === targetLabelTraditional || asset.label === targetLabelDuple), |
149 | 164 | ); |
| 165 | + |
150 | 166 | if (asset === undefined) { |
151 | 167 | 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 ${targetLabelTraditional} or ${targetLabelDuple}`, |
153 | 169 | ); |
154 | 170 | } |
| 171 | + |
155 | 172 | return { |
156 | 173 | binaryName: binaryName, |
157 | 174 | url: asset.url, |
158 | 175 | }; |
159 | 176 | } |
160 | 177 |
|
161 | | - // When the binary name is not provided, support two use cases: |
| 178 | + // When the binary name is not provided, support these use cases: |
162 | 179 | // 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). |
| 180 | + // 2. There is an asset label matching the target triple or target duple. |
164 | 181 | // In both cases, we assume that's the binary the user meant. |
165 | 182 | // If there is ambiguity, exit with an error. |
166 | | - const matchingTargetTriples = releaseMetadata.data.assets.filter( |
| 183 | + const matchingAssets = releaseMetadata.data.assets.filter( |
167 | 184 | (asset) => |
168 | | - typeof asset.label === "string" && asset.label.endsWith(targetTriple), |
| 185 | + typeof asset.label === "string" && |
| 186 | + (asset.label.endsWith(targetTriple) || asset.label.endsWith(targetDuple)), |
169 | 187 | ); |
170 | | - if (matchingTargetTriples.length === 0) { |
| 188 | + if (matchingAssets.length === 0) { |
171 | 189 | throw new Error( |
172 | | - `Expected to find asset in release ${slug.owner}/${slug.repository}@${tag} with label ending in ${targetTriple}`, |
| 190 | + `Expected to find asset in release ${slug.owner}/${slug.repository}@${tag} with label ending in ${targetTriple} or ${targetDuple}`, |
173 | 191 | ); |
174 | 192 | } |
175 | | - if (matchingTargetTriples.length > 1) { |
| 193 | + if (matchingAssets.length > 1) { |
176 | 194 | 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}. |
| 195 | + `Ambiguous targets: expected to find a single asset in release ${slug.owner}/${slug.repository}@${tag} matching target triple ${targetTriple} or target duple ${targetDuple}, but found ${matchingAssets.length}. |
178 | 196 |
|
179 | 197 | To resolve, specify the desired binary with the target format ${slug.owner}/${slug.repository}/<binary-name>@${tag}`, |
180 | 198 | ); |
181 | 199 | } |
182 | | - const asset = matchingTargetTriples.shift()!; |
| 200 | + const asset = matchingAssets.shift()!; |
183 | 201 | const targetName = stripTargetTriple(asset.label!); |
184 | 202 | return { |
185 | 203 | binaryName: targetName, |
186 | 204 | url: asset.url, |
187 | 205 | }; |
188 | 206 | } |
| 207 | + |
| 208 | +export async function fetchReleaseAssetMetadataFromTag( |
| 209 | + octokit: Octokit, |
| 210 | + slug: RepositorySlug, |
| 211 | + binaryName: Option<BinaryName>, |
| 212 | + tag: ExactSemanticVersion, |
| 213 | + targetTriple: TargetTriple, |
| 214 | + targetDuple: TargetDuple, |
| 215 | +): Promise<ReleaseAssetMetadata> { |
| 216 | + // Maintainer's note: this impure function call makes this function difficult to test. |
| 217 | + const releaseMetadata = await octokit.rest.repos.getReleaseByTag({ |
| 218 | + owner: slug.owner, |
| 219 | + repo: slug.repository, |
| 220 | + tag, |
| 221 | + }); |
| 222 | + |
| 223 | + return findMatchingReleaseAssetMetadata( |
| 224 | + releaseMetadata, |
| 225 | + slug, |
| 226 | + binaryName, |
| 227 | + tag, |
| 228 | + targetTriple, |
| 229 | + targetDuple, |
| 230 | + ); |
| 231 | +} |
0 commit comments