-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
162 lines (140 loc) · 5.56 KB
/
index.js
File metadata and controls
162 lines (140 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
const core = require('@actions/core');
const exec = require('@actions/exec');
const path = require('path');
const fs = require('fs');
// Using latest as default
const DEFAULT_VERSION = 'latest';
const NIGHTLY_VERSION = 'nightly';
const DEFAULT_BINARY_SOURCE = 'https://github.com/knative/func/releases/download';
const DEFAULT_LATEST_BINARY_SOURCE = 'https://github.com/knative/func/releases/latest/download';
const DEFAULT_NIGHTLY_BINARY_SOURCE = 'https://storage.googleapis.com/knative-nightly/func/latest';
function getOsBinName() {
const osBinName = core.getInput('binary');
if (osBinName) {
return osBinName;
}
const runnerOS = process.env.RUNNER_OS;
const runnerArch = process.env.RUNNER_ARCH;
if (runnerOS === 'Linux') {
switch (runnerArch) {
case 'X64': return 'func_linux_amd64';
case 'ARM64': return 'func_linux_arm64';
case 'PPC64LE': return 'func_linux_ppc64le';
case 'S390X': return 'func_linux_s390x';
default: throw new Error(`unknown runner arch: ${runnerArch}`);
}
} else if (runnerOS === 'macOS') {
return runnerArch === 'X64' ? 'func_darwin_amd64' : 'func_darwin_arm64';
} else if (runnerOS === 'Windows') {
return 'func_windows_amd64.exe';
} else {
throw new Error(`unknown runner os: ${runnerOS}`);
}
}
function resolveFullPathBin() {
const destination = core.getInput('destination') || process.cwd();
let bin = core.getInput('name') || 'func';
if (process.env.RUNNER_OS === 'Windows' && !bin.endsWith('.exe')) {
bin += '.exe';
}
if (!fs.existsSync(destination)) {
fs.mkdirSync(destination, { recursive: true });
}
return path.resolve(destination, bin);
}
function smartVersionUpdate(version) {
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() {
const version = core.getInput('version') || DEFAULT_VERSION;
if (version.toLowerCase().trim() === DEFAULT_VERSION) return DEFAULT_VERSION;
if (version.toLowerCase().trim() === NIGHTLY_VERSION) return NIGHTLY_VERSION;
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 === NIGHTLY_VERSION) {
core.info('Using nightly version...');
return `${DEFAULT_NIGHTLY_BINARY_SOURCE}/${binName}`;
}
if (version === DEFAULT_VERSION) {
core.info('Using latest version...');
return `${DEFAULT_LATEST_BINARY_SOURCE}/${binName}`;
}
core.info(`Using specific version ${version}`);
return `${DEFAULT_BINARY_SOURCE}/${version}/${binName}`;
}
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]);
}
}
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 += path.delimiter + dir;
core.info(`${dir} added to PATH`);
}
}
async function warnStaleVersion(version) {
// Skip version check for 'latest' or custom binary source
if (version === DEFAULT_VERSION || core.getInput('binarySource')) {
return;
}
let res;
try {
res = await fetch('https://github.com/knative/func/releases/latest', {
method: 'HEAD',
redirect: 'manual',
});
} catch (error) {
core.warning(`Failed to fetch latest version: ${error.message}`);
core.debug('Skipping stale version check');
return;
}
const loc = res.headers.get('location');
if (!loc) {
core.warning('Could not determine latest version: no redirect location');
core.debug('Skipping stale version check');
return;
}
const latest = loc.split('/').pop();
// Convert version string "vX.Y" to number (X*100 + Y) for comparison,
// e.g. "v1.21" → 121.
// Returns null if no match, otherwise multiplies major by 100 and adds minor
// (+ coerces string to number).
const toNum = (v) => { const m = v.match(/(\d+)\.(\d+)/); return m && m[1] * 100 + +m[2]; };
const latestNum = toNum(latest);
const versionNum = toNum(version);
if (versionNum == null || latestNum == null) {
core.debug('could not parse version numbers to compare');
return;
}
const diff = latestNum - versionNum;
if (diff >= 3) {
core.warning(`You are using func ${version}, which is ${diff} minor versions behind the latest (${latest}). Upgrading is recommended.`);
}
}
async function run() {
const osBinName = getOsBinName();
const version = resolveVersion();
await warnStaleVersion(version);
const url = resolveDownloadUrl(version, osBinName);
const fullPathBin = resolveFullPathBin();
await downloadFuncBinary(url, fullPathBin);
addBinToPath(fullPathBin);
await exec.exec(fullPathBin, ['version']);
}
run().catch(error => core.setFailed(error.message));