Skip to content

Commit f693227

Browse files
committed
feat: support MacOS
1 parent bfd0881 commit f693227

File tree

2 files changed

+96
-19
lines changed

2 files changed

+96
-19
lines changed

.github/workflows/ci.yml

+15-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ concurrency:
1616

1717
jobs:
1818
build:
19-
name: Build
20-
runs-on: ubuntu-latest
19+
strategy:
20+
matrix:
21+
include:
22+
- { name: Windows, os: windows-latest }
23+
- { name: Ubuntu, os: ubuntu-latest }
24+
- { name: MacOS, os: macos-latest }
25+
26+
name: Build (${{ matrix.name }})
27+
runs-on: ${{ matrix.os }}
2128
steps:
2229
- name: Clone repository
2330
uses: actions/checkout@v4
@@ -33,7 +40,13 @@ jobs:
3340
- name: Tests
3441
run: npm test
3542

43+
- name: Setup Ninja
44+
if: runner.os == 'Windows'
45+
uses: seanmiddleditch/gha-setup-ninja@v5
46+
3647
- name: Example
48+
env:
49+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3750
run: npm run example
3851

3952
publish-npm:

lib/extension.js

+81-17
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,85 @@ class CppReferenceExtension {
263263
}
264264
}
265265

266+
/**
267+
* Finds the most appropriate download URL for MrDocs binaries
268+
* from the list of releases.
269+
*
270+
* Each object in the `releasesInfo` array represents a release.
271+
* Each release object contains a `tag_name` string and an `assets` array.
272+
*
273+
* Each asset in the `assets` array has an `updated_at` string and
274+
* a `browser_download_url` string.
275+
* The `updated_at` string is in the format "2024-01-01T00:00:00Z".
276+
*
277+
* This function sorts the releases in `releasesInfo` by the date
278+
* of their latest asset, with the latest release first.
279+
*
280+
* Then it iterates over the releases and finds a download URL
281+
* that's appropriate for the current platform. This iteration
282+
* also goes from the latest asset to the oldest asset in the release.
283+
*
284+
* The first asset we find that matches the platform is the one for which
285+
* we return the URL of the asset and the tag name of the release.
286+
*
287+
* We can identify if the asset is appropriate for the platform by checking
288+
* if the asset URL ends with the appropriate suffix for the platform:
289+
*
290+
* - win64.7z
291+
* - Linux.tar.gz
292+
* - Darwin.tar.gz
293+
*
294+
* @param {Array<Object>} releasesInfo - The list of releases.
295+
* @return {{downloadUrl, downloadTag}}
296+
*/
297+
static findDownloadUrl(releasesInfo) {
298+
// Sort the releases by the date of their latest asset
299+
releasesInfo.sort((a, b) => {
300+
const latestAssetA = a.assets.reduce((latest, asset) => {
301+
return new Date(asset.updated_at) > new Date(latest.updated_at) ? asset : latest;
302+
}, a.assets[0]);
303+
304+
const latestAssetB = b.assets.reduce((latest, asset) => {
305+
return new Date(asset.updated_at) > new Date(latest.updated_at) ? asset : latest;
306+
}, b.assets[0]);
307+
308+
return new Date(latestAssetB.updated_at) - new Date(latestAssetA.updated_at);
309+
});
310+
311+
// Determine the appropriate suffix for the current platform
312+
let platformSuffix;
313+
switch (process.platform) {
314+
case 'win32':
315+
platformSuffix = 'win64.7z';
316+
break;
317+
case 'linux':
318+
platformSuffix = 'Linux.tar.gz';
319+
break;
320+
case 'darwin':
321+
platformSuffix = 'Darwin.tar.gz';
322+
break;
323+
default:
324+
throw new Error(`Unsupported platform: ${process.platform}. Supported platforms are win32, linux, and darwin.`);
325+
}
326+
327+
// Iterate over the releases
328+
for (const release of releasesInfo) {
329+
// Sort assets descending by updated_at
330+
release.assets.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
331+
// Iterate over the assets of the release
332+
for (const asset of release.assets) {
333+
// Check if the asset URL ends with the appropriate suffix for the platform
334+
if (asset.browser_download_url.endsWith(platformSuffix)) {
335+
// Return the URL of the asset and the tag name of the release
336+
return {downloadUrl: asset.browser_download_url, downloadTag: release.tag_name};
337+
}
338+
}
339+
}
340+
341+
// If no appropriate asset is found, return an empty object
342+
return {downloadUrl: null, downloadTag: null}
343+
}
344+
266345
/**
267346
* Sets up MrDocs for the playbook.
268347
*
@@ -305,31 +384,16 @@ class CppReferenceExtension {
305384
const releasesResponse = await axios.get('https://api.github.com/repos/cppalliance/mrdocs/releases', {headers: apiHeaders})
306385
const releasesInfo = releasesResponse.data
307386
this.logger.debug(`Found ${releasesInfo.length} MrDocs releases`)
308-
let downloadUrl = undefined
309-
let downloadRelease = undefined
310-
for (const latestRelease of releasesInfo) {
311-
this.logger.debug(`Latest release: ${latestRelease['tag_name']}`)
312-
const latestAssets = latestRelease['assets'].map(asset => asset['browser_download_url'])
313-
this.logger.debug(`Latest assets: ${latestAssets.join(', ')}`)
314-
const releaseFileSuffix = process.platform === "win32" ? 'win64.7z' : 'Linux.tar.gz'
315-
downloadUrl = latestAssets.find(asset => asset.endsWith(releaseFileSuffix))
316-
downloadRelease = latestRelease
317-
if (downloadUrl) {
318-
break
319-
}
320-
this.logger.warn(`Could not find MrDocs binaries in ${latestRelease['tag_name']} release for ${process.platform}`)
321-
}
387+
const { downloadUrl, downloadTag } = CppReferenceExtension.findDownloadUrl(releasesInfo)
322388
if (!downloadUrl) {
323389
this.logger.error(`Could not find MrDocs binaries for ${process.platform}`)
324390
process.exit(1)
325391
}
326392
const mrdocsDownloadDir = path.join(mrDocsTreeDir, process.platform)
327-
const releaseTagname = downloadRelease['tag_name']
328-
const versionSubdir = releaseTagname.endsWith('-release') ? releaseTagname.slice(0, -8) : downloadRelease['tag_name']
393+
const versionSubdir = downloadTag.endsWith('-release') ? downloadTag.slice(0, -8) : downloadTag
329394
const mrdocsExtractDir = path.join(mrdocsDownloadDir, versionSubdir)
330395
const platformExtension = process.platform === 'win32' ? '.exe' : ''
331396
const mrdocsExecPath = path.join(mrdocsExtractDir, 'bin', 'mrdocs') + platformExtension
332-
333397
if (await CppReferenceExtension.fileExists(mrdocsExecPath)) {
334398
this.logger.debug(`MrDocs already exists at ${mrdocsExtractDir}`)
335399
} else {

0 commit comments

Comments
 (0)