Compare commits

...

9 Commits

Author SHA1 Message Date
2c3dd9e7e2 Add OS info to the error message (#559) 2022-12-07 18:12:42 +01:00
76bbdfadd7 Update minimatch (#558) 2022-12-07 18:08:22 +01:00
1aafadcfb9 Caching projects that use setup.py (#549) 2022-11-29 12:46:57 -05:00
b80efd6bc5 Update to latest actions/publish-action (#546)
To avoid Actions core deprecation messages.

https://github.com/actions/publish-action/releases/tag/v0.2.1
2022-11-24 12:14:51 +01:00
5cddb27885 Recommend setting python-version (#545)
* Recommend setting python-version

* Recommend both options to set Python version

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
2022-11-21 13:47:16 +01:00
47c4a7af1d fix(ci): run .github/workflows/workflow.yml on ubuntu-20.04 (#535) 2022-11-07 13:10:21 +01:00
af57b64994 Extend docu regarding rate limit issues. (#510) 2022-10-31 09:50:28 +01:00
4818a5a153 Handle download HTTP error (#511) 2022-10-24 11:10:18 +02:00
8bcd2560e2 Add architecture input check for PyPy for Windows platform (#520)
* Revert cache index.js

* build cache index file

* Refactor

* Debug

* Debug

* Debug

* Debug

* Debug

* Debug

* Debug

* Debug

* Format code

* Rebuild dist

* Minor refactor

* Format code

* Minor fixes

* Check platform firstly
2022-10-18 11:01:15 +02:00
14 changed files with 529 additions and 281 deletions

View File

@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Update the ${{ env.TAG_NAME }} tag - name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.2.0 uses: actions/publish-action@v0.2.1
with: with:
source-tag: ${{ env.TAG_NAME }} source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ${{ matrix.operating-system }} runs-on: ${{ matrix.operating-system }}
strategy: strategy:
matrix: matrix:
operating-system: [ubuntu-latest, windows-latest] operating-system: [ubuntu-20.04, windows-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3

View File

@ -1,6 +1,6 @@
--- ---
name: minimatch name: minimatch
version: 3.0.4 version: 3.1.2
type: npm type: npm
summary: a glob matcher in javascript summary: a glob matcher in javascript
homepage: https://github.com/isaacs/minimatch#readme homepage: https://github.com/isaacs/minimatch#readme

View File

@ -33,7 +33,7 @@ steps:
python-version: 'pypy3.9' python-version: 'pypy3.9'
- run: python my_script.py - run: python my_script.py
``` ```
The `python-version` input is optional. If not supplied, the action will try to resolve the version from the default `.python-version` file. If the `.python-version` file doesn't exist Python or PyPy version from the PATH will be used. The default version of Python or PyPy in PATH varies between runners and can be changed unexpectedly so we recommend always using `setup-python`. The `python-version` input is optional. If not supplied, the action will try to resolve the version from the default `.python-version` file. If the `.python-version` file doesn't exist Python or PyPy version from the PATH will be used. The default version of Python or PyPy in PATH varies between runners and can be changed unexpectedly so we recommend always setting Python version explicitly using the `python-version` or `python-version-file` inputs.
The action will first check the local [tool cache](docs/advanced-usage.md#hosted-tool-cache) for a [semver](https://github.com/npm/node-semver#versions) match. If unable to find a specific version in the tool cache, the action will attempt to download a version of Python from [GitHub Releases](https://github.com/actions/python-versions/releases) and for PyPy from the official [PyPy's dist](https://downloads.python.org/pypy/). The action will first check the local [tool cache](docs/advanced-usage.md#hosted-tool-cache) for a [semver](https://github.com/npm/node-semver#versions) match. If unable to find a specific version in the tool cache, the action will attempt to download a version of Python from [GitHub Releases](https://github.com/actions/python-versions/releases) and for PyPy from the official [PyPy's dist](https://downloads.python.org/pypy/).

View File

@ -30,7 +30,6 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
let saveSatetSpy: jest.SpyInstance; let saveSatetSpy: jest.SpyInstance;
let getStateSpy: jest.SpyInstance; let getStateSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance; let setOutputSpy: jest.SpyInstance;
let getLinuxOSReleaseInfoSpy: jest.SpyInstance;
// cache spy // cache spy
let restoreCacheSpy: jest.SpyInstance; let restoreCacheSpy: jest.SpyInstance;
@ -67,6 +66,9 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
if (input.includes('poetry')) { if (input.includes('poetry')) {
return {stdout: poetryConfigOutput, stderr: '', exitCode: 0}; return {stdout: poetryConfigOutput, stderr: '', exitCode: 0};
} }
if (input.includes('lsb_release')) {
return {stdout: 'Ubuntu\n20.04', stderr: '', exitCode: 0};
}
return {stdout: '', stderr: 'Error occured', exitCode: 2}; return {stdout: '', stderr: 'Error occured', exitCode: 2};
}); });
@ -83,7 +85,6 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
whichSpy = jest.spyOn(io, 'which'); whichSpy = jest.spyOn(io, 'which');
whichSpy.mockImplementation(() => '/path/to/python'); whichSpy.mockImplementation(() => '/path/to/python');
getLinuxOSReleaseInfoSpy = jest.spyOn(utils, 'getLinuxOSReleaseInfo');
}); });
describe('Validate provided package manager', () => { describe('Validate provided package manager', () => {
@ -120,17 +121,11 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
dependencyFile dependencyFile
); );
if (process.platform === 'linux') {
getLinuxOSReleaseInfoSpy.mockImplementation(() =>
Promise.resolve('Ubuntu-20.4')
);
}
await cacheDistributor.restoreCache(); await cacheDistributor.restoreCache();
if (process.platform === 'linux' && packageManager === 'pip') { if (process.platform === 'linux' && packageManager === 'pip') {
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-Ubuntu-20.4-python-${pythonVersion}-${packageManager}-${fileHash}` `Cache restored from key: setup-python-${process.env['RUNNER_OS']}-20.04-Ubuntu-python-${pythonVersion}-${packageManager}-${fileHash}`
); );
} else { } else {
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(

View File

@ -45304,10 +45304,10 @@ function populateMaps (extensions, types) {
module.exports = minimatch module.exports = minimatch
minimatch.Minimatch = Minimatch minimatch.Minimatch = Minimatch
var path = { sep: '/' } var path = (function () { try { return __nccwpck_require__(1017) } catch (e) {}}()) || {
try { sep: '/'
path = __nccwpck_require__(1017) }
} catch (er) {} minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = __nccwpck_require__(3717) var expand = __nccwpck_require__(3717)
@ -45359,43 +45359,64 @@ function filter (pattern, options) {
} }
function ext (a, b) { function ext (a, b) {
a = a || {}
b = b || {} b = b || {}
var t = {} var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) { Object.keys(a).forEach(function (k) {
t[k] = a[k] t[k] = a[k]
}) })
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t return t
} }
minimatch.defaults = function (def) { minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch if (!def || typeof def !== 'object' || !Object.keys(def).length) {
return minimatch
}
var orig = minimatch var orig = minimatch
var m = function minimatch (p, pattern, options) { var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options)) return orig(p, pattern, ext(def, options))
} }
m.Minimatch = function Minimatch (pattern, options) { m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options)) return new orig.Minimatch(pattern, ext(def, options))
} }
m.Minimatch.defaults = function defaults (options) {
return orig.defaults(ext(def, options)).Minimatch
}
m.filter = function filter (pattern, options) {
return orig.filter(pattern, ext(def, options))
}
m.defaults = function defaults (options) {
return orig.defaults(ext(def, options))
}
m.makeRe = function makeRe (pattern, options) {
return orig.makeRe(pattern, ext(def, options))
}
m.braceExpand = function braceExpand (pattern, options) {
return orig.braceExpand(pattern, ext(def, options))
}
m.match = function (list, pattern, options) {
return orig.match(list, pattern, ext(def, options))
}
return m return m
} }
Minimatch.defaults = function (def) { Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch return minimatch.defaults(def).Minimatch
} }
function minimatch (p, pattern, options) { function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') { assertValidPattern(pattern)
throw new TypeError('glob pattern string required')
}
if (!options) options = {} if (!options) options = {}
@ -45404,9 +45425,6 @@ function minimatch (p, pattern, options) {
return false return false
} }
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p) return new Minimatch(pattern, options).match(p)
} }
@ -45415,15 +45433,14 @@ function Minimatch (pattern, options) {
return new Minimatch(pattern, options) return new Minimatch(pattern, options)
} }
if (typeof pattern !== 'string') { assertValidPattern(pattern)
throw new TypeError('glob pattern string required')
}
if (!options) options = {} if (!options) options = {}
pattern = pattern.trim() pattern = pattern.trim()
// windows support: need to use /, not \ // windows support: need to use /, not \
if (path.sep !== '/') { if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/') pattern = pattern.split(path.sep).join('/')
} }
@ -45434,6 +45451,7 @@ function Minimatch (pattern, options) {
this.negate = false this.negate = false
this.comment = false this.comment = false
this.empty = false this.empty = false
this.partial = !!options.partial
// make the set of regexps etc. // make the set of regexps etc.
this.make() this.make()
@ -45443,9 +45461,6 @@ Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make Minimatch.prototype.make = make
function make () { function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern var pattern = this.pattern
var options = this.options var options = this.options
@ -45465,7 +45480,7 @@ function make () {
// step 2: expand braces // step 2: expand braces
var set = this.globSet = this.braceExpand() var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
this.debug(this.pattern, set) this.debug(this.pattern, set)
@ -45545,12 +45560,11 @@ function braceExpand (pattern, options) {
pattern = typeof pattern === 'undefined' pattern = typeof pattern === 'undefined'
? this.pattern : pattern ? this.pattern : pattern
if (typeof pattern === 'undefined') { assertValidPattern(pattern)
throw new TypeError('undefined pattern')
}
if (options.nobrace || // Thanks to Yeting Li <https://github.com/yetingli> for
!pattern.match(/\{.*\}/)) { // improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand. // shortcut. no need to expand.
return [pattern] return [pattern]
} }
@ -45558,6 +45572,17 @@ function braceExpand (pattern, options) {
return expand(pattern) return expand(pattern)
} }
var MAX_PATTERN_LENGTH = 1024 * 64
var assertValidPattern = function (pattern) {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern')
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long')
}
}
// parse a component of the expanded set. // parse a component of the expanded set.
// At this point, no pattern may contain "/" in it // At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full // so we're going to return a 2d array, where each entry is the full
@ -45572,14 +45597,17 @@ function braceExpand (pattern, options) {
Minimatch.prototype.parse = parse Minimatch.prototype.parse = parse
var SUBPARSE = {} var SUBPARSE = {}
function parse (pattern, isSub) { function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) { assertValidPattern(pattern)
throw new TypeError('pattern is too long')
}
var options = this.options var options = this.options
// shortcuts // shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return '' if (pattern === '') return ''
var re = '' var re = ''
@ -45635,10 +45663,12 @@ function parse (pattern, isSub) {
} }
switch (c) { switch (c) {
case '/': /* istanbul ignore next */
case '/': {
// completely not allowed, even escaped. // completely not allowed, even escaped.
// Should already be path-split by now. // Should already be path-split by now.
return false return false
}
case '\\': case '\\':
clearStateChar() clearStateChar()
@ -45757,7 +45787,6 @@ function parse (pattern, isSub) {
// handle the case where we left a class open. // handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]" // "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have // split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the // an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that // would-be class to re-translate any characters that
@ -45776,7 +45805,6 @@ function parse (pattern, isSub) {
inClass = false inClass = false
continue continue
} }
}
// finish up the class. // finish up the class.
hasMagic = true hasMagic = true
@ -45859,9 +45887,7 @@ function parse (pattern, isSub) {
// something that could conceivably capture a dot // something that could conceivably capture a dot
var addPatternStart = false var addPatternStart = false
switch (re.charAt(0)) { switch (re.charAt(0)) {
case '.': case '[': case '.': case '(': addPatternStart = true
case '[':
case '(': addPatternStart = true
} }
// Hack to work around lack of negative lookbehind in JS // Hack to work around lack of negative lookbehind in JS
@ -45923,7 +45949,7 @@ function parse (pattern, isSub) {
var flags = options.nocase ? 'i' : '' var flags = options.nocase ? 'i' : ''
try { try {
var regExp = new RegExp('^' + re + '$', flags) var regExp = new RegExp('^' + re + '$', flags)
} catch (er) { } catch (er) /* istanbul ignore next - should be impossible */ {
// If it was an invalid regular expression, then it can't match // If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of // anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line // the string, which is of course impossible, except in multi-line
@ -45981,7 +46007,7 @@ function makeRe () {
try { try {
this.regexp = new RegExp(re, flags) this.regexp = new RegExp(re, flags)
} catch (ex) { } catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false this.regexp = false
} }
return this.regexp return this.regexp
@ -45999,8 +46025,8 @@ minimatch.match = function (list, pattern, options) {
return list return list
} }
Minimatch.prototype.match = match Minimatch.prototype.match = function match (f, partial) {
function match (f, partial) { if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern) this.debug('match', f, this.pattern)
// short-circuit in the case of busted things. // short-circuit in the case of busted things.
// comments, etc. // comments, etc.
@ -46082,6 +46108,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// should be impossible. // should be impossible.
// some invalid regexp stuff in the set. // some invalid regexp stuff in the set.
/* istanbul ignore if */
if (p === false) return false if (p === false) return false
if (p === GLOBSTAR) { if (p === GLOBSTAR) {
@ -46155,6 +46182,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// no match was found. // no match was found.
// However, in partial mode, we can't say this is necessarily over. // However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then // If there's more *pattern* left, then
/* istanbul ignore if */
if (partial) { if (partial) {
// ran out of file // ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr) this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
@ -46168,11 +46196,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// patterns with magic have been turned into regexps. // patterns with magic have been turned into regexps.
var hit var hit
if (typeof p === 'string') { if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p hit = f === p
}
this.debug('string match', p, f, hit) this.debug('string match', p, f, hit)
} else { } else {
hit = f.match(p) hit = f.match(p)
@ -46203,16 +46227,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// this is ok if we're doing the match as part of // this is ok if we're doing the match as part of
// a glob fs traversal. // a glob fs traversal.
return partial return partial
} else if (pi === pl) { } else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left. // ran out of pattern, still have file left.
// this is only acceptable if we're on the very last // this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash. // empty segment of a file with a trailing slash.
// a/* should match a/b/ // a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') return (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
} }
// should be unreachable. // should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?') throw new Error('wtf?')
} }

264
dist/setup/index.js vendored
View File

@ -49469,10 +49469,10 @@ function populateMaps (extensions, types) {
module.exports = minimatch module.exports = minimatch
minimatch.Minimatch = Minimatch minimatch.Minimatch = Minimatch
var path = { sep: '/' } var path = (function () { try { return __nccwpck_require__(1017) } catch (e) {}}()) || {
try { sep: '/'
path = __nccwpck_require__(1017) }
} catch (er) {} minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = __nccwpck_require__(3717) var expand = __nccwpck_require__(3717)
@ -49524,43 +49524,64 @@ function filter (pattern, options) {
} }
function ext (a, b) { function ext (a, b) {
a = a || {}
b = b || {} b = b || {}
var t = {} var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) { Object.keys(a).forEach(function (k) {
t[k] = a[k] t[k] = a[k]
}) })
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t return t
} }
minimatch.defaults = function (def) { minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch if (!def || typeof def !== 'object' || !Object.keys(def).length) {
return minimatch
}
var orig = minimatch var orig = minimatch
var m = function minimatch (p, pattern, options) { var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options)) return orig(p, pattern, ext(def, options))
} }
m.Minimatch = function Minimatch (pattern, options) { m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options)) return new orig.Minimatch(pattern, ext(def, options))
} }
m.Minimatch.defaults = function defaults (options) {
return orig.defaults(ext(def, options)).Minimatch
}
m.filter = function filter (pattern, options) {
return orig.filter(pattern, ext(def, options))
}
m.defaults = function defaults (options) {
return orig.defaults(ext(def, options))
}
m.makeRe = function makeRe (pattern, options) {
return orig.makeRe(pattern, ext(def, options))
}
m.braceExpand = function braceExpand (pattern, options) {
return orig.braceExpand(pattern, ext(def, options))
}
m.match = function (list, pattern, options) {
return orig.match(list, pattern, ext(def, options))
}
return m return m
} }
Minimatch.defaults = function (def) { Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch return minimatch.defaults(def).Minimatch
} }
function minimatch (p, pattern, options) { function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') { assertValidPattern(pattern)
throw new TypeError('glob pattern string required')
}
if (!options) options = {} if (!options) options = {}
@ -49569,9 +49590,6 @@ function minimatch (p, pattern, options) {
return false return false
} }
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p) return new Minimatch(pattern, options).match(p)
} }
@ -49580,15 +49598,14 @@ function Minimatch (pattern, options) {
return new Minimatch(pattern, options) return new Minimatch(pattern, options)
} }
if (typeof pattern !== 'string') { assertValidPattern(pattern)
throw new TypeError('glob pattern string required')
}
if (!options) options = {} if (!options) options = {}
pattern = pattern.trim() pattern = pattern.trim()
// windows support: need to use /, not \ // windows support: need to use /, not \
if (path.sep !== '/') { if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/') pattern = pattern.split(path.sep).join('/')
} }
@ -49599,6 +49616,7 @@ function Minimatch (pattern, options) {
this.negate = false this.negate = false
this.comment = false this.comment = false
this.empty = false this.empty = false
this.partial = !!options.partial
// make the set of regexps etc. // make the set of regexps etc.
this.make() this.make()
@ -49608,9 +49626,6 @@ Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make Minimatch.prototype.make = make
function make () { function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern var pattern = this.pattern
var options = this.options var options = this.options
@ -49630,7 +49645,7 @@ function make () {
// step 2: expand braces // step 2: expand braces
var set = this.globSet = this.braceExpand() var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
this.debug(this.pattern, set) this.debug(this.pattern, set)
@ -49710,12 +49725,11 @@ function braceExpand (pattern, options) {
pattern = typeof pattern === 'undefined' pattern = typeof pattern === 'undefined'
? this.pattern : pattern ? this.pattern : pattern
if (typeof pattern === 'undefined') { assertValidPattern(pattern)
throw new TypeError('undefined pattern')
}
if (options.nobrace || // Thanks to Yeting Li <https://github.com/yetingli> for
!pattern.match(/\{.*\}/)) { // improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand. // shortcut. no need to expand.
return [pattern] return [pattern]
} }
@ -49723,6 +49737,17 @@ function braceExpand (pattern, options) {
return expand(pattern) return expand(pattern)
} }
var MAX_PATTERN_LENGTH = 1024 * 64
var assertValidPattern = function (pattern) {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern')
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long')
}
}
// parse a component of the expanded set. // parse a component of the expanded set.
// At this point, no pattern may contain "/" in it // At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full // so we're going to return a 2d array, where each entry is the full
@ -49737,14 +49762,17 @@ function braceExpand (pattern, options) {
Minimatch.prototype.parse = parse Minimatch.prototype.parse = parse
var SUBPARSE = {} var SUBPARSE = {}
function parse (pattern, isSub) { function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) { assertValidPattern(pattern)
throw new TypeError('pattern is too long')
}
var options = this.options var options = this.options
// shortcuts // shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return '' if (pattern === '') return ''
var re = '' var re = ''
@ -49800,10 +49828,12 @@ function parse (pattern, isSub) {
} }
switch (c) { switch (c) {
case '/': /* istanbul ignore next */
case '/': {
// completely not allowed, even escaped. // completely not allowed, even escaped.
// Should already be path-split by now. // Should already be path-split by now.
return false return false
}
case '\\': case '\\':
clearStateChar() clearStateChar()
@ -49922,7 +49952,6 @@ function parse (pattern, isSub) {
// handle the case where we left a class open. // handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]" // "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have // split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the // an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that // would-be class to re-translate any characters that
@ -49941,7 +49970,6 @@ function parse (pattern, isSub) {
inClass = false inClass = false
continue continue
} }
}
// finish up the class. // finish up the class.
hasMagic = true hasMagic = true
@ -50024,9 +50052,7 @@ function parse (pattern, isSub) {
// something that could conceivably capture a dot // something that could conceivably capture a dot
var addPatternStart = false var addPatternStart = false
switch (re.charAt(0)) { switch (re.charAt(0)) {
case '.': case '[': case '.': case '(': addPatternStart = true
case '[':
case '(': addPatternStart = true
} }
// Hack to work around lack of negative lookbehind in JS // Hack to work around lack of negative lookbehind in JS
@ -50088,7 +50114,7 @@ function parse (pattern, isSub) {
var flags = options.nocase ? 'i' : '' var flags = options.nocase ? 'i' : ''
try { try {
var regExp = new RegExp('^' + re + '$', flags) var regExp = new RegExp('^' + re + '$', flags)
} catch (er) { } catch (er) /* istanbul ignore next - should be impossible */ {
// If it was an invalid regular expression, then it can't match // If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of // anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line // the string, which is of course impossible, except in multi-line
@ -50146,7 +50172,7 @@ function makeRe () {
try { try {
this.regexp = new RegExp(re, flags) this.regexp = new RegExp(re, flags)
} catch (ex) { } catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false this.regexp = false
} }
return this.regexp return this.regexp
@ -50164,8 +50190,8 @@ minimatch.match = function (list, pattern, options) {
return list return list
} }
Minimatch.prototype.match = match Minimatch.prototype.match = function match (f, partial) {
function match (f, partial) { if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern) this.debug('match', f, this.pattern)
// short-circuit in the case of busted things. // short-circuit in the case of busted things.
// comments, etc. // comments, etc.
@ -50247,6 +50273,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// should be impossible. // should be impossible.
// some invalid regexp stuff in the set. // some invalid regexp stuff in the set.
/* istanbul ignore if */
if (p === false) return false if (p === false) return false
if (p === GLOBSTAR) { if (p === GLOBSTAR) {
@ -50320,6 +50347,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// no match was found. // no match was found.
// However, in partial mode, we can't say this is necessarily over. // However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then // If there's more *pattern* left, then
/* istanbul ignore if */
if (partial) { if (partial) {
// ran out of file // ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr) this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
@ -50333,11 +50361,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// patterns with magic have been turned into regexps. // patterns with magic have been turned into regexps.
var hit var hit
if (typeof p === 'string') { if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p hit = f === p
}
this.debug('string match', p, f, hit) this.debug('string match', p, f, hit)
} else { } else {
hit = f.match(p) hit = f.match(p)
@ -50368,16 +50392,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// this is ok if we're doing the match as part of // this is ok if we're doing the match as part of
// a glob fs traversal. // a glob fs traversal.
return partial return partial
} else if (pi === pl) { } else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left. // ran out of pattern, still have file left.
// this is only acceptable if we're on the very last // this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash. // empty segment of a file with a trailing slash.
// a/* should match a/b/ // a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') return (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
} }
// should be unreachable. // should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?') throw new Error('wtf?')
} }
@ -65919,9 +65943,9 @@ class PipCache extends cache_distributor_1.default {
let primaryKey = ''; let primaryKey = '';
let restoreKey = ''; let restoreKey = '';
if (utils_1.IS_LINUX) { if (utils_1.IS_LINUX) {
const osRelease = yield utils_1.getLinuxOSReleaseInfo(); const osInfo = yield utils_1.getLinuxInfo();
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osRelease}-python-${this.pythonVersion}-${this.packageManager}-${hash}`; primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osRelease}-python-${this.pythonVersion}-${this.packageManager}`; restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}`;
} }
else { else {
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}-${hash}`; primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
@ -66377,8 +66401,11 @@ function useCpythonVersion(version, architecture, updateEnvironment, checkLatest
} }
} }
if (!installDir) { if (!installDir) {
const osInfo = yield utils_1.getOSInfo();
throw new Error([ throw new Error([
`Version ${version} with arch ${architecture} not found`, `The version '${version}' with architecture '${architecture}' was not found for ${osInfo
? `${osInfo.osName} ${osInfo.osVersion}`
: 'this operating system'}.`,
`The list of all available versions can be found here: ${installer.MANIFEST_URL}` `The list of all available versions can be found here: ${installer.MANIFEST_URL}`
].join(os.EOL)); ].join(os.EOL));
} }
@ -66511,6 +66538,7 @@ function installPyPy(pypyVersion, pythonVersion, architecture, releases) {
const { foundAsset, resolvedPythonVersion, resolvedPyPyVersion } = releaseData; const { foundAsset, resolvedPythonVersion, resolvedPyPyVersion } = releaseData;
let downloadUrl = `${foundAsset.download_url}`; let downloadUrl = `${foundAsset.download_url}`;
core.info(`Downloading PyPy from "${downloadUrl}" ...`); core.info(`Downloading PyPy from "${downloadUrl}" ...`);
try {
const pypyPath = yield tc.downloadTool(downloadUrl); const pypyPath = yield tc.downloadTool(downloadUrl);
core.info('Extracting downloaded archive...'); core.info('Extracting downloaded archive...');
if (utils_1.IS_WINDOWS) { if (utils_1.IS_WINDOWS) {
@ -66532,6 +66560,23 @@ function installPyPy(pypyVersion, pythonVersion, architecture, releases) {
yield createPyPySymlink(binaryPath, resolvedPythonVersion); yield createPyPySymlink(binaryPath, resolvedPythonVersion);
yield installPip(binaryPath); yield installPip(binaryPath);
return { installDir, resolvedPythonVersion, resolvedPyPyVersion }; return { installDir, resolvedPythonVersion, resolvedPyPyVersion };
}
catch (err) {
if (err instanceof Error) {
// Rate limit?
if (err instanceof tc.HTTPError &&
(err.httpStatusCode === 403 || err.httpStatusCode === 429)) {
core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`);
}
else {
core.info(err.message);
}
if (err.stack !== undefined) {
core.debug(err.stack);
}
}
throw err;
}
}); });
} }
exports.installPyPy = installPyPy; exports.installPyPy = installPyPy;
@ -66577,7 +66622,7 @@ function findRelease(releases, pythonVersion, pypyVersion, architecture) {
semver.satisfies(pypyVersionToSemantic(item.pypy_version), pypyVersion); semver.satisfies(pypyVersionToSemantic(item.pypy_version), pypyVersion);
const isArchPresent = item.files && const isArchPresent = item.files &&
(utils_1.IS_WINDOWS (utils_1.IS_WINDOWS
? isArchPresentForWindows(item) ? isArchPresentForWindows(item, architecture)
: isArchPresentForMacOrLinux(item, architecture, process.platform)); : isArchPresentForMacOrLinux(item, architecture, process.platform));
return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent; return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent;
}); });
@ -66590,7 +66635,7 @@ function findRelease(releases, pythonVersion, pypyVersion, architecture) {
}); });
const foundRelease = sortedReleases[0]; const foundRelease = sortedReleases[0];
const foundAsset = utils_1.IS_WINDOWS const foundAsset = utils_1.IS_WINDOWS
? findAssetForWindows(foundRelease) ? findAssetForWindows(foundRelease, architecture)
: findAssetForMacOrLinux(foundRelease, architecture, process.platform); : findAssetForMacOrLinux(foundRelease, architecture, process.platform);
return { return {
foundAsset, foundAsset,
@ -66613,24 +66658,31 @@ function pypyVersionToSemantic(versionSpec) {
return versionSpec.replace(prereleaseVersion, '$1-$2.$3'); return versionSpec.replace(prereleaseVersion, '$1-$2.$3');
} }
exports.pypyVersionToSemantic = pypyVersionToSemantic; exports.pypyVersionToSemantic = pypyVersionToSemantic;
function isArchPresentForWindows(item) { function isArchPresentForWindows(item, architecture) {
return item.files.some((file) => utils_1.WINDOWS_ARCHS.includes(file.arch) && architecture = replaceX32toX86(architecture);
utils_1.WINDOWS_PLATFORMS.includes(file.platform)); return item.files.some((file) => utils_1.WINDOWS_PLATFORMS.includes(file.platform) && file.arch === architecture);
} }
exports.isArchPresentForWindows = isArchPresentForWindows; exports.isArchPresentForWindows = isArchPresentForWindows;
function isArchPresentForMacOrLinux(item, architecture, platform) { function isArchPresentForMacOrLinux(item, architecture, platform) {
return item.files.some((file) => file.arch === architecture && file.platform === platform); return item.files.some((file) => file.arch === architecture && file.platform === platform);
} }
exports.isArchPresentForMacOrLinux = isArchPresentForMacOrLinux; exports.isArchPresentForMacOrLinux = isArchPresentForMacOrLinux;
function findAssetForWindows(releases) { function findAssetForWindows(releases, architecture) {
return releases.files.find((item) => utils_1.WINDOWS_ARCHS.includes(item.arch) && architecture = replaceX32toX86(architecture);
utils_1.WINDOWS_PLATFORMS.includes(item.platform)); return releases.files.find((item) => utils_1.WINDOWS_PLATFORMS.includes(item.platform) && item.arch === architecture);
} }
exports.findAssetForWindows = findAssetForWindows; exports.findAssetForWindows = findAssetForWindows;
function findAssetForMacOrLinux(releases, architecture, platform) { function findAssetForMacOrLinux(releases, architecture, platform) {
return releases.files.find((item) => item.arch === architecture && item.platform === platform); return releases.files.find((item) => item.arch === architecture && item.platform === platform);
} }
exports.findAssetForMacOrLinux = findAssetForMacOrLinux; exports.findAssetForMacOrLinux = findAssetForMacOrLinux;
function replaceX32toX86(architecture) {
// convert x32 to x86 because os.arch() returns x32 for 32-bit systems but PyPy releases json has x86 arch value.
if (architecture === 'x32') {
architecture = 'x86';
}
return architecture;
}
/***/ }), /***/ }),
@ -66723,7 +66775,9 @@ function installCpythonFromRelease(release) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const downloadUrl = release.files[0].download_url; const downloadUrl = release.files[0].download_url;
core.info(`Download from "${downloadUrl}"`); core.info(`Download from "${downloadUrl}"`);
const pythonPath = yield tc.downloadTool(downloadUrl, undefined, AUTH); let pythonPath = '';
try {
pythonPath = yield tc.downloadTool(downloadUrl, undefined, AUTH);
core.info('Extract downloaded archive'); core.info('Extract downloaded archive');
let pythonExtractedFolder; let pythonExtractedFolder;
if (utils_1.IS_WINDOWS) { if (utils_1.IS_WINDOWS) {
@ -66734,6 +66788,22 @@ function installCpythonFromRelease(release) {
} }
core.info('Execute installation script'); core.info('Execute installation script');
yield installPython(pythonExtractedFolder); yield installPython(pythonExtractedFolder);
}
catch (err) {
if (err instanceof tc.HTTPError) {
// Rate limit?
if (err.httpStatusCode === 403 || err.httpStatusCode === 429) {
core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`);
}
else {
core.info(err.message);
}
if (err.stack) {
core.debug(err.stack);
}
}
throw err;
}
}); });
} }
exports.installCpythonFromRelease = installCpythonFromRelease; exports.installCpythonFromRelease = installCpythonFromRelease;
@ -66908,7 +66978,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.logWarning = exports.getLinuxOSReleaseInfo = exports.isCacheFeatureAvailable = exports.isGhes = exports.validatePythonVersionFormatForPyPy = exports.writeExactPyPyVersionFile = exports.readExactPyPyVersionFile = exports.getPyPyVersionFromPath = exports.isNightlyKeyword = exports.validateVersion = exports.createSymlinkInFolder = exports.WINDOWS_PLATFORMS = exports.WINDOWS_ARCHS = exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0; exports.getOSInfo = exports.getLinuxInfo = exports.logWarning = exports.isCacheFeatureAvailable = exports.isGhes = exports.validatePythonVersionFormatForPyPy = exports.writeExactPyPyVersionFile = exports.readExactPyPyVersionFile = exports.getPyPyVersionFromPath = exports.isNightlyKeyword = exports.validateVersion = exports.createSymlinkInFolder = exports.WINDOWS_PLATFORMS = exports.WINDOWS_ARCHS = exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0;
const cache = __importStar(__nccwpck_require__(7799)); const cache = __importStar(__nccwpck_require__(7799));
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const fs_1 = __importDefault(__nccwpck_require__(7147)); const fs_1 = __importDefault(__nccwpck_require__(7147));
@ -66999,22 +67069,64 @@ function isCacheFeatureAvailable() {
return true; return true;
} }
exports.isCacheFeatureAvailable = isCacheFeatureAvailable; exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
function getLinuxOSReleaseInfo() {
return __awaiter(this, void 0, void 0, function* () {
const { stdout, stderr, exitCode } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], {
silent: true
});
const [osRelease, osVersion] = stdout.trim().split('\n');
core.debug(`OS Release: ${osRelease}, Version: ${osVersion}`);
return `${osVersion}-${osRelease}`;
});
}
exports.getLinuxOSReleaseInfo = getLinuxOSReleaseInfo;
function logWarning(message) { function logWarning(message) {
const warningPrefix = '[warning]'; const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`); core.info(`${warningPrefix}${message}`);
} }
exports.logWarning = logWarning; exports.logWarning = logWarning;
function getWindowsInfo() {
return __awaiter(this, void 0, void 0, function* () {
const { stdout } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, {
silent: true
});
const windowsVersion = stdout.trim().split(' ')[3];
return { osName: 'Windows', osVersion: windowsVersion };
});
}
function getMacOSInfo() {
return __awaiter(this, void 0, void 0, function* () {
const { stdout } = yield exec.getExecOutput('sw_vers', ['-productVersion'], {
silent: true
});
const macOSVersion = stdout.trim();
return { osName: 'macOS', osVersion: macOSVersion };
});
}
function getLinuxInfo() {
return __awaiter(this, void 0, void 0, function* () {
const { stdout } = yield 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 };
});
}
exports.getLinuxInfo = getLinuxInfo;
function getOSInfo() {
return __awaiter(this, void 0, void 0, function* () {
let osInfo;
try {
if (exports.IS_WINDOWS) {
osInfo = yield getWindowsInfo();
}
else if (exports.IS_LINUX) {
osInfo = yield getLinuxInfo();
}
else if (exports.IS_MAC) {
osInfo = yield getMacOSInfo();
}
}
catch (err) {
const error = err;
core.debug(error.message);
}
finally {
return osInfo;
}
});
}
exports.getOSInfo = getOSInfo;
/***/ }), /***/ }),

View File

@ -281,6 +281,20 @@ steps:
- run: pip install -e . -r subdirectory/requirements-dev.txt - run: pip install -e . -r subdirectory/requirements-dev.txt
``` ```
**Caching projects that use setup.py:**
```yaml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: setup.py
- run: pip install -e .
# Or pip install -e '.[test]' to install test dependencies
```
# Outputs and environment variables # Outputs and environment variables
## Outputs ## Outputs
@ -471,15 +485,29 @@ One quick way to grant access is to change the user and group of `/Users/runner/
## Using `setup-python` on GHES ## Using `setup-python` on GHES
`setup-python` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Python distributions, `setup-python` downloads distributions from [`actions/python-versions`](https://github.com/actions/python-versions) on github.com (outside of the appliance). These calls to `actions/python-versions` are made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then you will start to see rate-limit errors during downloading that looks like: `##[error]API rate limit exceeded for...`. ### Avoiding rate limit issues
To get a higher rate limit, you can [generate a personal access token on github.com](https://github.com/settings/tokens/new) and pass it as the `token` input for the action: `setup-python` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Python distributions, `setup-python` downloads distributions from [`actions/python-versions`](https://github.com/actions/python-versions) on github.com (outside of the appliance). These calls to `actions/python-versions` are by default made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then you will start to see rate-limit errors during downloading that look like this:
##[error]API rate limit exceeded for YOUR_IP. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
To get a higher rate limit, you can [generate a personal access token (PAT) on github.com](https://github.com/settings/tokens/new) and pass it as the `token` input for the action. It is important to understand that this needs to be a token from github.com and _not_ from your GHES instance. If you or your colleagues do not yet have a github.com account, you might need to create one.
Here are the steps you need to follow to avoid the rate limit:
1. Create a PAT on any github.com account by using [this link](https://github.com/settings/tokens/new) after logging into github.com (not your Enterprise instance). This PAT does _not_ need any rights, so make sure all the boxes are unchecked.
2. Store this PAT in the repository / organization where you run your workflow, e.g. as `GH_GITHUB_COM_TOKEN`. You can do this by navigating to your repository -> **Settings** -> **Secrets** -> **Actions** -> **New repository secret**.
3. To use this functionality, you need to use any version newer than `v4.3`. Also, change _python-version_ as needed.
```yml ```yml
uses: actions/setup-python@v4 - name: Set up Python
with: uses: actions/setup-python@4
token: ${{ secrets.GH_DOTCOM_TOKEN }} with:
python-version: 3.11 python-version: 3.8
token: ${{ secrets.GH_GITHUB_COM_TOKEN }}
``` ```
Requests should now be authenticated. To verify that you are getting the higher rate limit, you can call GitHub's [rate limit API](https://docs.github.com/en/rest/rate-limit) from within your workflow ([example](https://github.com/actions/setup-python/pull/443#issuecomment-1206776401)).
### No access to github.com
If the runner is not able to access github.com, any Python versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information. If the runner is not able to access github.com, any Python versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information.

12
package-lock.json generated
View File

@ -10177,9 +10177,9 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.0.4", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
}, },
@ -19490,9 +19490,9 @@
"dev": true "dev": true
}, },
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }

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 {getLinuxOSReleaseInfo, IS_LINUX, IS_WINDOWS} from '../utils'; import {getLinuxInfo, IS_LINUX, IS_WINDOWS} from '../utils';
class PipCache extends CacheDistributor { class PipCache extends CacheDistributor {
constructor( constructor(
@ -61,9 +61,9 @@ class PipCache extends CacheDistributor {
let restoreKey = ''; let restoreKey = '';
if (IS_LINUX) { if (IS_LINUX) {
const osRelease = await getLinuxOSReleaseInfo(); const osInfo = await getLinuxInfo();
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osRelease}-python-${this.pythonVersion}-${this.packageManager}-${hash}`; primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osRelease}-python-${this.pythonVersion}-${this.packageManager}`; restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osInfo.osVersion}-${osInfo.osName}-python-${this.pythonVersion}-${this.packageManager}`;
} else { } else {
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}-${hash}`; primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}`; restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}`;

View File

@ -1,6 +1,6 @@
import * as os from 'os'; import * as os from 'os';
import * as path from 'path'; import * as path from 'path';
import {IS_WINDOWS, IS_LINUX} from './utils'; import {IS_WINDOWS, IS_LINUX, getOSInfo} from './utils';
import * as semver from 'semver'; import * as semver from 'semver';
@ -85,9 +85,14 @@ export async function useCpythonVersion(
} }
if (!installDir) { if (!installDir) {
const osInfo = await getOSInfo();
throw new Error( throw new Error(
[ [
`Version ${version} with arch ${architecture} not found`, `The version '${version}' with architecture '${architecture}' was not found for ${
osInfo
? `${osInfo.osName} ${osInfo.osVersion}`
: 'this operating system'
}.`,
`The list of all available versions can be found here: ${installer.MANIFEST_URL}` `The list of all available versions can be found here: ${installer.MANIFEST_URL}`
].join(os.EOL) ].join(os.EOL)
); );

View File

@ -8,7 +8,6 @@ import fs from 'fs';
import { import {
IS_WINDOWS, IS_WINDOWS,
WINDOWS_ARCHS,
WINDOWS_PLATFORMS, WINDOWS_PLATFORMS,
IPyPyManifestRelease, IPyPyManifestRelease,
createSymlinkInFolder, createSymlinkInFolder,
@ -47,6 +46,8 @@ export async function installPyPy(
let downloadUrl = `${foundAsset.download_url}`; let downloadUrl = `${foundAsset.download_url}`;
core.info(`Downloading PyPy from "${downloadUrl}" ...`); core.info(`Downloading PyPy from "${downloadUrl}" ...`);
try {
const pypyPath = await tc.downloadTool(downloadUrl); const pypyPath = await tc.downloadTool(downloadUrl);
core.info('Extracting downloaded archive...'); core.info('Extracting downloaded archive...');
@ -78,6 +79,25 @@ export async function installPyPy(
await installPip(binaryPath); await installPip(binaryPath);
return {installDir, resolvedPythonVersion, resolvedPyPyVersion}; return {installDir, resolvedPythonVersion, resolvedPyPyVersion};
} catch (err) {
if (err instanceof Error) {
// Rate limit?
if (
err instanceof tc.HTTPError &&
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
) {
core.info(
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
);
} else {
core.info(err.message);
}
if (err.stack !== undefined) {
core.debug(err.stack);
}
}
throw err;
}
} }
export async function getAvailablePyPyVersions() { export async function getAvailablePyPyVersions() {
@ -157,7 +177,7 @@ export function findRelease(
const isArchPresent = const isArchPresent =
item.files && item.files &&
(IS_WINDOWS (IS_WINDOWS
? isArchPresentForWindows(item) ? isArchPresentForWindows(item, architecture)
: isArchPresentForMacOrLinux(item, architecture, process.platform)); : isArchPresentForMacOrLinux(item, architecture, process.platform));
return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent; return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent;
}); });
@ -181,7 +201,7 @@ export function findRelease(
const foundRelease = sortedReleases[0]; const foundRelease = sortedReleases[0];
const foundAsset = IS_WINDOWS const foundAsset = IS_WINDOWS
? findAssetForWindows(foundRelease) ? findAssetForWindows(foundRelease, architecture)
: findAssetForMacOrLinux(foundRelease, architecture, process.platform); : findAssetForMacOrLinux(foundRelease, architecture, process.platform);
return { return {
@ -205,11 +225,11 @@ export function pypyVersionToSemantic(versionSpec: string) {
return versionSpec.replace(prereleaseVersion, '$1-$2.$3'); return versionSpec.replace(prereleaseVersion, '$1-$2.$3');
} }
export function isArchPresentForWindows(item: any) { export function isArchPresentForWindows(item: any, architecture: string) {
architecture = replaceX32toX86(architecture);
return item.files.some( return item.files.some(
(file: any) => (file: any) =>
WINDOWS_ARCHS.includes(file.arch) && WINDOWS_PLATFORMS.includes(file.platform) && file.arch === architecture
WINDOWS_PLATFORMS.includes(file.platform)
); );
} }
@ -223,11 +243,11 @@ export function isArchPresentForMacOrLinux(
); );
} }
export function findAssetForWindows(releases: any) { export function findAssetForWindows(releases: any, architecture: string) {
architecture = replaceX32toX86(architecture);
return releases.files.find( return releases.files.find(
(item: any) => (item: any) =>
WINDOWS_ARCHS.includes(item.arch) && WINDOWS_PLATFORMS.includes(item.platform) && item.arch === architecture
WINDOWS_PLATFORMS.includes(item.platform)
); );
} }
@ -240,3 +260,11 @@ export function findAssetForMacOrLinux(
(item: any) => item.arch === architecture && item.platform === platform (item: any) => item.arch === architecture && item.platform === platform
); );
} }
function replaceX32toX86(architecture: string): string {
// convert x32 to x86 because os.arch() returns x32 for 32-bit systems but PyPy releases json has x86 arch value.
if (architecture === 'x32') {
architecture = 'x86';
}
return architecture;
}

View File

@ -72,7 +72,9 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) {
const downloadUrl = release.files[0].download_url; const downloadUrl = release.files[0].download_url;
core.info(`Download from "${downloadUrl}"`); core.info(`Download from "${downloadUrl}"`);
const pythonPath = await tc.downloadTool(downloadUrl, undefined, AUTH); let pythonPath = '';
try {
pythonPath = await tc.downloadTool(downloadUrl, undefined, AUTH);
core.info('Extract downloaded archive'); core.info('Extract downloaded archive');
let pythonExtractedFolder; let pythonExtractedFolder;
if (IS_WINDOWS) { if (IS_WINDOWS) {
@ -83,4 +85,20 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) {
core.info('Execute installation script'); core.info('Execute installation script');
await installPython(pythonExtractedFolder); await installPython(pythonExtractedFolder);
} catch (err) {
if (err instanceof tc.HTTPError) {
// Rate limit?
if (err.httpStatusCode === 403 || err.httpStatusCode === 429) {
core.info(
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
);
} else {
core.info(err.message);
}
if (err.stack) {
core.debug(err.stack);
}
}
throw err;
}
} }

View File

@ -122,23 +122,61 @@ export function isCacheFeatureAvailable(): boolean {
return true; return true;
} }
export async function getLinuxOSReleaseInfo() { export function logWarning(message: string): void {
const {stdout, stderr, exitCode} = await exec.getExecOutput( const warningPrefix = '[warning]';
'lsb_release', core.info(`${warningPrefix}${message}`);
['-i', '-r', '-s'], }
async function getWindowsInfo() {
const {stdout} = await exec.getExecOutput(
'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"',
undefined,
{ {
silent: true silent: true
} }
); );
const [osRelease, osVersion] = stdout.trim().split('\n'); const windowsVersion = stdout.trim().split(' ')[3];
core.debug(`OS Release: ${osRelease}, Version: ${osVersion}`); return {osName: 'Windows', osVersion: windowsVersion};
return `${osVersion}-${osRelease}`;
} }
export function logWarning(message: string): void { async function getMacOSInfo() {
const warningPrefix = '[warning]'; const {stdout} = await exec.getExecOutput('sw_vers', ['-productVersion'], {
core.info(`${warningPrefix}${message}`); silent: true
});
const macOSVersion = stdout.trim();
return {osName: 'macOS', osVersion: macOSVersion};
}
export 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};
}
export async function getOSInfo() {
let osInfo;
try {
if (IS_WINDOWS) {
osInfo = await getWindowsInfo();
} else if (IS_LINUX) {
osInfo = await getLinuxInfo();
} else if (IS_MAC) {
osInfo = await getMacOSInfo();
}
} catch (err) {
const error = err as Error;
core.debug(error.message);
} finally {
return osInfo;
}
} }