Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: actions/setup-python
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.1.0
Choose a base ref
...
head repository: actions/setup-python
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.2.0
Choose a head ref

Commits on Jul 3, 2022

  1. Update actions

    wrt54g authored Jul 3, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f4b85ae View commit details
  2. Update actions

    wrt54g authored Jul 3, 2022
    Copy the full SHA
    5a1dd6b View commit details
  3. Copy the full SHA
    7d9c63d View commit details
  4. Update actions

    wrt54g authored Jul 3, 2022
    Copy the full SHA
    d08a9d7 View commit details
  5. Update actions

    wrt54g authored Jul 3, 2022
    Copy the full SHA
    4a7ca55 View commit details
  6. Copy the full SHA
    b318cec View commit details

Commits on Jul 12, 2022

  1. Rearrange README.md, add advanced-usage.md

    IvanZosimov committed Jul 12, 2022
    Copy the full SHA
    9a40041 View commit details
  2. Change tool cache wording

    IvanZosimov committed Jul 12, 2022
    Copy the full SHA
    6dd8ff7 View commit details

Commits on Jul 13, 2022

  1. Update REAMDE.md and advanced-usage.md

    IvanZosimov committed Jul 13, 2022
    Copy the full SHA
    746f28a View commit details
  2. Update action.yml file

    IvanZosimov committed Jul 13, 2022
    Copy the full SHA
    09086cc View commit details
  3. Fix review points

    IvanZosimov committed Jul 13, 2022
    Copy the full SHA
    61fb4e4 View commit details
  4. Fix review points

    IvanZosimov committed Jul 13, 2022
    Copy the full SHA
    386e4ea View commit details
  5. Fix action.yml file

    IvanZosimov committed Jul 13, 2022
    Copy the full SHA
    799afeb View commit details

Commits on Jul 14, 2022

  1. Merge pull request #454 from wrt54g/update

    Update actions
    marko-zivic-93 authored Jul 14, 2022
    Copy the full SHA
    c474c82 View commit details

Commits on Jul 15, 2022

  1. Fix resolveVersionInput() logic

    IvanZosimov committed Jul 15, 2022
    Copy the full SHA
    b88a682 View commit details

Commits on Jul 18, 2022

  1. Fix documentation

    Docs were updated to incorporate changes regarding tool cache folder
    on the self-hosted runner and changes in resolveVersionInput()
    IvanZosimov committed Jul 18, 2022
    Copy the full SHA
    5517d5f View commit details

Commits on Jul 19, 2022

  1. Merge pull request #465 from IvanZosimov/pythonversionfile

    Fixed resolveVersionInput() logic
    marko-zivic-93 authored Jul 19, 2022
    Copy the full SHA
    aba6f4b View commit details
  2. Copy the full SHA
    592a7a7 View commit details

Commits on Jul 25, 2022

  1. Copy the full SHA
    49a521f View commit details
  2. Copy the full SHA
    2f06e9d View commit details
  3. Change part with realted to self-hosted runners

    IvanZosimov committed Jul 25, 2022
    Copy the full SHA
    00d9c42 View commit details
  4. Fix typo

    IvanZosimov committed Jul 25, 2022
    Copy the full SHA
    889226a View commit details
  5. Update README.md

    Add a section to advise using only pip instead of poetry.
    scooby authored Jul 25, 2022
    Copy the full SHA
    e147df2 View commit details

Commits on Jul 26, 2022

  1. Fix typo

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    0d94a5d View commit details
  2. Change yml and rebuild action

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    b2241a4 View commit details
  3. Sync with Main branch

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    1f0a39a View commit details
  4. Fix merge artifacts

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    dd40245 View commit details
  5. Merge pull request #471 from scooby/main

    Recommend using pip for simple poetry projects
    marko-zivic-93 authored Jul 26, 2022
    Copy the full SHA
    5df6377 View commit details
  6. Fix grammar in both documents

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    a624f1f View commit details
  7. Fix typo in advanced-usage.md

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    b152b04 View commit details
  8. docs: Agent Tool Cache

    This updates and simplies the tool cache documentation to match the implementation in
    both  and
    
      Relates #459
    techman83 committed Jul 26, 2022
    Copy the full SHA
    10b8409 View commit details
  9. fix: Self-Hosted Tool Cache

    This fixes the tool cache path for self-hosted runners, along
    with handling AGENT_TOOLSDIRECTORY for both hosted + self-hosted.
    
        Fixes #459
    techman83 committed Jul 26, 2022
    Copy the full SHA
    9f1915a View commit details
  10. feat: Add 'IS_MAC' util

    techman83 committed Jul 26, 2022
    Copy the full SHA
    467a981 View commit details
  11. fix: Mac Toolpath

    Shared libraries for the Mac python builds are not configured with the
    relocatable flag, thus must always be configured with the hosted path.
    
    Relates #459
    techman83 committed Jul 26, 2022
    2
    Copy the full SHA
    bc8ee42 View commit details
  12. docs: Mac Tool Path

    Ensure that the path requirements and reasoning is clear, to reduce
    confusion when using self-hosted, or attempting to set an
    'AGENT_TOOLSDIRECTORY' environment variable.
    techman83 committed Jul 26, 2022
    Copy the full SHA
    d5d6770 View commit details
  13. Copy the full SHA
    7e39d25 View commit details
  14. Fix review points

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    81cda82 View commit details
  15. Fix typo

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    c6e66a7 View commit details
  16. Change contents to make them more readable

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    fd6f59d View commit details
  17. Change advanced-usage.md

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    853c012 View commit details
  18. Revert changes

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    fe396d3 View commit details
  19. Fix typo

    IvanZosimov committed Jul 26, 2022
    Copy the full SHA
    72394d1 View commit details
  20. Merge pull request #466 from techman83/fix/tool_path

    Fix Tool Path handling for self-hosted runners
    marko-zivic-93 authored Jul 26, 2022
    Copy the full SHA
    a93d541 View commit details

