Skip to content

Commit 5808a6d

Browse files
committed
feature: fallback to pre-release when no stable version is found
This allows to specify version like `3.11` or `pypy3.10` in workflows before those versions are released. This lessen the burden for users of `setup-python` by not having to modify their workflow twice: once when a pre-release is available (e.g. `3.11-dev`) and once when the first stable release is published (e.g. `3.11`)
1 parent dec86ec commit 5808a6d

14 files changed

+520
-61
lines changed

.github/workflows/test-python.yml

+30-1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,35 @@ jobs:
149149
- name: Run simple code
150150
run: python -c 'import math; print(math.factorial(5))'
151151

152+
setup-prerelease-version:
153+
name: Setup 3.12 ${{ matrix.os }}
154+
runs-on: ${{ matrix.os }}
155+
strategy:
156+
fail-fast: false
157+
matrix:
158+
os: [macos-latest, windows-latest, ubuntu-latest]
159+
steps:
160+
- name: Checkout
161+
uses: actions/checkout@v3
162+
163+
- name: setup-python 3.12
164+
id: setup-python
165+
uses: ./
166+
with:
167+
python-version: '3.12'
168+
allow-prereleases: true
169+
170+
- name: Check python-path
171+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
172+
shell: bash
173+
174+
- name: Validate version
175+
run: ${{ startsWith(steps.setup-python.outputs.python-version, '3.12.') }}
176+
shell: bash
177+
178+
- name: Run simple code
179+
run: python -c 'import math; print(math.factorial(5))'
180+
152181
setup-versions-noenv:
153182
name: Setup ${{ matrix.python }} ${{ matrix.os }} (noenv)
154183
runs-on: ${{ matrix.os }}
@@ -223,4 +252,4 @@ jobs:
223252
exit 1
224253
}
225254
$pythonVersion
226-
shell: pwsh
255+
shell: pwsh

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ See examples of using `cache` and `cache-dependency-path` for `pipenv` and `poet
8585
- [Hosted tool cache](docs/advanced-usage.md#hosted-tool-cache)
8686
- [Using `setup-python` with a self-hosted runner](docs/advanced-usage.md#using-setup-python-with-a-self-hosted-runner)
8787
- [Using `setup-python` on GHES](docs/advanced-usage.md#using-setup-python-on-ghes)
88+
- [Allow pre-releases](docs/advanced-usage.md#allow-pre-releases)
8889

8990
## License
9091

__tests__/data/pypy.json

+91-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,94 @@
11
[
2+
{
3+
"pypy_version": "7.3.8rc2",
4+
"python_version": "3.8.12",
5+
"stable": false,
6+
"latest_pypy": false,
7+
"date": "2022-02-11",
8+
"files": [
9+
{
10+
"filename": "pypy3.8-v7.3.8rc2-linux32.tar.bz2",
11+
"arch": "i686",
12+
"platform": "linux",
13+
"download_url": "https://test.download.python.org/pypy/pypy3.8-v7.3.8rc2-linux32.tar.bz2"
14+
},
15+
{
16+
"filename": "pypy3.8-v7.3.8rc2-linux64.tar.bz2",
17+
"arch": "x64",
18+
"platform": "linux",
19+
"download_url": "https://test.download.python.org/pypy/pypy3.8-v7.3.8rc2-linux64.tar.bz2"
20+
},
21+
{
22+
"filename": "pypy3.8-v7.3.8rc2-darwin64.tar.bz2",
23+
"arch": "x64",
24+
"platform": "darwin",
25+
"download_url": "https://test.download.python.org/pypy/pypy3.8-v7.3.8rc2-darwin64.tar.bz2"
26+
},
27+
{
28+
"filename": "pypy3.8-v7.3.8rc2-s390x.tar.bz2",
29+
"arch": "s390x",
30+
"platform": "linux",
31+
"download_url": "https://test.download.python.org/pypy/pypy3.8-v7.3.8rc2-s390x.tar.bz2"
32+
},
33+
{
34+
"filename": "pypy3.8-v7.3.8rc2-win64.zip",
35+
"arch": "x64",
36+
"platform": "win64",
37+
"download_url": "https://test.download.python.org/pypy/pypy3.8-v7.3.8rc2-win64.zip"
38+
},
39+
{
40+
"filename": "pypy3.8-v7.3.8rc2-win32.zip",
41+
"arch": "x86",
42+
"platform": "win32",
43+
"download_url": "https://test.download.python.org/pypy/pypy3.8-v7.3.8rc2-win32.zip"
44+
}
45+
]
46+
},
47+
{
48+
"pypy_version": "7.4.0rc1",
49+
"python_version": "3.6.12",
50+
"stable": false,
51+
"latest_pypy": false,
52+
"date": "2021-11-11",
53+
"files": [
54+
{
55+
"filename": "pypy3.6-v7.4.0rc1-aarch64.tar.bz2",
56+
"arch": "aarch64",
57+
"platform": "linux",
58+
"download_url": "https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-aarch64.tar.bz2"
59+
},
60+
{
61+
"filename": "pypy3.6-v7.4.0rc1-linux32.tar.bz2",
62+
"arch": "i686",
63+
"platform": "linux",
64+
"download_url": "https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-linux32.tar.bz2"
65+
},
66+
{
67+
"filename": "pypy3.6-v7.4.0rc1-linux64.tar.bz2",
68+
"arch": "x64",
69+
"platform": "linux",
70+
"download_url": "https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-linux64.tar.bz2"
71+
},
72+
{
73+
"filename": "pypy3.6-v7.4.0rc1-darwin64.tar.bz2",
74+
"arch": "x64",
75+
"platform": "darwin",
76+
"download_url": "https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-darwin64.tar.bz2"
77+
},
78+
{
79+
"filename": "pypy3.6-v7.4.0rc1-win32.zip",
80+
"arch": "x86",
81+
"platform": "win32",
82+
"download_url": "https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-win32.zip"
83+
},
84+
{
85+
"filename": "pypy3.6-v7.4.0rc1-s390x.tar.bz2",
86+
"arch": "s390x",
87+
"platform": "linux",
88+
"download_url": "https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-s390x.tar.bz2"
89+
}
90+
]
91+
},
292
{
393
"pypy_version": "7.3.3",
494
"python_version": "3.6.12",
@@ -530,4 +620,4 @@
530620
}
531621
]
532622
}
533-
]
623+
]

__tests__/data/versions-manifest.json

+34-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,29 @@
11
[
2+
{
3+
"version": "1.2.4-beta.2",
4+
"stable": false,
5+
"release_url": "https://github.com/actions/sometool/releases/tag/1.2.4-beta.2-20200402.5",
6+
"files": [
7+
{
8+
"filename": "sometool-1.2.4-linux-x64.tar.gz",
9+
"arch": "x64",
10+
"platform": "linux",
11+
"download_url": "https://github.com/actions/sometool/releases/tag/1.2.4-beta.2-20200402.5/sometool-1.2.4-linux-x64.tar.gz"
12+
},
13+
{
14+
"filename": "sometool-1.2.4-darwin-x64.tar.gz",
15+
"arch": "x64",
16+
"platform": "darwin",
17+
"download_url": "https://github.com/actions/sometool/releases/tag/1.2.4-beta.2-20200402.5/sometool-1.2.4-darwin-x64.tar.gz"
18+
},
19+
{
20+
"filename": "sometool-1.2.4-win32-x64.tar.gz",
21+
"arch": "x64",
22+
"platform": "win32",
23+
"download_url": "https://github.com/actions/sometool/releases/tag/1.2.4-beta.2-20200402.5/sometool-1.2.4-win32-x64.tar.gz"
24+
}
25+
]
26+
},
227
{
328
"version": "1.2.3",
429
"stable": true,
@@ -25,28 +50,28 @@
2550
]
2651
},
2752
{
28-
"version": "1.2.3-beta.2",
53+
"version": "1.1.0-beta.2",
2954
"stable": false,
30-
"release_url": "https://github.com/actions/sometool/releases/tag/1.2.3-beta.2-20200402.5",
55+
"release_url": "https://github.com/actions/sometool/releases/tag/1.1.0-beta.2-20200402.5",
3156
"files": [
3257
{
33-
"filename": "sometool-1.2.3-linux-x64.tar.gz",
58+
"filename": "sometool-1.1.0-linux-x64.tar.gz",
3459
"arch": "x64",
3560
"platform": "linux",
36-
"download_url": "https://github.com/actions/sometool/releases/tag/1.2.3-beta.2-20200402.5/sometool-1.2.3-linux-x64.tar.gz"
61+
"download_url": "https://github.com/actions/sometool/releases/tag/1.1.0-beta.2-20200402.5/sometool-1.1.0-linux-x64.tar.gz"
3762
},
3863
{
39-
"filename": "sometool-1.2.3-darwin-x64.tar.gz",
64+
"filename": "sometool-1.1.0-darwin-x64.tar.gz",
4065
"arch": "x64",
4166
"platform": "darwin",
42-
"download_url": "https://github.com/actions/sometool/releases/tag/1.2.3-20200402.5/sometool-1.2.3-darwin-x64.tar.gz"
67+
"download_url": "https://github.com/actions/sometool/releases/tag/1.1.0-beta.2-20200402.5/sometool-1.1.0-darwin-x64.tar.gz"
4368
},
4469
{
45-
"filename": "sometool-1.2.3-win32-x64.tar.gz",
70+
"filename": "sometool-1.1.0-win32-x64.tar.gz",
4671
"arch": "x64",
4772
"platform": "win32",
48-
"download_url": "https://github.com/actions/sometool/releases/tag/1.2.3-20200402.5/sometool-1.2.3-win32-x64.tar.gz"
73+
"download_url": "https://github.com/actions/sometool/releases/tag/1.1.0-beta.2-20200402.5/sometool-1.1.0-win32-x64.tar.gz"
4974
}
5075
]
5176
}
52-
]
77+
]

__tests__/find-pypy.test.ts

+69-9
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,13 @@ describe('findPyPyVersion', () => {
273273

274274
it('found PyPy in toolcache', async () => {
275275
await expect(
276-
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, true, false)
276+
finder.findPyPyVersion(
277+
'pypy-3.6-v7.3.x',
278+
architecture,
279+
true,
280+
false,
281+
false
282+
)
277283
).resolves.toEqual({
278284
resolvedPythonVersion: '3.6.12',
279285
resolvedPyPyVersion: '7.3.3'
@@ -291,13 +297,13 @@ describe('findPyPyVersion', () => {
291297

292298
it('throw on invalid input format', async () => {
293299
await expect(
294-
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true, false)
300+
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true, false, false)
295301
).rejects.toThrow();
296302
});
297303

298304
it('throw on invalid input format pypy3.7-7.3.x', async () => {
299305
await expect(
300-
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true, false)
306+
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true, false, false)
301307
).rejects.toThrow();
302308
});
303309

@@ -309,7 +315,13 @@ describe('findPyPyVersion', () => {
309315
spyChmodSync = jest.spyOn(fs, 'chmodSync');
310316
spyChmodSync.mockImplementation(() => undefined);
311317
await expect(
312-
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, true, false)
318+
finder.findPyPyVersion(
319+
'pypy-3.7-v7.3.x',
320+
architecture,
321+
true,
322+
false,
323+
false
324+
)
313325
).resolves.toEqual({
314326
resolvedPythonVersion: '3.7.9',
315327
resolvedPyPyVersion: '7.3.3'
@@ -333,7 +345,13 @@ describe('findPyPyVersion', () => {
333345
spyChmodSync = jest.spyOn(fs, 'chmodSync');
334346
spyChmodSync.mockImplementation(() => undefined);
335347
await expect(
336-
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false, false)
348+
finder.findPyPyVersion(
349+
'pypy-3.7-v7.3.x',
350+
architecture,
351+
false,
352+
false,
353+
false
354+
)
337355
).resolves.toEqual({
338356
resolvedPythonVersion: '3.7.9',
339357
resolvedPyPyVersion: '7.3.3'
@@ -344,15 +362,27 @@ describe('findPyPyVersion', () => {
344362

345363
it('throw if release is not found', async () => {
346364
await expect(
347-
finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture, true, false)
365+
finder.findPyPyVersion(
366+
'pypy-3.7-v7.5.x',
367+
architecture,
368+
true,
369+
false,
370+
false
371+
)
348372
).rejects.toThrowError(
349373
`PyPy version 3.7 (v7.5.x) with arch ${architecture} not found`
350374
);
351375
});
352376

353377
it('check-latest enabled version found and used from toolcache', async () => {
354378
await expect(
355-
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, false, true)
379+
finder.findPyPyVersion(
380+
'pypy-3.6-v7.3.x',
381+
architecture,
382+
false,
383+
true,
384+
false
385+
)
356386
).resolves.toEqual({
357387
resolvedPythonVersion: '3.6.12',
358388
resolvedPyPyVersion: '7.3.3'
@@ -371,7 +401,13 @@ describe('findPyPyVersion', () => {
371401
spyChmodSync = jest.spyOn(fs, 'chmodSync');
372402
spyChmodSync.mockImplementation(() => undefined);
373403
await expect(
374-
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false, true)
404+
finder.findPyPyVersion(
405+
'pypy-3.7-v7.3.x',
406+
architecture,
407+
false,
408+
true,
409+
false
410+
)
375411
).resolves.toEqual({
376412
resolvedPythonVersion: '3.7.9',
377413
resolvedPyPyVersion: '7.3.3'
@@ -391,7 +427,13 @@ describe('findPyPyVersion', () => {
391427
return pypyPath;
392428
});
393429
await expect(
394-
finder.findPyPyVersion('pypy-3.8-v7.3.x', architecture, false, true)
430+
finder.findPyPyVersion(
431+
'pypy-3.8-v7.3.x',
432+
architecture,
433+
false,
434+
true,
435+
false
436+
)
395437
).resolves.toEqual({
396438
resolvedPythonVersion: '3.8.8',
397439
resolvedPyPyVersion: '7.3.3'
@@ -401,4 +443,22 @@ describe('findPyPyVersion', () => {
401443
'Failed to resolve PyPy v7.3.x with Python (3.8) from manifest'
402444
);
403445
});
446+
447+
it('found and install successfully, pre-release fallback', async () => {
448+
spyCacheDir = jest.spyOn(tc, 'cacheDir');
449+
spyCacheDir.mockImplementation(() =>
450+
path.join(toolDir, 'PyPy', '3.8.12', architecture)
451+
);
452+
spyChmodSync = jest.spyOn(fs, 'chmodSync');
453+
spyChmodSync.mockImplementation(() => undefined);
454+
await expect(
455+
finder.findPyPyVersion('pypy3.8', architecture, false, false, false)
456+
).rejects.toThrowError();
457+
await expect(
458+
finder.findPyPyVersion('pypy3.8', architecture, false, false, true)
459+
).resolves.toEqual({
460+
resolvedPythonVersion: '3.8.12',
461+
resolvedPyPyVersion: '7.3.8rc2'
462+
});
463+
});
404464
});

0 commit comments

Comments
 (0)