Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19,050 changes: 12,192 additions & 6,858 deletions dist/cache-save/index.js

Large diffs are not rendered by default.

125 changes: 106 additions & 19 deletions dist/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53813,6 +53813,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.State = void 0;
const cache = __importStar(__nccwpck_require__(5116));
const core = __importStar(__nccwpck_require__(37484));
const utils_1 = __nccwpck_require__(71798);
const constants_1 = __nccwpck_require__(10565);
var State;
(function (State) {
Expand All @@ -53829,6 +53830,20 @@ class CacheDistributor {
this.cacheDependencyPath = cacheDependencyPath;
}
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.getLinuxInfo)();
const osVersion = osInfo.osName === 'rhel'
? osInfo.osVersion.split('.')[0]
: osInfo.osVersion;
return `-${osVersion}-${osInfo.osName}`;
}
async restoreCache() {
const { primaryKey, restoreKey } = await this.computeKeys();
if (primaryKey.endsWith('-')) {
Expand Down Expand Up @@ -54011,17 +54026,9 @@ class PipCache extends cache_distributor_1.default {
async computeKeys() {
const hash = (await glob.hashFiles(this.cacheDependencyPath)) ||
(await glob.hashFiles(this.cacheDependencyBackupPath));
let primaryKey = '';
let restoreKey = '';
if (utils_1.IS_LINUX) {
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}`;
}
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 = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}`;
return {
primaryKey,
restoreKey: [restoreKey]
Expand Down Expand Up @@ -54105,7 +54112,8 @@ class PipenvCache extends cache_distributor_1.default {
}
async computeKeys() {
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;
return {
primaryKey,
Expand Down Expand Up @@ -54197,8 +54205,9 @@ class PoetryCache extends cache_distributor_1.default {
}
async computeKeys() {
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:
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;
return {
primaryKey,
Expand Down Expand Up @@ -55275,17 +55284,78 @@ const core = __importStar(__nccwpck_require__(37484));
const tc = __importStar(__nccwpck_require__(33472));
const exec = __importStar(__nccwpck_require__(95236));
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 TOKEN = core.getInput('token');
const AUTH = !TOKEN ? undefined : `token ${TOKEN}`;
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions';
const MANIFEST_REPO_BRANCH = 'main';
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) {
if (!manifest) {
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);
return foundRelease;
}
Expand Down Expand Up @@ -55743,12 +55813,29 @@ async function getMacOSInfo() {
return { osName: 'macOS', osVersion: macOSVersion };
}
async function getLinuxInfo() {
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}`);
return { osName: osName, osVersion: osVersion };
try {
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}`);
return { osName, osVersion };
}
catch {
core.debug('lsb_release command not found. 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() {
let osInfo;
Expand Down
19 changes: 19 additions & 0 deletions src/cache-distributions/cache-distributor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import {getLinuxInfo, IS_LINUX} from '../utils';
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';

export enum State {
Expand All @@ -22,6 +23,24 @@ abstract class CacheDistributor {
}>;
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 getLinuxInfo();
const osVersion =
osInfo.osName === 'rhel'
? osInfo.osVersion.split('.')[0]
: osInfo.osVersion;

return `-${osVersion}-${osInfo.osName}`;
Comment thread
v-priyagupta108 marked this conversation as resolved.
Resolved
}

public async restoreCache() {
const {primaryKey, restoreKey} = await this.computeKeys();
if (primaryKey.endsWith('-')) {
Expand Down
16 changes: 4 additions & 12 deletions src/cache-distributions/pip-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as path from 'path';
import os from 'os';

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';

class PipCache extends CacheDistributor {
Expand Down Expand Up @@ -62,17 +62,9 @@ class PipCache extends CacheDistributor {
const hash =
(await glob.hashFiles(this.cacheDependencyPath)) ||
(await glob.hashFiles(this.cacheDependencyBackupPath));
let primaryKey = '';
let restoreKey = '';

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}`;
}
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 = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}`;

return {
primaryKey,
Expand Down
3 changes: 2 additions & 1 deletion src/cache-distributions/pipenv-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class PipenvCache extends CacheDistributor {

protected async computeKeys() {
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;
Comment thread
v-priyagupta108 marked this conversation as resolved.
Resolved
return {
primaryKey,
Expand Down
3 changes: 2 additions & 1 deletion src/cache-distributions/poetry-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ class PoetryCache extends CacheDistributor {

protected async computeKeys() {
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:
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;
return {
primaryKey,
Expand Down
85 changes: 85 additions & 0 deletions src/install-python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec';
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 {IS_WINDOWS, IS_LINUX, getDownloadFileName} from './utils';
import {IToolRelease} from '@actions/tool-cache';
Expand All @@ -14,6 +16,70 @@ const MANIFEST_REPO_NAME = 'python-versions';
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`;

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(
semanticVersionSpec: string,
architecture: string,
Expand All @@ -23,6 +89,23 @@ export async function findReleaseFromManifest(
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
);
}
}
Comment thread
v-priyagupta108 marked this conversation as resolved.
Resolved

const foundRelease = await tc.findFromManifest(
semanticVersionSpec,
false,
Expand All @@ -32,6 +115,7 @@ export async function findReleaseFromManifest(

return foundRelease;
}

function isIToolRelease(obj: any): obj is IToolRelease {
return (
typeof obj === 'object' &&
Expand All @@ -48,6 +132,7 @@ function isIToolRelease(obj: any): obj is IToolRelease {
)
);
}

export async function getManifest(): Promise<tc.IToolRelease[]> {
try {
const repoManifest = await getManifestFromRepo();
Expand Down
Loading
Loading