66 * found in the LICENSE file at https://angular.io/license
77 */
88
9+ import * as semver from 'semver' ;
10+
11+ import { ReleaseConfig } from '../config/index' ;
12+
13+ import { fetchProjectNpmPackageInfo } from './npm-registry' ;
14+
15+ /** Interface describing determined LTS branches. */
16+ export interface LtsBranches {
17+ /** List of active LTS version branches. */
18+ active : LtsBranch [ ] ;
19+ /** List of inactive LTS version branches. */
20+ inactive : LtsBranch [ ] ;
21+ }
22+
23+ /** Interface describing an LTS version branch. */
24+ export interface LtsBranch {
25+ /** Name of the branch. */
26+ name : string ;
27+ /** Most recent version for the given LTS branch. */
28+ version : semver . SemVer ;
29+ /** NPM dist tag for the LTS version. */
30+ npmDistTag : string ;
31+ }
32+
933/**
1034 * Number of months a major version in Angular is actively supported. See:
1135 * https://angular.io/guide/releases#support-policy-and-schedule.
@@ -18,6 +42,44 @@ export const majorActiveSupportDuration = 6;
1842 */
1943export const majorActiveTermSupportDuration = 12 ;
2044
45+ /** Regular expression that matches LTS NPM dist tags. */
46+ export const ltsNpmDistTagRegex = / ^ v ( \d + ) - l t s $ / ;
47+
48+ /** Finds all long-term support release trains from the specified NPM package. */
49+ export async function fetchLongTermSupportBranchesFromNpm ( config : ReleaseConfig ) :
50+ Promise < LtsBranches > {
51+ const { 'dist-tags' : distTags , time} = await fetchProjectNpmPackageInfo ( config ) ;
52+ const today = new Date ( ) ;
53+ const active : LtsBranch [ ] = [ ] ;
54+ const inactive : LtsBranch [ ] = [ ] ;
55+
56+ // Iterate through the NPM package information and determine active/inactive LTS versions with
57+ // their corresponding branches. We assume that a LTS tagged version in NPM belongs to the
58+ // last-minor branch of a given major (i.e. we assume there are no outdated LTS NPM dist tags).
59+ for ( const npmDistTag in distTags ) {
60+ if ( ltsNpmDistTagRegex . test ( npmDistTag ) ) {
61+ const version = semver . parse ( distTags [ npmDistTag ] ) ! ;
62+ const branchName = `${ version . major } .${ version . minor } .x` ;
63+ const majorReleaseDate = new Date ( time [ `${ version . major } .0.0` ] ) ;
64+ const ltsEndDate = computeLtsEndDateOfMajor ( majorReleaseDate ) ;
65+ const ltsBranch : LtsBranch = { name : branchName , version, npmDistTag} ;
66+ // Depending on whether the LTS phase is still active, add the branch
67+ // the list of active or inactive LTS branches.
68+ if ( today <= ltsEndDate ) {
69+ active . push ( ltsBranch ) ;
70+ } else {
71+ inactive . push ( ltsBranch ) ;
72+ }
73+ }
74+ }
75+
76+ // Sort LTS branches in descending order. i.e. most recent ones first.
77+ active . sort ( ( a , b ) => semver . rcompare ( a . version , b . version ) ) ;
78+ inactive . sort ( ( a , b ) => semver . rcompare ( a . version , b . version ) ) ;
79+
80+ return { active, inactive} ;
81+ }
82+
2183/**
2284 * Computes the date when long-term support ends for a major released at the
2385 * specified date.
0 commit comments