Skip to content

Commit

Permalink
feat: support MacOS
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Oct 16, 2024
1 parent 7593e8b commit ee0892d
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 19 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ concurrency:

jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
matrix:
include:
- { name: Windows, os: windows-latest }
- { name: Ubuntu, os: ubuntu-latest }
- { name: MacOS, os: macos-latest }

name: Build (${{ matrix.name }})
runs-on: ${{ matrix.os }}
steps:
- name: Clone repository
uses: actions/checkout@v4
Expand All @@ -34,6 +41,8 @@ jobs:
run: npm test

- name: Example
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm run example

publish-npm:
Expand Down
98 changes: 81 additions & 17 deletions lib/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,85 @@ class CppReferenceExtension {
}
}

/**
* Finds the most appropriate download URL for MrDocs binaries
* from the list of releases.
*
* Each object in the `releasesInfo` array represents a release.
* Each release object contains a `tag_name` string and an `assets` array.
*
* Each asset in the `assets` array has an `updated_at` string and
* a `browser_download_url` string.
* The `updated_at` string is in the format "2024-01-01T00:00:00Z".
*
* This function sorts the releases in `releasesInfo` by the date
* of their latest asset, with the latest release first.
*
* Then it iterates over the releases and finds a download URL
* that's appropriate for the current platform. This iteration
* also goes from the latest asset to the oldest asset in the release.
*
* The first asset we find that matches the platform is the one for which
* we return the URL of the asset and the tag name of the release.
*
* We can identify if the asset is appropriate for the platform by checking
* if the asset URL ends with the appropriate suffix for the platform:
*
* - win64.7z
* - Linux.tar.gz
* - Darwin.tar.gz
*
* @param {Array<Object>} releasesInfo - The list of releases.
* @return {{downloadUrl, downloadTag}}
*/
static findDownloadUrl(releasesInfo) {
// Sort the releases by the date of their latest asset
releasesInfo.sort((a, b) => {
const latestAssetA = a.assets.reduce((latest, asset) => {
return new Date(asset.updated_at) > new Date(latest.updated_at) ? asset : latest;
}, a.assets[0]);

const latestAssetB = b.assets.reduce((latest, asset) => {
return new Date(asset.updated_at) > new Date(latest.updated_at) ? asset : latest;
}, b.assets[0]);

return new Date(latestAssetB.updated_at) - new Date(latestAssetA.updated_at);
});

// Determine the appropriate suffix for the current platform
let platformSuffix;
switch (process.platform) {
case 'win32':
platformSuffix = 'win64.7z';
break;
case 'linux':
platformSuffix = 'Linux.tar.gz';
break;
case 'darwin':
platformSuffix = 'Darwin.tar.gz';
break;
default:
throw new Error(`Unsupported platform: ${process.platform}. Supported platforms are win32, linux, and darwin.`);
}

// Iterate over the releases
for (const release of releasesInfo) {
// Sort assets descending by updated_at
release.assets.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
// Iterate over the assets of the release
for (const asset of release.assets) {
// Check if the asset URL ends with the appropriate suffix for the platform
if (asset.browser_download_url.endsWith(platformSuffix)) {
// Return the URL of the asset and the tag name of the release
return {downloadUrl: asset.browser_download_url, downloadTag: release.tag_name};
}
}
}

// If no appropriate asset is found, return an empty object
return {downloadUrl: null, downloadTag: null}
}

/**
* Sets up MrDocs for the playbook.
*
Expand Down Expand Up @@ -305,31 +384,16 @@ class CppReferenceExtension {
const releasesResponse = await axios.get('https://api.github.com/repos/cppalliance/mrdocs/releases', {headers: apiHeaders})
const releasesInfo = releasesResponse.data
this.logger.debug(`Found ${releasesInfo.length} MrDocs releases`)
let downloadUrl = undefined
let downloadRelease = undefined
for (const latestRelease of releasesInfo) {
this.logger.debug(`Latest release: ${latestRelease['tag_name']}`)
const latestAssets = latestRelease['assets'].map(asset => asset['browser_download_url'])
this.logger.debug(`Latest assets: ${latestAssets.join(', ')}`)
const releaseFileSuffix = process.platform === "win32" ? 'win64.7z' : 'Linux.tar.gz'
downloadUrl = latestAssets.find(asset => asset.endsWith(releaseFileSuffix))
downloadRelease = latestRelease
if (downloadUrl) {
break
}
this.logger.warn(`Could not find MrDocs binaries in ${latestRelease['tag_name']} release for ${process.platform}`)
}
const { downloadUrl, downloadTag } = CppReferenceExtension.findDownloadUrl(releasesInfo)
if (!downloadUrl) {
this.logger.error(`Could not find MrDocs binaries for ${process.platform}`)
process.exit(1)
}
const mrdocsDownloadDir = path.join(mrDocsTreeDir, process.platform)
const releaseTagname = downloadRelease['tag_name']
const versionSubdir = releaseTagname.endsWith('-release') ? releaseTagname.slice(0, -8) : downloadRelease['tag_name']
const versionSubdir = downloadTag.endsWith('-release') ? downloadTag.slice(0, -8) : downloadTag
const mrdocsExtractDir = path.join(mrdocsDownloadDir, versionSubdir)
const platformExtension = process.platform === 'win32' ? '.exe' : ''
const mrdocsExecPath = path.join(mrdocsExtractDir, 'bin', 'mrdocs') + platformExtension

if (await CppReferenceExtension.fileExists(mrdocsExecPath)) {
this.logger.debug(`MrDocs already exists at ${mrdocsExtractDir}`)
} else {
Expand Down

0 comments on commit ee0892d

Please sign in to comment.