@@ -13,7 +13,43 @@ async function runCommand(cmd) {
13
13
} ) ;
14
14
}
15
15
16
- function getBaseUpperBound ( packageYamlPath ) {
16
+ function getBaseUpperBound ( baseBound ) {
17
+ const baseBoundMatch = baseBound . match ( / ( < = | < ) \s * ( ( \d + ) ( \. ( \d + ) ) ? ( \. ( \d + ) ) ? ) / ) ;
18
+ if ( ! baseBoundMatch ) return null ;
19
+
20
+ const operator = baseBoundMatch [ 1 ] ;
21
+ const version = baseBoundMatch [ 2 ] ;
22
+ const inclusive = operator === "<=" ;
23
+
24
+ return { inclusive, version } ;
25
+ }
26
+
27
+ function normalizeVersion ( version , segments = 3 ) {
28
+ const parts = version . split ( '.' ) . map ( Number ) ;
29
+ while ( parts . length < segments ) parts . push ( 0 ) ;
30
+ return parts . slice ( 0 , segments ) . join ( '.' ) ;
31
+ }
32
+
33
+ function compareVersions ( a , b ) {
34
+ const pa = normalizeVersion ( a ) . split ( '.' ) . map ( Number ) ;
35
+ const pb = normalizeVersion ( b ) . split ( '.' ) . map ( Number ) ;
36
+ const len = Math . max ( pa . length , pb . length ) ;
37
+
38
+ for ( let i = 0 ; i < len ; i ++ ) {
39
+ const na = pa [ i ] || 0 ;
40
+ const nb = pb [ i ] || 0 ;
41
+ if ( na > nb ) return 1 ;
42
+ if ( na < nb ) return - 1 ;
43
+ }
44
+ return 0 ;
45
+ }
46
+
47
+ function versionLess ( baseVersion , bound ) {
48
+ const cmp = compareVersions ( baseVersion , bound . version ) ;
49
+ return cmp < 0 || ( cmp === 0 && bound . inclusive ) ;
50
+ }
51
+
52
+ function parseBaseUpperBound ( packageYamlPath ) {
17
53
const fileContent = fs . readFileSync ( packageYamlPath , "utf-8" ) ;
18
54
const parsed = yaml . load ( fileContent ) ;
19
55
@@ -27,54 +63,40 @@ function getBaseUpperBound(packageYamlPath) {
27
63
throw new Error ( "No base dependency found in package.yaml" ) ;
28
64
}
29
65
30
- const versionConstraint = baseDep . match ( / < \s * ( [ \d . ] + ) / ) ;
66
+ const versionConstraint = getBaseUpperBound ( baseDep ) ;
31
67
if ( ! versionConstraint ) {
32
68
throw new Error ( "No upper bound for base found in package.yaml" ) ;
33
69
}
34
70
35
- return versionConstraint [ 1 ] ;
36
- }
37
-
38
- function versionLess ( v1 , v2 ) {
39
- const a = v1 . split ( '.' ) . map ( Number ) ;
40
- const b = v2 . split ( '.' ) . map ( Number ) ;
41
- for ( let i = 0 ; i < Math . max ( a . length , b . length ) ; i ++ ) {
42
- const n1 = a [ i ] || 0 ;
43
- const n2 = b [ i ] || 0 ;
44
- if ( n1 < n2 ) return true ;
45
- if ( n1 > n2 ) return false ;
46
- }
47
- return false ;
71
+ return versionConstraint ;
48
72
}
49
73
50
74
async function main ( ) {
51
75
try {
52
- const files = fs . readdirSync ( process . cwd ( ) ) ;
53
76
const packageYamlPath = githubCore . getInput ( "package-yaml-path" ) || path . join ( process . cwd ( ) , "package.yaml" ) ;
54
-
55
- const baseUpperBound = getBaseUpperBound ( packageYamlPath ) ;
77
+ const baseUpperBound = parseBaseUpperBound ( packageYamlPath ) ;
56
78
57
79
const ghcupListStr = await runCommand ( "ghcup list -t ghc -r" ) ;
58
80
const lines = ghcupListStr . split ( "\n" ) . filter ( Boolean ) ;
59
81
60
- const ghcupList = lines . map ( line => {
61
- const match = line . match ( / ^ g h c \s ( [ ^ \s ] + ) \s .* ?b a s e - ( [ 0 - 9 . ] + ) / ) ;
62
- if ( ! match ) return null ;
63
- return { version : match [ 1 ] , base : match [ 2 ] } ;
64
- } ) . filter ( Boolean ) ;
82
+ const ghcupList = lines . map ( line => {
83
+ const match = line . match ( / ^ g h c \s ( [ ^ \s ] + ) \s .* ?b a s e - ( [ 0 - 9 . ] + ) / ) ;
84
+ if ( ! match ) return null ;
85
+ return { version : match [ 1 ] , base : match [ 2 ] } ;
86
+ } ) . filter ( Boolean ) ;
65
87
66
- if ( ghcupList . length > 0 ) {
67
- console . log ( `Found ${ ghcupList . length } GHC versions` ) ;
68
- } else {
69
- throw new Error ( 'Failed to get GHC versions from GHCup' ) ;
70
- }
88
+ if ( ghcupList . length > 0 ) {
89
+ console . log ( `Found ${ ghcupList . length } GHC versions` ) ;
90
+ } else {
91
+ throw new Error ( 'Failed to get GHC versions from GHCup' ) ;
92
+ }
71
93
72
94
const validVersions = ghcupList . filter ( ghcEntry => {
73
95
return versionLess ( ghcEntry . base , baseUpperBound ) ;
74
96
} ) ;
75
97
76
98
if ( validVersions . length === 0 ) {
77
- throw new Error ( `No GHC version found with base < ${ baseUpperBound } ` ) ;
99
+ throw new Error ( `No GHC version found with base <${ baseUpperBound . inclusive ? "=" : "" } ${ baseUpperBound . version } ` ) ;
78
100
}
79
101
80
102
validVersions . sort ( ( a , b ) => {
@@ -91,7 +113,8 @@ async function main() {
91
113
92
114
const latestGhc = validVersions [ 0 ] . version ;
93
115
94
- console . log ( `Latest GHC under base < ${ baseUpperBound } : ${ latestGhc } ` ) ;
116
+ console . log ( `Latest GHC under base < ${ baseUpperBound . version } : ${ latestGhc } ` ) ;
117
+
95
118
const outputPath = process . env . GITHUB_OUTPUT ;
96
119
fs . appendFileSync ( outputPath , `ghc-version=${ latestGhc } \n` ) ;
97
120
} catch ( err ) {
0 commit comments