Skip to content

Commit 00a5248

Browse files
authored
feature: add update-environment input (#411)
This option allows to specify if the action shall update environment variables (default) or not. This allows to use the setup-python action in a composite action without side effect (except downloading/installing python if version is missing).
1 parent ffcd000 commit 00a5248

File tree

16 files changed

+4399
-3868
lines changed

16 files changed

+4399
-3868
lines changed

.github/workflows/test-pypy.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,29 @@ jobs:
6565
EXECUTABLE=${EXECUTABLE%%-*} # remove any -* suffixe
6666
${EXECUTABLE} --version
6767
shell: bash
68+
69+
setup-pypy-noenv:
70+
name: Setup PyPy ${{ matrix.pypy }} ${{ matrix.os }} (noenv)
71+
runs-on: ${{ matrix.os }}
72+
strategy:
73+
fail-fast: false
74+
matrix:
75+
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-latest]
76+
pypy: ['pypy2.7', 'pypy3.7', 'pypy3.8', 'pypy3.9-nightly']
77+
78+
steps:
79+
- name: Checkout
80+
uses: actions/checkout@v3
81+
82+
- name: setup-python ${{ matrix.pypy }}
83+
id: setup-python
84+
uses: ./
85+
with:
86+
python-version: ${{ matrix.pypy }}
87+
update-environment: false
88+
89+
- name: PyPy and Python version
90+
run: ${{ steps.setup-python.outputs.python-path }} --version
91+
92+
- name: Run simple code
93+
run: ${{ steps.setup-python.outputs.python-path }} -c 'import math; print(math.factorial(5))'

.github/workflows/test-python.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,28 @@ jobs:
147147

148148
- name: Run simple code
149149
run: python -c 'import math; print(math.factorial(5))'
150+
151+
setup-versions-noenv:
152+
name: Setup ${{ matrix.python }} ${{ matrix.os }} (noenv)
153+
runs-on: ${{ matrix.os }}
154+
strategy:
155+
fail-fast: false
156+
matrix:
157+
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
158+
python: ["3.7", "3.8", "3.9", "3.10"]
159+
steps:
160+
- name: Checkout
161+
uses: actions/checkout@v3
162+
163+
- name: setup-python ${{ matrix.python }}
164+
id: setup-python
165+
uses: ./
166+
with:
167+
python-version: ${{ matrix.python }}
168+
update-environment: false
169+
170+
- name: Python version
171+
run: ${{ steps.setup-python.outputs.python-path }} --version
172+
173+
- name: Run simple code
174+
run: ${{ steps.setup-python.outputs.python-path }} -c 'import math; print(math.factorial(5))'

.licenses/npm/@actions/core.dep.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.licenses/npm/@actions/http-client-1.0.8.dep.yml

