Skip to content

Commit

Permalink
feat: mrdocs version options
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Jan 2, 2025
1 parent 166bacd commit a237846
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 10 deletions.
10 changes: 10 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ antora:
* <2> List of dependencies to be downloaded and extracted. The directory where these dependencies are extracted will be available to all components as an environment variable.
* <3> The name of the environment variable describing where the path can be found. If this path exists and is a valid directory, it will be used as the source root for the dependency, skipping the download and extraction steps. If this is different from `variable`, the extension will set the value of `variable` to the path where the dependency is already located.

Besides the `dependencies` configuration, you can also set the following options:

|===
| Option | Description | Default

| `version` | A semver range that specifies the version of MrDocs to use. | `*`
| `allow-master` | If `true`, the extension will allow the use of the `master` branch for MrDocs if `version` is `*`. | `true`
| `allow-develop` | If `true`, the extension will allow the use of the `develop` branch for MrDocs if `version` is `*`. | `true`
|===

=== Components

Components that will include reference documentation should set the path of the MrDocs configuration file. Append following in your `antora.yaml`:
Expand Down
91 changes: 87 additions & 4 deletions lib/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const assert = require('node:assert')
const axios = require('axios')
const {spawn} = require('node:child_process')
const {PassThrough} = require('node:stream')
const semver = require('semver')
const {matchAny} = require("fast-glob/out/utils/pattern");

const GLOB_OPTS = {ignore: ['.git'], objectMode: true, onlyFiles: false, unique: false}
const PACKAGE_NAME = 'cpp-reference-extension'
Expand Down Expand Up @@ -69,6 +71,7 @@ class CppReferenceExtension {
this.context.once('contentAggregated', onContentAggregatedFn)

this.MrDocsExecutable = undefined
this.MrDocsVersion = undefined

// https://www.npmjs.com/package/@antora/logger
// https://github.com/pinojs/pino/blob/main/docs/api.md
Expand Down Expand Up @@ -292,9 +295,27 @@ class CppReferenceExtension {
* - Darwin.tar.gz
*
* @param {Array<Object>} releasesInfo - The list of releases.
* @param {string} configVersion - The version requirement from the configuration.
* @return {{downloadUrl, downloadTag}}
*/
static findDownloadUrl(releasesInfo) {
findDownloadUrl(releasesInfo) {
// Parse config version
const versionRequirement =
(this.config.version && !["master", "develop"].includes(this.config.version)) ?
new semver.Range(this.config.version) :
new semver.Range('*')
const allowMaster =
this.config.version === 'master' ||
(this.config.allowMaster ? this.config.allowMaster === true || this.config.allowMaster === 'true' : false) ||
true
const allowDevelop =
this.config.version === 'develop' ||
(this.config.allowDevelop ? this.config.allowDevelop === true || this.config.allowDevelop === 'true' : false) ||
true
const isMatchAny = (this.config.version || '*') === '*' && allowMaster && allowDevelop
const isMasterOnly = this.config.version === 'master'
const isDevelopOnly = this.config.version === 'develop'

// Sort the releases by the date of their latest asset
releasesInfo.sort((a, b) => {
const latestAssetA = a.assets.reduce((latest, asset) => {
Expand Down Expand Up @@ -324,17 +345,66 @@ class CppReferenceExtension {
throw new Error(`Unsupported platform: ${process.platform}. Supported platforms are win32, linux, and darwin.`);
}

function isReleaseMatch(releaseTag) {
if (isMatchAny) {
this.logger.debug(`Matching any version. Found a release that satisfies the version requirement: ${releaseTag}`)
return true;
}
if (isMasterOnly) {
if (!releaseTag.includes('master')) {
this.logger.debug(`Matching only master. Skipping release: ${releaseTag}`)
return false
}
return true
}
if (isDevelopOnly) {
if (!releaseTag.includes('develop')) {
this.logger.debug(`Matching only develop. Skipping release: ${releaseTag}`)
return false
}
return true
}
if (allowMaster) {
if (releaseTag.includes('master')) {
this.logger.debug(`Matching master. Found a release that satisfies the version requirement: ${releaseTag}`)
return true
}
}
if (allowDevelop) {
if (releaseTag.includes('develop')) {
this.logger.debug(`Matching develop. Found a release that satisfies the version requirement: ${releaseTag}`)
return true
}
}
const satistiesRequirement = semver.satisfies(
releaseTag, versionRequirement, {includePrerelease: true, loose: true})
if (!satistiesRequirement) {
this.logger.debug(`Matching version requirement ${this.config.version || '*'}. Skipping release: ${releaseTag}`)
return false
}
this.logger.debug(`Matching version requirement ${this.config.version || '*'}. Found a release that satisfies the version requirement: ${releaseTag}`)
return true
}

// Iterate over the releases
for (const release of releasesInfo) {
// Sort assets descending by updated_at
if (!isReleaseMatch(release.tag_name)) {
continue
}

// Sort release 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
this.MrDocsVersion = release.tag_name
this.logger.debug(`Found asset ${asset.browser_download_url} for platform ${process.platform}`)
return {downloadUrl: asset.browser_download_url, downloadTag: release.tag_name};
}
this.logger.debug(`Skipping asset ${asset.browser_download_url} as it doesn't match the platform suffix ${platformSuffix}`)
}
}

Expand Down Expand Up @@ -373,6 +443,7 @@ class CppReferenceExtension {
* @throws {Error} If the MrDocs executable is not found.
*/
async setupMrDocs(playbook, cacheDir) {
this.logger.debug(`Looking for MrDocs version "${this.config.version || "*"}"`)
const mrDocsTreeDir = path.join(cacheDir, 'mrdocs')
const GH_TOKEN = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || ''
const apiHeaders = GH_TOKEN ? {
Expand All @@ -384,7 +455,7 @@ 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`)
const { downloadUrl, downloadTag } = CppReferenceExtension.findDownloadUrl(releasesInfo)
const { downloadUrl, downloadTag } = this.findDownloadUrl(releasesInfo)
if (!downloadUrl) {
this.logger.error(`Could not find MrDocs binaries for ${process.platform}`)
process.exit(1)
Expand Down Expand Up @@ -820,11 +891,23 @@ class CppReferenceExtension {
}
await fsp.mkdir(referenceOutputDir, {recursive: true})

// Identify commands according to MrDocs version
const versionIsMaster = this.MrDocsVersion.includes('master')
const versionIsDevelop = this.MrDocsVersion.includes('develop')
const versionIsSemver = semver.valid(this.MrDocsVersion, {loose: true, includePrerelease: true})
// If the version is >= 0.0.3, we can use the generator command
const generatorCommand =
versionIsMaster ||
versionIsDevelop ||
versionIsSemver ?
semver.satisfies(this.MrDocsVersion, '>=0.0.3', {loose: true, includePrerelease: true}) :
true

// Generate reference documentation with MrDocs
await this.runCommand(this.MrDocsExecutable, [
`--config=${collector.config}`,
`--output=${referenceOutputDir}`,
`--generate=adoc`,
`--${generatorCommand ? "generator" : "generate"}=adoc`,
`--multipage=true`
], {cwd: worktreeDir, quiet: playbook.runtime?.quiet})

Expand Down
22 changes: 17 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"cache-directory": "^2.0.0",
"fast-glob": "^3.3.2",
"isomorphic-git": "^1.27.1",
"js-yaml": "^4.1.0"
"js-yaml": "^4.1.0",
"semver": "^7.6.3"
}
}

0 comments on commit a237846

Please sign in to comment.