diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 455c363..b0c728c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,7 @@ jobs: laz-url: https://sourceforge.net/projects/lazarus/files/Lazarus%20macOS%20x86-64/Lazarus%202.2.2/Lazarus-2.2.2-0-x86_64-macosx.pkg fpc-url: | https://sourceforge.net/projects/lazarus/files/Lazarus%20macOS%20x86-64/Lazarus%202.2.2/fpc-3.2.2.intelarm64-macosx.dmg - https://sourceforge.net/projects/lazarus/files/Lazarus%20macOS%20x86-64/Lazarus%202.2.2/fpc-src-3.2.2-20210709-macosx.dmg + https://sourceforge.net/projects/lazarus/files/Lazarus%20macOS%20x86-64/Lazarus%202.2.2/fpc-src-3.2.2-20210709-macosx.dmg steps: - uses: actions/checkout@v3.0.2 diff --git a/action.yml b/action.yml index dfb43fa..53fcf83 100644 --- a/action.yml +++ b/action.yml @@ -1,6 +1,9 @@ name: 'Setup Lazarus' description: 'Setup Lazarus using installers from sourceforge' inputs: + use-cache: + required: false + default: 'true' laz-url: required: true fpc-url: @@ -9,6 +12,6 @@ runs: using: 'node16' main: 'dist/index/index.js' post: 'dist/post/index.js' - post-if: env.SAVE_CACHE_KEY != '' + post-if: success() && env.SAVE_CACHE_KEY != '' diff --git a/dist/index/index.js b/dist/index/index.js index 6a04f70..9698aa5 100644 --- a/dist/index/index.js +++ b/dist/index/index.js @@ -47346,6 +47346,14 @@ function regExpEscape (s) { } +/***/ }), + +/***/ 5775: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; +Object.defineProperty(exports, "__esModule", ({value:!0})),exports.DownloaderHelper=exports.DH_STATES=void 0;var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&'function'==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?'symbol':typeof a},_createClass=function(){function a(a,b){for(var c,d=0;dthis.__opts.progressThrottle)&&(this.__opts.progressThrottle=this.__defaultOpts.progressThrottle),this.__options=this.__getOptions(this.__opts.method,this.url,this.__opts.headers),this.__initProtocol(this.url)}},{key:'getStats',value:function a(){return{total:this.__total,name:this.__fileName,downloaded:this.__downloaded,progress:this.__progress,speed:this.__statsEstimate.bytes}}},{key:'getTotalSize',value:function c(){var a=this,b=Object.assign({},this.__headers);return b.hasOwnProperty('range')&&delete b.range,new Promise(function(c,d){var e=function(f,g){var h=a.__protocol.request(g,function(g){if(a.__isRequireRedirect(g)){var h=/^https?:\/\//.test(g.headers.location)?g.headers.location:new _url.URL(g.headers.location,f).href;return e(h,a.__getOptions('HEAD',h,b))}return 200===g.statusCode?void c({name:a.__getFileNameFromHeaders(g.headers,g),total:parseInt(g.headers['content-length'])||null}):d(new Error('Response status was '+g.statusCode))});h.on('error',function(a){return d(a)}),h.on('timeout',function(){return d(new Error('timeout'))}),h.on('uncaughtException',function(a){return d(a)}),h.end()};e(a.url,a.__getOptions('HEAD',a.url,b))})}},{key:'getResumeState',value:function a(){return{downloaded:this.__downloaded,filePath:this.__filePath,fileName:this.__fileName,total:this.__total}}},{key:'resumeFromFile',value:function d(a){var b=this,c=1=g))return this.emit('skip',{totalSize:this.__total,fileName:this.__fileName,filePath:this.__filePath,downloadedSize:f}),this.__setState(this.__states.SKIPPED),b(!0)}this.__fileStream=fs.createWriteStream(this.__filePath,{})}else this.__fileStream=fs.createWriteStream(this.__filePath,{flags:'a'});this.emit('download',{fileName:this.__fileName,filePath:this.__filePath,totalSize:this.__total,isResumed:this.__isResumed,downloadedSize:this.__downloaded}),this.__retryCount=0,this.__isResumed=!1,this.__isRedirected=!1,this.__setState(this.__states.DOWNLOADING),this.__statsEstimate.time=new Date,this.__statsEstimate.throttleTime=new Date,e.on('data',function(a){return d.__calculateStats(a.length)}),this.__pipes.forEach(function(a){e.pipe(a.stream,a.options),e=a.stream}),e.pipe(this.__fileStream),e.on('error',this.__onError(b,c)),this.__fileStream.on('finish',this.__onFinished(b,c)),this.__fileStream.on('error',this.__onError(b,c))}},{key:'__hasFinished',value:function a(){return this.state!==this.__states.PAUSED&&this.state!==this.__states.STOPPED&&this.state!==this.__states.RETRY&&this.state!==this.__states.FAILED}},{key:'__isRequireRedirect',value:function b(a){return 300a.statusCode&&a.headers.hasOwnProperty('location')&&a.headers.location}},{key:'__onFinished',value:function d(a,b){var c=this;return function(){c.__fileStream.close(function(d){return d?b(d):(c.__hasFinished()&&(c.__setState(c.__states.FINISHED),c.__pipes=[],c.emit('end',{fileName:c.__fileName,filePath:c.__filePath,totalSize:c.__total,incomplete:!!c.__total&&c.__downloaded!==c.__total,onDiskSize:c.__getFilesizeInBytes(c.__filePath),downloadedSize:c.__downloaded})),a(c.__downloaded===c.__total))})}}},{key:'__closeFileStream',value:function b(){var a=this;return this.__fileStream?new Promise(function(b,c){a.__fileStream.close(function(a){return a?c(a):b(!0)})}):Promise.resolve(!0)}},{key:'__onError',value:function e(a,b){var c=this,d=!!(2=this.__opts.retry.maxRetries?Promise.reject(b?b:new Error('reached the maximum retries')):(this.__retryCount++,this.__setState(this.__states.RETRY),this.emit('retry',this.__retryCount,this.__opts.retry,b),new Promise(function(b){return setTimeout(function(){return b(0this.__opts.progressThrottle)&&(this.__statsEstimate.throttleTime=b,this.emit('progress.throttled',this.getStats())),this.emit('progress',this.getStats()))}},{key:'__setState',value:function b(a){this.state=a,this.emit('stateChanged',this.state)}},{key:'__getOptions',value:function f(a,b){var c=2 setTimeout(resolve, millis)); +} + +async function downloadInstaller(url) { + + success = false + + options = { + fileName: { name: path.basename(url), ext: true }, + retry: { maxRetries: 5, delay: 3000 }, + override: true + } + + console.log('Downloading: ' + url); + + for (var retry = 0; retry < 20; retry++) { + + console.log('Retry: ' + retry); + + dl = new DownloaderHelper(url, installersLocation(), options); + dl.on('error', (e) => { console.log('Download error: ' + e.status) }); + dl.on("end", () => { console.log('Download complete'); success = true }); + dl.on('progress.throttled', (stats) => console.log('Download progress: ' + Math.round(stats.progress) + '%')); + + try { + await dl.start(); + } + catch(err) { + console.log('Errored') + } + + if (success) { + break; + } + + await sleep(3000); + } + + return success; } async function install_macos(file) { @@ -60527,17 +60588,24 @@ async function install_linux(file) { async function install_windows(file) { - await exec.exec(file + ' /VERYSILENT /DIR=' + path.join(process.env['RUNNER_TEMP'], 'lazarus')); + await exec.exec(file + ' /VERYSILENT /DIR=' + installedLocation()); } -async function install(url) { +async function install(url, download) { if (url == '') { return } - filename = await download_installer(url); - + filename = path.join(installersLocation(), path.basename(url)); + + if (download) { + const downloaded = await downloadInstaller(url); + if (!downloaded) { + throw new Error('Failed to download: ' + url); + } + } + switch (os.platform()) { case 'linux': await install_linux(filename); @@ -60556,28 +60624,29 @@ async function install(url) { async function run() { try { + await exec.exec('mkdir -p ' + installersLocation()); + if (os.platform() == 'linux') { await exec.exec('sudo apt-get update'); - } - - await restore_installers() + } + + var cacheLoaded = false; + if (useCache()) { + cacheLoaded = await cache.restoreCache([installersLocation()], cacheKey()) != null; + if (!cacheLoaded) { + core.exportVariable('SAVE_CACHE_DIR', installersLocation()); + core.exportVariable('SAVE_CACHE_KEY', cacheKey()); + } + } - for (const url of core.getInput('fpc-url').split(os.EOL)) { - await install(url); + for (const url of fpcURL()) { + await install(url, cacheLoaded == false); } - for (const url of core.getInput('laz-url').split(os.EOL)) { - await install(url); + for (const url of lazURL()) { + await install(url, cacheLoaded == false); } - switch (os.platform()) { - case 'win32': - core.addPath(path.join(process.env['RUNNER_TEMP'], 'lazarus')); - break; - - case 'darwin': - core.addPath('/Applications/Lazarus'); - break; - } + core.addPath(installedLocation()); } catch (error) { core.setFailed(error.message); } diff --git a/package-lock.json b/package-lock.json index c54bafe..8e0feaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,12 +15,13 @@ "@actions/tool-cache": "^2.0.1", "base-64": "^1.0.0", "fs": "0.0.1-security", + "node-downloader-helper": "^2.1.1", "os": "^0.1.2", "path": "^0.12.7", "process": "^0.11.10" }, "devDependencies": { - "@vercel/ncc": "^0.33.4" + "@vercel/ncc": "^0.34.0" } }, "node_modules/@actions/cache": { @@ -345,9 +346,9 @@ } }, "node_modules/@vercel/ncc": { - "version": "0.33.4", - "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.33.4.tgz", - "integrity": "sha512-ln18hs7dMffelP47tpkaR+V5Tj6coykNyxJrlcmCormPqRQjB/Gv4cu2FfBG+PMzIfdZp2CLDsrrB1NPU22Qhg==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz", + "integrity": "sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A==", "dev": true, "bin": { "ncc": "dist/ncc/cli.js" @@ -489,6 +490,17 @@ "node": "*" } }, + "node_modules/node-downloader-helper": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-downloader-helper/-/node-downloader-helper-2.1.1.tgz", + "integrity": "sha512-ouk8MGmJj1gYymbJwi1L8Mr6PdyheJLwfsmyx0KtsvyJ+7Fpf0kBBzM8Gmx8Mt/JBfRWP1PQm6dAGV6x7eNedw==", + "bin": { + "ndh": "bin/ndh" + }, + "engines": { + "node": ">=14.18" + } + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -948,9 +960,9 @@ } }, "@vercel/ncc": { - "version": "0.33.4", - "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.33.4.tgz", - "integrity": "sha512-ln18hs7dMffelP47tpkaR+V5Tj6coykNyxJrlcmCormPqRQjB/Gv4cu2FfBG+PMzIfdZp2CLDsrrB1NPU22Qhg==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz", + "integrity": "sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A==", "dev": true }, "abort-controller": { @@ -1059,6 +1071,11 @@ "brace-expansion": "^1.1.7" } }, + "node-downloader-helper": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-downloader-helper/-/node-downloader-helper-2.1.1.tgz", + "integrity": "sha512-ouk8MGmJj1gYymbJwi1L8Mr6PdyheJLwfsmyx0KtsvyJ+7Fpf0kBBzM8Gmx8Mt/JBfRWP1PQm6dAGV6x7eNedw==" + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", diff --git a/package.json b/package.json index 5dc771d..c746221 100644 --- a/package.json +++ b/package.json @@ -24,11 +24,12 @@ "@actions/tool-cache": "^2.0.1", "base-64": "^1.0.0", "fs": "0.0.1-security", + "node-downloader-helper": "^2.1.1", "os": "^0.1.2", "path": "^0.12.7", "process": "^0.11.10" }, "devDependencies": { - "@vercel/ncc": "^0.33.4" + "@vercel/ncc": "^0.34.0" } } diff --git a/source/main.js b/source/main.js index 8c2fa5c..12aa913 100644 --- a/source/main.js +++ b/source/main.js @@ -6,39 +6,92 @@ const path = require('path'); const os = require('os'); const fs = require('fs'); const base64 = require('base-64'); +const { DownloaderHelper } = require('node-downloader-helper'); -const cache_key = base64.encode(core.getInput('laz-url') + core.getInput('fpc-url')) -const installer_dir = path.join(process.env['RUNNER_TEMP'], 'installers') +function installersLocation() { -async function restore_installers() { - - await exec.exec('mkdir -p ' + installer_dir); - await cache.restoreCache([installer_dir], cache_key) != null; + return path.join(process.env['RUNNER_TEMP'], 'installers'); } -async function check_installer(filename) { +function installedLocation() { + + switch (os.platform()) { + case 'linux': + return ''; + break; + + case 'win32': + return path.join(process.env['RUNNER_TEMP'], 'lazarus'); + break; - if (fs.existsSync(filename) && (fs.statSync(filename).size == 0)) { - fs.unlinkSync(filename); + case 'darwin': + return '/Applications/Lazarus/'; + break; } +} + +function useCache() { - return fs.existsSync(filename); + return core.getInput('use-cache').toUpperCase() == 'TRUE'; } -async function download_installer(url) { +function lazURL() { - filename = path.join(installer_dir, path.basename(url)); + return core.getInput('laz-url').split(os.EOL); +} - if (await check_installer(filename) == false) { - await exec.exec('curl --progress-bar -L -o "' + filename + '" ' + url); +function fpcURL() { - if (await check_installer(filename)) { - core.exportVariable('SAVE_CACHE_DIR', installer_dir); - core.exportVariable('SAVE_CACHE_KEY', cache_key); - } - } + return core.getInput('fpc-url').split(os.EOL); +} + +function cacheKey() { + + return base64.encode(core.getInput('laz-url') + '-' + core.getInput('fpc-url')); +} + + +function sleep(millis) { + + return new Promise(resolve => setTimeout(resolve, millis)); +} - return filename; +async function downloadInstaller(url) { + + success = false + + options = { + fileName: { name: path.basename(url), ext: true }, + retry: { maxRetries: 5, delay: 3000 }, + override: true + } + + console.log('Downloading: ' + url); + + for (var retry = 0; retry < 20; retry++) { + + console.log('Retry: ' + retry); + + dl = new DownloaderHelper(url, installersLocation(), options); + dl.on('error', (e) => { console.log('Download error: ' + e.status) }); + dl.on("end", () => { console.log('Download complete'); success = true }); + dl.on('progress.throttled', (stats) => console.log('Download progress: ' + Math.round(stats.progress) + '%')); + + try { + await dl.start(); + } + catch(err) { + console.log('Errored') + } + + if (success) { + break; + } + + await sleep(3000); + } + + return success; } async function install_macos(file) { @@ -82,17 +135,24 @@ async function install_linux(file) { async function install_windows(file) { - await exec.exec(file + ' /VERYSILENT /DIR=' + path.join(process.env['RUNNER_TEMP'], 'lazarus')); + await exec.exec(file + ' /VERYSILENT /DIR=' + installedLocation()); } -async function install(url) { +async function install(url, download) { if (url == '') { return } - filename = await download_installer(url); - + filename = path.join(installersLocation(), path.basename(url)); + + if (download) { + const downloaded = await downloadInstaller(url); + if (!downloaded) { + throw new Error('Failed to download: ' + url); + } + } + switch (os.platform()) { case 'linux': await install_linux(filename); @@ -111,28 +171,29 @@ async function install(url) { async function run() { try { + await exec.exec('mkdir -p ' + installersLocation()); + if (os.platform() == 'linux') { await exec.exec('sudo apt-get update'); + } + + var cacheLoaded = false; + if (useCache()) { + cacheLoaded = await cache.restoreCache([installersLocation()], cacheKey()) != null; + if (!cacheLoaded) { + core.exportVariable('SAVE_CACHE_DIR', installersLocation()); + core.exportVariable('SAVE_CACHE_KEY', cacheKey()); + } + } + + for (const url of fpcURL()) { + await install(url, cacheLoaded == false); } - - await restore_installers() - - for (const url of core.getInput('fpc-url').split(os.EOL)) { - await install(url); + for (const url of lazURL()) { + await install(url, cacheLoaded == false); } - for (const url of core.getInput('laz-url').split(os.EOL)) { - await install(url); - } - - switch (os.platform()) { - case 'win32': - core.addPath(path.join(process.env['RUNNER_TEMP'], 'lazarus')); - break; - case 'darwin': - core.addPath('/Applications/Lazarus'); - break; - } + core.addPath(installedLocation()); } catch (error) { core.setFailed(error.message); }