talkpipe-agents 0.1.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.
- talkpipe_agents-0.1.0/.gitea/default_merge_message/MERGE_TEMPLATE.md +1 -0
- talkpipe_agents-0.1.0/.gitea/default_merge_message/SQUASH_TEMPLATE.md +1 -0
- talkpipe_agents-0.1.0/.github/ISSUE_TEMPLATE/release-checklist.md +20 -0
- talkpipe_agents-0.1.0/.github/SECURITY.md +47 -0
- talkpipe_agents-0.1.0/.github/dependabot.yml +38 -0
- talkpipe_agents-0.1.0/.github/workflows/ci-cd.yml +372 -0
- talkpipe_agents-0.1.0/.gitignore +14 -0
- talkpipe_agents-0.1.0/.pre-commit-config.yaml +20 -0
- talkpipe_agents-0.1.0/.safety-policy.yml +58 -0
- talkpipe_agents-0.1.0/CHANGELOG.md +336 -0
- talkpipe_agents-0.1.0/CLAUDE.md +69 -0
- talkpipe_agents-0.1.0/COPYRIGHT +3 -0
- talkpipe_agents-0.1.0/LICENSE +179 -0
- talkpipe_agents-0.1.0/MANIFEST.in +3 -0
- talkpipe_agents-0.1.0/PKG-INFO +268 -0
- talkpipe_agents-0.1.0/README.md +211 -0
- talkpipe_agents-0.1.0/RELEASING.md +134 -0
- talkpipe_agents-0.1.0/docs/design.md +116 -0
- talkpipe_agents-0.1.0/docs/getting-started.md +162 -0
- talkpipe_agents-0.1.0/docs/model-providers.md +131 -0
- talkpipe_agents-0.1.0/docs/talkpipe-agents.svg +140 -0
- talkpipe_agents-0.1.0/docs/testing.md +102 -0
- talkpipe_agents-0.1.0/docs/tools-and-skills.md +557 -0
- talkpipe_agents-0.1.0/pyproject.toml +184 -0
- talkpipe_agents-0.1.0/setup.cfg +4 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/__init__.py +123 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/_pytest_plugin.py +35 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/chat.py +187 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/common_tools.py +497 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/hooks.py +81 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/models.py +313 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/replies.py +116 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/script_tools.py +99 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/segments.py +201 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/support.py +125 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/testing.py +266 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents/tools.py +240 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/PKG-INFO +268 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/SOURCES.txt +47 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/dependency_links.txt +1 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/entry_points.txt +5 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/requires.txt +34 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/scm_file_list.json +44 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/scm_version.json +8 -0
- talkpipe_agents-0.1.0/src/talkpipe_agents.egg-info/top_level.txt +1 -0
- talkpipe_agents-0.1.0/tests/test_agents.py +1109 -0
- talkpipe_agents-0.1.0/tests/test_common_tools.py +434 -0
- talkpipe_agents-0.1.0/tests/test_plugin.py +49 -0
- talkpipe_agents-0.1.0/tests/test_tools_doc_examples.py +271 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Merge branch '${HeadBranch}': ${PullRequestTitle}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
${PullRequestTitle}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Release Checklist
|
|
3
|
+
about: Steps for doing a new release (see RELEASING.md for detail)
|
|
4
|
+
title: Release vX.Y.Z
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Assumes the TalkPipe release this depends on is already out and working.
|
|
11
|
+
|
|
12
|
+
- [ ] `main` up to date, CI green, working tree clean
|
|
13
|
+
- [ ] `talkpipe>=…` floor in `pyproject.toml` matches what this release needs (`uv lock` if changed)
|
|
14
|
+
- [ ] CHANGELOG: `## Unreleased` → `## X.Y.Z (YYYY-MM-DD)`, fresh empty section above; merged via MR
|
|
15
|
+
- [ ] Build the wheel and install it into a **new** virtual environment; `chatterlang_script` runs an `llmAgent[...]` step against a real model (Ollama or another configured provider)
|
|
16
|
+
- [ ] Anything found: fix via MR, re-test
|
|
17
|
+
- [ ] Tag the merge commit on `main` (`git tag -a vX.Y.Z -m vX.Y.Z`) and push the tag; advance `stable` for a full release
|
|
18
|
+
- [ ] Push `main`, the tag, and `stable` to GitHub
|
|
19
|
+
- [ ] Publish the release on GitHub (pre-release for alphas/betas/rcs); watch `publish-package` finish
|
|
20
|
+
- [ ] Verify: `pip install talkpipe-agents==X.Y.Z` in a fresh venv, `python -c "import talkpipe_agents; print(talkpipe_agents.__version__)"` prints `X.Y.Z`
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
Security fixes go into the latest release only.
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| ------- | ------------------ |
|
|
9
|
+
| Latest | :white_check_mark: |
|
|
10
|
+
|
|
11
|
+
## Reporting a Vulnerability
|
|
12
|
+
|
|
13
|
+
If you discover a security vulnerability in talkpipe-agents, please report
|
|
14
|
+
it responsibly:
|
|
15
|
+
|
|
16
|
+
1. **Do not** open a public GitHub issue for it.
|
|
17
|
+
2. Email the report to tlbauer@sandia.gov.
|
|
18
|
+
3. Include a description of the vulnerability, steps to reproduce it, the
|
|
19
|
+
potential impact, and a suggested fix if you have one.
|
|
20
|
+
|
|
21
|
+
A vulnerability in the agent's tool suite (for example a tool that reads
|
|
22
|
+
files or fetches URLs doing more than its documentation says) counts; one in
|
|
23
|
+
[talkpipe](https://github.com/sandialabs/talkpipe) or in
|
|
24
|
+
[Strands Agents](https://github.com/strands-agents/sdk-python) belongs to
|
|
25
|
+
that project.
|
|
26
|
+
|
|
27
|
+
### What to Expect
|
|
28
|
+
|
|
29
|
+
- **Response**: we aim to acknowledge receipt within 2 business days.
|
|
30
|
+
- **Assessment**: an initial assessment within 5 business days.
|
|
31
|
+
- **Updates**: progress updates every 7 days until resolution.
|
|
32
|
+
- **Disclosure**: public disclosure is coordinated with the reporter once a
|
|
33
|
+
fix is released.
|
|
34
|
+
|
|
35
|
+
### Security Measures
|
|
36
|
+
|
|
37
|
+
- Dependency scanning with Safety and static analysis with Bandit on every
|
|
38
|
+
CI run, both gating the build.
|
|
39
|
+
- Static code analysis with CodeQL.
|
|
40
|
+
- Automated dependency updates via Dependabot.
|
|
41
|
+
- Declared dependency floors are security minimums: the lowest release of
|
|
42
|
+
each dependency with no known advisory.
|
|
43
|
+
|
|
44
|
+
### Acknowledgments
|
|
45
|
+
|
|
46
|
+
Researchers who responsibly disclose vulnerabilities are acknowledged in the
|
|
47
|
+
release notes unless they prefer to remain anonymous.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Enable version updates for Python dependencies
|
|
4
|
+
- package-ecosystem: "pip"
|
|
5
|
+
directory: "/"
|
|
6
|
+
target-branch: "main"
|
|
7
|
+
schedule:
|
|
8
|
+
interval: "weekly"
|
|
9
|
+
open-pull-requests-limit: 10
|
|
10
|
+
reviewers:
|
|
11
|
+
- "tlbauer2"
|
|
12
|
+
assignees:
|
|
13
|
+
- "tlbauer2"
|
|
14
|
+
commit-message:
|
|
15
|
+
prefix: "deps"
|
|
16
|
+
prefix-development: "dev-deps"
|
|
17
|
+
include: "scope"
|
|
18
|
+
|
|
19
|
+
# Enable version updates for GitHub Actions
|
|
20
|
+
- package-ecosystem: "github-actions"
|
|
21
|
+
directory: "/"
|
|
22
|
+
target-branch: "main"
|
|
23
|
+
schedule:
|
|
24
|
+
interval: "weekly"
|
|
25
|
+
open-pull-requests-limit: 5
|
|
26
|
+
reviewers:
|
|
27
|
+
- "tlbauer2"
|
|
28
|
+
assignees:
|
|
29
|
+
- "tlbauer2"
|
|
30
|
+
commit-message:
|
|
31
|
+
prefix: "ci"
|
|
32
|
+
include: "scope"
|
|
33
|
+
# CodeQL refuses to run when its steps are on different versions, so
|
|
34
|
+
# update all github/codeql-action steps in one PR.
|
|
35
|
+
groups:
|
|
36
|
+
codeql-action:
|
|
37
|
+
patterns:
|
|
38
|
+
- "github/codeql-action*"
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
name: CI/CD Pipeline
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, 'bugfix/**', 'feature/**', 'chore/**' ]
|
|
6
|
+
tags: [ 'v*' ] # a version tag runs the gate and then publish-registry
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ main, 'bugfix/**', 'feature/**', 'chore/**' ]
|
|
9
|
+
release:
|
|
10
|
+
types: [ published ]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ['3.11', '3.12', '3.13']
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
uses: actions/setup-python@v7
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Cache pip dependencies
|
|
30
|
+
uses: actions/cache@v6
|
|
31
|
+
with:
|
|
32
|
+
path: ~/.cache/pip
|
|
33
|
+
key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}
|
|
34
|
+
restore-keys: |
|
|
35
|
+
${{ runner.os }}-pip-
|
|
36
|
+
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: |
|
|
39
|
+
# Install into a project venv rather than the interpreter itself. On a
|
|
40
|
+
# self-hosted runner /opt/hostedtoolcache is a volume shared by every
|
|
41
|
+
# job, so installing there leaks packages between repos.
|
|
42
|
+
python -m venv .venv
|
|
43
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
44
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
45
|
+
.venv/bin/pip install -e .[dev]
|
|
46
|
+
|
|
47
|
+
- name: Run tests with coverage
|
|
48
|
+
run: |
|
|
49
|
+
pytest --cov=src --cov-report=xml --cov-report=html
|
|
50
|
+
|
|
51
|
+
- name: Upload coverage to Codecov
|
|
52
|
+
# the action uploads to codecov.io on behalf of a GitHub repo; there is
|
|
53
|
+
# no equivalent when this runs on Gitea
|
|
54
|
+
if: matrix.python-version == '3.11' && github.server_url == 'https://github.com'
|
|
55
|
+
uses: codecov/codecov-action@v7
|
|
56
|
+
with:
|
|
57
|
+
files: ./coverage.xml
|
|
58
|
+
flags: unittests
|
|
59
|
+
|
|
60
|
+
lint:
|
|
61
|
+
# Ruff (lint + format) and mypy gate the build; there is no advisory
|
|
62
|
+
# pass and nothing here may swallow a failure. Local equivalent:
|
|
63
|
+
# `pre-commit run --all-files`, or the three commands below.
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v7
|
|
68
|
+
with:
|
|
69
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
70
|
+
|
|
71
|
+
- name: Set up Python
|
|
72
|
+
uses: actions/setup-python@v7
|
|
73
|
+
with:
|
|
74
|
+
python-version: '3.11'
|
|
75
|
+
|
|
76
|
+
- name: Install dependencies
|
|
77
|
+
run: |
|
|
78
|
+
# see the note on the test job's install step
|
|
79
|
+
python -m venv .venv
|
|
80
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
81
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
82
|
+
.venv/bin/pip install -e .[dev]
|
|
83
|
+
|
|
84
|
+
- name: Ruff lint
|
|
85
|
+
run: ruff check --output-format=github .
|
|
86
|
+
|
|
87
|
+
- name: Ruff format check
|
|
88
|
+
run: ruff format --check --diff .
|
|
89
|
+
|
|
90
|
+
- name: mypy
|
|
91
|
+
run: mypy
|
|
92
|
+
|
|
93
|
+
package:
|
|
94
|
+
# Build the sdist and wheel the way a release would, then install the
|
|
95
|
+
# wheel into a clean venv and prove it works as a talkpipe plugin.
|
|
96
|
+
# Without this a broken wheel is only discovered by the publish jobs, at
|
|
97
|
+
# release time. Host-neutral: runs unchanged on any Actions-compatible
|
|
98
|
+
# runner.
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v7
|
|
103
|
+
with:
|
|
104
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
105
|
+
|
|
106
|
+
- name: Set up Python
|
|
107
|
+
uses: actions/setup-python@v7
|
|
108
|
+
with:
|
|
109
|
+
python-version: '3.11'
|
|
110
|
+
|
|
111
|
+
- name: Build sdist and wheel
|
|
112
|
+
run: |
|
|
113
|
+
# see the note on the test job's install step
|
|
114
|
+
python -m venv .venv
|
|
115
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
116
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
117
|
+
.venv/bin/pip install build twine
|
|
118
|
+
.venv/bin/python -m build
|
|
119
|
+
.venv/bin/twine check dist/*
|
|
120
|
+
|
|
121
|
+
- name: Install the wheel into a clean venv and smoke-test it
|
|
122
|
+
run: |
|
|
123
|
+
python -m venv .smoke
|
|
124
|
+
.smoke/bin/python -m pip install --upgrade pip
|
|
125
|
+
# pytest only so the pytest11 entry point (the scripted_model
|
|
126
|
+
# fixture) can be loaded below; it is what imports that module.
|
|
127
|
+
.smoke/bin/pip install dist/*.whl pytest
|
|
128
|
+
# The version metadata must resolve from the installed wheel.
|
|
129
|
+
.smoke/bin/python -c "import talkpipe_agents; print(talkpipe_agents.__version__)"
|
|
130
|
+
# The plugin contract: importing talkpipe alone -- no import of
|
|
131
|
+
# talkpipe_agents -- must register the segments, and every declared
|
|
132
|
+
# entry point must resolve in the installed wheel.
|
|
133
|
+
.smoke/bin/python - <<'PY'
|
|
134
|
+
from importlib.metadata import entry_points
|
|
135
|
+
|
|
136
|
+
import talkpipe # noqa: F401
|
|
137
|
+
from talkpipe.chatterlang import registry
|
|
138
|
+
|
|
139
|
+
for name in ("llmAgent", "scriptTool"):
|
|
140
|
+
if name not in registry.segment_registry.available_names:
|
|
141
|
+
raise SystemExit(f"{name} is not registered after importing talkpipe")
|
|
142
|
+
bad = []
|
|
143
|
+
for group in ("talkpipe.plugins", "pytest11"):
|
|
144
|
+
for ep in entry_points(group=group):
|
|
145
|
+
try:
|
|
146
|
+
ep.load()
|
|
147
|
+
except Exception as exc: # noqa: BLE001
|
|
148
|
+
bad.append(f"{group}:{ep.name} -> {exc!r}")
|
|
149
|
+
if bad:
|
|
150
|
+
raise SystemExit("unresolvable entry points:\n" + "\n".join(bad))
|
|
151
|
+
print("plugin registers and all entry points resolve")
|
|
152
|
+
PY
|
|
153
|
+
|
|
154
|
+
lockfile-check:
|
|
155
|
+
# uv.lock is a development convenience only -- CI installs with pip on
|
|
156
|
+
# purpose (see README, "Development environment"). This job installs
|
|
157
|
+
# nothing from the lock; it only fails when uv.lock has drifted out of
|
|
158
|
+
# sync with pyproject.toml, so the committed lock cannot go stale
|
|
159
|
+
# unnoticed.
|
|
160
|
+
runs-on: ubuntu-latest
|
|
161
|
+
|
|
162
|
+
steps:
|
|
163
|
+
- uses: actions/checkout@v7
|
|
164
|
+
with:
|
|
165
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
166
|
+
|
|
167
|
+
- name: Install uv
|
|
168
|
+
uses: astral-sh/setup-uv@v7
|
|
169
|
+
|
|
170
|
+
- name: Check uv.lock is in sync with pyproject.toml
|
|
171
|
+
run: uv lock --check
|
|
172
|
+
|
|
173
|
+
security-scan:
|
|
174
|
+
runs-on: ubuntu-latest
|
|
175
|
+
needs: [test, lint]
|
|
176
|
+
env:
|
|
177
|
+
SAFETY_API_KEY: ${{ secrets.SAFETY_API_KEY }}
|
|
178
|
+
|
|
179
|
+
steps:
|
|
180
|
+
- uses: actions/checkout@v7
|
|
181
|
+
with:
|
|
182
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
183
|
+
|
|
184
|
+
- name: Set up Python
|
|
185
|
+
uses: actions/setup-python@v7
|
|
186
|
+
with:
|
|
187
|
+
python-version: '3.11'
|
|
188
|
+
|
|
189
|
+
- name: Install dependencies for security scan
|
|
190
|
+
run: |
|
|
191
|
+
# see the note on the test job's install step
|
|
192
|
+
python -m venv .venv
|
|
193
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
194
|
+
# Safety scans the whole installed environment, including the
|
|
195
|
+
# setuptools that `python -m venv` seeds on Python 3.11, which is not a
|
|
196
|
+
# project dependency and is not touched by upgrading pip. Upgrade it
|
|
197
|
+
# past CVE-2026-59890 (fixed in 83.0.0) so the scan reports only
|
|
198
|
+
# findings the project can act on.
|
|
199
|
+
.venv/bin/python -m pip install --upgrade pip "setuptools>=83"
|
|
200
|
+
# No extras: `dev` also installs the scanners.
|
|
201
|
+
.venv/bin/pip install -e .
|
|
202
|
+
# The scanners get a venv of their own, outside the workspace, so the
|
|
203
|
+
# scan covers what the project installs and not the scanners' own
|
|
204
|
+
# dependencies (safety brings in nltk, which nothing here depends on).
|
|
205
|
+
python -m venv "$RUNNER_TEMP/scan-tools"
|
|
206
|
+
echo "$RUNNER_TEMP/scan-tools/bin" >> "$GITHUB_PATH"
|
|
207
|
+
"$RUNNER_TEMP/scan-tools/bin/python" -m pip install --upgrade pip
|
|
208
|
+
"$RUNNER_TEMP/scan-tools/bin/pip" install bandit safety
|
|
209
|
+
|
|
210
|
+
- name: Run Bandit security scan
|
|
211
|
+
run: |
|
|
212
|
+
bandit -c pyproject.toml -r src/ -f json -o bandit-report.json
|
|
213
|
+
bandit -c pyproject.toml -r src/ -f txt
|
|
214
|
+
|
|
215
|
+
- name: Run Safety dependency scan
|
|
216
|
+
run: |
|
|
217
|
+
if [ -n "${SAFETY_API_KEY:-}" ]; then
|
|
218
|
+
# Authenticated: the commercial database, gated by .safety-policy.yml.
|
|
219
|
+
safety scan --save-as json safety-report.json
|
|
220
|
+
safety scan
|
|
221
|
+
else
|
|
222
|
+
# Gitea withholds every secret from pull_request runs -- it flags AGit
|
|
223
|
+
# merge requests as fork pull requests even when head and base are the
|
|
224
|
+
# same repo. Rather than skip the scan there (silently unscanned) or
|
|
225
|
+
# fail it for lack of auth, fall back to the free database. This still
|
|
226
|
+
# fails the build on a known vulnerability; the data is just staler
|
|
227
|
+
# than the authenticated scan that gates pushes.
|
|
228
|
+
echo "SAFETY_API_KEY unavailable; falling back to 'safety check' (free database)."
|
|
229
|
+
# `check` is the legacy command and the only one that runs without an
|
|
230
|
+
# account. It rejects .safety-policy.yml because that file is v3.0 and
|
|
231
|
+
# only `scan` parses v3, so run it from a directory holding no policy
|
|
232
|
+
# file. Left to itself it scans the venv it runs from, so hand it
|
|
233
|
+
# the project venv's packages instead.
|
|
234
|
+
report="$PWD/safety-report.json"
|
|
235
|
+
workdir="$(mktemp -d)"
|
|
236
|
+
.venv/bin/python -m pip freeze --exclude-editable > "$workdir/installed.txt"
|
|
237
|
+
(cd "$workdir" && safety check --stdin --save-json "$report" < installed.txt)
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
- name: Upload security scan results
|
|
241
|
+
uses: actions/upload-artifact@v7
|
|
242
|
+
# upload-artifact v4+ refuses to run when the server isn't github.com
|
|
243
|
+
if: always() && github.server_url == 'https://github.com'
|
|
244
|
+
with:
|
|
245
|
+
name: security-reports
|
|
246
|
+
path: |
|
|
247
|
+
bandit-report.json
|
|
248
|
+
safety-report.json
|
|
249
|
+
|
|
250
|
+
codeql-analysis:
|
|
251
|
+
name: CodeQL Analysis
|
|
252
|
+
runs-on: ubuntu-latest
|
|
253
|
+
# needs GitHub's code-scanning API, which Gitea does not implement
|
|
254
|
+
if: github.server_url == 'https://github.com'
|
|
255
|
+
permissions:
|
|
256
|
+
actions: read
|
|
257
|
+
contents: read
|
|
258
|
+
security-events: write
|
|
259
|
+
|
|
260
|
+
strategy:
|
|
261
|
+
fail-fast: false
|
|
262
|
+
matrix:
|
|
263
|
+
language: [ 'python' ]
|
|
264
|
+
|
|
265
|
+
steps:
|
|
266
|
+
- name: Checkout repository
|
|
267
|
+
uses: actions/checkout@v7
|
|
268
|
+
with:
|
|
269
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
270
|
+
|
|
271
|
+
- name: Initialize CodeQL
|
|
272
|
+
uses: github/codeql-action/init@v4
|
|
273
|
+
with:
|
|
274
|
+
languages: ${{ matrix.language }}
|
|
275
|
+
|
|
276
|
+
- name: Autobuild
|
|
277
|
+
uses: github/codeql-action/autobuild@v4
|
|
278
|
+
|
|
279
|
+
- name: Perform CodeQL Analysis
|
|
280
|
+
uses: github/codeql-action/analyze@v4
|
|
281
|
+
|
|
282
|
+
publish-registry:
|
|
283
|
+
# Pushing a version tag (vX.Y.Z) to a self-hosted server uploads the
|
|
284
|
+
# sdist and wheel to that server's PyPI package registry, from where
|
|
285
|
+
# `pip install` on the same network can fetch them. The registry URL is
|
|
286
|
+
# derived from the server running the job, so nothing about the host is
|
|
287
|
+
# recorded here.
|
|
288
|
+
#
|
|
289
|
+
# Never runs on github.com: there, publish-package below uploads to PyPI
|
|
290
|
+
# from a published release instead. To stop publishing to the local
|
|
291
|
+
# registry (once consumers install from PyPI), set the repository
|
|
292
|
+
# Actions variable PUBLISH_REGISTRY to `false`; no workflow change needed.
|
|
293
|
+
# `push` only: a release published for the same tag would otherwise run
|
|
294
|
+
# this job a second time and fail on the already-uploaded version.
|
|
295
|
+
runs-on: ubuntu-latest
|
|
296
|
+
needs: [test, lint, package, security-scan]
|
|
297
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.server_url != 'https://github.com' && vars.PUBLISH_REGISTRY != 'false'
|
|
298
|
+
|
|
299
|
+
steps:
|
|
300
|
+
- uses: actions/checkout@v7
|
|
301
|
+
with:
|
|
302
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
303
|
+
|
|
304
|
+
- name: Set up Python
|
|
305
|
+
uses: actions/setup-python@v7
|
|
306
|
+
with:
|
|
307
|
+
python-version: '3.11'
|
|
308
|
+
|
|
309
|
+
- name: Build sdist and wheel
|
|
310
|
+
run: |
|
|
311
|
+
# see the note on the test job's install step
|
|
312
|
+
python -m venv .venv
|
|
313
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
314
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
315
|
+
.venv/bin/pip install build twine
|
|
316
|
+
.venv/bin/python -m build
|
|
317
|
+
.venv/bin/twine check dist/*
|
|
318
|
+
# The built version must be the tag's: anything else (a .devN or
|
|
319
|
+
# +dirty version) means the checkout is not the tagged commit.
|
|
320
|
+
ls dist/*-"${GITHUB_REF_NAME#v}".tar.gz
|
|
321
|
+
|
|
322
|
+
- name: Upload to the package registry
|
|
323
|
+
env:
|
|
324
|
+
TWINE_REPOSITORY_URL: ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/pypi
|
|
325
|
+
TWINE_USERNAME: ${{ github.repository_owner }}
|
|
326
|
+
# The job's own token can read packages but not write them, so this
|
|
327
|
+
# is an access token with package write permission, stored as an
|
|
328
|
+
# Actions secret (owner-level, inherited by every repository).
|
|
329
|
+
TWINE_PASSWORD: ${{ secrets.PUBLISH_TOKEN }}
|
|
330
|
+
run: |
|
|
331
|
+
if [ -z "${TWINE_PASSWORD:-}" ]; then
|
|
332
|
+
echo "::error::PUBLISH_TOKEN secret is not set; nothing was uploaded."
|
|
333
|
+
exit 1
|
|
334
|
+
fi
|
|
335
|
+
twine upload dist/*
|
|
336
|
+
|
|
337
|
+
publish-package:
|
|
338
|
+
runs-on: ubuntu-latest
|
|
339
|
+
needs: [test, lint, package, security-scan]
|
|
340
|
+
# Publishes to PyPI with the PYPI_API_TOKEN repository secret, which
|
|
341
|
+
# exists only on GitHub: a release cut on a self-hosted server must not
|
|
342
|
+
# try to upload (publish-registry serves that side). Version tags only:
|
|
343
|
+
# a release under any other tag would upload a distribution whose
|
|
344
|
+
# setuptools_scm version came from a tag that is not one.
|
|
345
|
+
if: github.event_name == 'release' && github.event.action == 'published' && startsWith(github.event.release.tag_name, 'v') && github.server_url == 'https://github.com'
|
|
346
|
+
|
|
347
|
+
steps:
|
|
348
|
+
- uses: actions/checkout@v7
|
|
349
|
+
with:
|
|
350
|
+
fetch-depth: 0 # setuptools_scm derives the version from tags
|
|
351
|
+
|
|
352
|
+
- name: Set up Python
|
|
353
|
+
uses: actions/setup-python@v7
|
|
354
|
+
with:
|
|
355
|
+
python-version: '3.11'
|
|
356
|
+
|
|
357
|
+
- name: Install build dependencies
|
|
358
|
+
run: |
|
|
359
|
+
python -m pip install --upgrade pip
|
|
360
|
+
pip install build twine
|
|
361
|
+
|
|
362
|
+
- name: Build package
|
|
363
|
+
run: python -m build
|
|
364
|
+
|
|
365
|
+
- name: Check package
|
|
366
|
+
run: twine check dist/*
|
|
367
|
+
|
|
368
|
+
- name: Publish to PyPI
|
|
369
|
+
env:
|
|
370
|
+
TWINE_USERNAME: __token__
|
|
371
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
372
|
+
run: twine upload dist/*
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Opt-in desktop hooks mirroring the CI lint job: `pre-commit install` once
|
|
2
|
+
# per clone; `pre-commit run --all-files` reproduces the gate locally.
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
5
|
+
rev: v0.17.0 # keep in step with the ruff pin in pyproject.toml
|
|
6
|
+
hooks:
|
|
7
|
+
- id: ruff-check
|
|
8
|
+
args: [--fix, --show-fixes]
|
|
9
|
+
- id: ruff-format
|
|
10
|
+
- repo: local
|
|
11
|
+
hooks:
|
|
12
|
+
- id: mypy
|
|
13
|
+
name: mypy
|
|
14
|
+
# The project venv's mypy (so versions match uv.lock): install and
|
|
15
|
+
# run pre-commit from inside it -- `uv run pre-commit ...` or an
|
|
16
|
+
# activated .venv -- so `mypy` resolves on PATH.
|
|
17
|
+
entry: mypy
|
|
18
|
+
language: system
|
|
19
|
+
types: [python]
|
|
20
|
+
pass_filenames: false
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
version: '3.0'
|
|
2
|
+
|
|
3
|
+
scanning-settings:
|
|
4
|
+
max-depth: 6
|
|
5
|
+
exclude: []
|
|
6
|
+
include-files: []
|
|
7
|
+
system:
|
|
8
|
+
targets: []
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
report:
|
|
12
|
+
dependency-vulnerabilities:
|
|
13
|
+
enabled: true
|
|
14
|
+
auto-ignore-in-report:
|
|
15
|
+
python:
|
|
16
|
+
# Both are deliberately false: findings against the installed
|
|
17
|
+
# environment and against unpinned declared requirements must show up
|
|
18
|
+
# in the report and fail the scan. Do not flip these back to true to
|
|
19
|
+
# get a red build green -- fix the requirement instead.
|
|
20
|
+
environment-results: false
|
|
21
|
+
unpinned-requirements: false
|
|
22
|
+
cvss-severity: []
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
fail-scan-with-exit-code:
|
|
26
|
+
dependency-vulnerabilities:
|
|
27
|
+
enabled: true
|
|
28
|
+
fail-on-any-of:
|
|
29
|
+
cvss-severity:
|
|
30
|
+
- high
|
|
31
|
+
- medium
|
|
32
|
+
- critical
|
|
33
|
+
exploitability:
|
|
34
|
+
- high
|
|
35
|
+
- medium
|
|
36
|
+
- critical
|
|
37
|
+
|
|
38
|
+
security-updates:
|
|
39
|
+
dependency-vulnerabilities:
|
|
40
|
+
auto-security-updates-limit:
|
|
41
|
+
- patch
|
|
42
|
+
|
|
43
|
+
installation:
|
|
44
|
+
default-action: allow
|
|
45
|
+
audit-logging:
|
|
46
|
+
enabled: true
|
|
47
|
+
allow:
|
|
48
|
+
packages: []
|
|
49
|
+
vulnerabilities: {}
|
|
50
|
+
deny:
|
|
51
|
+
packages: {}
|
|
52
|
+
vulnerabilities:
|
|
53
|
+
warning-on-any-of:
|
|
54
|
+
cvss-severity: []
|
|
55
|
+
block-on-any-of:
|
|
56
|
+
cvss-severity: []
|
|
57
|
+
|
|
58
|
+
|