@@ -35,18 +35,6 @@ function getOsBinName() {
3535 }
3636}
3737
38- function resolveFullPathBin ( ) {
39- const destination = core . getInput ( 'destination' ) || process . cwd ( ) ;
40- let bin = core . getInput ( 'name' ) || 'func' ;
41- if ( process . env . RUNNER_OS === 'Windows' && ! bin . endsWith ( '.exe' ) ) {
42- bin += '.exe' ;
43- }
44- if ( ! fs . existsSync ( destination ) ) {
45- fs . mkdirSync ( destination , { recursive : true } ) ;
46- }
47- return path . resolve ( destination , bin ) ;
48- }
49-
5038// Normalizes version to release tag format: knative-vX.Y.Z
5139// Ex.: '1.16' or 'v1.16' will return 'knative-v1.16.0'
5240function smartVersionUpdate ( version ) {
@@ -61,6 +49,37 @@ function smartVersionUpdate(version) {
6149 return `${ knprefix } ${ prefix } ${ match . groups . major } .${ match . groups . minor } .${ patch } ` ;
6250}
6351
52+ function resolveVersion ( ) {
53+ if ( core . getInput ( 'binarySource' ) !== "" ) return null ;
54+ const versionInput = core . getInput ( 'version' ) || DEFAULT_FUNC_VERSION ;
55+ if ( versionInput . toLowerCase ( ) . trim ( ) === DEFAULT_FUNC_VERSION ) return null ;
56+ return smartVersionUpdate ( versionInput ) ;
57+ }
58+
59+ // Resolve download url based on given input
60+ // binName: name of func binary when it is to be constructed for full URL
61+ // (when not using binarySource)
62+ function resolveDownloadUrl ( version , binName ) {
63+ const binarySource = core . getInput ( 'binarySource' ) ;
64+ if ( binarySource !== "" ) {
65+ core . info ( `Using custom binary source: ${ binarySource } ` ) ;
66+ return binarySource ;
67+ }
68+
69+ if ( ! version ) {
70+ core . info ( "Using latest version..." ) ;
71+ return buildUrlString ( DEFAULT_FUNC_VERSION ) ;
72+ }
73+ core . info ( `Using specific version ${ version } ` ) ;
74+ return buildUrlString ( version ) ;
75+
76+ function buildUrlString ( version ) {
77+ return version === DEFAULT_FUNC_VERSION
78+ ? `${ DEFAULT_LATEST_BINARY_SOURCE } /${ binName } `
79+ : `${ DEFAULT_BINARY_SOURCE } /${ version } /${ binName } ` ;
80+ }
81+ }
82+
6483// Downloads binary from release URL and makes it executable
6584async function downloadFuncBinary ( url , binPath ) {
6685 core . info ( `Downloading from: ${ url } ` ) ;
@@ -76,6 +95,18 @@ async function downloadFuncBinary(url, binPath) {
7695 }
7796}
7897
98+ function resolveFullPathBin ( ) {
99+ const destination = core . getInput ( 'destination' ) || process . cwd ( ) ;
100+ let bin = core . getInput ( 'name' ) || 'func' ;
101+ if ( process . env . RUNNER_OS === 'Windows' && ! bin . endsWith ( '.exe' ) ) {
102+ bin += '.exe' ;
103+ }
104+ if ( ! fs . existsSync ( destination ) ) {
105+ fs . mkdirSync ( destination , { recursive : true } ) ;
106+ }
107+ return path . resolve ( destination , bin ) ;
108+ }
109+
79110// Adds binary directory to PATH for current and subsequent steps
80111function addBinToPath ( binPath ) {
81112 const dir = path . dirname ( binPath ) ;
@@ -87,29 +118,45 @@ function addBinToPath(binPath) {
87118 }
88119}
89120
90- // Resolve download url based on given input
91- // binName: name of func binary when it is to be constructed for full URL
92- // (when not using binarySource)
93- function resolveDownloadUrl ( binName ) {
94- const binarySource = core . getInput ( 'binarySource' ) ;
95- if ( binarySource !== "" ) {
96- core . info ( `Using custom binary source: ${ binarySource } ` ) ;
97- return binarySource ;
98- }
121+ // Returns difference of minor versions between 'latest' and 'version'
122+ // subtracts 'version' from 'latest' (returns negative if 'version' is ahead)
123+ // If minor version cannot be extracted on either number - return 0
124+ function versionDiff ( latest , version ) {
125+ const extractMinor = ( v ) => {
126+ const match = v . match ( / ( \d + ) \. ( \d + ) / ) ;
127+ return match ? parseInt ( match [ 2 ] , 10 ) : null ;
128+ } ;
129+
130+ const latestMinor = extractMinor ( latest ) ;
131+ const versionMinor = extractMinor ( version ) ;
132+ if ( latestMinor === null || versionMinor === null ) {
133+ return 0 ;
134+ }
135+ return latestMinor - versionMinor ;
136+ }
99137
100- const versionInput = core . getInput ( 'version' ) || DEFAULT_FUNC_VERSION ;
101- if ( versionInput . toLowerCase ( ) . trim ( ) === DEFAULT_FUNC_VERSION ) {
102- core . info ( "Using latest version..." ) ;
103- return buildUrlString ( DEFAULT_FUNC_VERSION ) ;
104- }
105- const version = smartVersionUpdate ( versionInput ) ;
106- core . info ( `Using specific version ${ version } ` ) ;
107- return buildUrlString ( version ) ;
138+ // Warn if version requested is more than 2 versions behind latest (>= 3)
139+ // This function does NOT error
140+ async function warnStaleVersion ( version ) {
141+ const API_LATEST = 'https://api.github.com/repos/knative/func/releases/latest' ;
142+ const THRESHOLD = 3 ;
108143
109- function buildUrlString ( version ) {
110- return version === DEFAULT_FUNC_VERSION
111- ? `${ DEFAULT_LATEST_BINARY_SOURCE } /${ binName } `
112- : `${ DEFAULT_BINARY_SOURCE } /${ version } /${ binName } ` ;
144+ try {
145+ const response = await fetch ( API_LATEST ) ;
146+ if ( ! response . ok ) {
147+ throw new Error ( `failed to fetch latest version: ${ response . status } ` ) ;
148+ }
149+
150+ const data = await response . json ( ) ;
151+ const latest = data . tag_name ;
152+ const diff = versionDiff ( latest , version ) ;
153+ if ( diff >= THRESHOLD ) {
154+ core . warning (
155+ `You are using func ${ version } , which is ${ diff } versions behind the latest (${ latest } ). Upgrading is recommended.`
156+ ) ;
157+ }
158+ } catch ( error ) {
159+ core . debug ( `Skipping stale version check: ${ error . message } ` ) ;
113160 }
114161}
115162
@@ -122,9 +169,17 @@ async function run() {
122169 return ;
123170 }
124171
172+ let version ;
173+ try {
174+ version = resolveVersion ( ) ;
175+ } catch ( error ) {
176+ core . setFailed ( error . message ) ;
177+ return ;
178+ }
179+
125180 let url ;
126181 try {
127- url = resolveDownloadUrl ( osBinName ) ;
182+ url = resolveDownloadUrl ( version , osBinName ) ;
128183 } catch ( error ) {
129184 core . setFailed ( `Failed to resolve url: ${ error . message } ` ) ;
130185 return ;
@@ -152,6 +207,11 @@ async function run() {
152207 return ;
153208 }
154209
210+ // Warn if using an old version (only for specific versions, not binarySource or latest)
211+ if ( version ) {
212+ await warnStaleVersion ( version ) ;
213+ }
214+
155215 try {
156216 await exec . exec ( fullPathBin , [ 'version' ] ) ;
157217 } catch ( error ) {
0 commit comments