Compare commits

...

26 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
13ae5bb136 Merge pull request #517 from rentziass/rentziass/update-actions-core
Update @actions/core to 1.10.0
2022-10-07 13:51:04 +02:00
0c4d7b878c Update @actions/core to 1.10.0 2022-10-06 12:16:00 +01:00
wzy
13a464fa11 Fix typo (#503) 2022-09-21 00:45:00 +02:00
b4fe97ecda upgrade @actions/cache so it respects SEGMENT_DOWNLOAD_TIMEOUT_MINS (#499) 2022-09-13 11:04:29 -04:00
434aeabbb4 Bump @actions/core from 1.7.0 to 1.9.1 (#495)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.7.0 to 1.9.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-07 13:07:01 -04:00
98c991d13f Only use github.token on github.com (#443)
* Only use github.token on github.com

This expression evaluates to `''` if called from GHES hosted elsewhere
You can still provide your token on both github.com and GHES

* Enshure blank result of expression and not false

* Revert "Revert "Pass the `token` input through on GHES (#427)" (#437)"

This reverts commit cf86e08a31.

* fix typo

* Add back the doc on the tool cache for self-hosted

Co-authored-by: Brian Cristante <33549821+brcrista@users.noreply.github.com>
2022-08-30 15:02:20 -04:00
397a35f988 Merge pull request #492 from al-cheb/al-cheb/update-runner-link
Update runner links
2022-08-30 10:16:43 +02:00
48a0f006ff Update runner links 2022-08-29 16:20:07 +02:00
978fd06d1f Merge pull request #491 from lkfortuna/patch-2
Update README.md
2022-08-29 11:06:58 +02:00
050e616f66 Update README.md
Updating outdated reference to virtual environments
2022-08-26 08:26:51 -07:00
f6795b163d Merge pull request #479 from e-korolevskii/main
Update contributors guide
2022-08-10 16:45:43 +02:00
2e6ca74422 Merge branch 'actions:main' into main 2022-08-10 16:40:52 +02:00
aa5ddbf8fe Merge pull request #477 from Kludex/patch-1
Add `rc` mention to the `-dev` tag
2022-08-10 09:40:38 +02:00
c0abeaa470 Update docs/contributors.md
Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com>
2022-08-09 23:56:17 +02:00
197204a31c Update advanced-usage.md 2022-08-09 11:52:47 +02:00
c96b4b55f3 rephased documents 2022-08-03 19:24:32 +02:00
9aa1c6cb27 updated contributors guide 2022-08-01 01:44:15 +02:00
19 changed files with 4504 additions and 1776 deletions

View File

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

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: [ubuntu-latest, windows-latest]
operating-system: [ubuntu-20.04, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v3
@ -68,7 +68,7 @@ jobs:
python-version: 3.8
- name: Verify 3.8
run: python __tests__/verify-python.py 3.8
- name: Run with setup-python 3.7.5
uses: ./
with:

View File

@ -1,6 +1,6 @@
---
name: "@actions/cache"
version: 3.0.0
version: 3.0.4
type: npm
summary: Actions cache lib
homepage: https://github.com/actions/toolkit/tree/main/packages/cache

View File

@ -1,6 +1,6 @@
---
name: "@actions/core"
version: 1.7.0
version: 1.10.0
type: npm
summary: Actions core lib
homepage: https://github.com/actions/toolkit/tree/main/packages/core

View File

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

View File

@ -33,11 +33,11 @@ steps:
python-version: 'pypy3.9'
- 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/).
For information regarding locally cached versions of Python or PyPy on GitHub hosted runners, check out [GitHub Actions Virtual Environments](https://github.com/actions/virtual-environments).
For information regarding locally cached versions of Python or PyPy on GitHub hosted runners, check out [GitHub Actions Runner Images](https://github.com/actions/runner-images).
## Supported version syntax
@ -92,4 +92,4 @@ The scripts and documentation in this project are released under the [MIT Licens
## Contributions
Contributions are welcome! See our [Contributor's Guide](docs/contributors.md).
Contributions are welcome! See our [Contributor's Guide](docs/contributors.md).

View File

@ -30,7 +30,6 @@ 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;
@ -67,6 +66,9 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
if (input.includes('poetry')) {
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};
});
@ -83,7 +85,6 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
whichSpy = jest.spyOn(io, 'which');
whichSpy.mockImplementation(() => '/path/to/python');
getLinuxOSReleaseInfoSpy = jest.spyOn(utils, 'getLinuxOSReleaseInfo');
});
describe('Validate provided package manager', () => {
@ -120,17 +121,11 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
dependencyFile
);
if (process.platform === 'linux') {
getLinuxOSReleaseInfoSpy.mockImplementation(() =>
Promise.resolve('Ubuntu-20.4')
);
}
await cacheDistributor.restoreCache();
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}`
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-20.04-Ubuntu-python-${pythonVersion}-${packageManager}-${fileHash}`
);
} else {
expect(infoSpy).toHaveBeenCalledWith(

View File

@ -16,8 +16,8 @@ inputs:
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."
default: ${{ github.token }}
description: "The token used to authenticate when fetching Python distributions from https://github.com/actions/python-versions. When running this action on github.com, the default value is sufficient. When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting."
default: ${{ github.server_url == 'https://github.com' && 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."
update-environment:

3088
dist/cache-save/index.js vendored

File diff suppressed because it is too large Load Diff

2682
dist/setup/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ steps:
- run: python my_script.py
```
It's also possible to use **x.y-dev syntax** to download and set up the latest patch version of Python, alpha and beta releases included. (for specified major & minor versions):
It's also possible to use **x.y-dev syntax** to download and set up the latest patch version of Python, alpha, beta and rc (release candidate) releases included. (for specified major & minor versions):
```yaml
steps:
@ -281,6 +281,20 @@ steps:
- 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
@ -322,7 +336,7 @@ jobs:
**cache-hit** output is available with a boolean value that indicates whether a cache hit occurred on the primary key:
```
```yaml
jobs:
build:
runs-on: ubuntu-latest
@ -407,14 +421,14 @@ GitHub hosted runners have a tool cache that comes with a few versions of Python
|**Python tool cache**|`RUNNER_TOOL_CACHE/Python/*`|
|**PyPy tool cache**|`RUNNER_TOOL_CACHE/PyPy/*`|
GitHub virtual environments are set up in [actions/virtual-environments](https://github.com/actions/virtual-environments). During the setup, the available versions of Python and PyPy are automatically downloaded, set up and documented.
- Tool cache setup for Ubuntu: [Install-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/linux/scripts/installers/Install-Toolset.ps1) [Configure-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/linux/scripts/installers/Configure-Toolset.ps1)
- Tool cache setup for Windows: [Install-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/win/scripts/Installers/Install-Toolset.ps1) [Configure-Toolset.ps1](https://github.com/actions/virtual-environments/blob/main/images/win/scripts/Installers/Configure-Toolset.ps1)
GitHub runner images are set up in [actions/runner-images](https://github.com/actions/runner-images). During the setup, the available versions of Python and PyPy are automatically downloaded, set up and documented.
- Tool cache setup for Ubuntu: [Install-Toolset.ps1](https://github.com/actions/runner-images/blob/main/images/linux/scripts/installers/Install-Toolset.ps1) [Configure-Toolset.ps1](https://github.com/actions/runner-images/blob/main/images/linux/scripts/installers/Configure-Toolset.ps1)
- Tool cache setup for Windows: [Install-Toolset.ps1](https://github.com/actions/runner-images/blob/main/images/win/scripts/Installers/Install-Toolset.ps1) [Configure-Toolset.ps1](https://github.com/actions/runner-images/blob/main/images/win/scripts/Installers/Configure-Toolset.ps1)
## Using `setup-python` with a self-hosted runner
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` may not work.
Python distributions are only available for the same [environments](https://github.com/actions/runner-images#available-images) 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` may 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.
@ -471,6 +485,29 @@ One quick way to grant access is to change the user and group of `/Users/runner/
## 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 avoid hitting rate-limit problems, we recommend [setting up your own runner tool cache](https://docs.github.com/en/enterprise-server@2.22/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access#about-the-included-setup-actions-and-the-runner-tool-cache).
`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
- name: Set up Python
uses: actions/setup-python@4
with:
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.

View File

@ -1,37 +1,113 @@
# Contributors
### Checkin
Thank you for contributing!
- Do check in source (`src/`)
- Do check in a single `index.js` file after running `ncc`
- Do not check in `node_modules/`
We have prepared a short guide so that the process of making your contribution is as simple and clear as possible. Please check it out before you contribute!
### NCC
## How can I contribute...
In order to avoid uploading `node_modules/` to the repository, we use [vercel/ncc](https://github.com/vercel/ncc) to create a single `index.js` file that gets saved in `dist/`.
* [Contribute Documentation:green_book:](#contribute-documentation)
### Developing
* [Contribute Code :computer:](#contribute-code)
If you're developing locally, you can run
* [Provide Support on Issues:pencil:](#provide-support-on-issues)
```sh
npm install
tsc
ncc build src/setup-python.ts
```
* [Review Pull Requests:mag:](#review-pull-requests)
Any files generated using `tsc` will be added to `lib/`, however those files also are not uploaded to the repository and are excluded using `.gitignore`.
## Contribute documentation
During the commit step, Husky will take care of formatting all files with [Prettier](https://github.com/prettier/prettier) (to run manually, use `npm run format`).
Documentation is a super important, critical part of this project. Docs are how we keep track of what we're doing, how, and why. It's how we stay on the same page about our policies and how we tell others everything they need to be able to use this project or contribute to it.
### Testing
Documentation contributions of any size are welcome! Feel free to contribute even if you're just rewording a sentence to be more clear, or fixing a spelling mistake!
We ask that you include a link to a successful run that utilizes the changes you are working on. For example, if your changes are in the branch `newAwesomeFeature`, then show an example run that uses `setup-python@newAwesomeFeature` or `my-fork@newAwesomeFeature`. This will help speed up testing and help us confirm that there are no breaking changes or bugs.
**How to contribute:**
### Licensed
Pull requests are the easiest way to contribute changes to git repos at GitHub. They are the preferred contribution method, as they offer a convenient way of commenting and amending the proposed changes.
This repository uses a tool called [Licensed](https://github.com/github/licensed) to verify third party dependencies. You may need to locally install licensed and run `licensed cache` to update the dependency cache if you install or update a production dependency. If licensed cache is unable to determine the dependency, you may need to modify the cache file yourself to put the correct license. You should still verify the dependency, licensed is a tool to help, but is not a substitute for human review of dependencies.
- Please check that no one else has already created a pull request with these or similar changes
- Use a "feature branch" for your changes. That separates the changes in the pull request from your other changes and makes it easy to edit/amend commits in the pull request
- Make sure your changes are formatted properly and consistently with the rest of the documentation
- Re-read what you wrote, and run a spellchecker on it to make sure you didn't miss anything
- If your pull request is connected to an open issue, please, leave a link to this issue in the `Related issue:` section
- If you later need to add new commits to the pull request, you can simply commit the changes to the local branch and then push them. The pull request gets automatically updated
### Releases
**Once you've filed the pull request:**
There is a `master` branch where contributor changes are merged into. There are also release branches such as `releases/v1` that are used for tagging (for example the `v1` tag) and publishing new versions of the action. Changes from `master` are periodically merged into a releases branch. You do not need to create any PR that merges changes from master into a releases branch.
- Maintainers will review your pull request
- If a maintainer requests changes, first of all, try to think about this request critically and only after that implement and request another review
- If your PR gets accepted, it will soon be merged into the main branch. But your contribution will take effect only after the release of a new version of the action and updating the major tag
> Sometimes maintainers reject pull requests and that's ok! Usually, along with rejection, we supply the reason for it. Nonetheless, we still really appreciate you taking the time to do it, and we don't take that lightly :heart:
## Contribute code
We like code commits a lot! They're super handy, and they keep the project going and doing the work it needs to do to be useful to others.
Code contributions of just about any size are acceptable!
The main difference between code contributions and documentation contributions is that contributing code requires the inclusion of relevant tests for the code being added or changed. Contributions without accompanying tests will be held off until a test is added unless the maintainers consider the specific tests to be either impossible or way too much of a burden for such a contribution.
**How to contribute:**
Pull requests are the easiest way to contribute changes to git repos at GitHub. They are the preferred contribution method, as they offer a convenient way of commenting and amending the proposed changes.
- Please check that no one else has already created a pull request with these or similar changes
- Use a "feature branch" for your changes. That separates the changes in the pull request from your other changes and makes it easy to edit/amend commits in the pull request
- Make sure your changes are well formatted and that all tests are passing
- If your pull request is connected to an open issue, please, leave a link to this issue in the `Related issue:` section
- If you later need to add new commits to the pull request, you can simply commit the changes to the local branch and then push them. The pull request gets automatically updated
**Learn more about how to work with the repository:**
- To implement new features or fix bugs, you need to make changes to the `.ts` files, which are located in the `src` folder
- To comply with the code style, **you need to run the `format` script**
- To transpile source code to `javascript` we use [NCC](https://github.com/vercel/ncc). **It is very important to run the `build` script after making changes**, otherwise your changes will not get into the final `javascript` build
**Learn more about how to implement tests:**
Adding or changing tests is an integral part of making a change to the code.
Unit tests are in the `__tests__` folder, and end-to-end tests are in the `workflows` folder, particularly take a look at the files with `e2e` and `test` prefixes, for instance, [e2e-cache.yml](https://github.com/actions/setup-python/blob/main/.github/workflows/e2e-cache.yml).
- The contributor can add various types of tests (like unit tests or end-to-end tests), which, in his opinion, will be necessary and sufficient for testing new or changed functionality
- Tests should cover a successful execution, as well as some edge cases and possible errors
- As already mentioned, pull requests without tests will be considered more carefully by maintainers. If you are sure that in this situation the tests are not needed or cannot be implemented with a commensurate effort - please add this clarification message to your pull request
**Once you've filed the pull request:**
- CI will start automatically with some checks. Wait until the end of the execution and make sure that all checks passed successfully. If some checks fail, you can open them one by one, try to find the reason for failing and make changes to your code to resolve the problem
- Maintainers will review your pull request
- If a maintainer requests changes, first of all, try to think about his request critically and only after that implement and request another review
- If your PR gets accepted, it will soon be merged into the main branch. But your contribution will take effect only after the release of a new version of the action and updating the major tag
> Sometimes maintainers reject pull requests and that's ok! Usually, along with rejection, we supply the reason for it. Nonetheless, we still really appreciate you taking the time to do it, and we don't take that lightly :heart:
## Provide support on issues
Helping out other users with their questions is an awesome way of contributing to any community. It's not uncommon for most of the issues on open source projects to be support-related questions by users trying to understand something they ran into or find their way around a known bug.
**To help other folks out with their questions:**
- Go to the [issue tracker](https://github.com/actions/setup-python/issues)
- Read through the list until you find something that you're familiar enough with to answer to
- Respond to the issue with whatever details are needed to clarify the question, or get more details about what's going on
- Once the discussion wraps up and things are clarified, ask the original issue filer (or a maintainer) to close it for you
*Some notes on picking up support issues:*
- Avoid responding to issues you don't know you can answer accurately
- Try to refer to past issues with accepted answers as much as possible. Link to them from your replies
- Be kind and patient with users. Often, folks who have run into confusing things might be upset or impatient. This is natural. If you feel uncomfortable in conversation with them, it's better to stay away or withdraw from the issue.
> If some user is violating our code of conduct [standards](https://github.com/actions/setup-python/blob/main/CODE_OF_CONDUCT.md#our-standards), refer to the [enforcement](https://github.com/actions/setup-python/blob/main/CODE_OF_CONDUCT.md#enforcement) section of the Code of Conduct to resolve the conflict
## Review pull requests
Another great way to contribute is to review pull request. Please, be extra kind: people who submit code/doc contributions are putting themselves in a pretty vulnerable position, and have put time and care into what they've done (even if that's not obvious to you!) Please, always respond with respect, and be understanding, but don't feel like you need to sacrifice your standards for their sake, either.
**How to review:**
- Go to the [pull requests](https://github.com/actions/setup-python/pulls)
- Make sure you're familiar with the code or documentation is updated, unless it's a minor change (spellchecking, minor formatting, etc.)
- Review changes using the GitHub functionality. You can ask a clarifying question, point out an error or suggest an alternative.
> Note: You may ask for minor changes - "nitpicks", but consider whether they are real blockers to merging or not
- Submit your review, which may include comments, an approval, or a changes request

77
package-lock.json generated
View File

@ -9,8 +9,8 @@
"version": "4.0.0",
"license": "MIT",
"dependencies": {
"@actions/cache": "^3.0.0",
"@actions/core": "^1.7.0",
"@actions/cache": "^3.0.4",
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.0",
"@actions/glob": "^0.2.0",
"@actions/io": "^1.0.2",
@ -31,9 +31,9 @@
}
},
"node_modules/@actions/cache": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.0.tgz",
"integrity": "sha512-GL9CT1Fnu+pqs8TTB621q8Xa8Cilw2n9MwvbgMedetH7L1q2n6jY61gzbwGbKgtVbp3gVJ12aNMi4osSGXx3KQ==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.4.tgz",
"integrity": "sha512-9RwVL8/ISJoYWFNH1wR/C26E+M3HDkGPWmbFJMMCKwTkjbNZJreMT4XaR/EB1bheIvN4PREQxEQQVJ18IPnf/Q==",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.1",
@ -72,11 +72,28 @@
}
},
"node_modules/@actions/core": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.7.0.tgz",
"integrity": "sha512-7fPSS7yKOhTpgLMbw7lBLc1QJWvJBBAgyTX2PEhagWcKK8t0H8AKCoPMfnrHqIm5cRYH4QFPqD1/ruhuUE7YcQ==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"dependencies": {
"@actions/http-client": "^1.0.11"
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/core/node_modules/@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"dependencies": {
"tunnel": "^0.0.6"
}
},
"node_modules/@actions/core/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@actions/exec": {
@ -10160,9 +10177,9 @@
}
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@ -11340,9 +11357,9 @@
},
"dependencies": {
"@actions/cache": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.0.tgz",
"integrity": "sha512-GL9CT1Fnu+pqs8TTB621q8Xa8Cilw2n9MwvbgMedetH7L1q2n6jY61gzbwGbKgtVbp3gVJ12aNMi4osSGXx3KQ==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.4.tgz",
"integrity": "sha512-9RwVL8/ISJoYWFNH1wR/C26E+M3HDkGPWmbFJMMCKwTkjbNZJreMT4XaR/EB1bheIvN4PREQxEQQVJ18IPnf/Q==",
"requires": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.1",
@ -11380,11 +11397,27 @@
}
},
"@actions/core": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.7.0.tgz",
"integrity": "sha512-7fPSS7yKOhTpgLMbw7lBLc1QJWvJBBAgyTX2PEhagWcKK8t0H8AKCoPMfnrHqIm5cRYH4QFPqD1/ruhuUE7YcQ==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"requires": {
"@actions/http-client": "^1.0.11"
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
},
"dependencies": {
"@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"requires": {
"tunnel": "^0.0.6"
}
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
}
}
},
"@actions/exec": {
@ -19457,9 +19490,9 @@
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": {
"brace-expansion": "^1.1.7"
}

View File

@ -23,8 +23,8 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@actions/cache": "^3.0.0",
"@actions/core": "^1.7.0",
"@actions/cache": "^3.0.4",
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.0",
"@actions/glob": "^0.2.0",
"@actions/io": "^1.0.2",

View File

@ -7,7 +7,7 @@ import * as path from 'path';
import os from 'os';
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 {
constructor(
@ -61,9 +61,9 @@ class PipCache extends CacheDistributor {
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}`;
const osInfo = await getLinuxInfo();
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']}-${osInfo.osVersion}-${osInfo.osName}-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}`;

View File

@ -1,6 +1,6 @@
import * as os from 'os';
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';
@ -85,9 +85,14 @@ export async function useCpythonVersion(
}
if (!installDir) {
const osInfo = await getOSInfo();
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}`
].join(os.EOL)
);

View File

@ -8,7 +8,6 @@ import fs from 'fs';
import {
IS_WINDOWS,
WINDOWS_ARCHS,
WINDOWS_PLATFORMS,
IPyPyManifestRelease,
createSymlinkInFolder,
@ -47,37 +46,58 @@ export async function installPyPy(
let downloadUrl = `${foundAsset.download_url}`;
core.info(`Downloading PyPy from "${downloadUrl}" ...`);
const pypyPath = await tc.downloadTool(downloadUrl);
core.info('Extracting downloaded archive...');
if (IS_WINDOWS) {
downloadDir = await tc.extractZip(pypyPath);
} else {
downloadDir = await tc.extractTar(pypyPath, undefined, 'x');
try {
const pypyPath = await tc.downloadTool(downloadUrl);
core.info('Extracting downloaded archive...');
if (IS_WINDOWS) {
downloadDir = await tc.extractZip(pypyPath);
} else {
downloadDir = await tc.extractTar(pypyPath, undefined, 'x');
}
// root folder in archive can have unpredictable name so just take the first folder
// downloadDir is unique folder under TEMP and can't contain any other folders
const archiveName = fs.readdirSync(downloadDir)[0];
const toolDir = path.join(downloadDir, archiveName);
let installDir = toolDir;
if (!isNightlyKeyword(resolvedPyPyVersion)) {
installDir = await tc.cacheDir(
toolDir,
'PyPy',
resolvedPythonVersion,
architecture
);
}
writeExactPyPyVersionFile(installDir, resolvedPyPyVersion);
const binaryPath = getPyPyBinaryPath(installDir);
await createPyPySymlink(binaryPath, resolvedPythonVersion);
await installPip(binaryPath);
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;
}
// root folder in archive can have unpredictable name so just take the first folder
// downloadDir is unique folder under TEMP and can't contain any other folders
const archiveName = fs.readdirSync(downloadDir)[0];
const toolDir = path.join(downloadDir, archiveName);
let installDir = toolDir;
if (!isNightlyKeyword(resolvedPyPyVersion)) {
installDir = await tc.cacheDir(
toolDir,
'PyPy',
resolvedPythonVersion,
architecture
);
}
writeExactPyPyVersionFile(installDir, resolvedPyPyVersion);
const binaryPath = getPyPyBinaryPath(installDir);
await createPyPySymlink(binaryPath, resolvedPythonVersion);
await installPip(binaryPath);
return {installDir, resolvedPythonVersion, resolvedPyPyVersion};
}
export async function getAvailablePyPyVersions() {
@ -157,7 +177,7 @@ export function findRelease(
const isArchPresent =
item.files &&
(IS_WINDOWS
? isArchPresentForWindows(item)
? isArchPresentForWindows(item, architecture)
: isArchPresentForMacOrLinux(item, architecture, process.platform));
return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent;
});
@ -181,7 +201,7 @@ export function findRelease(
const foundRelease = sortedReleases[0];
const foundAsset = IS_WINDOWS
? findAssetForWindows(foundRelease)
? findAssetForWindows(foundRelease, architecture)
: findAssetForMacOrLinux(foundRelease, architecture, process.platform);
return {
@ -205,11 +225,11 @@ export function pypyVersionToSemantic(versionSpec: string) {
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(
(file: any) =>
WINDOWS_ARCHS.includes(file.arch) &&
WINDOWS_PLATFORMS.includes(file.platform)
WINDOWS_PLATFORMS.includes(file.platform) && file.arch === architecture
);
}
@ -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(
(item: any) =>
WINDOWS_ARCHS.includes(item.arch) &&
WINDOWS_PLATFORMS.includes(item.platform)
WINDOWS_PLATFORMS.includes(item.platform) && item.arch === architecture
);
}
@ -240,3 +260,11 @@ export function findAssetForMacOrLinux(
(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

@ -3,10 +3,10 @@ import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import * as exec from '@actions/exec';
import {ExecOptions} from '@actions/exec/lib/interfaces';
import {IS_WINDOWS, IS_LINUX, isGhes} from './utils';
import {IS_WINDOWS, IS_LINUX} from './utils';
const TOKEN = core.getInput('token');
const AUTH = !TOKEN || isGhes() ? undefined : `token ${TOKEN}`;
const AUTH = !TOKEN ? undefined : `token ${TOKEN}`;
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'python-versions';
const MANIFEST_REPO_BRANCH = 'main';
@ -72,15 +72,33 @@ export async function installCpythonFromRelease(release: tc.IToolRelease) {
const downloadUrl = release.files[0].download_url;
core.info(`Download from "${downloadUrl}"`);
const pythonPath = await tc.downloadTool(downloadUrl, undefined, AUTH);
core.info('Extract downloaded archive');
let pythonExtractedFolder;
if (IS_WINDOWS) {
pythonExtractedFolder = await tc.extractZip(pythonPath);
} else {
pythonExtractedFolder = await tc.extractTar(pythonPath);
}
let pythonPath = '';
try {
pythonPath = await tc.downloadTool(downloadUrl, undefined, AUTH);
core.info('Extract downloaded archive');
let pythonExtractedFolder;
if (IS_WINDOWS) {
pythonExtractedFolder = await tc.extractZip(pythonPath);
} else {
pythonExtractedFolder = await tc.extractTar(pythonPath);
}
core.info('Execute installation script');
await installPython(pythonExtractedFolder);
core.info('Execute installation script');
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;
}
export async function getLinuxOSReleaseInfo() {
const {stdout, stderr, exitCode} = await exec.getExecOutput(
'lsb_release',
['-i', '-r', '-s'],
export function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}
async function getWindowsInfo() {
const {stdout} = await exec.getExecOutput(
'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"',
undefined,
{
silent: true
}
);
const [osRelease, osVersion] = stdout.trim().split('\n');
const windowsVersion = stdout.trim().split(' ')[3];
core.debug(`OS Release: ${osRelease}, Version: ${osVersion}`);
return `${osVersion}-${osRelease}`;
return {osName: 'Windows', osVersion: windowsVersion};
}
export function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
async function getMacOSInfo() {
const {stdout} = await exec.getExecOutput('sw_vers', ['-productVersion'], {
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;
}
}