confkit 2.1.1__tar.gz → 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- confkit-3.0.0/.github/actions/setup/action.yml +34 -0
- confkit-3.0.0/.github/ci-filters.yml +51 -0
- confkit-3.0.0/.github/workflows/bump-version-by-labels.yml +32 -0
- confkit-3.0.0/.github/workflows/ci.yml +147 -0
- confkit-3.0.0/.github/workflows/coverage.yml +55 -0
- confkit-3.0.0/.github/workflows/docs-publish.yml +81 -0
- confkit-3.0.0/.github/workflows/docs.yml +42 -0
- {confkit-2.1.1 → confkit-3.0.0}/.github/workflows/gitleaks.yml +4 -8
- confkit-3.0.0/.github/workflows/lint.yml +52 -0
- {confkit-2.1.1 → confkit-3.0.0}/.github/workflows/pypi.yml +1 -1
- {confkit-2.1.1 → confkit-3.0.0}/.github/workflows/release.yml +5 -10
- {confkit-2.1.1 → confkit-3.0.0}/.github/workflows/test.yml +12 -22
- {confkit-2.1.1 → confkit-3.0.0}/.pre-commit-config.yaml +9 -6
- {confkit-2.1.1 → confkit-3.0.0}/PKG-INFO +4 -4
- confkit-3.0.0/docs/ci.md +107 -0
- confkit-3.0.0/docs/examples/delegate.md +67 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/index.md +1 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/usage.md +2 -0
- confkit-3.0.0/examples/delegate.py +32 -0
- {confkit-2.1.1 → confkit-3.0.0}/mkdocs.yml +1 -0
- {confkit-2.1.1 → confkit-3.0.0}/pyproject.toml +26 -17
- {confkit-2.1.1 → confkit-3.0.0}/ruff.toml +1 -1
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/config.py +2 -2
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/data_types.py +1 -1
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/exceptions.py +4 -0
- confkit-3.0.0/src/confkit/ext/delegate.py +143 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/parsers.py +7 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_config_decorators.py +18 -4
- confkit-3.0.0/tests/test_delegate.py +168 -0
- confkit-3.0.0/uv.lock +1924 -0
- {confkit-2.1.1 → confkit-3.0.0}/zensical.toml +5 -1
- confkit-2.1.1/.github/workflows/bump-version-by-labels.yml +0 -34
- confkit-2.1.1/.github/workflows/coverage.yml +0 -46
- confkit-2.1.1/.github/workflows/docs.yml +0 -30
- confkit-2.1.1/.github/workflows/lint-public.yml +0 -70
- confkit-2.1.1/.github/workflows/lint.yml +0 -66
- confkit-2.1.1/uv.lock +0 -1298
- {confkit-2.1.1 → confkit-3.0.0}/.bumpversion.toml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/.github/FUNDING.yml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/.github/copilot-instructions.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/.github/dependabot.yml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/.gitignore +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/.python-version +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/.vscode/settings.json +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/LICENSE +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/README.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/argparse.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/basic.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/custom_data_type.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/data_types.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/decorators.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/enums.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/list_types.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/examples/optional_values.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/index.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/markdown.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/reference/config.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/reference/data_types.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/reference/exceptions.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/docs/reference/notes_two_instances.md +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/api.ini +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/argparse_example.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/args.ini +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/basic.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/config.ini +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/custom_data_type.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/data_types.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/database.ini +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/decorators.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/enums.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/example.json +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/example.toml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/example.yaml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/file_change_event.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/list_types.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/multiple_configs.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/nested_config.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/nested_example.ini +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/nested_example.json +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/nested_example.toml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/nested_example.yaml +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/optional_values.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/other_file_types.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/pydantic_example.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/references.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/examples/url_example.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/__init__.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/ext/__init__.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/ext/parsers.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/ext/pydantic.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/ext/reference.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/py.typed +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/sentinels.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/src/confkit/watcher.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/__init__.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/conftest.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_config.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_config_classvars.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_config_detect_parser.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_data_types.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_enum_allowed_values.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_enum_auto_conversion.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_env_parser.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_examples_run.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_list_type.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_metaclass.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_msgspec.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_msgspecparser_branches.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_msgspecparser_no_msgspec.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_msgspecparser_read.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_msgspecparser_sections.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_multiple_configurations.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_nested_config.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_on_file_change.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_pydantic_models.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_sentinel.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_two_instances.py +0 -0
- {confkit-2.1.1 → confkit-3.0.0}/tests/test_unreachable_paths.py +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Set up uv and the project
|
|
2
|
+
description: Install uv and a Python version, then sync the locked dependency groups.
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
python-version:
|
|
6
|
+
description: Python version to install.
|
|
7
|
+
default: "3.13"
|
|
8
|
+
sync-args:
|
|
9
|
+
description: Extra arguments for `uv sync`, such as `--group dev`.
|
|
10
|
+
default: ""
|
|
11
|
+
|
|
12
|
+
runs:
|
|
13
|
+
using: composite
|
|
14
|
+
steps:
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v7
|
|
17
|
+
with:
|
|
18
|
+
enable-cache: true
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ inputs.python-version }}
|
|
21
|
+
shell: bash
|
|
22
|
+
run: uv python install ${{ inputs.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
shell: bash
|
|
26
|
+
run: uv sync --locked --python ${{ inputs.python-version }} ${{ inputs.sync-args }}
|
|
27
|
+
|
|
28
|
+
# Without these, a later `uv run` follows .python-version back to 3.11
|
|
29
|
+
# and re-syncs only the default groups, dropping the ones synced above.
|
|
30
|
+
- name: Keep later uv commands on this environment
|
|
31
|
+
shell: bash
|
|
32
|
+
run: |
|
|
33
|
+
echo "UV_PYTHON=${{ inputs.python-version }}" >> "$GITHUB_ENV"
|
|
34
|
+
echo "UV_NO_SYNC=1" >> "$GITHUB_ENV"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Inputs for each check that ci.yml runs. A check only runs when one of its
|
|
2
|
+
# inputs changed. Editing CI itself reruns every check.
|
|
3
|
+
ci: &ci
|
|
4
|
+
- .github/workflows/ci.yml
|
|
5
|
+
- .github/ci-filters.yml
|
|
6
|
+
- .github/actions/setup/**
|
|
7
|
+
deps: &deps
|
|
8
|
+
- pyproject.toml
|
|
9
|
+
- uv.lock
|
|
10
|
+
|
|
11
|
+
test:
|
|
12
|
+
- *ci
|
|
13
|
+
- *deps
|
|
14
|
+
- .github/workflows/test.yml
|
|
15
|
+
- src/**
|
|
16
|
+
- tests/**
|
|
17
|
+
|
|
18
|
+
lint:
|
|
19
|
+
- *ci
|
|
20
|
+
- *deps
|
|
21
|
+
- .github/workflows/lint.yml
|
|
22
|
+
- ruff.toml
|
|
23
|
+
- src/**
|
|
24
|
+
- tests/**
|
|
25
|
+
- examples/**
|
|
26
|
+
|
|
27
|
+
lint-public:
|
|
28
|
+
- *ci
|
|
29
|
+
- *deps
|
|
30
|
+
- .github/workflows/lint.yml
|
|
31
|
+
- ruff.toml
|
|
32
|
+
- src/**
|
|
33
|
+
- examples/**
|
|
34
|
+
|
|
35
|
+
coverage:
|
|
36
|
+
- *ci
|
|
37
|
+
- *deps
|
|
38
|
+
- .github/workflows/coverage.yml
|
|
39
|
+
- src/**
|
|
40
|
+
- tests/**
|
|
41
|
+
- examples/**
|
|
42
|
+
|
|
43
|
+
docs:
|
|
44
|
+
- *ci
|
|
45
|
+
- *deps
|
|
46
|
+
- .github/workflows/docs.yml
|
|
47
|
+
- .github/workflows/docs-publish.yml
|
|
48
|
+
- zensical.toml
|
|
49
|
+
- mkdocs.yml
|
|
50
|
+
- src/**
|
|
51
|
+
- docs/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Bump Version By Labels
|
|
2
|
+
|
|
3
|
+
# Called from ci.yml once all-checks passes on a push to master. The action
|
|
4
|
+
# looks up the merged PR for the pushed commit and opens a bump PR from its
|
|
5
|
+
# Major, Minor or Patch label. Merging the bump PR runs CI again, and that
|
|
6
|
+
# run's release job publishes the new version.
|
|
7
|
+
on:
|
|
8
|
+
workflow_call:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
bump-version:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v7
|
|
24
|
+
|
|
25
|
+
# v4.1.0 is the first release that reads labels on push events.
|
|
26
|
+
- name: Bump by labels
|
|
27
|
+
uses: HEROgold/bump-by-label@v4.1.0
|
|
28
|
+
with:
|
|
29
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
30
|
+
command: "uv version --bump"
|
|
31
|
+
validate: "uv version"
|
|
32
|
+
base_branch: master
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# One entry point for every check. The changes job compares the push or PR
|
|
4
|
+
# against .github/ci-filters.yml, and each check only runs when its inputs
|
|
5
|
+
# changed. On pushes to master the chain continues once all-checks passes.
|
|
6
|
+
# Bump opens a version bump PR, then release tags and publishes any version
|
|
7
|
+
# that has no tag yet. Coverage stays outside the chain.
|
|
8
|
+
#
|
|
9
|
+
# The master ruleset requires none of these checks. To require them, require
|
|
10
|
+
# the all-checks job only. A called workflow's check names change with whether
|
|
11
|
+
# it ran ("test / test (3.13)") or was skipped ("test"), so neither name works
|
|
12
|
+
# as a required check on its own.
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
branches: [master]
|
|
16
|
+
pull_request:
|
|
17
|
+
branches: [master]
|
|
18
|
+
# closed only removes the docs preview.
|
|
19
|
+
types: [opened, synchronize, reopened, closed]
|
|
20
|
+
workflow_dispatch:
|
|
21
|
+
|
|
22
|
+
# A newer push to a PR cancels its older run. Pushes to master each get their
|
|
23
|
+
# own group, because GitHub keeps only one pending run per group and would
|
|
24
|
+
# drop a merge's run, along with its version bump.
|
|
25
|
+
concurrency:
|
|
26
|
+
group: ${{ github.event_name == 'push' && github.run_id || format('ci-{0}', github.ref) }}
|
|
27
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
28
|
+
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
changes:
|
|
34
|
+
if: github.event.action != 'closed'
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
permissions:
|
|
37
|
+
contents: read
|
|
38
|
+
pull-requests: read
|
|
39
|
+
outputs:
|
|
40
|
+
# A manual run checks everything.
|
|
41
|
+
test: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.test == 'true' }}
|
|
42
|
+
lint: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.lint == 'true' }}
|
|
43
|
+
lint-public: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.lint-public == 'true' }}
|
|
44
|
+
coverage: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.coverage == 'true' }}
|
|
45
|
+
docs: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.docs == 'true' }}
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v7
|
|
48
|
+
|
|
49
|
+
- uses: dorny/paths-filter@v3
|
|
50
|
+
id: filter
|
|
51
|
+
if: github.event_name != 'workflow_dispatch'
|
|
52
|
+
with:
|
|
53
|
+
filters: .github/ci-filters.yml
|
|
54
|
+
|
|
55
|
+
test:
|
|
56
|
+
needs: changes
|
|
57
|
+
if: needs.changes.outputs.test == 'true'
|
|
58
|
+
uses: ./.github/workflows/test.yml
|
|
59
|
+
|
|
60
|
+
lint:
|
|
61
|
+
needs: changes
|
|
62
|
+
if: needs.changes.outputs.lint == 'true'
|
|
63
|
+
uses: ./.github/workflows/lint.yml
|
|
64
|
+
with:
|
|
65
|
+
cache-prefix: lint
|
|
66
|
+
tools: >-
|
|
67
|
+
[
|
|
68
|
+
{"tool": "ruff", "args": "check ."},
|
|
69
|
+
{"tool": "ty", "args": "check . --ignore no-matching-overload"},
|
|
70
|
+
{"tool": "undersort", "args": ". --check"}
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
lint-public:
|
|
74
|
+
needs: changes
|
|
75
|
+
if: needs.changes.outputs.lint-public == 'true'
|
|
76
|
+
uses: ./.github/workflows/lint.yml
|
|
77
|
+
with:
|
|
78
|
+
cache-prefix: lint-public
|
|
79
|
+
tools: >-
|
|
80
|
+
[
|
|
81
|
+
{"tool": "ruff", "args": "check ./examples"},
|
|
82
|
+
{"tool": "ty", "args": "check ./examples --ignore no-matching-overload"},
|
|
83
|
+
{"tool": "pyrefly", "args": "check ./examples"},
|
|
84
|
+
{"tool": "zuban", "args": "check ./examples"},
|
|
85
|
+
{"tool": "mypy", "args": "./examples"},
|
|
86
|
+
{"tool": "pyright", "args": "./examples"}
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
gitleaks:
|
|
90
|
+
if: github.event.action != 'closed'
|
|
91
|
+
uses: ./.github/workflows/gitleaks.yml
|
|
92
|
+
|
|
93
|
+
docs:
|
|
94
|
+
needs: changes
|
|
95
|
+
if: needs.changes.outputs.docs == 'true'
|
|
96
|
+
uses: ./.github/workflows/docs.yml
|
|
97
|
+
|
|
98
|
+
# Not a check, so all-checks doesn't wait on it. Each PR and master get their
|
|
99
|
+
# own group. A newer run waiting in the group replaces an older waiting one,
|
|
100
|
+
# so the newest docs always win.
|
|
101
|
+
docs-publish:
|
|
102
|
+
needs: docs
|
|
103
|
+
# Always runs on closed, so the preview gets removed even when no docs input changed.
|
|
104
|
+
if: always() && (github.event.action == 'closed' || needs.docs.result == 'success')
|
|
105
|
+
concurrency:
|
|
106
|
+
group: gh-pages-${{ github.event.pull_request.number || 'master' }}
|
|
107
|
+
uses: ./.github/workflows/docs-publish.yml
|
|
108
|
+
permissions:
|
|
109
|
+
contents: write
|
|
110
|
+
pull-requests: write
|
|
111
|
+
|
|
112
|
+
coverage:
|
|
113
|
+
needs: changes
|
|
114
|
+
if: github.event_name == 'push' && needs.changes.outputs.coverage == 'true'
|
|
115
|
+
uses: ./.github/workflows/coverage.yml
|
|
116
|
+
secrets:
|
|
117
|
+
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
|
|
118
|
+
|
|
119
|
+
# Passes when every check passed or was skipped because its inputs didn't
|
|
120
|
+
# change. Coverage is informational, so it isn't listed.
|
|
121
|
+
all-checks:
|
|
122
|
+
if: always() && github.event.action != 'closed'
|
|
123
|
+
needs: [changes, test, lint, lint-public, gitleaks, docs]
|
|
124
|
+
runs-on: ubuntu-latest
|
|
125
|
+
steps:
|
|
126
|
+
- name: Fail if a check failed or was cancelled
|
|
127
|
+
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
|
|
128
|
+
run: exit 1
|
|
129
|
+
|
|
130
|
+
# always() is needed even though all-checks passed. Without it, GitHub's
|
|
131
|
+
# implicit success() also looks at the checks all-checks needs, and skips
|
|
132
|
+
# this job whenever one of them was skipped.
|
|
133
|
+
bump:
|
|
134
|
+
needs: all-checks
|
|
135
|
+
if: always() && github.event_name == 'push' && needs.all-checks.result == 'success'
|
|
136
|
+
uses: ./.github/workflows/bump-version-by-labels.yml
|
|
137
|
+
permissions:
|
|
138
|
+
contents: write
|
|
139
|
+
pull-requests: write
|
|
140
|
+
|
|
141
|
+
release:
|
|
142
|
+
needs: bump
|
|
143
|
+
if: always() && needs.bump.result == 'success'
|
|
144
|
+
uses: ./.github/workflows/release.yml
|
|
145
|
+
permissions:
|
|
146
|
+
contents: write
|
|
147
|
+
secrets: inherit
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Coverage
|
|
2
|
+
|
|
3
|
+
# Called from ci.yml on pushes to master. Informational, so nothing waits on it.
|
|
4
|
+
on:
|
|
5
|
+
workflow_call:
|
|
6
|
+
secrets:
|
|
7
|
+
COVERALLS_REPO_TOKEN:
|
|
8
|
+
required: false
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
coveralls-upload:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
|
+
|
|
19
|
+
# A hit means coverage for these exact inputs is already on Coveralls.
|
|
20
|
+
- name: Cache coverage result
|
|
21
|
+
id: cache-coverage
|
|
22
|
+
uses: actions/cache@v4
|
|
23
|
+
with:
|
|
24
|
+
path: .coverage_cache
|
|
25
|
+
key: ${{ runner.os }}-coverage-${{ hashFiles('src/**', 'tests/**', 'examples/**', 'pyproject.toml', 'uv.lock', '.github/workflows/coverage.yml', '.github/actions/setup/**') }}
|
|
26
|
+
|
|
27
|
+
- name: Set up the project
|
|
28
|
+
if: steps.cache-coverage.outputs.cache-hit != 'true'
|
|
29
|
+
uses: ./.github/actions/setup
|
|
30
|
+
with:
|
|
31
|
+
sync-args: --group dev
|
|
32
|
+
|
|
33
|
+
- name: Run tests with coverage
|
|
34
|
+
if: steps.cache-coverage.outputs.cache-hit != 'true'
|
|
35
|
+
run: uv run coverage run --source=. -m pytest tests/
|
|
36
|
+
|
|
37
|
+
- name: Upload coverage data to coveralls.io
|
|
38
|
+
if: steps.cache-coverage.outputs.cache-hit != 'true'
|
|
39
|
+
env:
|
|
40
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
41
|
+
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
|
|
42
|
+
COVERALLS_SERVICE_NAME: github-actions
|
|
43
|
+
COVERALLS_PARALLEL: true
|
|
44
|
+
run: uvx coveralls --service=github
|
|
45
|
+
|
|
46
|
+
- name: Coveralls Finished
|
|
47
|
+
if: steps.cache-coverage.outputs.cache-hit != 'true'
|
|
48
|
+
env:
|
|
49
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
50
|
+
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
|
|
51
|
+
run: uvx coveralls --finish
|
|
52
|
+
|
|
53
|
+
- name: Record the upload
|
|
54
|
+
if: steps.cache-coverage.outputs.cache-hit != 'true'
|
|
55
|
+
run: mkdir -p .coverage_cache && touch .coverage_cache/done
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Publish documentation
|
|
2
|
+
|
|
3
|
+
# Called from ci.yml after the docs build. Pages serves the gh-pages branch.
|
|
4
|
+
# Master publishes to its root, and each PR from this repo gets a preview under
|
|
5
|
+
# pr-previews/pr-<n>/. Fork PRs get no preview, because their token can't push
|
|
6
|
+
# to gh-pages. Both actions fetch and rebase when another run pushed first.
|
|
7
|
+
on:
|
|
8
|
+
workflow_call:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
preview:
|
|
15
|
+
if: >-
|
|
16
|
+
github.event_name == 'pull_request'
|
|
17
|
+
&& github.event.action != 'closed'
|
|
18
|
+
&& github.event.pull_request.head.repo.full_name == github.repository
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write
|
|
22
|
+
pull-requests: write
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
|
+
|
|
26
|
+
- uses: actions/download-artifact@v4
|
|
27
|
+
with:
|
|
28
|
+
name: site
|
|
29
|
+
path: site
|
|
30
|
+
|
|
31
|
+
- name: Deploy the PR preview
|
|
32
|
+
uses: rossjrw/pr-preview-action@v1
|
|
33
|
+
with:
|
|
34
|
+
source-dir: site
|
|
35
|
+
preview-branch: gh-pages
|
|
36
|
+
umbrella-dir: pr-previews
|
|
37
|
+
action: deploy
|
|
38
|
+
|
|
39
|
+
remove-preview:
|
|
40
|
+
if: >-
|
|
41
|
+
github.event_name == 'pull_request'
|
|
42
|
+
&& github.event.action == 'closed'
|
|
43
|
+
&& github.event.pull_request.head.repo.full_name == github.repository
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
permissions:
|
|
46
|
+
contents: write
|
|
47
|
+
pull-requests: write
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v7
|
|
50
|
+
|
|
51
|
+
- name: Remove the PR preview
|
|
52
|
+
uses: rossjrw/pr-preview-action@v1
|
|
53
|
+
with:
|
|
54
|
+
preview-branch: gh-pages
|
|
55
|
+
umbrella-dir: pr-previews
|
|
56
|
+
action: remove
|
|
57
|
+
|
|
58
|
+
deploy:
|
|
59
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
permissions:
|
|
62
|
+
contents: write
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v7
|
|
65
|
+
|
|
66
|
+
- uses: actions/download-artifact@v4
|
|
67
|
+
with:
|
|
68
|
+
name: site
|
|
69
|
+
path: site
|
|
70
|
+
|
|
71
|
+
# Only the root needs .nojekyll. In a preview it would outlive the
|
|
72
|
+
# preview's removal, which skips hidden files.
|
|
73
|
+
- name: Keep Pages from running Jekyll
|
|
74
|
+
run: touch site/.nojekyll
|
|
75
|
+
|
|
76
|
+
- name: Publish to the gh-pages root
|
|
77
|
+
uses: JamesIves/github-pages-deploy-action@v4
|
|
78
|
+
with:
|
|
79
|
+
folder: site
|
|
80
|
+
branch: gh-pages
|
|
81
|
+
clean-exclude: pr-previews
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
# Called from ci.yml. Builds the site and uploads it as the "site" artifact.
|
|
4
|
+
# docs-publish.yml publishes it, so a cancelled publish never fails this check.
|
|
5
|
+
on:
|
|
6
|
+
workflow_call:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v7
|
|
17
|
+
|
|
18
|
+
# A hit means the site for these exact inputs is already built.
|
|
19
|
+
- name: Cache the built site
|
|
20
|
+
id: cache-site
|
|
21
|
+
uses: actions/cache@v4
|
|
22
|
+
with:
|
|
23
|
+
path: site
|
|
24
|
+
key: ${{ runner.os }}-site-${{ hashFiles('src/**', 'docs/**', 'zensical.toml', 'mkdocs.yml', 'pyproject.toml', 'uv.lock', '.github/workflows/docs.yml', '.github/actions/setup/**') }}
|
|
25
|
+
|
|
26
|
+
- name: Set up the project
|
|
27
|
+
if: steps.cache-site.outputs.cache-hit != 'true'
|
|
28
|
+
uses: ./.github/actions/setup
|
|
29
|
+
with:
|
|
30
|
+
sync-args: --group docs
|
|
31
|
+
|
|
32
|
+
- name: Build the site
|
|
33
|
+
if: steps.cache-site.outputs.cache-hit != 'true'
|
|
34
|
+
run: |
|
|
35
|
+
uv run pdoc confkit -o docs/api
|
|
36
|
+
uv run zensical build --clean
|
|
37
|
+
|
|
38
|
+
- uses: actions/upload-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: site
|
|
41
|
+
path: site
|
|
42
|
+
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
name: Gitleaks
|
|
2
2
|
|
|
3
|
+
# Called from ci.yml on every push and PR, with no path filter, because a
|
|
4
|
+
# leaked secret can land in any file.
|
|
3
5
|
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [master]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [master]
|
|
8
|
-
workflow_dispatch:
|
|
9
6
|
workflow_call:
|
|
10
|
-
|
|
11
|
-
concurrency: gitleaks-${{ github.ref }}
|
|
7
|
+
workflow_dispatch:
|
|
12
8
|
|
|
13
9
|
permissions:
|
|
14
10
|
contents: read
|
|
@@ -18,7 +14,7 @@ jobs:
|
|
|
18
14
|
runs-on: ubuntu-latest
|
|
19
15
|
steps:
|
|
20
16
|
- name: Checkout code
|
|
21
|
-
uses: actions/checkout@
|
|
17
|
+
uses: actions/checkout@v7
|
|
22
18
|
with:
|
|
23
19
|
fetch-depth: 0
|
|
24
20
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Lint
|
|
2
|
+
|
|
3
|
+
# Called from ci.yml twice: once for the package and once for the public API
|
|
4
|
+
# as the examples use it.
|
|
5
|
+
on:
|
|
6
|
+
workflow_call:
|
|
7
|
+
inputs:
|
|
8
|
+
cache-prefix:
|
|
9
|
+
description: Cache key prefix that keeps the two callers apart.
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
tools:
|
|
13
|
+
description: JSON list of {"tool", "args"} objects, one matrix entry each.
|
|
14
|
+
required: true
|
|
15
|
+
type: string
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
lint:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
include: ${{ fromJSON(inputs.tools) }}
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
|
|
31
|
+
# The lint group in uv.lock pins every tool, so a tool upgrade changes
|
|
32
|
+
# the key. A hit means this tool already passed on these exact inputs.
|
|
33
|
+
- name: Cache lint result
|
|
34
|
+
id: cache-lint
|
|
35
|
+
uses: actions/cache@v4
|
|
36
|
+
with:
|
|
37
|
+
path: .lint_cache
|
|
38
|
+
key: ${{ runner.os }}-${{ inputs.cache-prefix }}-${{ matrix.tool }}-${{ hashFiles('src/**', 'tests/**', 'examples/**', 'pyproject.toml', 'uv.lock', 'ruff.toml', '.github/workflows/ci.yml', '.github/workflows/lint.yml', '.github/actions/setup/**') }}
|
|
39
|
+
|
|
40
|
+
- name: Set up the project
|
|
41
|
+
if: steps.cache-lint.outputs.cache-hit != 'true'
|
|
42
|
+
uses: ./.github/actions/setup
|
|
43
|
+
with:
|
|
44
|
+
sync-args: --group dev --group lint
|
|
45
|
+
|
|
46
|
+
- name: Run ${{ matrix.tool }}
|
|
47
|
+
if: steps.cache-lint.outputs.cache-hit != 'true'
|
|
48
|
+
run: uv run ${{ matrix.tool }} ${{ matrix.args }}
|
|
49
|
+
|
|
50
|
+
- name: Record the pass
|
|
51
|
+
if: steps.cache-lint.outputs.cache-hit != 'true'
|
|
52
|
+
run: mkdir -p .lint_cache && touch ".lint_cache/${{ matrix.tool }}"
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
name: Auto-release
|
|
2
2
|
|
|
3
|
+
# Called from ci.yml after the version bump, on pushes to master. A push
|
|
4
|
+
# that merged a bump PR has an untagged version, so this run releases it.
|
|
3
5
|
on:
|
|
4
|
-
|
|
5
|
-
workflows: ["Test"]
|
|
6
|
-
branches: [master]
|
|
7
|
-
types:
|
|
8
|
-
- completed
|
|
6
|
+
workflow_call:
|
|
9
7
|
workflow_dispatch:
|
|
10
8
|
|
|
11
9
|
jobs:
|
|
@@ -13,12 +11,11 @@ jobs:
|
|
|
13
11
|
runs-on: ubuntu-latest
|
|
14
12
|
permissions:
|
|
15
13
|
contents: write
|
|
16
|
-
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
|
|
17
14
|
outputs:
|
|
18
15
|
version_changed: ${{ steps.version-check.outputs.version_changed }}
|
|
19
16
|
|
|
20
17
|
steps:
|
|
21
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v7
|
|
22
19
|
with:
|
|
23
20
|
fetch-depth: 0 # Needed to get all tags for version comparison
|
|
24
21
|
|
|
@@ -28,9 +25,7 @@ jobs:
|
|
|
28
25
|
python-version: "3.*"
|
|
29
26
|
|
|
30
27
|
- name: Install uv
|
|
31
|
-
uses: astral-sh/setup-uv@
|
|
32
|
-
with:
|
|
33
|
-
version: "latest"
|
|
28
|
+
uses: astral-sh/setup-uv@v7
|
|
34
29
|
|
|
35
30
|
- name: Check if version changed
|
|
36
31
|
id: version-check
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
name: Test
|
|
2
2
|
|
|
3
|
+
# Called from ci.yml, which decides whether the inputs below changed.
|
|
3
4
|
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [master]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [master]
|
|
8
|
-
workflow_dispatch:
|
|
9
5
|
workflow_call:
|
|
10
|
-
|
|
11
|
-
concurrency: test-${{ github.sha }}
|
|
6
|
+
workflow_dispatch:
|
|
12
7
|
|
|
13
8
|
permissions:
|
|
14
9
|
contents: read
|
|
@@ -18,32 +13,27 @@ jobs:
|
|
|
18
13
|
runs-on: ubuntu-latest
|
|
19
14
|
strategy:
|
|
20
15
|
matrix:
|
|
21
|
-
python-version: ["3.
|
|
16
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
22
17
|
fail-fast: false
|
|
23
18
|
|
|
24
19
|
steps:
|
|
25
|
-
- uses: actions/checkout@
|
|
20
|
+
- uses: actions/checkout@v7
|
|
26
21
|
|
|
22
|
+
# A hit means these exact inputs already passed on this Python version.
|
|
23
|
+
# The cache only saves when the job succeeds, so a failure never hits.
|
|
27
24
|
- name: Cache pytest results
|
|
28
25
|
id: cache-pytest
|
|
29
26
|
uses: actions/cache@v4
|
|
30
27
|
with:
|
|
31
28
|
path: .pytest_cache
|
|
32
|
-
key: ${{ runner.os }}-pytest-${{ matrix.python-version }}-${{ hashFiles('
|
|
29
|
+
key: ${{ runner.os }}-pytest-${{ matrix.python-version }}-${{ hashFiles('src/**', 'tests/**', 'pyproject.toml', 'uv.lock', '.github/workflows/test.yml', '.github/actions/setup/**') }}
|
|
33
30
|
|
|
34
|
-
- name:
|
|
31
|
+
- name: Set up the project
|
|
35
32
|
if: steps.cache-pytest.outputs.cache-hit != 'true'
|
|
36
|
-
uses:
|
|
33
|
+
uses: ./.github/actions/setup
|
|
37
34
|
with:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- name: Set up Python ${{ matrix.python-version }}
|
|
41
|
-
if: steps.cache-pytest.outputs.cache-hit != 'true'
|
|
42
|
-
run: uv python install ${{ matrix.python-version }}
|
|
43
|
-
|
|
44
|
-
- name: Install dependencies
|
|
45
|
-
if: steps.cache-pytest.outputs.cache-hit != 'true'
|
|
46
|
-
run: uv sync --group dev
|
|
35
|
+
python-version: ${{ matrix.python-version }}
|
|
36
|
+
sync-args: --group dev
|
|
47
37
|
|
|
48
38
|
- name: Run tests
|
|
49
39
|
if: steps.cache-pytest.outputs.cache-hit != 'true'
|
|
@@ -55,7 +45,7 @@ jobs:
|
|
|
55
45
|
clean-install:
|
|
56
46
|
runs-on: ubuntu-latest
|
|
57
47
|
steps:
|
|
58
|
-
- uses: actions/checkout@
|
|
48
|
+
- uses: actions/checkout@v7
|
|
59
49
|
|
|
60
50
|
- name: Install uv
|
|
61
51
|
uses: astral-sh/setup-uv@v7
|