Commits on Jul 28, 2022

  1. Fix review points

    IvanZosimov committed Jul 28, 2022
    Copy the full SHA
    c318b92 View commit details

Commits on Aug 1, 2022

  1. Fix review points

    IvanZosimov committed Aug 1, 2022
    Copy the full SHA
    cfcafa5 View commit details
  2. Fix broken links

    IvanZosimov committed Aug 1, 2022
    Copy the full SHA
    c4e98b7 View commit details
  3. Fix broken links in the text body

    IvanZosimov committed Aug 1, 2022
    Copy the full SHA
    789730b View commit details
  4. Copy the full SHA
    e084fca View commit details

Commits on Aug 2, 2022

  1. Merge pull request #472 from IvanZosimov/ReadmeUpdate

    Updated README.md in setup-python
    marko-zivic-93 authored Aug 2, 2022
    Copy the full SHA
    b55428b View commit details
4 changes: 2 additions & 2 deletions .github/workflows/check-dist.yml
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Set Node.js 16.x
uses: actions/setup-node@v3
@@ -45,7 +45,7 @@ jobs:
id: diff

# If index.js was different than expected, upload the expected version as an artifact
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
with:
name: dist
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -18,19 +18,19 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -44,4 +44,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
6 changes: 3 additions & 3 deletions .github/workflows/e2e-cache.yml
Original file line number Diff line number Diff line change
@@ -72,15 +72,15 @@ jobs:
- uses: actions/checkout@v3
- name: Install poetry
run: pipx install poetry
- name: Init pyproject.toml
run: mv ./__tests__/data/pyproject.toml .
- name: Setup Python
uses: ./
with:
python-version: ${{ matrix.python-version }}
cache: 'poetry'
- name: Init pyproject.toml
run: poetry init -n
- name: Install dependencies
run: poetry add flake8
run: poetry install

python-pip-dependencies-caching-path:
name: Test pip (Python ${{ matrix.python-version}}, ${{ matrix.os }})
2 changes: 1 addition & 1 deletion .github/workflows/licensed.yml
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
name: Check licenses
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set Node.js 16.x
uses: actions/setup-node@v3
with:
4 changes: 2 additions & 2 deletions .github/workflows/release-new-action-version.yml
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.1.0
uses: actions/publish-action@v0.2.0
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
35 changes: 34 additions & 1 deletion .github/workflows/test-pypy.yml
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: setup-python ${{ matrix.pypy }}
id: setup-python
@@ -91,3 +91,36 @@ jobs:

- name: Run simple code
run: ${{ steps.setup-python.outputs.python-path }} -c 'import math; print(math.factorial(5))'

check-latest:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- name: Setup PyPy and check latest
uses: ./
with:
python-version: 'pypy-3.7-v7.3.x'
check-latest: true
- name: PyPy and Python version
run: python --version

- name: Run simple code
run: python -c 'import math; print(math.factorial(5))'

- name: Assert PyPy is running
run: |
import platform
assert platform.python_implementation().lower() == "pypy"
shell: python

- name: Assert expected binaries (or symlinks) are present
run: |
EXECUTABLE="pypy-3.7-v7.3.x"
EXECUTABLE=${EXECUTABLE/-/} # remove the first '-' in "pypy-X.Y" -> "pypyX.Y" to match executable name
EXECUTABLE=${EXECUTABLE%%-*} # remove any -* suffixe
${EXECUTABLE} --version
shell: bash
24 changes: 24 additions & 0 deletions .github/workflows/test-python.yml
Original file line number Diff line number Diff line change
@@ -172,3 +172,27 @@ jobs:

- name: Run simple code
run: ${{ steps.setup-python.outputs.python-path }} -c 'import math; print(math.factorial(5))'