Lines changed: 0 additions & 32 deletions
This file was deleted.

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,26 @@ steps:
320320
- run: pipenv install
321321
```
322322
323+
# Environment variables
324+
325+
The `update-environment` flag defaults to `true`.
326+
With this setting, the action will add/update environment variables (e.g. `PATH`, `PKG_CONFIG_PATH`, `pythonLocation`) for `python` to just work out of the box.
327+
328+
If `update-environment` is set to `false`, the action will not add/update environment variables.
329+
This can prove useful if you want the only side-effect to be to ensure python is installed and rely on the `python-path` output to run python.
330+
Such a requirement on side-effect could be because you don't want your composite action messing with your user's workflows.
331+
332+
```yaml
333+
steps:
334+
- uses: actions/checkout@v3
335+
- uses: actions/setup-python@v4
336+
id: cp310
337+
with:
338+
python-version: '3.10'
339+
update-environment: false
340+
- run: ${{ steps.cp310.outputs.python-path }} my_script.py
341+
```
342+
323343
# Using `setup-python` with a self hosted runner
324344

325345
Python distributions are only available for the same [environments](https://github.com/actions/virtual-environments#available-environments) that GitHub Actions hosted environments are available for. If you are using an unsupported version of Ubuntu such as `19.04` or another Linux distribution such as Fedora, `setup-python` will not work. If you have a supported self-hosted runner and you would like to use `setup-python`, there are a few extra things you need to make sure are set up so that new versions of Python can be downloaded and configured on your runner.

__tests__/find-pypy.test.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {HttpClient} from '@actions/http-client';
55
import * as ifm from '@actions/http-client/interfaces';
66
import * as tc from '@actions/tool-cache';
77
import * as exec from '@actions/exec';
8+
import * as core from '@actions/core';
89

910
import * as path from 'path';
1011
import * as semver from 'semver';
@@ -148,6 +149,8 @@ describe('findPyPyVersion', () => {
148149
let spyWriteExactPyPyVersionFile: jest.SpyInstance;
149150
let spyCacheDir: jest.SpyInstance;
150151
let spyChmodSync: jest.SpyInstance;
152+
let spyCoreAddPath: jest.SpyInstance;
153+
let spyCoreExportVariable: jest.SpyInstance;
151154

152155
beforeEach(() => {
153156
tcFind = jest.spyOn(tc, 'find');
@@ -201,6 +204,10 @@ describe('findPyPyVersion', () => {
201204

202205
spyExistsSync = jest.spyOn(fs, 'existsSync');
203206
spyExistsSync.mockReturnValue(true);
207+
208+
spyCoreAddPath = jest.spyOn(core, 'addPath');
209+
210+
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
204211
});
205212

206213
afterEach(() => {
@@ -211,22 +218,31 @@ describe('findPyPyVersion', () => {
211218

212219
it('found PyPy in toolcache', async () => {
213220
await expect(
214-
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture)
221+
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, true)
215222
).resolves.toEqual({
216223
resolvedPythonVersion: '3.6.12',
217224
resolvedPyPyVersion: '7.3.3'
218225
});
226+
expect(spyCoreAddPath).toHaveBeenCalled();
227+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
228+
'pythonLocation',
229+
expect.anything()
230+
);
231+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
232+
'PKG_CONFIG_PATH',
233+
expect.anything()
234+
);
219235
});
220236

221237
it('throw on invalid input format', async () => {
222238
await expect(
223-
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture)
239+
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true)
224240
).rejects.toThrow();
225241
});
226242

227243
it('throw on invalid input format pypy3.7-7.3.x', async () => {
228244
await expect(
229-
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture)
245+
finder.findPyPyVersion('pypy3.7-v7.3.x', architecture, true)
230246
).rejects.toThrow();
231247
});
232248

@@ -238,16 +254,42 @@ describe('findPyPyVersion', () => {
238254
spyChmodSync = jest.spyOn(fs, 'chmodSync');
239255
spyChmodSync.mockImplementation(() => undefined);
240256
await expect(
241-
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture)
257+
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, true)
258+
).resolves.toEqual({
259+
resolvedPythonVersion: '3.7.9',
260+
resolvedPyPyVersion: '7.3.3'
261+
});
262+
expect(spyCoreAddPath).toHaveBeenCalled();
263+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
264+
'pythonLocation',
265+
expect.anything()
266+
);
267+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
268+
'PKG_CONFIG_PATH',
269+
expect.anything()
270+
);
271+
});
272+
273+
it('found and install successfully without environment update', async () => {
274+
spyCacheDir = jest.spyOn(tc, 'cacheDir');
275+
spyCacheDir.mockImplementation(() =>
276+
path.join(toolDir, 'PyPy', '3.7.7', architecture)
277+
);
278+
spyChmodSync = jest.spyOn(fs, 'chmodSync');
279+
spyChmodSync.mockImplementation(() => undefined);
280+
await expect(
281+
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false)
242282
).resolves.toEqual({
243283
resolvedPythonVersion: '3.7.9',
244284
resolvedPyPyVersion: '7.3.3'
245285
});
286+
expect(spyCoreAddPath).not.toHaveBeenCalled();
287+
expect(spyCoreExportVariable).not.toHaveBeenCalled();
246288
});
247289

248290
it('throw if release is not found', async () => {
249291
await expect(
250-
finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture)
292+
finder.findPyPyVersion('pypy-3.7-v7.5.x', architecture, true)
251293
).rejects.toThrowError(
252294
`PyPy version 3.7 (v7.5.x) with arch ${architecture} not found`
253295
);

__tests__/finder.test.ts

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,54 @@ process.env['RUNNER_TOOL_CACHE'] = toolDir;
1919
process.env['RUNNER_TEMP'] = tempDir;
2020

2121
import * as tc from '@actions/tool-cache';
22+
import * as core from '@actions/core';
2223
import * as finder from '../src/find-python';
2324
import * as installer from '../src/install-python';
2425

2526
const manifestData = require('./data/versions-manifest.json');
2627

2728
describe('Finder tests', () => {
29+
let spyCoreAddPath: jest.SpyInstance;
30+
let spyCoreExportVariable: jest.SpyInstance;
31+
32+
beforeEach(() => {
33+
spyCoreAddPath = jest.spyOn(core, 'addPath');
34+
35+
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
36+
});
37+
2838
afterEach(() => {
2939
jest.resetAllMocks();
3040
jest.clearAllMocks();
41+
jest.restoreAllMocks();
3142
});
3243

3344
it('Finds Python if it is installed', async () => {
3445
const pythonDir: string = path.join(toolDir, 'Python', '3.0.0', 'x64');
3546
await io.mkdirP(pythonDir);
3647
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
3748
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
38-
await finder.useCpythonVersion('3.x', 'x64');
49+
await finder.useCpythonVersion('3.x', 'x64', true);
50+
expect(spyCoreAddPath).toHaveBeenCalled();
51+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
52+
'pythonLocation',
53+
expect.anything()
54+
);
55+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
56+
'PKG_CONFIG_PATH',
57+
expect.anything()
58+
);
59+
});
60+
61+
it('Finds Python if it is installed without environment update', async () => {
62+
const pythonDir: string = path.join(toolDir, 'Python', '3.0.0', 'x64');
63+
await io.mkdirP(pythonDir);
64+
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
65+
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
66+
await finder.useCpythonVersion('3.x', 'x64', false);
67+
expect(spyCoreAddPath).not.toHaveBeenCalled();
68+
expect(spyCoreExportVariable).not.toHaveBeenCalled();
69+
expect(spyCoreExportVariable).not.toHaveBeenCalled();
3970
});
4071

4172
it('Finds stable Python version if it is not installed, but exists in the manifest', async () => {
@@ -52,7 +83,16 @@ describe('Finder tests', () => {
5283
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
5384
});
5485
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
55-
await finder.useCpythonVersion('1.2.3', 'x64');
86+
await finder.useCpythonVersion('1.2.3', 'x64', true);
87+
expect(spyCoreAddPath).toHaveBeenCalled();
88+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
89+
'pythonLocation',
90+
expect.anything()
91+
);
92+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
93+
'PKG_CONFIG_PATH',
94+
expect.anything()
95+
);
5696
});
5797

5898
it('Finds pre-release Python version in the manifest', async () => {
@@ -74,17 +114,28 @@ describe('Finder tests', () => {
74114
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
75115
});
76116
// This will throw if it doesn't find it in the manifest (because no such version exists)
77-
await finder.useCpythonVersion('1.2.3-beta.2', 'x64');
117+
await finder.useCpythonVersion('1.2.3-beta.2', 'x64', true);
118+
expect(spyCoreAddPath).toHaveBeenCalled();
119+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
120+
'pythonLocation',
121+
expect.anything()
122+
);
123+
expect(spyCoreExportVariable).toHaveBeenCalledWith(
124+
'PKG_CONFIG_PATH',
125+
expect.anything()
126+
);
78127
});
79128

80129
it('Errors if Python is not installed', async () => {
81130
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
82131
let thrown = false;
83132
try {
84-
await finder.useCpythonVersion('3.300000', 'x64');
133+
await finder.useCpythonVersion('3.300000', 'x64', true);
85134
} catch {
86135
thrown = true;
87136
}
88137
expect(thrown).toBeTruthy();
138+
expect(spyCoreAddPath).not.toHaveBeenCalled();
139+
expect(spyCoreExportVariable).not.toHaveBeenCalled();
89140
});
90141
});

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ inputs:
1717
default: ${{ github.token }}
1818
cache-dependency-path:
1919
description: 'Used to specify the path to dependency files. Supports wildcards or a list of file names for caching multiple dependencies.'
20+
update-environment:
21+
description: 'Set this option if you want the action to update environment variables.'
22+
default: true
2023
outputs:
2124
python-version:
2225
description: "The installed python version. Useful when given a version range as input."

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy