Skip to content
This repository has been archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
Extension: Implement dynamic loading attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
mmattel committed Jan 7, 2025
1 parent ea89a21 commit 252e70f
Show file tree
Hide file tree
Showing 10 changed files with 3,832 additions and 2,647 deletions.
4 changes: 2 additions & 2 deletions .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ def build(ctx, environment, latest_version, deployment_branch, base_branch, pdf_
"pull": "always",
"image": "owncloudci/nodejs:18",
"commands": [
"yarn install",
"npm install",
],
},
{
"name": "docs-build",
"pull": "always",
"image": "owncloudci/nodejs:18",
"commands": [
"yarn antora",
"npm run antora",
],
},
{
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
global-attributes.yml
site-dev.yml
yarn-error.log
cache/
Expand Down
26 changes: 26 additions & 0 deletions ext-antora/attributes-used-in-antora-yml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict'

// Console print antora.yml attributes used per component

module.exports.register = function () {
this.once('contentClassified', ({ playbook, contentCatalog }) => {
console.log('antora-playbook.yml attributes')
console.log(playbook.asciidoc.attributes)
contentCatalog.getComponents().forEach((component) => {
component.versions.forEach((componentVersion) => {
getUniqueOrigins(contentCatalog, componentVersion).forEach((origin) => {
console.log(`antora.yml attributes (${componentVersion.version}@${componentVersion.name})`)
console.log(origin.descriptor.asciidoc?.attributes || {})
})
})
})
})
}

function getUniqueOrigins (contentCatalog, componentVersion) {
return contentCatalog.findBy({ component: componentVersion.name, version: componentVersion.version }).reduce((origins, file) => {
const origin = file.src.origin
if (origin && !origins.includes(origin)) origins.push(origin)
return origins
}, [])
}
16 changes: 16 additions & 0 deletions ext-antora/attributes-used-in-site-yml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict'

// Console print site.yml attributes used per component build

module.exports.register = function () {
this.once('contentClassified', ({ siteAsciiDocConfig, contentCatalog }) => {
console.log('site-wide attributes')
console.log(siteAsciiDocConfig.attributes)
contentCatalog.getComponents().forEach((component) => {
component.versions.forEach((componentVersion) => {
console.log(`${componentVersion.version}@${componentVersion.name} attributes`)
console.log(componentVersion.asciidoc.attributes)
})
})
})
}
15 changes: 15 additions & 0 deletions ext-antora/comp-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict'

// Extension to print the component + version that will be processed

module.exports.register = function () {
this.once('contentAggregated', ({ contentAggregate }) => {
console.log('\nProcessing the following components and versions\n')
const component_table = []
contentAggregate.forEach((bucket) => {
component_table.push ({Name: bucket.name, Version: bucket.version || '~', Files: bucket.files.length})
})
console.table(component_table)
console.log() // do not delete, else we get a double empty line
})
}
111 changes: 111 additions & 0 deletions ext-antora/load-global-site-attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// v1.0.0
"use strict"

const fs = require('fs')
const http = require('http')
const https = require('https')
const yaml = require('js-yaml')

// this extension loads (global) attributes into the playbook (site.yml)
// !! attributes in the playbook take precedence over loaded attributes !!
// allows test building a repo like in multi repo envs with custom local attribute values
// you can temporarily disable loading by setting 'enabled: false'
// error handling:
// if no 'attributefile' is configured: warn, but continue processing
// if loading or processing the file caused an error (like file not found, needs fixing): stop

module.exports.register = function ({ config }) {
const logger = this.getLogger('load-global-site-attributes-extension')
let attrib_file = ''
let attrib_yaml = {}
let orig_playbook = {}
let result = {}

this.on("playbookBuilt", async ({ playbook }) => {
// get the original playbook asciidoc attributes, note it can be empty
orig_playbook = JSON.parse(JSON.stringify(playbook.asciidoc.attributes)) || {}

// only if attributefile is configured in site.yml pointing to a resource (file or url)
if (config.attributefile) {
try {
// define the get function to use and load the file
if (config.attributefile.startsWith('http')) {
attrib_file = await get_file_from_url(config.attributefile)
} else {
attrib_file = await get_file_from_local(config.attributefile)
}

// convert and update
attrib_yaml = await convert_yaml(attrib_file)
result = Object.assign(attrib_yaml, playbook.asciidoc.attributes)
playbook.asciidoc.attributes = result
this.updateVariables( playbook )

// loading or processing the file caused an error
} catch (error) {
logger.error(error)
this.stop()
}
} else {
logger.warn('attributefile is not configured in the playbook (site.yml).')
}
// console.log(this.getVariables())
})
}

function get_file_from_url(url) {
// promise a file from url
// when executed it returns the contents if found
return new Promise((resolve, reject) => {
const client = url.startsWith('https') ? https : http
const req = client.request(url, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
reject(`Request Failed.\n` +
`Status Code: ${res.statusCode}\n` +
`${url}`)
}
var body = []
res.on('data', function(chunk) {
body.push(chunk)
})
res.on('end', function() {
try {
body = Buffer.concat(body).toString()
} catch(error) {
reject(error)
}
resolve(body)
})
})
req.on('error', (error) => {
reject(error.message)
})
// send the request
req.end()
})
}

function get_file_from_local(file) {
// promise a file from local filesystem
// when executed it returns the contents if found
return new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', (error, data) => {
if (error) reject(error)
resolve(data)
})
})
}

function convert_yaml(data) {
// promise to parse yaml data
// when executed it returns the parsed contents
return new Promise((resolve, reject) => {
try {
var d = yaml.load(data)
// the parser found an error, no object will be returned
} catch (error) {
reject(`yaml parser: ` + error)
}
resolve(d)
})
}
Loading

0 comments on commit 252e70f

Please sign in to comment.