From 331fadb4b31a8f0d6ac75211c724b3e593700563 Mon Sep 17 00:00:00 2001 From: Boris Stepanenko Date: Mon, 19 Sep 2022 17:43:04 +0300 Subject: [PATCH 1/2] feature: use lsb_release to identify distro id This should make this action usable on any debian-based distros. --- dist/main/index.js | 14 ++++++++++++-- src/main.ts | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/dist/main/index.js b/dist/main/index.js index 981f2df..106cb2f 100644 --- a/dist/main/index.js +++ b/dist/main/index.js @@ -62353,6 +62353,13 @@ async function lsb_release() { } return _lsb_release; } +let _lsb_release_id; +async function lsb_release_id() { + if (!_lsb_release_id) { + _lsb_release_id = capture('lsb_release -i -s', { silent: true }); + } + return _lsb_release_id; +} let _httpc; async function http_get(url) { if (!_httpc) { @@ -62425,7 +62432,9 @@ function construct_base_url() { } async function available_versions(version_prefix) { const baseUrl = construct_base_url(); - const repo = baseUrl + '/ubuntu/dists/' + (await lsb_release()); + const distro = await lsb_release(); + const distro_id = (await lsb_release_id()).toLowerCase(); + const repo = baseUrl + '/' + distro_id + '/dists/' + distro; // Don't return 1.10.10, when the version prefix is 1.10.1. const prefix = version_prefix ? version_prefix + '.' : ''; return http_get(`${repo}/main/binary-amd64/Packages`) @@ -62465,6 +62474,7 @@ exports.latest_version = latest_version; async function run_linux() { try { const distro = await lsb_release(); + const distro_id = (await lsb_release_id()).toLowerCase(); const cache_dir = 'cache-tarantool'; const baseUrl = construct_base_url(); core.startGroup(`Checking latest tarantool ${tarantool_version} version`); @@ -62496,7 +62506,7 @@ async function run_linux() { }); await core.group('Setting up repository', async () => { await exec.exec('sudo tee /etc/apt/sources.list.d/tarantool.list', [], { - input: Buffer.from(`deb ${baseUrl}/ubuntu/ ${distro} main\n`) + input: Buffer.from(`deb ${baseUrl}/${distro_id}/ ${distro} main\n`) }); }); await core.group('Running apt-get update', async () => { diff --git a/src/main.ts b/src/main.ts index 859c656..dd8e9d0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -40,6 +40,15 @@ async function lsb_release(): Promise { return _lsb_release } +let _lsb_release_id: Promise +async function lsb_release_id(): Promise { + if (!_lsb_release_id) { + _lsb_release_id = capture('lsb_release -i -s', {silent: true}) + } + + return _lsb_release_id +} + let _httpc: httpm.HttpClient async function http_get(url: string): Promise { if (!_httpc) { @@ -119,7 +128,9 @@ async function available_versions( version_prefix: string ): Promise> { const baseUrl = construct_base_url() - const repo = baseUrl + '/ubuntu/dists/' + (await lsb_release()) + const distro = await lsb_release() + const distro_id = (await lsb_release_id()).toLowerCase() + const repo = baseUrl + '/' + distro_id + '/dists/' + distro // Don't return 1.10.10, when the version prefix is 1.10.1. const prefix = version_prefix ? version_prefix + '.' : '' @@ -162,6 +173,7 @@ export async function latest_version(version_prefix: string): Promise { async function run_linux(): Promise { try { const distro = await lsb_release() + const distro_id = (await lsb_release_id()).toLowerCase() const cache_dir = 'cache-tarantool' const baseUrl = construct_base_url() @@ -197,7 +209,7 @@ async function run_linux(): Promise { await core.group('Setting up repository', async () => { await exec.exec('sudo tee /etc/apt/sources.list.d/tarantool.list', [], { - input: Buffer.from(`deb ${baseUrl}/ubuntu/ ${distro} main\n`) + input: Buffer.from(`deb ${baseUrl}/${distro_id}/ ${distro} main\n`) }) }) From dbb505ac00d430f53e69a40f393d27ae3140f247 Mon Sep 17 00:00:00 2001 From: Boris Stepanenko Date: Tue, 20 Sep 2022 13:37:47 +0300 Subject: [PATCH 2/2] bugfix: catch io.cp error In ubuntu:22.04 docker man dpkg contains followng: "-L|--listfiles ... List files 'owned' by package(s)." dpkg -L cmake mentions file /usr/share/doc/cmake/NEWS.Debian.gz, which is not present in the system after successful apt-get -y install cmake. This led to setup-tarantool failing during packaging cache. This patch catches error while calling io.cp and prints it as a warning. --- src/main.ts | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/main.ts b/src/main.ts index dd8e9d0..96b1e07 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,6 +16,11 @@ interface CaptureOptions { silent?: boolean } +interface DpkgConfig { + excludes: RegExp[]; + includes: RegExp[]; +} + async function capture(cmd: string, options?: CaptureOptions): Promise { let output = '' @@ -170,6 +175,90 @@ export async function latest_version(version_prefix: string): Promise { }) } +function glob_to_regex(glob: string): RegExp { + return new RegExp(glob + .replace(/\./g, '\\.') + .replace(/\*/g, '.*') + .replace(/\?/g, '.') + ); +} + +function list_files_in_dir(directory: string, files: string[] = []): string[] { + fs.readdirSync(directory).forEach(file => { + const p = path.join(directory, file); + if (fs.statSync(p).isDirectory()) { + return list_files_in_dir(p, files); + } else { + return files.push(p); + } + }); + + return files; +} + +function dpkg_read_config(): DpkgConfig { + const dpkgConfigFilepath = 'excludes'; + const dpkgConfigDirPath = 'excludes.d'; + + const configs = list_files_in_dir(dpkgConfigDirPath, [dpkgConfigFilepath]); + + const dpkgConfig: DpkgConfig = { + excludes: [], + includes: [], + }; + + configs.forEach((config) => { + try { + const dpkgExcludesFile = fs.readFileSync(config, 'utf8'); + dpkgExcludesFile.split('\n').forEach((line) => { + // Exclude + const excludePattern = 'path-exclude='; + if (line.startsWith(excludePattern)) { + const regex = glob_to_regex(line.substring(excludePattern.length)); + dpkgConfig.excludes.push(regex); + return; + } + + // Include + const includePattern = 'path-include='; + if (line.startsWith(includePattern)) { + const regex = glob_to_regex(line.substring(includePattern.length)); + dpkgConfig.includes.push(regex); + return; + } + }); + } catch (err) { + core.info(`dpkg excludes file not available: ${err}`); + } + }); + + return dpkgConfig; +} + +function dpkg_is_file_included(dpkgConfig: DpkgConfig, filepath: string): boolean { + var included = true; + + dpkgConfig.excludes.forEach((exclude) => { + if (exclude.test(filepath)) { + included = false; + return; + } + }); + + if (included) { + return true; + } + + dpkgConfig.includes.forEach((include) => { + if (include.test(filepath)) { + included = true; + return; + } + }); + + return included; +}; + async function run_linux(): Promise { try { const distro = await lsb_release() @@ -234,10 +323,12 @@ async function run_linux(): Promise { core.info('Caching APT packages: ' + dpkg_diff.join(', ')) for (const pkg of dpkg_diff) { + const dpkgConfig = dpkg_read_config(); const output = await capture(`sudo dpkg -L ${pkg}`, {silent: true}) const files: Array = output .split('\n') .filter(f => fs.statSync(f).isFile()) + .filter(f => dpkg_is_file_included(dpkgConfig, f)) for (const f of files) { const dest = path.join(cache_dir, path.dirname(f)) await io.mkdirP(dest)