Writing Scripts¶
Overview¶
Workflow deinitions are text files in YAML format, that are read, compiled, and executed by the Task Runner.
Note
Unless you are a Python programmer, you may have to get used to the fact
that whitespace matters in YAML files:
Make sure you indent uniformly. Don’t mix tabs and spaces.
We recommend to use an editor that supports the YAML syntax (e.g. VS Code).
A simple confuguration script may look like this:
yabs.yaml
:
1# Yabs Workflow Definition
2# See https://github.com/mar10/yabs
3file_version: yabs#1
4
5config:
6 repo: 'mar10/test-release-tool'
7 version:
8 - type: __version__
9 file: src/test_release_tool/__init__.py
10 branches: main # or master?
11
12
13tasks:
14 # The following tools are available. They are executed in the order
15 # listed here
16
17 # 'check': Assert preconditons and fail otherwise
18 - task: check
19 build: true # dist/ folder exists
20 can_push: true # Test if 'git push' would/would not succeed
21 clean: true # Repo must/must not contain modifications
22 python: ">=3.9" # SemVer specifier
23 twine: true # `twine` is available
24 up_to_date: true # everything pulled from remote
25 venv: true # running inside a virtual environment
26 version: true # `setup.py --version` returns the configured version
27 # winget: true # `wingetcreate` is available
28 yabs: ">=0.5" # SemVer specifier
29
30 # 'exec': Run arbitrary shell command
31 - task: exec
32 args: ["tox", "-e", "lint"] # shell command and optional arguments
33 always: true # `true`: run even in dry-run mode
34
35 # 'bump': Increment project version (requires argument: `yabs run --inc INC`)
36 - task: bump
37 inc: null # Use value passed as 'yabs run --inc INC'
38
39 # 'commit': Commit modified files
40 - task: commit
41 add_known: true # Commit with -a flag
42 message: |
43 Bump version to {version}
44
45 # 'tag': Create an annotated tag
46 - task: tag
47 name: v{version}
48 message: |
49 Version {version}
50
51 # 'push': Push changes and tags
52 - task: push
53 tags: true
54
55 # 'pypi_release': Create a release on PyPI using `twine`
56 - task: pypi_release
57 build:
58 - sdist
59 - bdist_wheel
60 upload: true
61
62 # 'github_release': Create a release on GitHub
63 - task: github_release
64 draft: false
65
66 # Bump 'v1.2.3' => 'v1.2.4-a1'
67 - task: bump
68 inc: "postrelease"
69
70 # Commit using '[ci skip]' as part of the message to prevent CI testing
71 - task: commit
72 add_known: true
73 message: |
74 Bump prerelease ({version}) [ci skip]
75
76 # Push to GitHub
77 - task: push
See yabs.yaml for a complete configuration with all available options and defaults.
Note
To get started, run yabs init
inside your project’s directory.
This will prompt for a few details and create a fresh yabs.yaml
file.
Task Types¶
See also
See Script Reference for a list of all tasks and options
and yabs.yaml for a complete configuration file
with all available tasks.
Template Macros¶
Some tasks have string options such as tag names, commit messges, etc. These strings may contain inline macros that will be expanded.
Typical macros are version, tag_name, repo, …
Macro names must be embedded in curly braces, for example:
- task: github_release
name: 'v{version}'
message: |
Released {version}
[Changelog](https://github.com/{repo}/blob/master/CHANGELOG.md),
[Commit details](https://github.com/{repo}/compare/{org_tag_name}...{tag_name}).
All attributes of the task context are available as macros:
- {inc}
Value of the
--inc
argument.- {org_tag_name}
The repo’s latest tag name (before ‘bump’).
- {org_version}
Latest version (before ‘bump’).
- {repo}
GitHub repo name, e.g. ‘USER/PROJECT’.
- {tag_name}
The current tag name (after ‘bump’).
- {version}
Current version (after ‘bump’).
See TaskContext
for a complete list.
Version Locations¶
Note
Currently only a small subset is implemented.
Please open an issue if you need
another one and are ready to help with testing.
(TODO: verify this section.)
Although there seems to be consent that Python projects should have a version number that is stored at one central location, the community has not agreed upon that location yet.
In order to find and bump this versions, we need to pass a hint in the configuration yabs.yaml like so:
file_version: yabs#1
config:
...
version:
- type: __version__ # Example!
file: src/my_project/__init__.py
...
Yabs supports some common approaches.
Following some typical patterns how Python projects store version numbers.
Note
Currently we would recommend this variant (unless Poetry is used):
Store the version in __init__.py
of the project’s root folder:
__version__ = "1.2.3"
Then reference this in setup.cfg
:
[metadata]
name = my_package
version = attr: my_project.__version__
This would then configured in yabs.yaml
like so:
config:
version:
- type: __version__
file: my_project/__init__.py
See below for details about the different use cases.
Poetry¶
Todo
Not yet implemented.
Poetry stores the version
number in its own section in pyproject.toml
(defined in PEP-518):
pyproject.toml
:
[project]
...
[tool.poetry]
name = "my_project"
version = "1.2.3"
yabs.yaml
:
config:
version:
- type: poetry
flit¶
Todo
Not yet implemented.
__init__.py of the project’s root package¶
__init__.py
:
__version__ = "1.2.3"
yabs.yaml
:
config:
version:
- type: __version__
file: src/my_project/__init__.py
Or a variant the mimics Python’s sys.version_info style:
__init__.py
:
version_info = (1, 2, 3)
version = ".".join(str(c) for c in version_info)
yabs.yaml
:
config:
version:
# TODO
Plain Text File¶
For example a _version.txt file in the project’s src folder containing:
_version.txt
:
1.2.3
yabs.yaml
:
config:
version:
# TODO
setup.cfg¶
See also PEP-396 and setuptools .
setup.cfg
in the project’s root folder:
[metadata]
name = my_package
version = 1.2.3
yabs.yaml
:
config:
version:
# TODO
The follwing two examples for setup.cfg use the special attr:
and file:
directives that where introduced with
setuptools v39.2 ).
Note: This assumes that the version is stored in a separate text- or Python file, which is covered in the examples above.
[metadata]
name = my_package
version = attr: my_project.__version__
[metadata]
name = my_package
version = file: path/to/file
The follwing two examples for setup.cfg use the special version-file
and
version-from-file
options that where proposed for
distutils2.
Note: This assumes that the version is stored in a separate text- or Python file, which is covered in the examples above.
[metadata]
# The entire contents of the file contains the version number
version-file = version.txt
[metadata]
# The version number is contained within a larger file, e.g. of Python code,
# such that the file must be parsed to extract the version
version-from-file = elle.py
Debugging¶
Use the --verbose
(short -v
) option to generate more console logging.
Use the --dry-run
(short -n
) option to run all tasks in a simulation mode:
$ yabs run --inc patch -vn