5
0
mirror of https://gitea.com/actions/setup-python.git synced 2026-06-20 02:31:17 +00:00

Add RHEL support and include Linux distro in cache keys (#1323)

* Add RHEL support for manifest matching and OS detection

* update dist

* make cache keys distro-aware and key RHEL by major version

* Normalize RHEL OS detection and improve cache key consistency

* Refactor OS info retrieval to use getOSInfo and handle null cases for improved reliability
This commit is contained in:
Priya Gupta
2026-06-19 05:17:28 +05:30
committed by GitHub
parent c8813ba1bc
commit 0cb1a84326
9 changed files with 5612 additions and 52 deletions
+6 -13
View File
@@ -190,19 +190,12 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
restoredKeys.forEach(restoredKey => { restoredKeys.forEach(restoredKey => {
if (restoredKey) { if (restoredKey) {
if (process.platform === 'linux' && packageManager === 'pip') { const osSegment =
expect(infoSpy).toHaveBeenCalledWith( process.platform === 'linux' ? '-20.04-Ubuntu' : '';
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-${process.arch}-20.04-Ubuntu-python-${pythonVersion}-${packageManager}-${fileHash}` const versionSuffix = packageManager === 'poetry' ? '-v2' : '';
); expect(infoSpy).toHaveBeenCalledWith(
} else if (packageManager === 'poetry') { `Cache restored from key: setup-python-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${pythonVersion}-${packageManager}${versionSuffix}-${fileHash}`
expect(infoSpy).toHaveBeenCalledWith( );
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-${process.arch}-python-${pythonVersion}-${packageManager}-v2-${fileHash}`
);
} else {
expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-${process.arch}-python-${pythonVersion}-${packageManager}-${fileHash}`
);
}
} else { } else {
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`${packageManager} cache is not found` `${packageManager} cache is not found`
+5342
View File
File diff suppressed because it is too large Load Diff
+114 -19
View File
@@ -53813,6 +53813,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.State = void 0; exports.State = void 0;
const cache = __importStar(__nccwpck_require__(5116)); const cache = __importStar(__nccwpck_require__(5116));
const core = __importStar(__nccwpck_require__(37484)); const core = __importStar(__nccwpck_require__(37484));
const utils_1 = __nccwpck_require__(71798);
const constants_1 = __nccwpck_require__(10565); const constants_1 = __nccwpck_require__(10565);
var State; var State;
(function (State) { (function (State) {
@@ -53829,6 +53830,28 @@ class CacheDistributor {
this.cacheDependencyPath = cacheDependencyPath; this.cacheDependencyPath = cacheDependencyPath;
} }
async handleLoadedCache() { } async handleLoadedCache() { }
/**
* Builds the Linux distro portion of a cache key (e.g. `-26.04-Ubuntu`, `-9-rhel`).
* RHEL is keyed by major version since it ships one ABI-stable artifact per major.
*/
async getLinuxInfoKeySegment() {
if (!utils_1.IS_LINUX) {
return '';
}
const osInfo = await (0, utils_1.getOSInfo)();
if (!osInfo) {
return '';
}
// lsb_release reports RHEL as "RedHatEnterpriseLinux" while /etc/os-release
// reports it as "rhel"; normalize both to "rhel" so the key is consistent.
const normalizedName = osInfo.osName.toLowerCase();
const isRhel = normalizedName === 'rhel' || normalizedName.includes('redhat');
const osName = isRhel ? 'rhel' : osInfo.osName;
const osVersion = isRhel
? osInfo.osVersion.split('.')[0]
: osInfo.osVersion;
return `-${osVersion}-${osName}`;
}
async restoreCache() { async restoreCache() {
const { primaryKey, restoreKey } = await this.computeKeys(); const { primaryKey, restoreKey } = await this.computeKeys();
if (primaryKey.endsWith('-')) { if (primaryKey.endsWith('-')) {
@@ -54011,17 +54034,9 @@ class PipCache extends cache_distributor_1.default {
async computeKeys() { async computeKeys() {
const hash = (await glob.hashFiles(this.cacheDependencyPath)) || const hash = (await glob.hashFiles(this.cacheDependencyPath)) ||
(await glob.hashFiles(this.cacheDependencyBackupPath)); (await glob.hashFiles(this.cacheDependencyBackupPath));
let primaryKey = ''; const osSegment = await this.getLinuxInfoKeySegment();
let restoreKey = ''; const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
if (utils_1.IS_LINUX) { const restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}`;
const osInfo = await (0, utils_1.getLinuxInfo)();
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}`;
}
else {
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}`;
}
return { return {
primaryKey, primaryKey,
restoreKey: [restoreKey] restoreKey: [restoreKey]
@@ -54105,7 +54120,8 @@ class PipenvCache extends cache_distributor_1.default {
} }
async computeKeys() { async computeKeys() {
const hash = await glob.hashFiles(this.patterns); const hash = await glob.hashFiles(this.patterns);
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}-${hash}`; const osSegment = await this.getLinuxInfoKeySegment();
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
const restoreKey = undefined; const restoreKey = undefined;
return { return {
primaryKey, primaryKey,
@@ -54197,8 +54213,9 @@ class PoetryCache extends cache_distributor_1.default {
} }
async computeKeys() { async computeKeys() {
const hash = await glob.hashFiles(this.patterns); const hash = await glob.hashFiles(this.patterns);
const osSegment = await this.getLinuxInfoKeySegment();
// "v2" is here to invalidate old caches of this cache distributor, which were created broken: // "v2" is here to invalidate old caches of this cache distributor, which were created broken:
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}-v2-${hash}`; const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-v2-${hash}`;
const restoreKey = undefined; const restoreKey = undefined;
return { return {
primaryKey, primaryKey,
@@ -55275,6 +55292,8 @@ const core = __importStar(__nccwpck_require__(37484));
const tc = __importStar(__nccwpck_require__(33472)); const tc = __importStar(__nccwpck_require__(33472));
const exec = __importStar(__nccwpck_require__(95236)); const exec = __importStar(__nccwpck_require__(95236));
const httpm = __importStar(__nccwpck_require__(54844)); const httpm = __importStar(__nccwpck_require__(54844));
const fs = __importStar(__nccwpck_require__(79896));
const semver = __importStar(__nccwpck_require__(62088));
const utils_1 = __nccwpck_require__(71798); const utils_1 = __nccwpck_require__(71798);
const TOKEN = core.getInput('token'); const TOKEN = core.getInput('token');
const AUTH = !TOKEN ? undefined : `token ${TOKEN}`; const AUTH = !TOKEN ? undefined : `token ${TOKEN}`;
@@ -55282,10 +55301,69 @@ const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions'; const MANIFEST_REPO_NAME = 'python-versions';
const MANIFEST_REPO_BRANCH = 'main'; const MANIFEST_REPO_BRANCH = 'main';
exports.MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`; exports.MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
function getLinuxOsRelease() {
try {
const content = fs.readFileSync('/etc/os-release', 'utf8');
const lines = content.split('\n');
let id = '';
let versionId = '';
for (const line of lines) {
const parts = line.split('=');
if (parts.length === 2) {
const key = parts[0].trim();
const value = parts[1].trim().replace(/^"/, '').replace(/"$/, '');
if (key === 'ID')
id = value;
if (key === 'VERSION_ID')
versionId = value;
}
}
if (id && versionId) {
return { id, versionId };
}
return null;
}
catch {
return null;
}
}
function findRhelRelease(semanticVersionSpec, architecture, manifest, osVersion) {
for (const candidate of manifest) {
const version = candidate.version;
core.debug(`check ${version} satisfies ${semanticVersionSpec}`);
if (!semver.satisfies(version, semanticVersionSpec))
continue;
const file = candidate.files.find(item => {
core.debug(`${item.arch}===${architecture} && ${item.platform}===rhel && ${item.platform_version}===${osVersion}`);
const archMatch = item.arch === architecture;
const platformMatch = item.platform === 'rhel';
const versionMatch = !item.platform_version ||
item.platform_version === osVersion ||
osVersion.startsWith(item.platform_version);
return archMatch && platformMatch && versionMatch;
});
if (file) {
core.debug(`matched ${candidate.version}`);
const result = Object.assign({}, candidate);
result.files = [file];
return result;
}
}
return undefined;
}
async function findReleaseFromManifest(semanticVersionSpec, architecture, manifest) { async function findReleaseFromManifest(semanticVersionSpec, architecture, manifest) {
if (!manifest) { if (!manifest) {
manifest = await getManifest(); manifest = await getManifest();
} }
// On RHEL, tc.findFromManifest() won't match because os.platform() returns 'linux'
// but manifest entries use platform 'rhel'. Use custom filtering for RHEL.
if (utils_1.IS_LINUX) {
const osRelease = getLinuxOsRelease();
if (osRelease && osRelease.id === 'rhel') {
core.debug(`Detected RHEL ${osRelease.versionId}, using custom manifest filtering`);
return findRhelRelease(semanticVersionSpec, architecture, manifest, osRelease.versionId);
}
}
const foundRelease = await tc.findFromManifest(semanticVersionSpec, false, manifest, architecture); const foundRelease = await tc.findFromManifest(semanticVersionSpec, false, manifest, architecture);
return foundRelease; return foundRelease;
} }
@@ -55743,12 +55821,29 @@ async function getMacOSInfo() {
return { osName: 'macOS', osVersion: macOSVersion }; return { osName: 'macOS', osVersion: macOSVersion };
} }
async function getLinuxInfo() { async function getLinuxInfo() {
const { stdout } = await exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { try {
silent: true const { stdout } = await exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], {
}); silent: true
const [osName, osVersion] = stdout.trim().split('\n'); });
core.debug(`OS Name: ${osName}, Version: ${osVersion}`); const [osName, osVersion] = stdout.trim().split('\n');
return { osName: osName, osVersion: osVersion }; core.debug(`OS Name: ${osName}, Version: ${osVersion}`);
return { osName, osVersion };
}
catch (err) {
core.debug(`lsb_release failed (${err.message}). Falling back to /etc/os-release.`);
const osReleaseContent = fs_1.default.readFileSync('/etc/os-release', 'utf8');
const osInfo = {};
osReleaseContent.split('\n').forEach(line => {
const [key, value] = line.split('=');
if (key && value) {
osInfo[key.trim()] = value.trim().replace(/"/g, '');
}
});
const osName = osInfo['ID'] || 'Linux';
const osVersion = osInfo['VERSION_ID'] || '';
core.debug(`OS Name: ${osName}, Version: ${osVersion}`);
return { osName, osVersion };
}
} }
async function getOSInfo() { async function getOSInfo() {
let osInfo; let osInfo;
@@ -1,5 +1,6 @@
import * as cache from '@actions/cache'; import * as cache from '@actions/cache';
import * as core from '@actions/core'; import * as core from '@actions/core';
import {getOSInfo, IS_LINUX} from '../utils';
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants'; import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';
export enum State { export enum State {
@@ -22,6 +23,33 @@ abstract class CacheDistributor {
}>; }>;
protected async handleLoadedCache() {} protected async handleLoadedCache() {}
/**
* Builds the Linux distro portion of a cache key (e.g. `-26.04-Ubuntu`, `-9-rhel`).
* RHEL is keyed by major version since it ships one ABI-stable artifact per major.
*/
protected async getLinuxInfoKeySegment(): Promise<string> {
if (!IS_LINUX) {
return '';
}
const osInfo = await getOSInfo();
if (!osInfo) {
return '';
}
// lsb_release reports RHEL as "RedHatEnterpriseLinux" while /etc/os-release
// reports it as "rhel"; normalize both to "rhel" so the key is consistent.
const normalizedName = osInfo.osName.toLowerCase();
const isRhel =
normalizedName === 'rhel' || normalizedName.includes('redhat');
const osName = isRhel ? 'rhel' : osInfo.osName;
const osVersion = isRhel
? osInfo.osVersion.split('.')[0]
: osInfo.osVersion;
return `-${osVersion}-${osName}`;
}
public async restoreCache() { public async restoreCache() {
const {primaryKey, restoreKey} = await this.computeKeys(); const {primaryKey, restoreKey} = await this.computeKeys();
if (primaryKey.endsWith('-')) { if (primaryKey.endsWith('-')) {
+4 -12
View File
@@ -7,7 +7,7 @@ import * as path from 'path';
import os from 'os'; import os from 'os';
import CacheDistributor from './cache-distributor'; import CacheDistributor from './cache-distributor';
import {getLinuxInfo, IS_LINUX, IS_WINDOWS} from '../utils'; import {IS_WINDOWS} from '../utils';
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants'; import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';
class PipCache extends CacheDistributor { class PipCache extends CacheDistributor {
@@ -62,17 +62,9 @@ class PipCache extends CacheDistributor {
const hash = const hash =
(await glob.hashFiles(this.cacheDependencyPath)) || (await glob.hashFiles(this.cacheDependencyPath)) ||
(await glob.hashFiles(this.cacheDependencyBackupPath)); (await glob.hashFiles(this.cacheDependencyBackupPath));
let primaryKey = ''; const osSegment = await this.getLinuxInfoKeySegment();
let restoreKey = ''; const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
const restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}`;
if (IS_LINUX) {
const osInfo = await getLinuxInfo();
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}`;
} else {
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}`;
}
return { return {
primaryKey, primaryKey,
+2 -1
View File
@@ -32,7 +32,8 @@ class PipenvCache extends CacheDistributor {
protected async computeKeys() { protected async computeKeys() {
const hash = await glob.hashFiles(this.patterns); const hash = await glob.hashFiles(this.patterns);
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}-${hash}`; const osSegment = await this.getLinuxInfoKeySegment();
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
const restoreKey = undefined; const restoreKey = undefined;
return { return {
primaryKey, primaryKey,
+2 -1
View File
@@ -46,8 +46,9 @@ class PoetryCache extends CacheDistributor {
protected async computeKeys() { protected async computeKeys() {
const hash = await glob.hashFiles(this.patterns); const hash = await glob.hashFiles(this.patterns);
const osSegment = await this.getLinuxInfoKeySegment();
// "v2" is here to invalidate old caches of this cache distributor, which were created broken: // "v2" is here to invalidate old caches of this cache distributor, which were created broken:
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}-python-${this.pythonVersion}-${this.packageManager}-v2-${hash}`; const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-v2-${hash}`;
const restoreKey = undefined; const restoreKey = undefined;
return { return {
primaryKey, primaryKey,
+85
View File
@@ -3,6 +3,8 @@ import * as core from '@actions/core';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import * as httpm from '@actions/http-client'; import * as httpm from '@actions/http-client';
import * as fs from 'fs';
import * as semver from 'semver';
import {ExecOptions} from '@actions/exec/lib/interfaces'; import {ExecOptions} from '@actions/exec/lib/interfaces';
import {IS_WINDOWS, IS_LINUX, getDownloadFileName} from './utils'; import {IS_WINDOWS, IS_LINUX, getDownloadFileName} from './utils';
import {IToolRelease} from '@actions/tool-cache'; import {IToolRelease} from '@actions/tool-cache';
@@ -14,6 +16,70 @@ const MANIFEST_REPO_NAME = 'python-versions';
const MANIFEST_REPO_BRANCH = 'main'; const MANIFEST_REPO_BRANCH = 'main';
export const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`; export const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
interface LinuxOsRelease {
id: string;
versionId: string;
}
function getLinuxOsRelease(): LinuxOsRelease | null {
try {
const content = fs.readFileSync('/etc/os-release', 'utf8');
const lines = content.split('\n');
let id = '';
let versionId = '';
for (const line of lines) {
const parts = line.split('=');
if (parts.length === 2) {
const key = parts[0].trim();
const value = parts[1].trim().replace(/^"/, '').replace(/"$/, '');
if (key === 'ID') id = value;
if (key === 'VERSION_ID') versionId = value;
}
}
if (id && versionId) {
return {id, versionId};
}
return null;
} catch {
return null;
}
}
function findRhelRelease(
semanticVersionSpec: string,
architecture: string,
manifest: tc.IToolRelease[],
osVersion: string
): tc.IToolRelease | undefined {
for (const candidate of manifest) {
const version = candidate.version;
core.debug(`check ${version} satisfies ${semanticVersionSpec}`);
if (!semver.satisfies(version, semanticVersionSpec)) continue;
const file = candidate.files.find(item => {
core.debug(
`${item.arch}===${architecture} && ${item.platform}===rhel && ${item.platform_version}===${osVersion}`
);
const archMatch = item.arch === architecture;
const platformMatch = item.platform === 'rhel';
const versionMatch =
!item.platform_version ||
item.platform_version === osVersion ||
osVersion.startsWith(item.platform_version);
return archMatch && platformMatch && versionMatch;
});
if (file) {
core.debug(`matched ${candidate.version}`);
const result = Object.assign({}, candidate);
result.files = [file];
return result;
}
}
return undefined;
}
export async function findReleaseFromManifest( export async function findReleaseFromManifest(
semanticVersionSpec: string, semanticVersionSpec: string,
architecture: string, architecture: string,
@@ -23,6 +89,23 @@ export async function findReleaseFromManifest(
manifest = await getManifest(); manifest = await getManifest();
} }
// On RHEL, tc.findFromManifest() won't match because os.platform() returns 'linux'
// but manifest entries use platform 'rhel'. Use custom filtering for RHEL.
if (IS_LINUX) {
const osRelease = getLinuxOsRelease();
if (osRelease && osRelease.id === 'rhel') {
core.debug(
`Detected RHEL ${osRelease.versionId}, using custom manifest filtering`
);
return findRhelRelease(
semanticVersionSpec,
architecture,
manifest,
osRelease.versionId
);
}
}
const foundRelease = await tc.findFromManifest( const foundRelease = await tc.findFromManifest(
semanticVersionSpec, semanticVersionSpec,
false, false,
@@ -32,6 +115,7 @@ export async function findReleaseFromManifest(
return foundRelease; return foundRelease;
} }
function isIToolRelease(obj: any): obj is IToolRelease { function isIToolRelease(obj: any): obj is IToolRelease {
return ( return (
typeof obj === 'object' && typeof obj === 'object' &&
@@ -48,6 +132,7 @@ function isIToolRelease(obj: any): obj is IToolRelease {
) )
); );
} }
export async function getManifest(): Promise<tc.IToolRelease[]> { export async function getManifest(): Promise<tc.IToolRelease[]> {
try { try {
const repoManifest = await getManifestFromRepo(); const repoManifest = await getManifestFromRepo();
+29 -6
View File
@@ -173,15 +173,38 @@ async function getMacOSInfo() {
} }
export async function getLinuxInfo() { export async function getLinuxInfo() {
const {stdout} = await exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { try {
silent: true const {stdout} = await exec.getExecOutput(
}); 'lsb_release',
['-i', '-r', '-s'],
{
silent: true
}
);
const [osName, osVersion] = stdout.trim().split('\n'); const [osName, osVersion] = stdout.trim().split('\n');
core.debug(`OS Name: ${osName}, Version: ${osVersion}`);
return {osName, osVersion};
} catch (err) {
core.debug(
`lsb_release failed (${(err as Error).message}). Falling back to /etc/os-release.`
);
core.debug(`OS Name: ${osName}, Version: ${osVersion}`); const osReleaseContent = fs.readFileSync('/etc/os-release', 'utf8');
const osInfo: {[key: string]: string} = {};
return {osName: osName, osVersion: osVersion}; osReleaseContent.split('\n').forEach(line => {
const [key, value] = line.split('=');
if (key && value) {
osInfo[key.trim()] = value.trim().replace(/"/g, '');
}
});
const osName = osInfo['ID'] || 'Linux';
const osVersion = osInfo['VERSION_ID'] || '';
core.debug(`OS Name: ${osName}, Version: ${osVersion}`);
return {osName, osVersion};
}
} }
export async function getOSInfo() { export async function getOSInfo() {