build(docs-infra): compute previous version list (#39689)
Previously we hand coded the list of previous major versions that are displayed in the left navigation. Now these are generated from the tags in GitHub. Closes #39688 PR Close #39689
This commit is contained in:
parent
7d68f92315
commit
e4028ae5c4
@ -1060,35 +1060,5 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"docVersions": [
|
|
||||||
{
|
|
||||||
"title": "v9",
|
|
||||||
"url": "https://v9.angular.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "v8",
|
|
||||||
"url": "https://v8.angular.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "v7",
|
|
||||||
"url": "https://v7.angular.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "v6",
|
|
||||||
"url": "https://v6.angular.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "v5",
|
|
||||||
"url": "https://v5.angular.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "v4",
|
|
||||||
"url": "https://v4.angular.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "v2",
|
|
||||||
"url": "https://v2.angular.io/"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const Package = require('dgeni').Package;
|
const Package = require('dgeni').Package;
|
||||||
|
|
||||||
|
const gitPackage = require('dgeni-packages/git');
|
||||||
const jsdocPackage = require('dgeni-packages/jsdoc');
|
const jsdocPackage = require('dgeni-packages/jsdoc');
|
||||||
const nunjucksPackage = require('dgeni-packages/nunjucks');
|
const nunjucksPackage = require('dgeni-packages/nunjucks');
|
||||||
const linksPackage = require('../links-package');
|
const linksPackage = require('../links-package');
|
||||||
@ -19,7 +20,7 @@ const postProcessPackage = require('dgeni-packages/post-process-html');
|
|||||||
const { PROJECT_ROOT, CONTENTS_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, TEMPLATES_PATH, AIO_PATH, requireFolder } = require('../config');
|
const { PROJECT_ROOT, CONTENTS_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, TEMPLATES_PATH, AIO_PATH, requireFolder } = require('../config');
|
||||||
|
|
||||||
module.exports = new Package('angular-base', [
|
module.exports = new Package('angular-base', [
|
||||||
jsdocPackage, nunjucksPackage, linksPackage, examplesPackage, targetPackage, remarkPackage, postProcessPackage
|
gitPackage, jsdocPackage, nunjucksPackage, linksPackage, examplesPackage, targetPackage, remarkPackage, postProcessPackage
|
||||||
])
|
])
|
||||||
|
|
||||||
// Register the processors
|
// Register the processors
|
||||||
@ -37,6 +38,7 @@ module.exports = new Package('angular-base', [
|
|||||||
.factory(require('./readers/json'))
|
.factory(require('./readers/json'))
|
||||||
.factory(require('./services/copyFolder'))
|
.factory(require('./services/copyFolder'))
|
||||||
.factory(require('./services/getImageDimensions'))
|
.factory(require('./services/getImageDimensions'))
|
||||||
|
.factory(require('./services/getPreviousMajorVersions'))
|
||||||
.factory(require('./services/auto-link-filters/filterPipes'))
|
.factory(require('./services/auto-link-filters/filterPipes'))
|
||||||
.factory(require('./services/auto-link-filters/filterAmbiguousDirectiveAliases'))
|
.factory(require('./services/auto-link-filters/filterAmbiguousDirectiveAliases'))
|
||||||
.factory(require('./services/auto-link-filters/ignoreHttpInUrls'))
|
.factory(require('./services/auto-link-filters/ignoreHttpInUrls'))
|
||||||
|
54
aio/tools/transforms/angular-base-package/services/getPreviousMajorVersions.js
vendored
Normal file
54
aio/tools/transforms/angular-base-package/services/getPreviousMajorVersions.js
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const child = require('child_process');
|
||||||
|
const semver = require('semver');
|
||||||
|
const versionMatcher = /refs\/tags\/(\d+.+)$/mg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a collection of all the previous "last major" versions sorted by semantic version.
|
||||||
|
*
|
||||||
|
* @param packageInfo injected from dgeni-packages/git
|
||||||
|
* @param versionInfo injected from dgeni-packages/git
|
||||||
|
* @returns an array of SemVer objects
|
||||||
|
*/
|
||||||
|
module.exports = function getPreviousMajorVersions(packageInfo, versionInfo) {
|
||||||
|
return () => {
|
||||||
|
// always use the remote tags as the local clone might not contain all commits when cloned with
|
||||||
|
// `git clone --depth=...`
|
||||||
|
const repoUrl = packageInfo.repository.url;
|
||||||
|
const tagResults = child.spawnSync('git', ['ls-remote', '--tags', repoUrl], {encoding: 'utf8'});
|
||||||
|
|
||||||
|
if (tagResults.status !== 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const majorVersions = {};
|
||||||
|
tagResults.stdout.replace(versionMatcher, (_, tag) => {
|
||||||
|
const version = semver.parse(tag);
|
||||||
|
|
||||||
|
// Not interested in tags that do not match semver format.
|
||||||
|
if (version === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not interested in pre-release versions.
|
||||||
|
if (version.prerelease !== null && version.prerelease.length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only interested in versions that are earlier than the current major.
|
||||||
|
if (version.major >= versionInfo.currentVersion.major) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentMajor = majorVersions[version.major];
|
||||||
|
if (currentMajor === undefined || semver.compare(version, currentMajor) === 1) {
|
||||||
|
// This version is newer than the currently captured version for this major.
|
||||||
|
majorVersions[version.major] = version;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort them in descending order
|
||||||
|
return semver.sort(Object.values(majorVersions)).reverse();
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,63 @@
|
|||||||
|
const child = require('child_process');
|
||||||
|
const Dgeni = require('dgeni');
|
||||||
|
const semver = require('semver');
|
||||||
|
|
||||||
|
const basePackage = require('../index');
|
||||||
|
|
||||||
|
describe('getPreviousMajorVersions', () => {
|
||||||
|
let getPreviousMajorVersions;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const mockPackage = new Dgeni.Package('mock-package', [basePackage])
|
||||||
|
.factory('versionInfo', mockVersionInfo)
|
||||||
|
.factory('packageInfo', mockPackageInfo);
|
||||||
|
const dgeni = new Dgeni([mockPackage]);
|
||||||
|
const injector = dgeni.configureInjector();
|
||||||
|
getPreviousMajorVersions = injector.get('getPreviousMajorVersions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should spawn a child process to git', () => {
|
||||||
|
spyOn(child, 'spawnSync').and.returnValue({status: 0, stdout: ''});
|
||||||
|
getPreviousMajorVersions();
|
||||||
|
expect(child.spawnSync).toHaveBeenCalledWith('git', ['ls-remote', '--tags', 'SOME_GIT_URL'], {
|
||||||
|
encoding: 'utf8'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty list for a failed git command', () => {
|
||||||
|
spyOn(child, 'spawnSync').and.returnValue({status: 1});
|
||||||
|
expect(getPreviousMajorVersions()).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty list for no tags', () => {
|
||||||
|
spyOn(child, 'spawnSync').and.returnValue({status: 0, stdout: ''});
|
||||||
|
expect(getPreviousMajorVersions()).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an array of latest major versions with major greater than current', () => {
|
||||||
|
spyOn(child, 'spawnSync').and.returnValue({
|
||||||
|
status: 0,
|
||||||
|
stdout: `
|
||||||
|
refs/pull/655
|
||||||
|
refs/tags/some-tag
|
||||||
|
refs/tags/3.8.1
|
||||||
|
refs/tags/4.2.9
|
||||||
|
refs/tags/4.2.10
|
||||||
|
refs/tags/5.6.1
|
||||||
|
refs/tags/6.1.1
|
||||||
|
`
|
||||||
|
});
|
||||||
|
expect(getPreviousMajorVersions()).toEqual([
|
||||||
|
semver('4.2.10'),
|
||||||
|
semver('3.8.1'),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function mockVersionInfo() {
|
||||||
|
return {currentVersion: new semver('5.1.0')};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockPackageInfo() {
|
||||||
|
return {repository: {url: 'SOME_GIT_URL'}};
|
||||||
|
}
|
@ -1,15 +1,14 @@
|
|||||||
module.exports = function processNavigationMap(versionInfo, log) {
|
module.exports = function processNavigationMap(versionInfo, getPreviousMajorVersions, log) {
|
||||||
return {
|
return {
|
||||||
$runAfter: ['paths-computed'],
|
$runAfter: ['paths-computed'],
|
||||||
$runBefore: ['rendering-docs'],
|
$runBefore: ['rendering-docs'],
|
||||||
$process: function(docs) {
|
$process: function(docs) {
|
||||||
|
|
||||||
const navigationDoc = docs.find(doc => doc.docType === 'navigation-json');
|
const navigationDoc = docs.find(doc => doc.docType === 'navigation-json');
|
||||||
|
|
||||||
if (!navigationDoc) {
|
if (!navigationDoc) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Missing navigation map document (docType="navigation-json").' +
|
'Missing navigation map document (docType="navigation-json").' +
|
||||||
'Did you forget to add it to the readFileProcessor?');
|
'Did you forget to add it to the readFileProcessor?');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that all the navigation paths are to valid docs
|
// Verify that all the navigation paths are to valid docs
|
||||||
@ -24,6 +23,9 @@ module.exports = function processNavigationMap(versionInfo, log) {
|
|||||||
throw new Error('processNavigationMap failed');
|
throw new Error('processNavigationMap failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
navigationDoc.data['docVersions'] = getPreviousMajorVersions().map(
|
||||||
|
v => ({title: `v${v.major}`, url: `https://v${v.major}.angular.io/`}));
|
||||||
|
|
||||||
// Add in the version data in a "secret" field to be extracted in the docs app
|
// Add in the version data in a "secret" field to be extracted in the docs app
|
||||||
navigationDoc.data['__versionInfo'] = versionInfo.currentVersion;
|
navigationDoc.data['__versionInfo'] = versionInfo.currentVersion;
|
||||||
}
|
}
|
||||||
@ -32,13 +34,13 @@ module.exports = function processNavigationMap(versionInfo, log) {
|
|||||||
|
|
||||||
function walk(node, map, path) {
|
function walk(node, map, path) {
|
||||||
let errors = [];
|
let errors = [];
|
||||||
for(const key in node) {
|
for (const key in node) {
|
||||||
const child = node[key];
|
const child = node[key];
|
||||||
if (child !== null) { // null is allowed
|
if (child !== null) { // null is allowed
|
||||||
if (key === 'url') {
|
if (key === 'url') {
|
||||||
const url = child.replace(/#.*$/, ''); // strip hash
|
const url = child.replace(/#.*$/, ''); // strip hash
|
||||||
if (isRelative(url) && !map[url]) {
|
if (isRelative(url) && !map[url]) {
|
||||||
errors.push({ path: path.join('.'), url });
|
errors.push({path: path.join('.'), url});
|
||||||
}
|
}
|
||||||
} else if (typeof child !== 'string') {
|
} else if (typeof child !== 'string') {
|
||||||
errors = errors.concat(walk(child, map, path.concat([key])));
|
errors = errors.concat(walk(child, map, path.concat([key])));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user