check-latest:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v3
- name: Setup Python and check latest
uses: ./
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Validate version
run: |
$pythonVersion = (python --version)
if ("$pythonVersion" -NotMatch "${{ matrix.python }}"){
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
exit 1
}
$pythonVersion
shell: pwsh
2 changes: 1 addition & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ jobs:
operating-system: [ubuntu-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Set Node.js 16.x
uses: actions/setup-node@v3
32 changes: 0 additions & 32 deletions .licenses/npm/@actions/http-client.dep.yml

This file was deleted.

419 changes: 41 additions & 378 deletions README.md

Large diffs are not rendered by default.

29 changes: 26 additions & 3 deletions __tests__/cache-restore.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as core from '@actions/core';
import * as cache from '@actions/cache';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import {getCacheDistributor} from '../src/cache-distributions/cache-factory';
import * as utils from './../src/utils';

describe('restore-cache', () => {
const pipFileLockHash =
@@ -28,13 +30,17 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
let saveSatetSpy: jest.SpyInstance;
let getStateSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance;
let getLinuxOSReleaseInfoSpy: jest.SpyInstance;

// cache spy
let restoreCacheSpy: jest.SpyInstance;

// exec spy
let getExecOutputSpy: jest.SpyInstance;

// io spy
let whichSpy: jest.SpyInstance;

beforeEach(() => {
process.env['RUNNER_OS'] = process.env['RUNNER_OS'] ?? 'linux';

@@ -74,6 +80,10 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
return primaryKey;
}
);

whichSpy = jest.spyOn(io, 'which');
whichSpy.mockImplementation(() => '/path/to/python');
getLinuxOSReleaseInfoSpy = jest.spyOn(utils, 'getLinuxOSReleaseInfo');
});

describe('Validate provided package manager', () => {
@@ -109,11 +119,24 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
pythonVersion,
dependencyFile
);

if (process.platform === 'linux') {
getLinuxOSReleaseInfoSpy.mockImplementation(() =>
Promise.resolve('Ubuntu-20.4')
);
}

await cacheDistributor.restoreCache();

expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-python-${pythonVersion}-${packageManager}-${fileHash}`
);
if (process.platform === 'linux' && packageManager === 'pip') {
expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-Ubuntu-20.4-python-${pythonVersion}-${packageManager}-${fileHash}`
);
} else {
expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-python-${pythonVersion}-${packageManager}-${fileHash}`
);
}
},
30000
);
15 changes: 15 additions & 0 deletions __tests__/data/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[tool.poetry]
name = "testactiontasks"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = "^3.8"
flake8 = "^4.0.1"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
117 changes: 110 additions & 7 deletions __tests__/find-pypy.test.ts
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ import * as finder from '../src/find-pypy';
import {
IPyPyManifestRelease,
IS_WINDOWS,
validateVersion,
getPyPyVersionFromPath
} from '../src/utils';

@@ -82,6 +81,12 @@ describe('findPyPyToolCache', () => {
const pypyPath = path.join('PyPy', actualPythonVersion, architecture);
let tcFind: jest.SpyInstance;
let spyReadExactPyPyVersion: jest.SpyInstance;
let infoSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
let addPathSpy: jest.SpyInstance;
let exportVariableSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance;

beforeEach(() => {
tcFind = jest.spyOn(tc, 'find');
@@ -94,6 +99,24 @@ describe('findPyPyToolCache', () => {

spyReadExactPyPyVersion = jest.spyOn(utils, 'readExactPyPyVersionFile');
spyReadExactPyPyVersion.mockImplementation(() => actualPyPyVersion);

infoSpy = jest.spyOn(core, 'info');
infoSpy.mockImplementation(() => null);

warningSpy = jest.spyOn(core, 'warning');
warningSpy.mockImplementation(() => null);

debugSpy = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(() => null);

addPathSpy = jest.spyOn(core, 'addPath');
addPathSpy.mockImplementation(() => null);

exportVariableSpy = jest.spyOn(core, 'exportVariable');
exportVariableSpy.mockImplementation(() => null);

setOutputSpy = jest.spyOn(core, 'setOutput');
setOutputSpy.mockImplementation(() => null);
});

afterEach(() => {
@@ -136,6 +159,13 @@ describe('findPyPyToolCache', () => {
});

describe('findPyPyVersion', () => {
let getBooleanInputSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
let infoSpy: jest.SpyInstance;
let addPathSpy: jest.SpyInstance;
let exportVariableSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance;
let tcFind: jest.SpyInstance;
let spyExtractZip: jest.SpyInstance;
let spyExtractTar: jest.SpyInstance;
@@ -154,6 +184,27 @@ describe('findPyPyVersion', () => {
const env = process.env;

beforeEach(() => {
getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
getBooleanInputSpy.mockImplementation(() => false);

infoSpy = jest.spyOn(core, 'info');
infoSpy.mockImplementation(() => {});

warningSpy = jest.spyOn(core, 'warning');
warningSpy.mockImplementation(() => null);

debugSpy = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(() => null);

addPathSpy = jest.spyOn(core, 'addPath');
addPathSpy.mockImplementation(() => null);

exportVariableSpy = jest.spyOn(core, 'exportVariable');
exportVariableSpy.mockImplementation(() => null);

setOutputSpy = jest.spyOn(core, 'setOutput');
setOutputSpy.mockImplementation(() => null);

jest.resetModules();
process.env = {...env};
tcFind = jest.spyOn(tc, 'find');
@@ -222,7 +273,7 @@ describe('findPyPyVersion', () => {

it('found PyPy in toolcache', async () => {
await expect(
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, true)
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, true, false)
).resolves.toEqual({
resolvedPythonVersion: '3.6.12',
resolvedPyPyVersion: '7.3.3'
@@ -240,13 +291,13 @@ describe('findPyPyVersion', () => {

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

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

@@ -258,7 +309,7 @@ describe('findPyPyVersion', () => {
spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined);
await expect(
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, true)
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, true, false)
).resolves.toEqual({
resolvedPythonVersion: '3.7.9',
resolvedPyPyVersion: '7.3.3'
@@ -282,7 +333,7 @@ describe('findPyPyVersion', () => {
spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined);
await expect(
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false)
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false, false)
).resolves.toEqual({
resolvedPythonVersion: '3.7.9',
resolvedPyPyVersion: '7.3.3'
@@ -293,9 +344,61 @@ describe('findPyPyVersion', () => {

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

it('check-latest enabled version found and used from toolcache', async () => {
await expect(
finder.findPyPyVersion('pypy-3.6-v7.3.x', architecture, false, true)
).resolves.toEqual({
resolvedPythonVersion: '3.6.12',
resolvedPyPyVersion: '7.3.3'
});

expect(infoSpy).toHaveBeenCalledWith(
'Resolved as PyPy 7.3.3 with Python (3.6.12)'
);
});

it('check-latest enabled version found and install successfully', async () => {
spyCacheDir = jest.spyOn(tc, 'cacheDir');
spyCacheDir.mockImplementation(() =>
path.join(toolDir, 'PyPy', '3.7.7', architecture)
);
spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined);
await expect(
finder.findPyPyVersion('pypy-3.7-v7.3.x', architecture, false, true)
).resolves.toEqual({
resolvedPythonVersion: '3.7.9',
resolvedPyPyVersion: '7.3.3'
});
expect(infoSpy).toHaveBeenCalledWith(
'Resolved as PyPy 7.3.3 with Python (3.7.9)'
);
});

it('check-latest enabled version is not found and used from toolcache', async () => {
tcFind.mockImplementationOnce((tool: string, version: string) => {
const semverRange = new semver.Range(version);
let pypyPath = '';
if (semver.satisfies('3.8.8', semverRange)) {
pypyPath = path.join(toolDir, 'PyPy', '3.8.8', architecture);
}
return pypyPath;
});
await expect(
finder.findPyPyVersion('pypy-3.8-v7.3.x', architecture, false, true)
).resolves.toEqual({
resolvedPythonVersion: '3.8.8',
resolvedPyPyVersion: '7.3.3'
});

expect(infoSpy).toHaveBeenCalledWith(
'Failed to resolve PyPy v7.3.x with Python (3.8) from manifest'
);
});
});
87 changes: 79 additions & 8 deletions __tests__/finder.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io = require('@actions/io');
import fs = require('fs');
import path = require('path');
import * as io from '@actions/io';
import os from 'os';
import fs from 'fs';
import path from 'path';

const toolDir = path.join(
__dirname,
@@ -26,11 +27,14 @@ import * as installer from '../src/install-python';
const manifestData = require('./data/versions-manifest.json');

describe('Finder tests', () => {
let writeSpy: jest.SpyInstance;
let spyCoreAddPath: jest.SpyInstance;
let spyCoreExportVariable: jest.SpyInstance;
const env = process.env;

beforeEach(() => {
writeSpy = jest.spyOn(process.stdout, 'write');
writeSpy.mockImplementation(() => {});
jest.resetModules();
process.env = {...env};
spyCoreAddPath = jest.spyOn(core, 'addPath');
@@ -45,11 +49,14 @@ describe('Finder tests', () => {
});

it('Finds Python if it is installed', async () => {
const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
getBooleanInputSpy.mockImplementation(input => false);

const pythonDir: string = path.join(toolDir, 'Python', '3.0.0', 'x64');
await io.mkdirP(pythonDir);
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('3.x', 'x64', true);
await finder.useCpythonVersion('3.x', 'x64', true, false);
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
@@ -66,7 +73,7 @@ describe('Finder tests', () => {
await io.mkdirP(pythonDir);
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('3.x', 'x64', false);
await finder.useCpythonVersion('3.x', 'x64', false, false);
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
});
@@ -75,6 +82,9 @@ describe('Finder tests', () => {
const findSpy: jest.SpyInstance = jest.spyOn(tc, 'getManifestFromRepo');
findSpy.mockImplementation(() => <tc.IToolRelease[]>manifestData);

const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
getBooleanInputSpy.mockImplementation(input => false);

const installSpy: jest.SpyInstance = jest.spyOn(
installer,
'installCpythonFromRelease'
@@ -85,7 +95,7 @@ describe('Finder tests', () => {
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
});
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('1.2.3', 'x64', true);
await finder.useCpythonVersion('1.2.3', 'x64', true, false);
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
@@ -101,6 +111,9 @@ describe('Finder tests', () => {
const findSpy: jest.SpyInstance = jest.spyOn(tc, 'getManifestFromRepo');
findSpy.mockImplementation(() => <tc.IToolRelease[]>manifestData);

const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
getBooleanInputSpy.mockImplementation(input => false);

const installSpy: jest.SpyInstance = jest.spyOn(
installer,
'installCpythonFromRelease'
@@ -116,7 +129,65 @@ describe('Finder tests', () => {
fs.writeFileSync(`${pythonDir}.complete`, 'hello');
});
// This will throw if it doesn't find it in the manifest (because no such version exists)
await finder.useCpythonVersion('1.2.3-beta.2', 'x64', true);
await finder.useCpythonVersion('1.2.3-beta.2', 'x64', false, false);
});

it('Check-latest true, finds the latest version in the manifest', async () => {
const findSpy: jest.SpyInstance = jest.spyOn(tc, 'getManifestFromRepo');
findSpy.mockImplementation(() => <tc.IToolRelease[]>manifestData);

const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
getBooleanInputSpy.mockImplementation(input => true);

const cnSpy: jest.SpyInstance = jest.spyOn(process.stdout, 'write');
cnSpy.mockImplementation(line => {
// uncomment to debug
// process.stderr.write('write:' + line + '\n');
});

const addPathSpy: jest.SpyInstance = jest.spyOn(core, 'addPath');
addPathSpy.mockImplementation(() => null);

const infoSpy: jest.SpyInstance = jest.spyOn(core, 'info');
infoSpy.mockImplementation(() => {});

const debugSpy: jest.SpyInstance = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(() => {});

const pythonDir: string = path.join(toolDir, 'Python', '1.2.2', 'x64');
const expPath: string = path.join(toolDir, 'Python', '1.2.3', 'x64');

const installSpy: jest.SpyInstance = jest.spyOn(
installer,
'installCpythonFromRelease'
);
installSpy.mockImplementation(async () => {
await io.mkdirP(expPath);
fs.writeFileSync(`${expPath}.complete`, 'hello');
});

const tcFindSpy: jest.SpyInstance = jest.spyOn(tc, 'find');
tcFindSpy
.mockImplementationOnce(() => '')
.mockImplementationOnce(() => expPath);

await io.mkdirP(pythonDir);
await io.rmRF(path.join(toolDir, 'Python', '1.2.3'));

fs.writeFileSync(`${pythonDir}.complete`, 'hello');
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
await finder.useCpythonVersion('1.2', 'x64', true, true);

expect(infoSpy).toHaveBeenCalledWith("Resolved as '1.2.3'");
expect(infoSpy).toHaveBeenCalledWith(
'Version 1.2.3 was not found in the local cache'
);
expect(infoSpy).toBeCalledWith(
'Version 1.2.3 is available for downloading'
);
expect(installSpy).toHaveBeenCalled();
expect(addPathSpy).toHaveBeenCalledWith(expPath);
await finder.useCpythonVersion('1.2.3-beta.2', 'x64', false, true);
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalledWith(
'pythonLocation',
@@ -132,7 +203,7 @@ describe('Finder tests', () => {
// This will throw if it doesn't find it in the cache and in the manifest (because no such version exists)
let thrown = false;
try {
await finder.useCpythonVersion('3.300000', 'x64', true);
await finder.useCpythonVersion('3.300000', 'x64', true, false);
} catch {
thrown = true;
}
34 changes: 32 additions & 2 deletions __tests__/install-pypy.test.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import {HttpClient} from '@actions/http-client';
import * as ifm from '@actions/http-client/interfaces';
import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec';
import * as core from '@actions/core';
import * as path from 'path';

import * as installer from '../src/install-pypy';
@@ -51,6 +52,22 @@ describe('findRelease', () => {
download_url: `https://test.download.python.org/pypy/pypy3.6-v7.3.3-${extensionName}`
};

let getBooleanInputSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
let infoSpy: jest.SpyInstance;

beforeEach(() => {
infoSpy = jest.spyOn(core, 'info');
infoSpy.mockImplementation(() => {});

warningSpy = jest.spyOn(core, 'warning');
warningSpy.mockImplementation(() => null);

debugSpy = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(() => null);
});

it("Python version is found, but PyPy version doesn't match", () => {
const pythonVersion = '3.6';
const pypyVersion = '7.3.7';
@@ -133,6 +150,10 @@ describe('findRelease', () => {

describe('installPyPy', () => {
let tcFind: jest.SpyInstance;
let getBooleanInputSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
let infoSpy: jest.SpyInstance;
let spyExtractZip: jest.SpyInstance;
let spyExtractTar: jest.SpyInstance;
let spyFsReadDir: jest.SpyInstance;
@@ -158,6 +179,15 @@ describe('installPyPy', () => {
spyExtractTar = jest.spyOn(tc, 'extractTar');
spyExtractTar.mockImplementation(() => tempDir);

infoSpy = jest.spyOn(core, 'info');
infoSpy.mockImplementation(() => {});

warningSpy = jest.spyOn(core, 'warning');
warningSpy.mockImplementation(() => null);

debugSpy = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(() => null);

spyFsReadDir = jest.spyOn(fs, 'readdirSync');
spyFsReadDir.mockImplementation(() => ['PyPyTest']);

@@ -194,7 +224,7 @@ describe('installPyPy', () => {

it('throw if release is not found', async () => {
await expect(
installer.installPyPy('7.3.3', '3.6.17', architecture)
installer.installPyPy('7.3.3', '3.6.17', architecture, undefined)
).rejects.toThrowError(
`PyPy version 3.6.17 (7.3.3) with arch ${architecture} not found`
);
@@ -214,7 +244,7 @@ describe('installPyPy', () => {
spyChmodSync.mockImplementation(() => undefined);

await expect(
installer.installPyPy('7.3.x', '3.6.12', architecture)
installer.installPyPy('7.3.x', '3.6.12', architecture, undefined)
).resolves.toEqual({
installDir: path.join(toolDir, 'PyPy', '3.6.12', architecture),
resolvedPythonVersion: '3.6.12',
27 changes: 15 additions & 12 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
---
name: 'Setup Python'
description: 'Set up a specific version of Python and add the command-line tools to the PATH.'
author: 'GitHub'
name: "Setup Python"
description: "Set up a specific version of Python and add the command-line tools to the PATH."
author: "GitHub"
inputs:
python-version:
description: "Version range or exact version of Python to use, using SemVer's version range syntax. Reads from .python-version if unset."
description: "Version range or exact version of Python or PyPy to use, using SemVer's version range syntax. Reads from .python-version if unset."
python-version-file:
description: "File containing the Python version to use. Example: .python-version"
cache:
description: 'Used to specify a package manager for caching in the default directory. Supported values: pip, pipenv, poetry.'
description: "Used to specify a package manager for caching in the default directory. Supported values: pip, pipenv, poetry."
required: false
architecture:
description: 'The target architecture (x86, x64) of the Python interpreter.'
description: "The target architecture (x86, x64) of the Python or PyPy interpreter."
check-latest:
description: "Set this option if you want the action to check for the latest available version that satisfies the version spec."
default: false
token:
description: Used to pull python distributions from actions/python-versions. Since there's a default, this is typically not supplied by the user.
description: "Used to pull python distributions from actions/python-versions. Since there's a default, this is typically not supplied by the user."
default: ${{ github.token }}
cache-dependency-path:
description: 'Used to specify the path to dependency files. Supports wildcards or a list of file names for caching multiple dependencies.'
description: "Used to specify the path to dependency files. Supports wildcards or a list of file names for caching multiple dependencies."
update-environment:
description: 'Set this option if you want the action to update environment variables.'
description: "Set this option if you want the action to update environment variables."
default: true
outputs:
python-version:
description: "The installed python version. Useful when given a version range as input."
description: "The installed Python or PyPy version. Useful when given a version range as input."
cache-hit:
description: 'A boolean value to indicate a cache entry was found'
description: "A boolean value to indicate a cache entry was found"
python-path:
description: "The absolute path to the Python executable."
description: "The absolute path to the Python or PyPy executable."
runs:
using: 'node16'
main: 'dist/setup/index.js'
156 changes: 119 additions & 37 deletions dist/setup/index.js

Large diffs are not rendered by default.

476 changes: 476 additions & 0 deletions docs/advanced-usage.md

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions src/cache-distributions/pip-cache.ts
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ import * as path from 'path';
import os from 'os';

import CacheDistributor from './cache-distributor';
import {IS_WINDOWS} from '../utils';
import {getLinuxOSReleaseInfo, IS_LINUX, IS_WINDOWS} from '../utils';

class PipCache extends CacheDistributor {
constructor(
@@ -57,8 +57,17 @@ class PipCache extends CacheDistributor {

protected async computeKeys() {
const hash = await glob.hashFiles(this.cacheDependencyPath);
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
const restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.packageManager}`;
let primaryKey = '';
let restoreKey = '';

if (IS_LINUX) {
const osRelease = await getLinuxOSReleaseInfo();
primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osRelease}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${osRelease}-python-${this.pythonVersion}-${this.packageManager}`;
} else {
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}`;
}

return {
primaryKey,
24 changes: 23 additions & 1 deletion src/cache-distributions/poetry-cache.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as glob from '@actions/glob';
import * as os from 'os';
import * as io from '@actions/io';
import * as path from 'path';
import * as exec from '@actions/exec';
import * as core from '@actions/core';

import CacheDistributor from './cache-distributor';
import {logWarning} from '../utils';

class PoetryCache extends CacheDistributor {
constructor(
@@ -28,6 +30,26 @@ class PoetryCache extends CacheDistributor {
paths.push(path.join(process.cwd(), '.venv'));
}

const pythonLocation = await io.which('python');

if (pythonLocation) {
core.debug(`pythonLocation is ${pythonLocation}`);
const {
exitCode,
stderr
} = await exec.getExecOutput(
`poetry env use ${pythonLocation}`,
undefined,
{ignoreReturnCode: true}
);

if (exitCode) {
logWarning(stderr);
}
} else {
logWarning('python binaries were not found in PATH');
}

return paths;
}

34 changes: 31 additions & 3 deletions src/find-pypy.ts
Original file line number Diff line number Diff line change
@@ -6,7 +6,8 @@ import {
validateVersion,
getPyPyVersionFromPath,
readExactPyPyVersionFile,
validatePythonVersionFormatForPyPy
validatePythonVersionFormatForPyPy,
IPyPyManifestRelease
} from './utils';

import * as semver from 'semver';
@@ -21,14 +22,40 @@ interface IPyPyVersionSpec {
export async function findPyPyVersion(
versionSpec: string,
architecture: string,
updateEnvironment: boolean
updateEnvironment: boolean,
checkLatest: boolean
): Promise<{resolvedPyPyVersion: string; resolvedPythonVersion: string}> {
let resolvedPyPyVersion = '';
let resolvedPythonVersion = '';
let installDir: string | null;
let releases: IPyPyManifestRelease[] | undefined;

const pypyVersionSpec = parsePyPyVersion(versionSpec);

if (checkLatest) {
releases = await pypyInstall.getAvailablePyPyVersions();
if (releases && releases.length > 0) {
const releaseData = pypyInstall.findRelease(
releases,
pypyVersionSpec.pythonVersion,
pypyVersionSpec.pypyVersion,
architecture
);

if (releaseData) {
core.info(
`Resolved as PyPy ${releaseData.resolvedPyPyVersion} with Python (${releaseData.resolvedPythonVersion})`
);
pypyVersionSpec.pythonVersion = releaseData.resolvedPythonVersion;
pypyVersionSpec.pypyVersion = releaseData.resolvedPyPyVersion;
} else {
core.info(
`Failed to resolve PyPy ${pypyVersionSpec.pypyVersion} with Python (${pypyVersionSpec.pythonVersion}) from manifest`
);
}
}
}

({installDir, resolvedPythonVersion, resolvedPyPyVersion} = findPyPyToolCache(
pypyVersionSpec.pythonVersion,
pypyVersionSpec.pypyVersion,
@@ -43,7 +70,8 @@ export async function findPyPyVersion(
} = await pypyInstall.installPyPy(
pypyVersionSpec.pypyVersion,
pypyVersionSpec.pythonVersion,
architecture
architecture,
releases
));
}

29 changes: 26 additions & 3 deletions src/find-python.ts
Original file line number Diff line number Diff line change
@@ -33,12 +33,34 @@ function binDir(installDir: string): string {
export async function useCpythonVersion(
version: string,
architecture: string,
updateEnvironment: boolean
updateEnvironment: boolean,
checkLatest: boolean
): Promise<InstalledVersion> {
let manifest: tc.IToolRelease[] | null = null;
const desugaredVersionSpec = desugarDevVersion(version);
const semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
let semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec);
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);

if (checkLatest) {
manifest = await installer.getManifest();
const resolvedVersion = (
await installer.findReleaseFromManifest(
semanticVersionSpec,
architecture,
manifest
)
)?.version;

if (resolvedVersion) {
semanticVersionSpec = resolvedVersion;
core.info(`Resolved as '${semanticVersionSpec}'`);
} else {
core.info(
`Failed to resolve version ${semanticVersionSpec} from manifest`
);
}
}

let installDir: string | null = tc.find(
'Python',
semanticVersionSpec,
@@ -50,7 +72,8 @@ export async function useCpythonVersion(
);
const foundRelease = await installer.findReleaseFromManifest(
semanticVersionSpec,
architecture
architecture,
manifest
);

if (foundRelease && foundRelease.files && foundRelease.files.length > 0) {
8 changes: 5 additions & 3 deletions src/install-pypy.ts
Original file line number Diff line number Diff line change
@@ -19,11 +19,13 @@ import {
export async function installPyPy(
pypyVersion: string,
pythonVersion: string,
architecture: string
architecture: string,
releases: IPyPyManifestRelease[] | undefined
) {
let downloadDir;

const releases = await getAvailablePyPyVersions();
releases = releases ?? (await getAvailablePyPyVersions());

if (!releases || releases.length === 0) {
throw new Error('No release was found in PyPy version.json');
}
@@ -78,7 +80,7 @@ export async function installPyPy(
return {installDir, resolvedPythonVersion, resolvedPyPyVersion};
}

async function getAvailablePyPyVersions() {
export async function getAvailablePyPyVersions() {
const url = 'https://downloads.python.org/pypy/versions.json';
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');

29 changes: 21 additions & 8 deletions src/install-python.ts
Original file line number Diff line number Diff line change
@@ -14,20 +14,33 @@ export const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_O

export async function findReleaseFromManifest(
semanticVersionSpec: string,
architecture: string
architecture: string,
manifest: tc.IToolRelease[] | null
): Promise<tc.IToolRelease | undefined> {
const manifest: tc.IToolRelease[] = await tc.getManifestFromRepo(
MANIFEST_REPO_OWNER,
MANIFEST_REPO_NAME,
AUTH,
MANIFEST_REPO_BRANCH
);
return await tc.findFromManifest(
if (!manifest) {
manifest = await getManifest();
}

const foundRelease = await tc.findFromManifest(
semanticVersionSpec,
false,
manifest,
architecture
);

return foundRelease;
}

export function getManifest(): Promise<tc.IToolRelease[]> {
core.debug(
`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`
);
return tc.getManifestFromRepo(
MANIFEST_REPO_OWNER,
MANIFEST_REPO_NAME,
AUTH,
MANIFEST_REPO_BRANCH
);
}

async function installPython(workingDirectory: string) {
50 changes: 26 additions & 24 deletions src/setup-python.ts
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ import * as path from 'path';
import * as os from 'os';
import fs from 'fs';
import {getCacheDistributor} from './cache-distributions/cache-factory';
import {isCacheFeatureAvailable, IS_LINUX, IS_WINDOWS} from './utils';
import {isCacheFeatureAvailable, logWarning, IS_MAC} from './utils';

function isPyPyVersion(versionSpec: string) {
return versionSpec.startsWith('pypy');
@@ -38,41 +38,46 @@ function resolveVersionInput(): string {

if (versionFile) {
if (!fs.existsSync(versionFile)) {
logWarning(
`The specified python version file at: ${versionFile} doesn't exist. Attempting to find .python-version file.`
throw new Error(
`The specified python version file at: ${versionFile} doesn't exist.`
);
versionFile = '.python-version';
if (!fs.existsSync(versionFile)) {
throw new Error(`The ${versionFile} doesn't exist.`);
}
}

version = fs.readFileSync(versionFile, 'utf8');
core.info(`Resolved ${versionFile} as ${version}`);

return version;
}

core.warning(
"Neither 'python-version' nor 'python-version-file' inputs were supplied."
logWarning(
"Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '.python-version' file."
);
versionFile = '.python-version';
if (fs.existsSync(versionFile)) {
version = fs.readFileSync(versionFile, 'utf8');
core.info(`Resolved ${versionFile} as ${version}`);
return version;
}

logWarning(`${versionFile} doesn't exist.`);

return version;
}

async function run() {
// According to the README windows binaries do not require to be installed
// in the specific location, but Mac and Linux do
if (!IS_WINDOWS && !process.env.AGENT_TOOLSDIRECTORY?.trim()) {
if (IS_LINUX) process.env['AGENT_TOOLSDIRECTORY'] = '/opt/hostedtoolcache';
else process.env['AGENT_TOOLSDIRECTORY'] = '/Users/runner/hostedtoolcache';
if (IS_MAC) {
process.env['AGENT_TOOLSDIRECTORY'] = '/Users/runner/hostedtoolcache';
}

if (process.env.AGENT_TOOLSDIRECTORY?.trim()) {
process.env['RUNNER_TOOL_CACHE'] = process.env['AGENT_TOOLSDIRECTORY'];
}

core.debug(
`Python is expected to be installed into RUNNER_TOOL_CACHE=${process.env['RUNNER_TOOL_CACHE']}`
`Python is expected to be installed into ${process.env['RUNNER_TOOL_CACHE']}`
);
try {
const version = resolveVersionInput();
const checkLatest = core.getBooleanInput('check-latest');

if (version) {
let pythonVersion: string;
const arch: string = core.getInput('architecture') || os.arch();
@@ -81,7 +86,8 @@ async function run() {
const installed = await finderPyPy.findPyPyVersion(
version,
arch,
updateEnvironment
updateEnvironment,
checkLatest
);
pythonVersion = `${installed.resolvedPyPyVersion}-${installed.resolvedPythonVersion}`;
core.info(
@@ -91,7 +97,8 @@ async function run() {
const installed = await finder.useCpythonVersion(
version,
arch,
updateEnvironment
updateEnvironment,
checkLatest
);
pythonVersion = installed.version;
core.info(`Successfully set up ${installed.impl} (${pythonVersion})`);
@@ -113,9 +120,4 @@ async function run() {
}
}

export function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}

run();
23 changes: 23 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -3,9 +3,11 @@ import * as core from '@actions/core';
import fs from 'fs';
import * as path from 'path';
import * as semver from 'semver';
import * as exec from '@actions/exec';

export const IS_WINDOWS = process.platform === 'win32';
export const IS_LINUX = process.platform === 'linux';
export const IS_MAC = process.platform === 'darwin';
export const WINDOWS_ARCHS = ['x86', 'x64'];
export const WINDOWS_PLATFORMS = ['win32', 'win64'];
const PYPY_VERSION_FILE = 'PYPY_VERSION';
@@ -119,3 +121,24 @@ export function isCacheFeatureAvailable(): boolean {

return true;
}

export async function getLinuxOSReleaseInfo() {
const {stdout, stderr, exitCode} = await 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}`;
}

export function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}