Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This workflow will upload a Python Package using Twine when a release is created
# This workflow will build the package with uv and upload it using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Upload Python Package
Expand All @@ -14,18 +14,22 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install dependencies
run: |
git fetch --all --tags
python -m pip install --upgrade pip
pip install setuptools wheel twine
pip install uv twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
uv lock --check
uv build
twine upload dist/*
53 changes: 39 additions & 14 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,37 @@ on:
branches: [master]

jobs:
build:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Build distributions
run: |
python -m pip install --upgrade pip
pip install uv
uv lock --check
uv build
- name: Upload dists as artifact
uses: actions/upload-artifact@v4
with:
name: dists
path: dist/
test:
runs-on: ubuntu-24.04
permissions:
contents: read
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]

steps:
- uses: actions/checkout@v4
Expand All @@ -27,34 +50,32 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Verify Python version
shell: bash
run: |
echo "Active Python: $(python --version)"
python --version 2>&1 | grep -q "^Python ${{ inputs.python-version }}" || (echo "ERROR: Expected Python ${{ inputs.python-version }}" && exit 1)
- name: Install dependencies
- name: Install uv and sync dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pyright pytest setuptools wheel
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
python -m pip install uv
echo "${{ matrix.python-version }}" > .python-version
uv lock --check
uv sync
- name: Lint with flake8
run: |
python -m flake8 . --ignore=E203,W503,E722,E731 --max-complexity=100 --max-line-length=160
uv run flake8 cfbs/ tests/ --extend-exclude=tests/tmp --ignore=E203,W503,E722,E731 --max-complexity=100 --max-line-length=160
- name: Lint with pyright (type checking)
run: |
python -m pyright cfbs --pythonversion ${{ matrix.python-version }}
uv tool run pyright cfbs --pythonversion ${{ matrix.python-version }}
- name: Test with pytest
run: |
python -m pytest
uv run pytest
- name: Install
run: |
python setup.py sdist bdist_wheel
uv build
pip install dist/cfbs-*.whl
- name: Run bash tests
run: |
UNSAFE_TESTS=1 bash tests/shell/all.sh
test-legacy:
runs-on: ubuntu-24.04
needs: build
permissions:
contents: read
env:
Expand Down Expand Up @@ -88,9 +109,13 @@ jobs:
- name: Test with pytest
run: |
python -m pytest
- name: Retrieve dists built on modern Python
uses: actions/download-artifact@v4
with:
name: dists
path: dist/
- name: Install
run: |
python setup.py sdist bdist_wheel
pip install dist/cfbs-*.whl
- name: Run bash tests
run: |
Expand Down
30 changes: 29 additions & 1 deletion .github/workflows/python-validate-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,32 @@ on:
branches: [master]

jobs:
build:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Build distributions
run: |
python -m pip install --upgrade pip
pip install uv
uv lock --check
uv build
- name: Upload dists as artifact
uses: actions/upload-artifact@v4
with:
name: dists
path: dist/
test-legacy:
runs-on: ubuntu-24.04
needs: build
permissions:
contents: read
env:
Expand All @@ -30,9 +54,13 @@ jobs:
uses: ./.github/actions/set-up-legacy-python
with:
python-version: ${{ matrix.python-version }}
- name: Retrieve dists built on modern Python
uses: actions/download-artifact@v4
with:
name: dists
path: dist/
- name: Install
run: |
python setup.py sdist bdist_wheel
pip install dist/cfbs-*.whl
- name: Run bash tests
run: |
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ __pycache__/
cfbs.egg-info
cfbs/VERSION
*.pyc
.venv/
.pytest_cache/

# Node / npm:
node_modules/
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
81 changes: 81 additions & 0 deletions HACKING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Developing / maintaining cfbs

This document aims to have relevant information for people contributing to and maintaining cfbs.
It is not necessary for users of the tool to know about these processes.
For general user information, see the [README](./README.md).

## Development environment

We use [uv](https://docs.astral.sh/uv/) to manage the virtual environment, dependencies, and builds.
Development dependencies are declared in [pyproject.toml](./pyproject.toml) and locked in [uv.lock](./uv.lock).

Note that while developing cfbs requires a modern version of Python (see [.python-version](./.python-version)), the tool itself still supports very old versions of Python at runtime (see `requires-python` in [pyproject.toml](./pyproject.toml)).
Keep this in mind when writing code — newer syntax and standard library features cannot be used.

## Code formatting

We use [black](https://pypi.org/project/black/) to ensure consistent code style / indentation:

```bash
make format
```

## Installing from source

For developers working on cfbs, you can install it globally using pipx:

```bash
make install
```

This is optional — `make check` and `uv run` work without a global install.

## Running commands without installing

You can run commands without installing globally, using `uv`:

```bash
uv run cfbs --version
```

## Running tests

Use the makefile command to run formatting, linting, and unit tests:

```bash
make check
```

Running individual test suites:

```bash
uv run pytest
```

The shell based tests use the cfbs you have installed globally, and some of them alter files outside the repo (and are thus gated behind an environment variable):

```bash
pip install .
UNSAFE_TESTS=1 bash tests/shell/all.sh
```

## Versioning

The version number is determined from git tags using [setuptools-scm](https://pypi.org/project/setuptools-scm/).
At build time, the version is written to `cfbs/VERSION`, which is read at runtime by `cfbs --version`.

## Releasing new versions

Releases are [automated using a GH Action](https://github.com/cfengine/cfbs/blob/master/.github/workflows/python-publish.yml).
We create tags and releases through the GitHub UI:

https://github.com/cfengine/cfbs/releases

Determine the new version number according to SemVer, then:

1. Enter the version number into the **Choose a tag** dropdown.
2. Click the **Create new tag on publish** alternative.
3. Target should say **master**, don't change it.
4. Put exactly the same version number into the **Release title** field.
5. Click **Generate release notes**.
6. Click **Publish release**.
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.PHONY: default format lint install check venv

default: check

venv:
uv venv --clear
uv sync

format: venv
uv tool run black cfbs/ tests/

lint: venv
uv tool run black --check cfbs/ tests/ --fast
uv run flake8 cfbs/ tests/ --extend-exclude=tests/tmp --ignore=E203,W503,E722,E731 --max-complexity=100 --max-line-length=160
uv tool run pyright cfbs/

install:
pipx install --force --editable .

check: venv format lint
uv run pytest
51 changes: 51 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[build-system]
# Note: These lower bounds are the newest versions which still work on
# Python 3.8, the oldest version we build / develop on (see the CI matrix).
requires = ["setuptools>=75.3", "setuptools-scm>=8.1"]
build-backend = "setuptools.build_meta"

[project]
name = "cfbs"
dynamic = ["version"]
description = "Tooling to build, manage and deploy CFEngine policy"
readme = "README.md"
authors = [{ name = "Northern.tech, Inc.", email = "contact@northern.tech" }]
requires-python = ">=3.5"
dependencies = []
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]

[project.urls]
Homepage = "https://github.com/cfengine/cfbs"

[project.scripts]
cfbs = "cfbs.main:main"

[tool.setuptools]
license-files = [] # Workaround bug in setuptools https://github.com/astral-sh/uv/issues/9513

[tool.setuptools.packages.find]
include = ["cfbs*"]

[tool.setuptools.package-data]
cfbs = ["VERSION", "cfbs.1"]

[tool.setuptools_scm]
version_file = "cfbs/VERSION"
version_file_template = "{version}\n"

[tool.pyright]
include = ["cfbs"]
venvPath = "."
venv = ".venv"

# cfbs itself supports very old Python versions (see requires-python above),
# but the development tools below do not, hence the markers:
[dependency-groups]
dev = [
"flake8>=5.0; python_full_version >= '3.8.1'",
"pytest>=7.0; python_full_version >= '3.8.1'",
]
Empty file removed requirements.txt
Empty file.
50 changes: 0 additions & 50 deletions setup.py

This file was deleted.

Loading
Loading