@redpanda-data/docs-extensions-and-macros 3.3.3 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.adoc +71 -5
- package/extensions/find-related-docs.js +52 -33
- package/extensions/modify-connect-tag-playbook.js +26 -0
- package/extensions/unlisted-pages.js +67 -41
- package/extensions/unpublish-pages.js +32 -7
- package/extensions/version-fetcher/get-latest-connect.js +28 -0
- package/extensions/version-fetcher/get-latest-redpanda-version.js +27 -6
- package/extensions/version-fetcher/set-latest-version.js +18 -6
- package/package.json +2 -1
package/README.adoc
CHANGED
|
@@ -44,13 +44,13 @@ To use the development version instead, refer to the <<development-quickstart,De
|
|
|
44
44
|
|
|
45
45
|
This section documents the Antora extensions that are provided by this library and how to configure them.
|
|
46
46
|
|
|
47
|
-
IMPORTANT:
|
|
47
|
+
IMPORTANT: Ensure you register each extension under the `antora.extensions` key in the playbook, not the `asciidoc.extensions` key.
|
|
48
48
|
|
|
49
49
|
=== Algolia indexer
|
|
50
50
|
|
|
51
51
|
This extension generates an Algolia index for each version of each component. The index entries are then saved to Algolia using the `saveObjects()` method, and also saved as JSON files in the site catalog. JSON files are published to the site root using the following template: `algolia-<component>-<version>.json`.
|
|
52
52
|
|
|
53
|
-
NOTE: Only pages that include an `<article>` element with the `doc` class are indexed.
|
|
53
|
+
NOTE: Only pages that include an `<article>` element with the `doc` class are indexed.
|
|
54
54
|
|
|
55
55
|
==== Environment variables
|
|
56
56
|
|
|
@@ -85,6 +85,14 @@ This extension maps Redpanda Connect component data into a structured format:
|
|
|
85
85
|
- Populates `connectCategoriesData` and `flatComponentsData` attributes.
|
|
86
86
|
- Skips deprecated components.
|
|
87
87
|
|
|
88
|
+
==== Environment variables
|
|
89
|
+
|
|
90
|
+
This extension does not require any environment variables.
|
|
91
|
+
|
|
92
|
+
==== Configuration options
|
|
93
|
+
|
|
94
|
+
There are no configurable options for this extension.
|
|
95
|
+
|
|
88
96
|
==== Registration Example
|
|
89
97
|
|
|
90
98
|
```yaml
|
|
@@ -93,19 +101,41 @@ antora:
|
|
|
93
101
|
- require: '@redpanda-data/docs-extensions-and-macros/extensions/generate-rp-connect-categories'
|
|
94
102
|
```
|
|
95
103
|
|
|
104
|
+
=== Redpanda Connect tag modifier
|
|
105
|
+
|
|
106
|
+
This extension updates the playbook to use the latest release tag for the Redpanda Connect documentation. It ensures that the Redpanda Connect documentation is always pulled from the latest release tag available on GitHub.
|
|
107
|
+
|
|
108
|
+
==== Environment variables
|
|
109
|
+
|
|
110
|
+
- `REDPANDA_GITHUB_TOKEN` (optional): A Personal access token (PAT) that has `repo` permissions for the `redpanda-data` GitHub organization.
|
|
111
|
+
|
|
112
|
+
NOTE: If you don't set the environment variable, the latest version of Redpanda Connect may not be fetched. When the environment variable is not set, the extension sends unauthenticated requests to GitHub. Unauthenticated requests may result in hitting the API rate limit and cause GitHub to reject the request. In this case the fallback version is used. This version is defined in the playbook where the extension is registered.
|
|
113
|
+
|
|
114
|
+
==== Configuration options
|
|
115
|
+
|
|
116
|
+
There are no configurable options for this extension.
|
|
117
|
+
|
|
118
|
+
==== Registration Example
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
antora:
|
|
122
|
+
extensions:
|
|
123
|
+
- require: '@redpanda-data/docs-extensions-and-macros/extensions/modify-connect-tag-playbook'
|
|
124
|
+
```
|
|
125
|
+
|
|
96
126
|
=== Version fetcher
|
|
97
127
|
|
|
98
128
|
This extension fetches the latest release versions from GitHub.
|
|
99
129
|
|
|
100
|
-
The latest Console
|
|
130
|
+
The latest versions of Redpanda Console and Redpanda Connect are made available to all versions of all Antora components.
|
|
101
131
|
|
|
102
|
-
The latest Redpanda version and the latest Redpanda Operator version
|
|
132
|
+
The latest Redpanda version and the latest Redpanda Operator version are made available to the latest version of the `ROOT` component (Redpanda docs).
|
|
103
133
|
|
|
104
134
|
==== Environment variables
|
|
105
135
|
|
|
106
136
|
- `REDPANDA_GITHUB_TOKEN` (optional): A Personal access token (PAT) that has `repo` permissions for the `redpanda-data` GitHub organization.
|
|
107
137
|
|
|
108
|
-
NOTE: If you don't set the environment variable, the latest versions may not be
|
|
138
|
+
NOTE: If you don't set the environment variable, the latest versions may not be fetched. When the environment variable is not set, the extension sends unauthenticated requests to GitHub. Unauthenticated requests may result in hitting the API rate limit and cause GitHub to reject the request.
|
|
109
139
|
|
|
110
140
|
==== Registration example
|
|
111
141
|
|
|
@@ -188,6 +218,14 @@ antora:
|
|
|
188
218
|
|
|
189
219
|
This extension collects Asciidoc attributes from the {url-playbook}[`shared` component] and makes them available to all component versions. Having global attributes is useful for consistent configuration of local and production builds.
|
|
190
220
|
|
|
221
|
+
==== Environment variables
|
|
222
|
+
|
|
223
|
+
This extension does not require any environment variables.
|
|
224
|
+
|
|
225
|
+
==== Configuration options
|
|
226
|
+
|
|
227
|
+
There are no configurable options for this extension.
|
|
228
|
+
|
|
191
229
|
==== Registration example
|
|
192
230
|
|
|
193
231
|
```yaml
|
|
@@ -200,6 +238,14 @@ antora:
|
|
|
200
238
|
|
|
201
239
|
This extension replaces the default https://gitlab.com/antora/antora/-/tree/v3.1.x/packages/redirect-producer[`produceRedirects()` function] in Antora to handle redirect loops caused by https://docs.antora.org/antora/latest/page/page-aliases/[page aliases]. Normally, page aliases in Antora are used to resolve outdated links without causing issues. However, with https://docs.antora.org/antora/latest/playbook/urls-html-extension-style/#html-extension-style-key[`indexify`], the same URL may inadvertently be used for both the source and target of a redirect, leading to loops. This problem is https://antora.zulipchat.com/#narrow/stream/282400-users/topic/Redirect.20Loop.20Issue.20with.20Page.20Renaming.20and.20Indexify/near/433691700[recognized as a bug] in core Antora. For example, creating a page alias for `modules/manage/security/authorization.adoc` to point to `modules/manage/security/authorization/index.adoc' can lead to a redirect loop where `manage/security/authorization/` points to `manage/security/authorization/`. Furthermore, omitting the alias would lead to `xref not found` errors because Antora relies on the alias to resolve the old xrefs. This extension is necessary until such behaviors are natively supported or fixed in Antora core.
|
|
202
240
|
|
|
241
|
+
==== Environment variables
|
|
242
|
+
|
|
243
|
+
This extension does not require any environment variables.
|
|
244
|
+
|
|
245
|
+
==== Configuration options
|
|
246
|
+
|
|
247
|
+
There are no configurable options for this extension.
|
|
248
|
+
|
|
203
249
|
==== Registration example
|
|
204
250
|
|
|
205
251
|
```yaml
|
|
@@ -219,6 +265,14 @@ This extension replaces AsciiDoc attribute placeholders with their respective va
|
|
|
219
265
|
- If the same attribute placeholder is used multiple times within a file, all instances will be replaced with the attribute's value.
|
|
220
266
|
====
|
|
221
267
|
|
|
268
|
+
==== Environment variables
|
|
269
|
+
|
|
270
|
+
This extension does not require any environment variables.
|
|
271
|
+
|
|
272
|
+
==== Configuration options
|
|
273
|
+
|
|
274
|
+
There are no configurable options for this extension.
|
|
275
|
+
|
|
222
276
|
==== Registration example
|
|
223
277
|
|
|
224
278
|
```yaml
|
|
@@ -235,6 +289,14 @@ This extension aggregates all term pages from the {url-playbook}[`shared` compon
|
|
|
235
289
|
- Looks for glossary pages named `reference:glossary.adoc` in all versions of all components and appends the contents of each term file to the glossary in alphabetical order.
|
|
236
290
|
- If a glossary page is found, sets the `glossary-page` attribute of the <<glossterm, `glossterm` macro>> to `reference:glossary.adoc` so that terms can be linked to the glossary page.
|
|
237
291
|
|
|
292
|
+
==== Environment variables
|
|
293
|
+
|
|
294
|
+
This extension does not require any environment variables.
|
|
295
|
+
|
|
296
|
+
==== Configuration options
|
|
297
|
+
|
|
298
|
+
There are no configurable options for this extension.
|
|
299
|
+
|
|
238
300
|
==== Registration example
|
|
239
301
|
|
|
240
302
|
```yaml
|
|
@@ -249,6 +311,10 @@ This extension identifies and logs any pages that aren't listed in the navigatio
|
|
|
249
311
|
|
|
250
312
|
IMPORTANT: By default, this extension excludes components named 'api'. This behavior is hardcoded and cannot be changed in the configuration.
|
|
251
313
|
|
|
314
|
+
==== Environment variables
|
|
315
|
+
|
|
316
|
+
This extension does not require any environment variables.
|
|
317
|
+
|
|
252
318
|
==== Configuration options
|
|
253
319
|
|
|
254
320
|
This extension accepts the following configuration options:
|
|
@@ -4,67 +4,86 @@ module.exports.register = function ({ config }) {
|
|
|
4
4
|
const logger = this.getLogger('related-docs-extension');
|
|
5
5
|
|
|
6
6
|
this.on('documentsConverted', async ({ contentCatalog, siteCatalog }) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
// Find the latest version of each component
|
|
8
|
+
const latestVersions = {};
|
|
9
|
+
contentCatalog.getComponents().forEach(component => {
|
|
10
|
+
latestVersions[component.name] = component.latest.version;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Retrieve all documents and labs from the latest versions of each component
|
|
14
|
+
const allDocs = [];
|
|
15
|
+
const allLabs = contentCatalog.findBy({ component: 'redpanda-labs', family: 'page', version: latestVersions['redpanda-labs'] });
|
|
16
|
+
|
|
17
|
+
Object.keys(latestVersions).forEach(component => {
|
|
18
|
+
if (component === 'redpanda-labs') return;
|
|
19
|
+
allDocs.push(...contentCatalog.findBy({ component, family: 'page', version: latestVersions[component] }));
|
|
20
|
+
});
|
|
21
|
+
allLabs.forEach((labPage) => {
|
|
22
|
+
const relatedDocs = new Set();
|
|
23
|
+
const relatedLabs = new Set();
|
|
24
|
+
const sourceAttributes = labPage.asciidoc.attributes;
|
|
12
25
|
const pageCategories = sourceAttributes['page-categories'];
|
|
13
26
|
if (!pageCategories) return;
|
|
14
27
|
const sourceCategoryList = pageCategories.split(',').map(c => c.trim());
|
|
15
|
-
const sourceDeploymentType = getDeploymentType(sourceAttributes)
|
|
16
|
-
const docs = contentCatalog.findBy({ component: 'ROOT', family: 'page' });
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
related
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
const sourceDeploymentType = getDeploymentType(sourceAttributes);
|
|
29
|
+
const docs = contentCatalog.findBy({ component: 'ROOT', family: 'page', version: latestVersions['ROOT'] });
|
|
30
|
+
|
|
31
|
+
allDocs.forEach((docPage) => {
|
|
32
|
+
const related = findRelated(docPage, sourceCategoryList, sourceDeploymentType, logger);
|
|
33
|
+
if (related) relatedDocs.add(JSON.stringify(related));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
allLabs.forEach((targetLabPage) => {
|
|
22
37
|
if (targetLabPage === labPage) return;
|
|
23
38
|
|
|
24
39
|
const related = findRelated(targetLabPage, sourceCategoryList, sourceDeploymentType, logger);
|
|
25
|
-
if (related) relatedLabs.
|
|
40
|
+
if (related) relatedLabs.add(JSON.stringify(related));
|
|
26
41
|
});
|
|
27
42
|
|
|
43
|
+
// Convert Sets back to arrays and remove duplicates
|
|
44
|
+
const uniqueRelatedDocs = Array.from(relatedDocs).map(item => JSON.parse(item));
|
|
45
|
+
const uniqueRelatedLabs = Array.from(relatedLabs).map(item => JSON.parse(item));
|
|
46
|
+
|
|
28
47
|
// Store related docs and labs in the lab page attributes
|
|
29
|
-
if (
|
|
30
|
-
labPage.asciidoc.attributes['page-related-docs'] = JSON.stringify(
|
|
48
|
+
if (uniqueRelatedDocs.length > 0) {
|
|
49
|
+
labPage.asciidoc.attributes['page-related-docs'] = JSON.stringify(uniqueRelatedDocs);
|
|
31
50
|
}
|
|
32
51
|
|
|
33
|
-
if (
|
|
34
|
-
labPage.asciidoc.attributes['page-related-labs'] = JSON.stringify(
|
|
52
|
+
if (uniqueRelatedLabs.length > 0) {
|
|
53
|
+
labPage.asciidoc.attributes['page-related-labs'] = JSON.stringify(uniqueRelatedLabs);
|
|
35
54
|
}
|
|
36
55
|
|
|
37
|
-
if (
|
|
56
|
+
if (uniqueRelatedDocs.length > 0 || uniqueRelatedLabs.length > 0) {
|
|
38
57
|
logger.info(`Set related docs and labs attributes for ${labPage.asciidoc.doctitle}`);
|
|
39
58
|
}
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
};
|
|
43
62
|
|
|
44
63
|
function findRelated(docPage, sourceCategoryList, sourceDeploymentType, logger) {
|
|
45
|
-
const targetAttributes = docPage.asciidoc.attributes
|
|
64
|
+
const targetAttributes = docPage.asciidoc.attributes;
|
|
46
65
|
const pageCategories = targetAttributes['page-categories'];
|
|
47
66
|
if (!pageCategories) return null;
|
|
48
67
|
const targetCategoryList = pageCategories.split(',').map(c => c.trim());
|
|
49
|
-
const targetDeploymentType = getDeploymentType(targetAttributes)
|
|
50
|
-
const categoryMatch = hasMatchingCategory(sourceCategoryList, targetCategoryList)
|
|
51
|
-
if (categoryMatch && (!targetDeploymentType ||sourceDeploymentType === targetDeploymentType)) {
|
|
68
|
+
const targetDeploymentType = getDeploymentType(targetAttributes);
|
|
69
|
+
const categoryMatch = hasMatchingCategory(sourceCategoryList, targetCategoryList);
|
|
70
|
+
if (categoryMatch && (!targetDeploymentType || sourceDeploymentType === targetDeploymentType)) {
|
|
52
71
|
return {
|
|
53
72
|
title: docPage.asciidoc.doctitle,
|
|
54
73
|
url: docPage.pub.url,
|
|
55
|
-
}
|
|
74
|
+
};
|
|
56
75
|
}
|
|
57
|
-
return null
|
|
76
|
+
return null;
|
|
58
77
|
}
|
|
59
78
|
|
|
60
|
-
function getDeploymentType
|
|
79
|
+
function getDeploymentType(attributes) {
|
|
61
80
|
return attributes['env-kubernetes'] ? 'Kubernetes'
|
|
62
81
|
: attributes['env-linux'] ? 'Linux'
|
|
63
82
|
: attributes['env-docker'] ? 'Docker'
|
|
64
|
-
: attributes.cloud ? 'Redpanda Cloud'
|
|
65
|
-
: ''
|
|
83
|
+
: attributes.cloud ? 'Redpanda Cloud'
|
|
84
|
+
: '';
|
|
66
85
|
}
|
|
67
86
|
|
|
68
|
-
function hasMatchingCategory
|
|
69
|
-
return sourcePageCategories.every(
|
|
70
|
-
}
|
|
87
|
+
function hasMatchingCategory(sourcePageCategories, targetPageCategories) {
|
|
88
|
+
return sourcePageCategories.every(category => targetPageCategories.includes(category));
|
|
89
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const GetLatestConnectTag = require('./version-fetcher/get-latest-connect');
|
|
4
|
+
|
|
5
|
+
module.exports.register = function ({ config }) {
|
|
6
|
+
const logger = this.getLogger('modify-connect-tag-playbook-extension');
|
|
7
|
+
|
|
8
|
+
this.on('contextStarted', async ({ playbook }) => {
|
|
9
|
+
try {
|
|
10
|
+
// Fetch the latest release tag for redpanda-data/connect
|
|
11
|
+
const sourceUrl = 'https://github.com/redpanda-data/connect';
|
|
12
|
+
if (playbook && playbook.content && playbook.content.sources) {
|
|
13
|
+
const source = playbook.content.sources.find(source => source.url === sourceUrl);
|
|
14
|
+
if (source) {
|
|
15
|
+
const latestTag = await GetLatestConnectTag();
|
|
16
|
+
if (latestTag) {
|
|
17
|
+
source.tags[0] = latestTag;
|
|
18
|
+
this.updateVariables({ playbook });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error('Failed to update playbook with the latest Redpanda Connect tag:', error);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -1,54 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
1
3
|
module.exports.register = function ({ config }) {
|
|
2
|
-
const { addToNavigation, unlistedPagesHeading = 'Unlisted Pages' } = config
|
|
3
|
-
const logger = this.getLogger('unlisted-pages-extension')
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} else if (unlistedPages.length && addToNavigation) {
|
|
23
|
-
nav.push({
|
|
24
|
-
content: unlistedPagesHeading,
|
|
25
|
-
items: unlistedPages.map((page) => {
|
|
26
|
-
return { content: page.asciidoc.navtitle, url: page.pub.url, urlType: 'internal' }
|
|
27
|
-
}),
|
|
28
|
-
root: true,
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
}
|
|
4
|
+
const { addToNavigation, unlistedPagesHeading = 'Unlisted Pages' } = config;
|
|
5
|
+
const logger = this.getLogger('unlisted-pages-extension');
|
|
6
|
+
|
|
7
|
+
this.on('navigationBuilt', ({ siteCatalog, contentCatalog }) => {
|
|
8
|
+
contentCatalog.getComponents().forEach(({ versions }) => {
|
|
9
|
+
versions.forEach(({ name: component, version, navigation: nav, url: defaultUrl }) => {
|
|
10
|
+
if (component === 'api') return;
|
|
11
|
+
if (!nav) return;
|
|
12
|
+
const currentComponent = contentCatalog.getComponent(component);
|
|
13
|
+
const prerelease = currentComponent && currentComponent.latestPrerelease ? currentComponent.latestPrerelease : false;
|
|
14
|
+
|
|
15
|
+
const navEntriesByUrl = getNavEntriesByUrl(nav);
|
|
16
|
+
const unlistedPages = contentCatalog
|
|
17
|
+
.findBy({ component, version, family: 'page' })
|
|
18
|
+
.reduce((collector, page) => {
|
|
19
|
+
if (siteCatalog.unpublishedPages.includes(page.pub.url)) {
|
|
20
|
+
logger.info({ file: page.src, source: page.src.origin }, 'removing unpublished page from nav tree');
|
|
21
|
+
removePageFromNav(nav, page.pub.url); // Remove the page from navigationCatalog
|
|
22
|
+
return collector; // Skip adding this page to the collector
|
|
23
|
+
}
|
|
35
24
|
|
|
36
|
-
|
|
25
|
+
if (!(page.pub.url in navEntriesByUrl) && page.pub.url !== defaultUrl) {
|
|
26
|
+
logger.warn({ file: page.src, source: page.src.origin }, 'detected unlisted page');
|
|
27
|
+
return collector.concat(page);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return collector;
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
if (unlistedPages.length && component === 'redpanda-connect') {
|
|
34
|
+
// Some component pages for Redpanda Connect are autogenerated. This function tries to add unlisted component pages to the nav in case a new one gets created without updating the nav.
|
|
35
|
+
addRedpandaConnectPagesToNav(nav[0].items, unlistedPages);
|
|
36
|
+
} else if (unlistedPages.length && addToNavigation) {
|
|
37
|
+
nav.push({
|
|
38
|
+
content: unlistedPagesHeading,
|
|
39
|
+
items: unlistedPages.map((page) => {
|
|
40
|
+
return { content: page.asciidoc.navtitle, url: page.pub.url, urlType: 'internal' };
|
|
41
|
+
}),
|
|
42
|
+
root: true,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function getNavEntriesByUrl(items = [], accum = {}) {
|
|
37
51
|
items.forEach((item) => {
|
|
38
|
-
if (item.urlType === 'internal') accum[item.url.split('#')[0]] = item
|
|
39
|
-
getNavEntriesByUrl(item.items, accum)
|
|
40
|
-
})
|
|
41
|
-
return accum
|
|
52
|
+
if (item.urlType === 'internal') accum[item.url.split('#')[0]] = item;
|
|
53
|
+
getNavEntriesByUrl(item.items, accum);
|
|
54
|
+
});
|
|
55
|
+
return accum;
|
|
42
56
|
}
|
|
43
57
|
|
|
44
58
|
function addRedpandaConnectPagesToNav(navItems, pages) {
|
|
45
59
|
// get the Components nav section
|
|
46
60
|
let componentsSection = navItems.find(item => item.content === 'Components');
|
|
47
|
-
if (!componentsSection) return
|
|
61
|
+
if (!componentsSection) return;
|
|
48
62
|
|
|
49
63
|
pages.forEach(page => {
|
|
50
64
|
const dirname = page.out.dirname;
|
|
51
|
-
if (!dirname.includes('/components/')) return
|
|
65
|
+
if (!dirname.includes('/components/')) return;
|
|
52
66
|
const heading = page.asciidoc.attributes.doctitle;
|
|
53
67
|
const pathParts = dirname.split('/').slice(2); // Get the type
|
|
54
68
|
// get existing nav items inside the Components tree
|
|
@@ -66,4 +80,16 @@ function addRedpandaConnectPagesToNav(navItems, pages) {
|
|
|
66
80
|
|
|
67
81
|
currentLevel.push({ content: page.asciidoc.navtitle || page.src.stem, url: page.pub.url, urlType: 'internal' });
|
|
68
82
|
});
|
|
69
|
-
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function removePageFromNav(navItems, urlToRemove) {
|
|
86
|
+
// Remove the page from the navigation items
|
|
87
|
+
for (let i = navItems.length - 1; i >= 0; i--) {
|
|
88
|
+
const item = navItems[i];
|
|
89
|
+
if (item.url === urlToRemove) {
|
|
90
|
+
navItems.splice(i, 1);
|
|
91
|
+
} else if (item.items && item.items.length > 0) {
|
|
92
|
+
removePageFromNav(item.items, urlToRemove);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,9 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
1
3
|
module.exports.register = function () {
|
|
2
|
-
this.on('documentsConverted', ({ contentCatalog }) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
this.on('documentsConverted', ({ siteCatalog, contentCatalog }) => {
|
|
5
|
+
// Get all pages that have an `out` property
|
|
6
|
+
const pages = contentCatalog.getPages((page) => page.out);
|
|
7
|
+
let componentName;
|
|
8
|
+
siteCatalog.unpublishedPages = []
|
|
9
|
+
|
|
10
|
+
// Iterate over each page
|
|
11
|
+
pages.forEach((page) => {
|
|
12
|
+
// Retrieve the component associated with the page
|
|
13
|
+
componentName = page.asciidoc?.attributes['page-component-name'];
|
|
14
|
+
const component = contentCatalog.getComponent(componentName);
|
|
15
|
+
|
|
16
|
+
// Check if the component has a latest prerelease
|
|
17
|
+
const prerelease = component && component.latestPrerelease ? component.latestPrerelease : false;
|
|
18
|
+
|
|
19
|
+
// Check the conditions for unpublishing the page
|
|
20
|
+
const shouldUnpublish = (
|
|
21
|
+
page.asciidoc?.attributes['page-unpublish'] ||
|
|
22
|
+
(page.asciidoc?.attributes['publish-only-during-beta']
|
|
23
|
+
&& !prerelease // No beta version available, meaning the beta period has ended
|
|
24
|
+
)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// If any condition is met, unpublish the page
|
|
28
|
+
if (shouldUnpublish) {
|
|
29
|
+
siteCatalog.unpublishedPages.push(page.pub.url)
|
|
30
|
+
delete page.out;
|
|
6
31
|
}
|
|
7
|
-
})
|
|
8
|
-
})
|
|
9
|
-
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Fetch the latest release version from GitHub
|
|
2
|
+
const { Octokit } = require("@octokit/rest");
|
|
3
|
+
const { retry } = require("@octokit/plugin-retry");
|
|
4
|
+
const OctokitWithRetries = Octokit.plugin(retry);
|
|
5
|
+
const owner = 'redpanda-data';
|
|
6
|
+
const repo = 'connect';
|
|
7
|
+
|
|
8
|
+
let githubOptions = {
|
|
9
|
+
userAgent: 'Redpanda Docs',
|
|
10
|
+
baseUrl: 'https://api.github.com',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
if (process.env.REDPANDA_GITHUB_TOKEN) {
|
|
14
|
+
githubOptions.auth = process.env.REDPANDA_GITHUB_TOKEN;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const github = new OctokitWithRetries(githubOptions);
|
|
18
|
+
|
|
19
|
+
module.exports = async () => {
|
|
20
|
+
try {
|
|
21
|
+
const release = await github.rest.repos.getLatestRelease({ owner, repo });
|
|
22
|
+
tag = release.data.tag_name;
|
|
23
|
+
return tag;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error(error);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -27,15 +27,17 @@ module.exports = async () => {
|
|
|
27
27
|
per_page: 50
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
// Filter valid semver tags and sort them to find the highest version
|
|
30
|
+
// Filter valid semver tags, exclude drafts, and sort them to find the highest version
|
|
31
31
|
const sortedReleases = releases.data
|
|
32
|
+
.filter(release => !release.draft)
|
|
32
33
|
.map(release => release.tag_name.replace(/^v/, ''))
|
|
33
|
-
.filter(tag => semver.valid(tag)
|
|
34
|
+
.filter(tag => semver.valid(tag))
|
|
34
35
|
// Sort in descending order to get the highest version first
|
|
35
36
|
.sort(semver.rcompare);
|
|
36
37
|
|
|
37
38
|
if (sortedReleases.length > 0) {
|
|
38
|
-
const latestRedpandaReleaseVersion = sortedReleases
|
|
39
|
+
const latestRedpandaReleaseVersion = sortedReleases.find(tag => !tag.includes('rc'));
|
|
40
|
+
const latestRcReleaseVersion = sortedReleases.find(tag => tag.includes('rc'));
|
|
39
41
|
|
|
40
42
|
// Get the commit hash for the highest version tag
|
|
41
43
|
const commitData = await github.rest.git.getRef({
|
|
@@ -45,13 +47,32 @@ module.exports = async () => {
|
|
|
45
47
|
});
|
|
46
48
|
const latestRedpandaReleaseCommitHash = commitData.data.object.sha;
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
let latestRcReleaseCommitHash = null;
|
|
51
|
+
if (latestRcReleaseVersion) {
|
|
52
|
+
const rcCommitData = await github.rest.git.getRef({
|
|
53
|
+
owner,
|
|
54
|
+
repo,
|
|
55
|
+
ref: `tags/v${latestRcReleaseVersion}`
|
|
56
|
+
});
|
|
57
|
+
latestRcReleaseCommitHash = rcCommitData.data.object.sha;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
latestRedpandaRelease: {
|
|
62
|
+
version: latestRedpandaReleaseVersion,
|
|
63
|
+
commitHash: latestRedpandaReleaseCommitHash.substring(0, 7)
|
|
64
|
+
},
|
|
65
|
+
latestRcRelease: latestRcReleaseVersion ? {
|
|
66
|
+
version: latestRcReleaseVersion,
|
|
67
|
+
commitHash: latestRcReleaseCommitHash.substring(0, 7)
|
|
68
|
+
} : null
|
|
69
|
+
};
|
|
49
70
|
} else {
|
|
50
71
|
console.log("No valid semver releases found for Redpanda.");
|
|
51
|
-
return
|
|
72
|
+
return { latestRedpandaRelease: null, latestRcRelease: null };
|
|
52
73
|
}
|
|
53
74
|
} catch (error) {
|
|
54
75
|
console.error('Failed to fetch Redpanda release information:', error);
|
|
55
|
-
return
|
|
76
|
+
return { latestRedpandaRelease: null, latestRcRelease: null };
|
|
56
77
|
}
|
|
57
78
|
};
|
|
@@ -2,6 +2,7 @@ const GetLatestRedpandaVersion = require('./get-latest-redpanda-version')
|
|
|
2
2
|
const GetLatestConsoleVersion = require('./get-latest-console-version')
|
|
3
3
|
const GetLatestOperatorVersion = require('./get-latest-operator-version')
|
|
4
4
|
const GetLatestHelmChartVersion = require('./get-latest-redpanda-helm-version')
|
|
5
|
+
const GetLatestConnectVersion = require('./get-latest-connect')
|
|
5
6
|
const chalk = require('chalk')
|
|
6
7
|
const semver = require('semver')
|
|
7
8
|
|
|
@@ -17,13 +18,15 @@ module.exports.register = function ({ config }) {
|
|
|
17
18
|
GetLatestRedpandaVersion(),
|
|
18
19
|
GetLatestConsoleVersion(),
|
|
19
20
|
GetLatestOperatorVersion(),
|
|
20
|
-
GetLatestHelmChartVersion()
|
|
21
|
+
GetLatestHelmChartVersion(),
|
|
22
|
+
GetLatestConnectVersion()
|
|
21
23
|
])
|
|
22
24
|
|
|
23
25
|
const LatestRedpandaVersion = results[0].status === 'fulfilled' ? results[0].value : null
|
|
24
26
|
const LatestConsoleVersion = results[1].status === 'fulfilled' ? results[1].value : null
|
|
25
27
|
const LatestOperatorVersion = results[2].status === 'fulfilled' ? results[2].value : null
|
|
26
28
|
const LatestHelmChartVersion = results[3].status === 'fulfilled' ? results[3].value : null
|
|
29
|
+
const LatestConnectVersion = results[4].status === 'fulfilled' ? results[4].value : null
|
|
27
30
|
|
|
28
31
|
const components = await contentCatalog.getComponents()
|
|
29
32
|
components.forEach(component => {
|
|
@@ -32,18 +35,27 @@ module.exports.register = function ({ config }) {
|
|
|
32
35
|
asciidoc.attributes['latest-console-version'] = `${LatestConsoleVersion}@`
|
|
33
36
|
logger.info(`Set Redpanda Console version to ${LatestConsoleVersion} in ${name} ${version}`)
|
|
34
37
|
}
|
|
38
|
+
if (LatestConnectVersion) {
|
|
39
|
+
asciidoc.attributes['latest-connect-version'] = `${LatestConnectVersion}@`
|
|
40
|
+
logger.info(`Set Redpanda Connect version to ${LatestConnectVersion} in ${name} ${version}`)
|
|
41
|
+
}
|
|
42
|
+
if (LatestRedpandaVersion && LatestRedpandaVersion.latestRcRelease) {
|
|
43
|
+
asciidoc.attributes['redpanda-beta-version'] = `${LatestRedpandaVersion.latestRcRelease.version}@`
|
|
44
|
+
asciidoc.attributes['redpanda-beta-commit'] = `${LatestRedpandaVersion.latestRcRelease.commitHash}@`
|
|
45
|
+
logger.info(`Updated to latest Redpanda RC version: ${LatestRedpandaVersion.latestRcRelease.version} with commit: ${LatestRedpandaVersion.latestRcRelease.commitHash}`)
|
|
46
|
+
}
|
|
35
47
|
})
|
|
36
48
|
|
|
37
49
|
if (!component.latest.asciidoc) {
|
|
38
50
|
component.latest.asciidoc = { attributes: {} }
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
if (LatestRedpandaVersion && semver.valid(LatestRedpandaVersion
|
|
53
|
+
if (LatestRedpandaVersion && semver.valid(LatestRedpandaVersion.latestRedpandaRelease.version)) {
|
|
42
54
|
let currentVersion = component.latest.asciidoc.attributes['full-version'] || '0.0.0'
|
|
43
|
-
if (semver.gt(LatestRedpandaVersion
|
|
44
|
-
component.latest.asciidoc.attributes['full-version'] = `${LatestRedpandaVersion
|
|
45
|
-
component.latest.asciidoc.attributes['latest-release-commit'] = `${LatestRedpandaVersion
|
|
46
|
-
logger.info(`Updated to latest Redpanda version: ${LatestRedpandaVersion
|
|
55
|
+
if (semver.gt(LatestRedpandaVersion.latestRedpandaRelease.version, currentVersion)) {
|
|
56
|
+
component.latest.asciidoc.attributes['full-version'] = `${LatestRedpandaVersion.latestRedpandaRelease.version}@`
|
|
57
|
+
component.latest.asciidoc.attributes['latest-release-commit'] = `${LatestRedpandaVersion.latestRedpandaRelease.commitHash}@`
|
|
58
|
+
logger.info(`Updated to latest Redpanda version: ${LatestRedpandaVersion.latestRedpandaRelease.version} with commit: ${LatestRedpandaVersion.latestRedpandaRelease.commitHash}`)
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
61
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redpanda-data/docs-extensions-and-macros",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Antora extensions and macros developed for Redpanda documentation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antora",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"./extensions/generate-rp-connect-categories": "./extensions/generate-rp-connect-categories.js",
|
|
34
34
|
"./extensions/add-global-attributes": "./extensions/add-global-attributes.js",
|
|
35
35
|
"./extensions/version-fetcher/set-latest-version": "./extensions/version-fetcher/set-latest-version.js",
|
|
36
|
+
"./extensions/modify-connect-tag-playbook": "./extensions/modify-connect-tag-playbook.js",
|
|
36
37
|
"./extensions/validate-attributes": "./extensions/validate-attributes.js",
|
|
37
38
|
"./extensions/find-related-docs": "./extensions/find-related-docs.js",
|
|
38
39
|
"./extensions/unpublish-pages": "./extensions/unpublish-pages.js",
|