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