-
Notifications
You must be signed in to change notification settings - Fork 0
Warn on older versions of func #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,12 +3,6 @@ const exec = require('@actions/exec'); | |
| const path = require('path'); | ||
| const fs = require('fs'); | ||
|
|
||
| // Using latest as default | ||
| const DEFAULT_FUNC_VERSION = 'latest'; | ||
| const DEFAULT_BINARY_SOURCE = 'https://github.com/knative/func/releases/download'; | ||
| const DEFAULT_LATEST_BINARY_SOURCE = 'https://github.com/knative/func/releases/latest/download'; | ||
|
|
||
| // Returns the binary name for the current OS/arch from GitHub releases | ||
| function getOsBinName() { | ||
| const osBinName = core.getInput('binary'); | ||
| if (osBinName !== "") { | ||
|
|
@@ -47,116 +41,90 @@ function resolveFullPathBin() { | |
| return path.resolve(destination, bin); | ||
| } | ||
|
|
||
| // Normalizes version to release tag format: knative-vX.Y.Z | ||
| // Ex.: '1.16' or 'v1.16' will return 'knative-v1.16.0' | ||
| function smartVersionUpdate(version) { | ||
| const versionRegex = /^(?<knprefix>knative-)?(?<prefix>v?)(?<major>\d+)\.(?<minor>\d+)(\.(?<patch>\d+))?$/; | ||
| const match = version.match(versionRegex); | ||
| if (!match) { | ||
| throw new Error(`Invalid version format (${version}). Expected format: "1.16[.X]" or "v1.16[.X]"`); | ||
| const match = version.match(/^(?:knative-)?v?(\d+)\.(\d+)(?:\.(\d+))?$/); | ||
| if (!match) throw new Error(`Invalid version format (${version}). Expected format: "1.16[.X]" or "v1.16[.X]"`); | ||
| return `knative-v${match[1]}.${match[2]}.${match[3] ?? 0}`; | ||
| } | ||
|
|
||
| function resolveVersion() { | ||
| if (core.getInput('binarySource')) return null; | ||
| const version = core.getInput('version') || 'latest'; | ||
| if (version.toLowerCase().trim() === 'latest') return null; | ||
| return smartVersionUpdate(version); | ||
| } | ||
|
|
||
| function resolveDownloadUrl(version, binName) { | ||
| const binarySource = core.getInput('binarySource'); | ||
| if (binarySource) { | ||
| core.info(`Using custom binary source: ${binarySource}`); | ||
| return binarySource; | ||
| } | ||
|
|
||
| if (!version) { | ||
| core.info('Using latest version...'); | ||
| return `https://github.com/knative/func/releases/latest/download/${binName}`; | ||
| } | ||
| const knprefix = 'knative-'; | ||
| const prefix = 'v'; | ||
| const patch = match.groups.patch ?? 0; | ||
| return `${knprefix}${prefix}${match.groups.major}.${match.groups.minor}.${patch}`; | ||
| core.info(`Using specific version ${version}`); | ||
| return `https://github.com/knative/func/releases/download/${version}/${binName}`; | ||
| } | ||
|
|
||
| // Downloads binary from release URL and makes it executable | ||
| async function downloadFuncBinary(url, binPath) { | ||
| core.info(`Downloading from: ${url}`); | ||
|
|
||
| await exec.exec('curl', ['-L', '--fail', '-o', binPath, url]); | ||
|
|
||
| if (!fs.existsSync(binPath)) { | ||
| throw new Error("Download failed, couldn't find the binary on disk"); | ||
| } | ||
|
|
||
| if (process.env.RUNNER_OS !== 'Windows') { | ||
| await exec.exec('chmod', ['+x', binPath]); | ||
| } | ||
| } | ||
|
|
||
| // Adds binary directory to PATH for current and subsequent steps | ||
| function addBinToPath(binPath) { | ||
| const dir = path.dirname(binPath); | ||
| fs.appendFileSync(process.env.GITHUB_PATH, `\n${dir}`); | ||
|
|
||
| if (!process.env.PATH.split(path.delimiter).includes(dir)) { | ||
| process.env.PATH = process.env.PATH + path.delimiter + dir; | ||
| process.env.PATH += path.delimiter + dir; | ||
| core.info(`${dir} added to PATH`); | ||
| } | ||
| } | ||
|
|
||
| // Resolve download url based on given input | ||
| // binName: name of func binary when it is to be constructed for full URL | ||
| // (when not using binarySource) | ||
| function resolveDownloadUrl(binName) { | ||
| const binarySource = core.getInput('binarySource'); | ||
| if (binarySource !== "") { | ||
| core.info(`Using custom binary source: ${binarySource}`); | ||
| return binarySource; | ||
| } | ||
|
|
||
| const versionInput = core.getInput('version') || DEFAULT_FUNC_VERSION; | ||
| if (versionInput.toLowerCase().trim() === DEFAULT_FUNC_VERSION) { | ||
| core.info("Using latest version..."); | ||
| return buildUrlString(DEFAULT_FUNC_VERSION); | ||
| } | ||
| const version = smartVersionUpdate(versionInput); | ||
| core.info(`Using specific version ${version}`); | ||
|
Comment on lines
-105
to
-106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const version = smartVersionUpdate(versionInput);
warnStaleVersion(version);I would put the |
||
| return buildUrlString(version); | ||
|
|
||
| function buildUrlString(version) { | ||
| return version === DEFAULT_FUNC_VERSION | ||
| ? `${DEFAULT_LATEST_BINARY_SOURCE}/${binName}` | ||
| : `${DEFAULT_BINARY_SOURCE}/${version}/${binName}`; | ||
| async function warnStaleVersion(version) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be done a bit simpler using the github redirect to the latest version. No need for JSON etc.: async function getLatestVersion() {
const response = await fetch('https://github.com/knative/func/releases/latest', {
method: 'HEAD',
redirect: 'manual'
});
const location = response.headers.get('location');
// location: "https://github.com/knative/func/releases/tag/knative-v1.21.0"
return location.split('/').pop(); // "knative-v1.21.0"
}Then you can use this function to get the version here: async function warnStaleVersion(version) {
let latestVersion;
try {
latestVersion = getLatestVersion()
} catch (error) {
core.debug(`Failed fetching latest version: ${error.message}`);
return;
}
const offset = 3;
if (hasVersionDrift(latestVersion, version, offset)) {
core.warning(
`You are using func ${version}, which is ${offset} versions behind the latest (${latestVersion}). Upgrading is recommended.`
);
return;
}
core.info(`Using specific version ${version}`);
}
I would change It looks like the time is coming closer for unit tests for this action 😆 .
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the comment does say its a "difference of minor versions" 😄 but i get your point. I didnt take it would be needed any time soon. Will update it. The redirect location is super cool! will update that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You're right of course. My thinking was that if someone adds a very old version for some reason or in future when we have v2+. But you got it 😸 👍 |
||
| try { | ||
| const res = await fetch('https://github.com/knative/func/releases/latest', { | ||
| method: 'HEAD', | ||
| redirect: 'manual', | ||
| }); | ||
| const loc = res.headers.get('location'); | ||
| if (!loc) return; | ||
|
|
||
| const latest = loc.split('/').pop(); | ||
| const toNum = (v) => { const m = v.match(/(\d+)\.(\d+)/); return m && m[1] * 100 + +m[2]; }; | ||
| const diff = toNum(latest) - toNum(version); | ||
|
|
||
| if (diff >= 3) { | ||
| core.warning(`You are using func ${version}, which is ${diff} minor versions behind the latest (${latest}). Upgrading is recommended.`); | ||
| } | ||
| } catch { | ||
| core.debug('Skipping stale version check'); | ||
| } | ||
| } | ||
|
|
||
| async function run() { | ||
| let osBinName; | ||
| try { | ||
| osBinName = getOsBinName(); | ||
| } catch (error) { | ||
| core.setFailed(error.message); | ||
| return; | ||
| } | ||
|
|
||
| let url; | ||
| try { | ||
| url = resolveDownloadUrl(osBinName); | ||
| } catch (error) { | ||
| core.setFailed(`Failed to resolve url: ${error.message}`); | ||
| return; | ||
| } | ||
|
|
||
| let fullPathBin; | ||
| try { | ||
| fullPathBin = resolveFullPathBin(); | ||
| } catch (error) { | ||
| core.setFailed(error.message); | ||
| return; | ||
| } | ||
| const osBinName = getOsBinName(); | ||
| const version = resolveVersion(); | ||
| const url = resolveDownloadUrl(version, osBinName); | ||
| const fullPathBin = resolveFullPathBin(); | ||
|
|
||
| try { | ||
| await downloadFuncBinary(url, fullPathBin); | ||
| } catch (error) { | ||
| core.setFailed(`Download failed: ${error.message}`); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| addBinToPath(fullPathBin); | ||
| } catch (error) { | ||
| core.setFailed(error.message); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| if (version) await warnStaleVersion(version); | ||
| await exec.exec(fullPathBin, ['version']); | ||
| } catch (error) { | ||
| core.setFailed(error.message); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a big change for a small thing => the warning.
I would propose to revert most changes and put a small logic change right after
const version = smartVersionUpdate(versionInput);in line 105.