Repository navigation
Read the CI Python versions from the recipes' conda_build_config.yaml #264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4f6d0db
Read the CI Python versions from the recipes' conda_build_config.yaml
antonwolfy b568fab
Merge branch 'align-cf-workflow-with-feedstock' into python-versions-…
antonwolfy 7d65e1c
Skip comment lines and check the ABI and build of python entries
antonwolfy d62acb3
Don't restate the CI Python versions in the AGENTS.md files
antonwolfy d8b4cb6
Merge branch 'master' into python-versions-from-recipe
antonwolfy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| name: Conda Python matrix | ||
| description: >- | ||
| Build the conda build/test matrix from the python list of a recipe's | ||
| conda_build_config.yaml | ||
|
|
||
| inputs: | ||
| recipe-dir: | ||
| description: Path to the conda recipe directory | ||
| required: true | ||
|
|
||
| outputs: | ||
| matrix: | ||
| description: Matrix for strategy.matrix, as JSON | ||
| value: ${{ steps.read.outputs.matrix }} | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Read Python versions from conda_build_config.yaml | ||
| id: read | ||
| shell: bash | ||
| env: | ||
| CBC_PATH: ${{ inputs.recipe-dir }}/conda_build_config.yaml | ||
| run: python3 "${GITHUB_ACTION_PATH}/conda_python_matrix.py" "${CBC_PATH}" |
127 changes: 127 additions & 0 deletions
127
.github/actions/conda-python-matrix/conda_python_matrix.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| """Build the conda CI matrix from the python list of a conda_build_config.yaml. | ||
|
|
||
| Usage: | ||
| python conda_python_matrix.py RECIPE_DIR/conda_build_config.yaml | ||
|
|
||
| Prints the matrix entries and, when $GITHUB_OUTPUT is set, writes | ||
| matrix=<JSON> to it for strategy.matrix of later jobs. Standard library only, | ||
| so it runs on any runner without conda. | ||
|
|
||
| The python: key must hold full specs, one per line and without selectors, | ||
| such as "3.12.* *_cpython", "3.13.* *_cp313" or "3.14.* *_cp314t", quoted or | ||
| not, so that every job gets an explicit ABI. The ABI must be cpython or name | ||
| the entry's version (cp314 or cp314t for 3.14), and each build may be listed | ||
| only once, since its python_tag names its artifacts. Each entry becomes one | ||
| matrix entry with: | ||
| - python_spec: the entry itself, for conda build --python | ||
| - python_tag: the version, with a "t" suffix for free-threaded builds, for | ||
| artifact names | ||
| - label: the check name suffix. A version with a single build shows only the | ||
| version ("3.12"); a version with GIL and free-threaded builds shows the | ||
| version, spec and tag ("3.14, 3.14.* *_cp314t, 3.14t"). These are the | ||
| names of the former static matrix, which branch rulesets may require. | ||
| """ | ||
|
|
||
| import argparse | ||
| import collections | ||
| import json | ||
| import os | ||
| import re | ||
| import sys | ||
|
|
||
| SPEC_RE = re.compile(r"(\d+\.\d+)\.\* \*_(cpython|cp\d+t?)") | ||
|
|
||
|
|
||
| class DeclarationError(Exception): | ||
| """The python: list cannot be turned into a matrix.""" | ||
|
|
||
|
|
||
| def read_specs(path): | ||
| """Return the entries of the python: key of a conda_build_config.yaml.""" | ||
| specs, in_list = [], False | ||
| with open(path, encoding="utf-8") as f: | ||
| for line in f: | ||
| # In YAML, a comment line doesn't end the list, even at column 0 | ||
| if line.lstrip().startswith("#"): | ||
| continue | ||
| if line.startswith("python:"): | ||
| if specs or line.strip() != "python:": | ||
| raise DeclarationError( | ||
| "expected a single 'python:' key without selectors" | ||
| ) | ||
| in_list = True | ||
| elif in_list and re.match(r"\s+-", line): | ||
| if "#" in line: | ||
| raise DeclarationError( | ||
| "selectors on python entries are not supported: " | ||
| + line.strip() | ||
| ) | ||
| spec = line.split("-", 1)[1].strip() | ||
| if len(spec) > 1 and spec[0] == spec[-1] and spec[0] in "'\"": | ||
| spec = spec[1:-1] | ||
| specs.append(spec) | ||
| elif in_list and line.strip() and not line[0].isspace(): | ||
| in_list = False | ||
| if not specs: | ||
| raise DeclarationError("no python entries found") | ||
| return specs | ||
|
|
||
|
|
||
| def build_matrix(specs): | ||
| """Return the strategy.matrix for the given python entries.""" | ||
| parsed, seen = [], {} | ||
| for spec in specs: | ||
| m = SPEC_RE.fullmatch(spec) | ||
| if not m: | ||
| raise DeclarationError( | ||
| f"unsupported python entry '{spec}', " | ||
| "expected e.g. '3.14.* *_cp314t'" | ||
| ) | ||
| version, abi = m.groups() | ||
| cp = "cp" + version.replace(".", "") | ||
| if abi not in ("cpython", cp, cp + "t"): | ||
| raise DeclarationError( | ||
| f"python entry '{spec}': ABI {abi} doesn't match Python " | ||
| f"{version}, expected cpython, {cp} or {cp}t" | ||
| ) | ||
| tag = version + ("t" if abi.endswith("t") else "") | ||
| if tag in seen: | ||
| raise DeclarationError( | ||
| f"python entries '{seen[tag]}' and '{spec}' both build " | ||
| f"Python {tag}" | ||
| ) | ||
| seen[tag] = spec | ||
| parsed.append((spec, version, tag)) | ||
|
|
||
| builds = collections.Counter(version for _, version, _ in parsed) | ||
| include = [] | ||
| for spec, version, tag in parsed: | ||
| if builds[version] == 1: | ||
| label = version | ||
| else: | ||
| label = f"{version}, {spec}, {tag}" | ||
| include.append({"python_spec": spec, "python_tag": tag, "label": label}) | ||
| return {"include": include} | ||
|
|
||
|
|
||
| def main(argv=None): | ||
| parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) | ||
| parser.add_argument("cbc", help="path to conda_build_config.yaml") | ||
| args = parser.parse_args(argv) | ||
|
|
||
| try: | ||
| matrix = build_matrix(read_specs(args.cbc)) | ||
| except DeclarationError as e: | ||
| print(f"{args.cbc}: {e}", file=sys.stderr) | ||
| return 1 | ||
|
|
||
| print(json.dumps(matrix["include"], indent=2)) | ||
| output = os.environ.get("GITHUB_OUTPUT") | ||
| if output: | ||
| with open(output, "a", encoding="utf-8") as f: | ||
| f.write("matrix=" + json.dumps(matrix) + "\n") | ||
| return 0 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.