mirror of
https://github.com/actions/setup-python.git
synced 2026-07-18 06:19:58 +08:00
Merge remote-tracking branch 'origin/main' into depsfix
# Conflicts: # .licenses/npm/@nodable/entities.dep.yml # .licenses/npm/anynum.dep.yml # .licenses/npm/fast-xml-parser.dep.yml # .licenses/npm/strnum.dep.yml # .licenses/npm/xml-naming.dep.yml # dist/cache-save/index.js # dist/setup/index.js # package-lock.json
This commit is contained in:
commit
8dce45f04b
20 changed files with 5791 additions and 94 deletions
2
.licenses/npm/@actions/cache.dep.yml
generated
2
.licenses/npm/@actions/cache.dep.yml
generated
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
name: "@actions/cache"
|
name: "@actions/cache"
|
||||||
version: 5.0.5
|
version: 5.1.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions cache lib
|
summary: Actions cache lib
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
|
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
|
||||||
|
|
|
||||||
2
.licenses/npm/@nodable/entities.dep.yml
generated
2
.licenses/npm/@nodable/entities.dep.yml
generated
|
|
@ -3,7 +3,7 @@ name: "@nodable/entities"
|
||||||
version: 2.2.0
|
version: 2.2.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Entity parser for XML, HTML, External entites with security and NCR control
|
summary: Entity parser for XML, HTML, External entites with security and NCR control
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: README.md
|
- sources: README.md
|
||||||
|
|
|
||||||
4
.licenses/npm/anynum.dep.yml
generated
4
.licenses/npm/anynum.dep.yml
generated
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
name: anynum
|
name: anynum
|
||||||
version: 1.0.0
|
version: 1.0.1
|
||||||
type: npm
|
type: npm
|
||||||
summary: Normalize all Unicode decimal digits (Devanagari, Arabic, Thai, etc.) to
|
summary: Normalize all Unicode decimal digits (Devanagari, Arabic, Thai, etc.) to
|
||||||
ASCII numerals. Zero dependencies, performance-first.
|
ASCII numerals. Zero dependencies, performance-first.
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|
|
||||||
2
.licenses/npm/fast-xml-builder.dep.yml
generated
2
.licenses/npm/fast-xml-builder.dep.yml
generated
|
|
@ -3,7 +3,7 @@ name: fast-xml-builder
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Build XML from JSON without C/C++ based libraries
|
summary: Build XML from JSON without C/C++ based libraries
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|
|
||||||
4
.licenses/npm/fast-xml-parser.dep.yml
generated
4
.licenses/npm/fast-xml-parser.dep.yml
generated
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
name: fast-xml-parser
|
name: fast-xml-parser
|
||||||
version: 5.8.0
|
version: 5.9.2
|
||||||
type: npm
|
type: npm
|
||||||
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
|
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|
|
||||||
35
.licenses/npm/is-unsafe.dep.yml
generated
Normal file
35
.licenses/npm/is-unsafe.dep.yml
generated
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
name: is-unsafe
|
||||||
|
version: 1.0.1
|
||||||
|
type: npm
|
||||||
|
summary: Zero-dependency, DOM-free, pure predicate for detecting unsafe strings across
|
||||||
|
HTML, XML, SVG, SQL, SHELL, and REGEX contexts
|
||||||
|
homepage:
|
||||||
|
license: mit
|
||||||
|
licenses:
|
||||||
|
- sources: LICENSE
|
||||||
|
text: |
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Natural Intelligence
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
- sources: README.md
|
||||||
|
text: MIT
|
||||||
|
notices: []
|
||||||
4
.licenses/npm/strnum.dep.yml
generated
4
.licenses/npm/strnum.dep.yml
generated
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
name: strnum
|
name: strnum
|
||||||
version: 2.4.0
|
version: 2.4.1
|
||||||
type: npm
|
type: npm
|
||||||
summary: Parse String to Number based on configuration
|
summary: Parse String to Number based on configuration
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|
|
||||||
2
.licenses/npm/xml-naming.dep.yml
generated
2
.licenses/npm/xml-naming.dep.yml
generated
|
|
@ -4,7 +4,7 @@ version: 0.1.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Validates XML name productions — Name, NCName, QName, NMToken, NMTokens —
|
summary: Validates XML name productions — Name, NCName, QName, NMToken, NMTokens —
|
||||||
for XML 1.0 and 1.1
|
for XML 1.0 and 1.1
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: README.md
|
- sources: README.md
|
||||||
|
|
|
||||||
|
|
@ -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`
|
||||||
|
|
|
||||||
5397
dist/cache-save/index.js
vendored
5397
dist/cache-save/index.js
vendored
File diff suppressed because one or more lines are too long
182
dist/setup/index.js
vendored
182
dist/setup/index.js
vendored
File diff suppressed because one or more lines are too long
49
package-lock.json
generated
49
package-lock.json
generated
|
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"name": "setup-python",
|
"name": "setup-python",
|
||||||
"version": "6.2.0",
|
"version": "6.3.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "setup-python",
|
"name": "setup-python",
|
||||||
"version": "6.2.0",
|
"version": "6.3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^5.0.5",
|
"@actions/cache": "^5.1.0",
|
||||||
"@actions/core": "^2.0.3",
|
"@actions/core": "^2.0.3",
|
||||||
"@actions/exec": "^2.0.0",
|
"@actions/exec": "^2.0.0",
|
||||||
"@actions/glob": "^0.5.1",
|
"@actions/glob": "^0.5.1",
|
||||||
|
|
@ -41,9 +41,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/cache": {
|
"node_modules/@actions/cache": {
|
||||||
"version": "5.0.5",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.1.0.tgz",
|
||||||
"integrity": "sha512-jiQSg0gfd+C2KPgcmdCOq7dCuCIQQWQ4b1YfGIRaaA9w7PJbRwTOcCz4LiFEUnqZGf0ha/8OKL3BeNwetHzYsQ==",
|
"integrity": "sha512-kTIj4YPrjjRPKSGlj7f8eq+Pijoy/SKBEbJcAwNsQTFGEF29NGqj1mqD02/PmhV6r4bRAixycexAWpmUJ2aCwg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^2.0.0",
|
"@actions/core": "^2.0.0",
|
||||||
|
|
@ -2091,9 +2091,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/anynum": {
|
"node_modules/anynum": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz",
|
||||||
"integrity": "sha512-xjR9/zBVnUOP6ztMIIgShjsxui80nQUQH+5xJnvrYLs+90bF25/KJqaAi8mk+B4RDtX1Nspi6fmp4YTEts8SfA==",
|
"integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
|
@ -3149,9 +3149,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fast-xml-parser": {
|
"node_modules/fast-xml-parser": {
|
||||||
"version": "5.8.0",
|
"version": "5.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.9.2.tgz",
|
||||||
"integrity": "sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==",
|
"integrity": "sha512-DYPkXnVSJHAGAkSBeVYhEo/seIpz2SLr9OQcX7m6lXaX3gvoB+DCKzFdZIEhZGI3I1DUhObBAUOT/v2xfoXz/w==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
|
@ -3160,10 +3160,11 @@
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nodable/entities": "^2.1.0",
|
"@nodable/entities": "^2.2.0",
|
||||||
"fast-xml-builder": "^1.2.0",
|
"fast-xml-builder": "^1.2.0",
|
||||||
|
"is-unsafe": "^1.0.1",
|
||||||
"path-expression-matcher": "^1.5.0",
|
"path-expression-matcher": "^1.5.0",
|
||||||
"strnum": "^2.3.0",
|
"strnum": "^2.4.0",
|
||||||
"xml-naming": "^0.1.0"
|
"xml-naming": "^0.1.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -3679,6 +3680,18 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-unsafe": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
|
|
@ -5392,9 +5405,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/strnum": {
|
"node_modules/strnum": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.1.tgz",
|
||||||
"integrity": "sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg==",
|
"integrity": "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
|
@ -5403,7 +5416,7 @@
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anynum": "^1.0.0"
|
"anynum": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "setup-python",
|
"name": "setup-python",
|
||||||
"version": "6.2.0",
|
"version": "6.3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Setup python action",
|
"description": "Setup python action",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"author": "GitHub",
|
"author": "GitHub",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^5.0.5",
|
"@actions/cache": "^5.1.0",
|
||||||
"@actions/core": "^2.0.3",
|
"@actions/core": "^2.0.3",
|
||||||
"@actions/exec": "^2.0.0",
|
"@actions/exec": "^2.0.0",
|
||||||
"@actions/glob": "^0.5.1",
|
"@actions/glob": "^0.5.1",
|
||||||
|
|
@ -54,5 +54,8 @@
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"ts-jest": "^29.3.2",
|
"ts-jest": "^29.3.2",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"fast-xml-parser": "^5.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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('-')) {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,11 @@ async function saveCache(packageManager: string) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheId == -1) {
|
if (cacheId === -1) {
|
||||||
|
// saveCache returns -1 without throwing when the cache was not saved, e.g.
|
||||||
|
// a reserve collision or a read-only token (fork PR). @actions/cache has
|
||||||
|
// already logged the reason at the appropriate severity, so just trace it.
|
||||||
|
core.debug(`Cache was not saved for the key: ${primaryKey}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.info(`Cache saved with the key: ${primaryKey}`);
|
core.info(`Cache saved with the key: ${primaryKey}`);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
35
src/utils.ts
35
src/utils.ts
|
|
@ -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() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue