lib-cli-exit-tools 2.2.4__tar.gz → 2.3.1__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.
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.codacy/cli.sh +27 -25
- lib_cli_exit_tools-2.3.1/.data_arch_violations.json +38 -0
- lib_cli_exit_tools-2.3.1/.github/actions/extract-metadata/action.yml +92 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.github/workflows/default_cicd_public.yml +150 -67
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.github/workflows/default_release_public.yml +2 -2
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.gitignore +3 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/CHANGELOG.md +28 -0
- lib_cli_exit_tools-2.3.1/Makefile +260 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/PKG-INFO +18 -14
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/README.md +0 -1
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/pyproject.toml +50 -40
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/__init__.py +1 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/__init__conf__.py +1 -1
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/application/runner.py +21 -29
- lib_cli_exit_tools-2.3.1/src/lib_cli_exit_tools/cli/__init__.py +27 -0
- lib_cli_exit_tools-2.3.1/src/lib_cli_exit_tools/cli/commands.py +69 -0
- lib_cli_exit_tools-2.3.1/src/lib_cli_exit_tools/cli/group.py +123 -0
- lib_cli_exit_tools-2.3.1/src/lib_cli_exit_tools/cli/styling.py +111 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/core/configuration.py +22 -6
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/core/exit_codes.py +2 -2
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +2 -1
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/conftest.py +2 -1
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_cli.py +27 -19
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_core_configuration.py +5 -4
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_core_exit_codes.py +2 -1
- lib_cli_exit_tools-2.2.4/.github/workflows/ci.yml_backup +0 -208
- lib_cli_exit_tools-2.2.4/.github/workflows/release.yml_backup +0 -50
- lib_cli_exit_tools-2.2.4/CLAUDE.md +0 -164
- lib_cli_exit_tools-2.2.4/Makefile +0 -60
- lib_cli_exit_tools-2.2.4/scripts/__init__.py +0 -3
- lib_cli_exit_tools-2.2.4/scripts/__main__.py +0 -7
- lib_cli_exit_tools-2.2.4/scripts/_utils.py +0 -768
- lib_cli_exit_tools-2.2.4/scripts/build.py +0 -52
- lib_cli_exit_tools-2.2.4/scripts/bump.py +0 -32
- lib_cli_exit_tools-2.2.4/scripts/bump_major.py +0 -20
- lib_cli_exit_tools-2.2.4/scripts/bump_minor.py +0 -20
- lib_cli_exit_tools-2.2.4/scripts/bump_patch.py +0 -20
- lib_cli_exit_tools-2.2.4/scripts/bump_version.py +0 -80
- lib_cli_exit_tools-2.2.4/scripts/clean.py +0 -75
- lib_cli_exit_tools-2.2.4/scripts/cli.py +0 -232
- lib_cli_exit_tools-2.2.4/scripts/dependencies.py +0 -590
- lib_cli_exit_tools-2.2.4/scripts/dev.py +0 -19
- lib_cli_exit_tools-2.2.4/scripts/help.py +0 -41
- lib_cli_exit_tools-2.2.4/scripts/install.py +0 -19
- lib_cli_exit_tools-2.2.4/scripts/menu.py +0 -582
- lib_cli_exit_tools-2.2.4/scripts/push.py +0 -309
- lib_cli_exit_tools-2.2.4/scripts/release.py +0 -92
- lib_cli_exit_tools-2.2.4/scripts/run_cli.py +0 -154
- lib_cli_exit_tools-2.2.4/scripts/target_metadata.py +0 -202
- lib_cli_exit_tools-2.2.4/scripts/test.py +0 -1004
- lib_cli_exit_tools-2.2.4/scripts/toml_config.py +0 -433
- lib_cli_exit_tools-2.2.4/scripts/version_current.py +0 -20
- lib_cli_exit_tools-2.2.4/src/lib_cli_exit_tools/cli.py +0 -261
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.codacy/cli-config.yaml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.codacy/codacy.yaml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.codacy/tools-configs/lizard.yaml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.codacy/tools-configs/trivy.yaml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.devcontainer/devcontainer.json +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.devcontainer/settings.json +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.env.example +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.github/dependabot.yml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.github/workflows/codeql.yml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.qlty/qlty.toml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.snyk +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/CONTRIBUTING.md +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/DEVELOPMENT.md +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/INSTALL.md +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/LICENSE +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/codecov.yml +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/docs/system-design/module_reference.md +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/notebooks/Quickstart.ipynb +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/__main__.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/adapters/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/adapters/signals.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/application/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/core/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/src/lib_cli_exit_tools/py.typed +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_adapters_signals.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_application_runner.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_behaviors.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_metadata.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_module_entry.py +0 -0
- {lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/tests/test_signals_integration.py +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
set -e +o pipefail
|
|
5
4
|
|
|
6
5
|
# Set up paths first
|
|
@@ -11,15 +10,15 @@ os_name=$(uname)
|
|
|
11
10
|
arch=$(uname -m)
|
|
12
11
|
|
|
13
12
|
case "$arch" in
|
|
14
|
-
"x86_64")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"x86")
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"aarch64"|"arm64")
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
"x86_64")
|
|
14
|
+
arch="amd64"
|
|
15
|
+
;;
|
|
16
|
+
"x86")
|
|
17
|
+
arch="386"
|
|
18
|
+
;;
|
|
19
|
+
"aarch64" | "arm64")
|
|
20
|
+
arch="arm64"
|
|
21
|
+
;;
|
|
23
22
|
esac
|
|
24
23
|
|
|
25
24
|
if [ -z "$CODACY_CLI_V2_TMP_FOLDER" ]; then
|
|
@@ -34,10 +33,10 @@ fi
|
|
|
34
33
|
|
|
35
34
|
version_file="$CODACY_CLI_V2_TMP_FOLDER/version.yaml"
|
|
36
35
|
|
|
37
|
-
|
|
38
36
|
get_version_from_yaml() {
|
|
39
37
|
if [ -f "$version_file" ]; then
|
|
40
|
-
local version
|
|
38
|
+
local version
|
|
39
|
+
version=$(grep -o 'version: *"[^"]*"' "$version_file" | cut -d'"' -f2)
|
|
41
40
|
if [ -n "$version" ]; then
|
|
42
41
|
echo "$version"
|
|
43
42
|
return 0
|
|
@@ -49,20 +48,24 @@ get_version_from_yaml() {
|
|
|
49
48
|
get_latest_version() {
|
|
50
49
|
local response
|
|
51
50
|
if [ -n "$GH_TOKEN" ]; then
|
|
52
|
-
response=$(curl -Lq
|
|
51
|
+
response=$(curl -Lq \
|
|
52
|
+
--header "Authorization: Bearer $GH_TOKEN" \
|
|
53
|
+
"https://api.github.com/repos/codacy/codacy-cli-v2/releases/latest" 2>/dev/null)
|
|
53
54
|
else
|
|
54
|
-
response=$(curl -Lq
|
|
55
|
+
response=$(curl -Lq \
|
|
56
|
+
"https://api.github.com/repos/codacy/codacy-cli-v2/releases/latest" 2>/dev/null)
|
|
55
57
|
fi
|
|
56
58
|
|
|
57
59
|
handle_rate_limit "$response"
|
|
58
|
-
local version
|
|
60
|
+
local version
|
|
61
|
+
version=$(echo "$response" | grep -m 1 tag_name | cut -d'"' -f4)
|
|
59
62
|
echo "$version"
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
handle_rate_limit() {
|
|
63
66
|
local response="$1"
|
|
64
67
|
if echo "$response" | grep -q "API rate limit exceeded"; then
|
|
65
|
-
|
|
68
|
+
fatal "Error: GitHub API rate limit exceeded. Please try again later"
|
|
66
69
|
fi
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -70,9 +73,9 @@ download_file() {
|
|
|
70
73
|
local url="$1"
|
|
71
74
|
|
|
72
75
|
echo "Downloading from URL: ${url}"
|
|
73
|
-
if command -v curl
|
|
76
|
+
if command -v curl >/dev/null 2>&1; then
|
|
74
77
|
curl -# -LS "$url" -O
|
|
75
|
-
elif command -v wget
|
|
78
|
+
elif command -v wget >/dev/null 2>&1; then
|
|
76
79
|
wget "$url"
|
|
77
80
|
else
|
|
78
81
|
fatal "Error: Could not find curl or wget, please install one."
|
|
@@ -83,7 +86,7 @@ download() {
|
|
|
83
86
|
local url="$1"
|
|
84
87
|
local output_folder="$2"
|
|
85
88
|
|
|
86
|
-
(
|
|
89
|
+
(cd "$output_folder" && download_file "$url")
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
download_cli() {
|
|
@@ -95,7 +98,7 @@ download_cli() {
|
|
|
95
98
|
local version="$3"
|
|
96
99
|
|
|
97
100
|
if [ ! -f "$bin_path" ]; then
|
|
98
|
-
echo "
|
|
101
|
+
echo "Downloading CLI version $version..."
|
|
99
102
|
|
|
100
103
|
remote_file="codacy-cli-v2_${version}_${suffix}_${arch}.tar.gz"
|
|
101
104
|
url="https://github.com/codacy/codacy-cli-v2/releases/download/${version}/${remote_file}"
|
|
@@ -107,16 +110,16 @@ download_cli() {
|
|
|
107
110
|
|
|
108
111
|
# Warn if CODACY_CLI_V2_VERSION is set and update is requested
|
|
109
112
|
if [ -n "$CODACY_CLI_V2_VERSION" ] && [ "$1" = "update" ]; then
|
|
110
|
-
echo "
|
|
113
|
+
echo "Warning: Performing update with forced version $CODACY_CLI_V2_VERSION"
|
|
111
114
|
echo " Unset CODACY_CLI_V2_VERSION to use the latest version"
|
|
112
115
|
fi
|
|
113
116
|
|
|
114
117
|
# Ensure version.yaml exists and is up to date
|
|
115
118
|
if [ ! -f "$version_file" ] || [ "$1" = "update" ]; then
|
|
116
|
-
echo "
|
|
119
|
+
echo "Fetching latest version..."
|
|
117
120
|
version=$(get_latest_version)
|
|
118
121
|
mkdir -p "$CODACY_CLI_V2_TMP_FOLDER"
|
|
119
|
-
echo "version: \"$version\"" >
|
|
122
|
+
echo "version: \"$version\"" >"$version_file"
|
|
120
123
|
fi
|
|
121
124
|
|
|
122
125
|
# Set the version to use
|
|
@@ -126,7 +129,6 @@ else
|
|
|
126
129
|
version=$(get_version_from_yaml)
|
|
127
130
|
fi
|
|
128
131
|
|
|
129
|
-
|
|
130
132
|
# Set up version-specific paths
|
|
131
133
|
bin_folder="${CODACY_CLI_V2_TMP_FOLDER}/${version}"
|
|
132
134
|
|
|
@@ -146,4 +148,4 @@ if [ "$#" -eq 1 ] && [ "$1" = "download" ]; then
|
|
|
146
148
|
echo "Codacy cli v2 download succeeded"
|
|
147
149
|
else
|
|
148
150
|
eval "$run_command $*"
|
|
149
|
-
fi
|
|
151
|
+
fi
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pass": 1,
|
|
3
|
+
"total_violations": 0,
|
|
4
|
+
"files": {
|
|
5
|
+
"src/lib_cli_exit_tools/core/configuration.py": {
|
|
6
|
+
"violations": [],
|
|
7
|
+
"status": "clean"
|
|
8
|
+
},
|
|
9
|
+
"src/lib_cli_exit_tools/core/exit_codes.py": {
|
|
10
|
+
"violations": [],
|
|
11
|
+
"status": "clean"
|
|
12
|
+
},
|
|
13
|
+
"src/lib_cli_exit_tools/application/runner.py": {
|
|
14
|
+
"violations": [],
|
|
15
|
+
"status": "clean"
|
|
16
|
+
},
|
|
17
|
+
"src/lib_cli_exit_tools/__init__.py": {
|
|
18
|
+
"violations": [],
|
|
19
|
+
"status": "clean"
|
|
20
|
+
},
|
|
21
|
+
"src/lib_cli_exit_tools/__init__conf__.py": {
|
|
22
|
+
"violations": [],
|
|
23
|
+
"status": "clean"
|
|
24
|
+
},
|
|
25
|
+
"src/lib_cli_exit_tools/cli.py": {
|
|
26
|
+
"violations": [],
|
|
27
|
+
"status": "clean"
|
|
28
|
+
},
|
|
29
|
+
"src/lib_cli_exit_tools/lib_cli_exit_tools.py": {
|
|
30
|
+
"violations": [],
|
|
31
|
+
"status": "clean"
|
|
32
|
+
},
|
|
33
|
+
"src/lib_cli_exit_tools/adapters/signals.py": {
|
|
34
|
+
"violations": [],
|
|
35
|
+
"status": "clean"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
name: Extract project metadata
|
|
2
|
+
description: >-
|
|
3
|
+
Parse pyproject.toml and expose project metadata as step outputs.
|
|
4
|
+
Requires Python to be available in the runner environment.
|
|
5
|
+
Auto-installs rtoml if not already present.
|
|
6
|
+
|
|
7
|
+
outputs:
|
|
8
|
+
PACKAGE_MODULE:
|
|
9
|
+
description: Python-importable module name (underscored)
|
|
10
|
+
value: ${{ steps.meta.outputs.PACKAGE_MODULE }}
|
|
11
|
+
PROJECT_NAME:
|
|
12
|
+
description: Project name from pyproject.toml
|
|
13
|
+
value: ${{ steps.meta.outputs.PROJECT_NAME }}
|
|
14
|
+
CLI_BIN:
|
|
15
|
+
description: CLI entry-point binary name
|
|
16
|
+
value: ${{ steps.meta.outputs.CLI_BIN }}
|
|
17
|
+
SRC_PATH:
|
|
18
|
+
description: Source directory path (e.g. "src")
|
|
19
|
+
value: ${{ steps.meta.outputs.SRC_PATH }}
|
|
20
|
+
COV_FAIL_UNDER:
|
|
21
|
+
description: Minimum coverage percentage from tool.coverage.report.fail_under
|
|
22
|
+
value: ${{ steps.meta.outputs.COV_FAIL_UNDER }}
|
|
23
|
+
COV_REPORT_FILE:
|
|
24
|
+
description: Coverage report filename (e.g. "coverage.xml")
|
|
25
|
+
value: ${{ steps.meta.outputs.COV_REPORT_FILE }}
|
|
26
|
+
PYTEST_VERBOSITY:
|
|
27
|
+
description: Pytest verbosity flag (e.g. "-vv")
|
|
28
|
+
value: ${{ steps.meta.outputs.PYTEST_VERBOSITY }}
|
|
29
|
+
BANDIT_SKIP_FLAG:
|
|
30
|
+
description: Bandit skip flag string (e.g. "-s B101,B601") or empty
|
|
31
|
+
value: ${{ steps.meta.outputs.BANDIT_SKIP_FLAG }}
|
|
32
|
+
|
|
33
|
+
runs:
|
|
34
|
+
using: composite
|
|
35
|
+
steps:
|
|
36
|
+
- name: Extract project metadata from pyproject.toml
|
|
37
|
+
id: meta
|
|
38
|
+
shell: python
|
|
39
|
+
run: |
|
|
40
|
+
import os, subprocess, sys
|
|
41
|
+
try:
|
|
42
|
+
import rtoml
|
|
43
|
+
except ModuleNotFoundError:
|
|
44
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "rtoml", "-q"])
|
|
45
|
+
import rtoml
|
|
46
|
+
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
data = rtoml.load(Path('pyproject.toml'))
|
|
49
|
+
|
|
50
|
+
# --- [project] section ---
|
|
51
|
+
project = data['project']['name']
|
|
52
|
+
module = project.replace('-', '_')
|
|
53
|
+
dash = project.replace('_', '-')
|
|
54
|
+
scripts = list(data['project'].get('scripts', {}).keys())
|
|
55
|
+
cli_bin = scripts[0] if scripts else dash
|
|
56
|
+
|
|
57
|
+
# --- [tool.scripts.test] section ---
|
|
58
|
+
scripts_test = data.get('tool', {}).get('scripts', {}).get('test', {})
|
|
59
|
+
src_path = scripts_test.get('src-path', 'src')
|
|
60
|
+
pytest_verbosity = scripts_test.get('pytest-verbosity', '-vv')
|
|
61
|
+
cov_report_file = scripts_test.get('coverage-report-file', 'coverage.xml')
|
|
62
|
+
|
|
63
|
+
# --- [tool.coverage.report] section ---
|
|
64
|
+
cov_fail_under = (
|
|
65
|
+
data.get('tool', {}).get('coverage', {}).get('report', {}).get('fail_under', 90)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# --- [tool.bandit] section ---
|
|
69
|
+
bandit_skips = data.get('tool', {}).get('bandit', {}).get('skips', [])
|
|
70
|
+
bandit_skip_flag = f"-s {','.join(bandit_skips)}" if bandit_skips else ""
|
|
71
|
+
|
|
72
|
+
# Write to GITHUB_OUTPUT for composite action outputs
|
|
73
|
+
with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as out:
|
|
74
|
+
out.write(f"PROJECT_NAME={project}\n")
|
|
75
|
+
out.write(f"PACKAGE_MODULE={module}\n")
|
|
76
|
+
out.write(f"CLI_BIN={cli_bin}\n")
|
|
77
|
+
out.write(f"SRC_PATH={src_path}\n")
|
|
78
|
+
out.write(f"PYTEST_VERBOSITY={pytest_verbosity}\n")
|
|
79
|
+
out.write(f"COV_REPORT_FILE={cov_report_file}\n")
|
|
80
|
+
out.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
|
|
81
|
+
out.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
|
|
82
|
+
|
|
83
|
+
# Also write to GITHUB_ENV so subsequent steps can use ${{ env.VAR }}
|
|
84
|
+
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
85
|
+
env.write(f"PROJECT_NAME={project}\n")
|
|
86
|
+
env.write(f"PACKAGE_MODULE={module}\n")
|
|
87
|
+
env.write(f"CLI_BIN={cli_bin}\n")
|
|
88
|
+
env.write(f"SRC_PATH={src_path}\n")
|
|
89
|
+
env.write(f"PYTEST_VERBOSITY={pytest_verbosity}\n")
|
|
90
|
+
env.write(f"COV_REPORT_FILE={cov_report_file}\n")
|
|
91
|
+
env.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
|
|
92
|
+
env.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
|
{lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.github/workflows/default_cicd_public.yml
RENAMED
|
@@ -10,19 +10,61 @@ on:
|
|
|
10
10
|
- cron: '17 3 * * *'
|
|
11
11
|
|
|
12
12
|
jobs:
|
|
13
|
+
setup:
|
|
14
|
+
name: Extract Python versions and OS matrix from pyproject.toml
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
outputs:
|
|
17
|
+
python-versions: ${{ steps.metadata.outputs.python-versions }}
|
|
18
|
+
python-latest: ${{ steps.metadata.outputs.python-latest }}
|
|
19
|
+
os-matrix: ${{ steps.metadata.outputs.os-matrix }}
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v6
|
|
22
|
+
- uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.x"
|
|
25
|
+
- name: Parse pyproject.toml for Python versions and OS matrix
|
|
26
|
+
id: metadata
|
|
27
|
+
shell: python
|
|
28
|
+
run: |
|
|
29
|
+
import json, os, tomllib
|
|
30
|
+
|
|
31
|
+
with open("pyproject.toml", "rb") as f:
|
|
32
|
+
data = tomllib.load(f)
|
|
33
|
+
|
|
34
|
+
# Python versions from classifiers
|
|
35
|
+
classifiers = data.get("project", {}).get("classifiers", [])
|
|
36
|
+
prefix = "Programming Language :: Python :: "
|
|
37
|
+
versions = [
|
|
38
|
+
c[len(prefix):]
|
|
39
|
+
for c in classifiers
|
|
40
|
+
if c.startswith(prefix) and "." in c[len(prefix):]
|
|
41
|
+
]
|
|
42
|
+
if not versions:
|
|
43
|
+
raise SystemExit("No Python X.Y versions found in classifiers")
|
|
44
|
+
|
|
45
|
+
# OS matrix from [tool.ci]
|
|
46
|
+
ci_config = data.get("tool", {}).get("ci", {})
|
|
47
|
+
os_list = ci_config.get("os", ["ubuntu-latest"])
|
|
48
|
+
|
|
49
|
+
with open(os.environ["GITHUB_OUTPUT"], "a") as fh:
|
|
50
|
+
fh.write(f"python-versions={json.dumps(versions)}\n")
|
|
51
|
+
fh.write(f"python-latest={versions[-1]}\n")
|
|
52
|
+
fh.write(f"os-matrix={json.dumps(os_list)}\n")
|
|
53
|
+
|
|
13
54
|
test:
|
|
14
55
|
name: Tests (Python ${{ matrix.python }}, ${{ matrix.os }})
|
|
56
|
+
needs: setup
|
|
15
57
|
runs-on: ${{ matrix.os }}
|
|
16
58
|
strategy:
|
|
17
59
|
fail-fast: false
|
|
18
60
|
matrix:
|
|
19
|
-
os:
|
|
20
|
-
|
|
21
|
-
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
61
|
+
os: ${{ fromJSON(needs.setup.outputs.os-matrix) }}
|
|
62
|
+
python: ${{ fromJSON(needs.setup.outputs.python-versions) }}
|
|
22
63
|
env:
|
|
23
64
|
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: "1"
|
|
24
65
|
PYTHONIOENCODING: "utf-8"
|
|
25
66
|
UV_LINK_MODE: "copy"
|
|
67
|
+
UV_BREAK_SYSTEM_PACKAGES: "1"
|
|
26
68
|
steps:
|
|
27
69
|
- uses: actions/checkout@v6
|
|
28
70
|
- uses: actions/setup-python@v6
|
|
@@ -34,51 +76,98 @@ jobs:
|
|
|
34
76
|
enable-cache: true
|
|
35
77
|
prune-cache: false
|
|
36
78
|
|
|
37
|
-
- name: Install
|
|
38
|
-
|
|
39
|
-
run:
|
|
79
|
+
- name: Install bash 4+ on macOS
|
|
80
|
+
if: runner.os == 'macOS'
|
|
81
|
+
run: |
|
|
82
|
+
brew install bash
|
|
83
|
+
echo "$(brew --prefix)/bin" >> "$GITHUB_PATH"
|
|
40
84
|
|
|
41
85
|
- name: Extract project metadata
|
|
86
|
+
id: metadata
|
|
87
|
+
uses: ./.github/actions/extract-metadata
|
|
88
|
+
|
|
89
|
+
- name: Install CI system dependencies (Ubuntu)
|
|
90
|
+
if: runner.os == 'Linux'
|
|
42
91
|
shell: python
|
|
43
92
|
run: |
|
|
44
|
-
import
|
|
93
|
+
import subprocess
|
|
45
94
|
try:
|
|
46
95
|
import tomllib
|
|
47
96
|
except ModuleNotFoundError:
|
|
48
|
-
import tomli as tomllib
|
|
49
|
-
|
|
50
|
-
with open('pyproject.toml', 'rb') as f:
|
|
97
|
+
import pip._vendor.tomli as tomllib
|
|
98
|
+
with open("pyproject.toml", "rb") as f:
|
|
51
99
|
data = tomllib.load(f)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- name: Install journald prerequisites
|
|
64
|
-
if: runner.os == 'Linux'
|
|
65
|
-
shell: bash
|
|
100
|
+
deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-ubuntu", [])
|
|
101
|
+
if deps:
|
|
102
|
+
print(f"Installing system packages: {' '.join(deps)}")
|
|
103
|
+
subprocess.check_call(["sudo", "apt-get", "update"])
|
|
104
|
+
subprocess.check_call(["sudo", "apt-get", "install", "-y", *deps])
|
|
105
|
+
else:
|
|
106
|
+
print("No CI system dependencies configured for Ubuntu.")
|
|
107
|
+
|
|
108
|
+
- name: Install CI system dependencies (macOS)
|
|
109
|
+
if: runner.os == 'macOS'
|
|
110
|
+
shell: python
|
|
66
111
|
run: |
|
|
67
|
-
|
|
68
|
-
|
|
112
|
+
import subprocess
|
|
113
|
+
try:
|
|
114
|
+
import tomllib
|
|
115
|
+
except ModuleNotFoundError:
|
|
116
|
+
import pip._vendor.tomli as tomllib
|
|
117
|
+
with open("pyproject.toml", "rb") as f:
|
|
118
|
+
data = tomllib.load(f)
|
|
119
|
+
deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-macos", [])
|
|
120
|
+
if deps:
|
|
121
|
+
print(f"Installing system packages: {' '.join(deps)}")
|
|
122
|
+
subprocess.check_call(["brew", "install", *deps])
|
|
123
|
+
else:
|
|
124
|
+
print("No CI system dependencies configured for macOS.")
|
|
69
125
|
|
|
70
126
|
- name: Install dev deps
|
|
71
127
|
shell: bash
|
|
72
128
|
run: |
|
|
73
129
|
uv pip install -e .[dev] --system
|
|
74
130
|
|
|
75
|
-
- name: Install
|
|
131
|
+
- name: Install CI system dependencies (Windows/choco)
|
|
76
132
|
if: runner.os == 'Windows'
|
|
77
|
-
shell:
|
|
133
|
+
shell: python
|
|
78
134
|
run: |
|
|
79
|
-
|
|
80
|
-
|
|
135
|
+
import subprocess
|
|
136
|
+
try:
|
|
137
|
+
import tomllib
|
|
138
|
+
except ModuleNotFoundError:
|
|
139
|
+
import pip._vendor.tomli as tomllib
|
|
140
|
+
with open("pyproject.toml", "rb") as f:
|
|
141
|
+
data = tomllib.load(f)
|
|
142
|
+
deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-windows-choco", [])
|
|
143
|
+
if deps:
|
|
144
|
+
print(f"Installing choco packages: {' '.join(deps)}")
|
|
145
|
+
subprocess.check_call(["choco", "install", "-y", *deps])
|
|
146
|
+
else:
|
|
147
|
+
print("No CI choco dependencies configured for Windows.")
|
|
148
|
+
|
|
149
|
+
- name: Install CI pip dependencies (Windows)
|
|
150
|
+
if: runner.os == 'Windows'
|
|
151
|
+
shell: python
|
|
152
|
+
run: |
|
|
153
|
+
import subprocess
|
|
154
|
+
try:
|
|
155
|
+
import tomllib
|
|
156
|
+
except ModuleNotFoundError:
|
|
157
|
+
import pip._vendor.tomli as tomllib
|
|
158
|
+
with open("pyproject.toml", "rb") as f:
|
|
159
|
+
data = tomllib.load(f)
|
|
160
|
+
deps = data.get("tool", {}).get("ci", {}).get("system-dependencies-windows-pip", [])
|
|
161
|
+
if deps:
|
|
162
|
+
print(f"Installing pip packages: {' '.join(deps)}")
|
|
163
|
+
subprocess.check_call(["uv", "pip", "install", *deps, "--system"])
|
|
164
|
+
else:
|
|
165
|
+
print("No CI pip dependencies configured for Windows.")
|
|
166
|
+
|
|
167
|
+
# Self-hosted runners persist ruff cache via RUFF_CACHE_DIR volume mount,
|
|
168
|
+
# so actions/cache is only needed on GitHub-hosted runners.
|
|
81
169
|
- name: Restore ruff cache
|
|
170
|
+
if: runner.environment == 'github-hosted'
|
|
82
171
|
id: ruff-cache
|
|
83
172
|
uses: actions/cache/restore@v5
|
|
84
173
|
with:
|
|
@@ -93,8 +182,8 @@ jobs:
|
|
|
93
182
|
continue-on-error: true
|
|
94
183
|
shell: bash
|
|
95
184
|
run: |
|
|
96
|
-
ruff check
|
|
97
|
-
ruff format --check
|
|
185
|
+
ruff check .
|
|
186
|
+
ruff format --check .
|
|
98
187
|
|
|
99
188
|
- name: Run pyright (type check)
|
|
100
189
|
id: pyright
|
|
@@ -108,7 +197,27 @@ jobs:
|
|
|
108
197
|
shell: bash
|
|
109
198
|
env:
|
|
110
199
|
TEST_VERBOSE: "1"
|
|
111
|
-
|
|
200
|
+
# Write coverage SQLite database to local disk — network mounts
|
|
201
|
+
# and stale journal files cause "database is locked" errors.
|
|
202
|
+
COVERAGE_FILE: "${{ runner.temp }}/.coverage"
|
|
203
|
+
run: >-
|
|
204
|
+
pytest -m "not local_only"
|
|
205
|
+
--cov=${{ env.SRC_PATH }}/${{ env.PACKAGE_MODULE }}
|
|
206
|
+
--cov-report=term-missing
|
|
207
|
+
--cov-report=xml:${{ env.COV_REPORT_FILE }}
|
|
208
|
+
--cov-fail-under=${{ env.COV_FAIL_UNDER }}
|
|
209
|
+
${{ env.PYTEST_VERBOSITY }}
|
|
210
|
+
|
|
211
|
+
- name: Upload coverage to Codecov
|
|
212
|
+
if: >-
|
|
213
|
+
always()
|
|
214
|
+
&& steps.pytest.outcome == 'success'
|
|
215
|
+
&& matrix.os == 'ubuntu-latest'
|
|
216
|
+
&& matrix.python == needs.setup.outputs.python-latest
|
|
217
|
+
uses: codecov/codecov-action@v6
|
|
218
|
+
with:
|
|
219
|
+
files: ${{ env.COV_REPORT_FILE }}
|
|
220
|
+
fail_ci_if_error: false
|
|
112
221
|
|
|
113
222
|
- name: Run import-linter (architecture)
|
|
114
223
|
id: importlinter
|
|
@@ -120,7 +229,7 @@ jobs:
|
|
|
120
229
|
id: bandit
|
|
121
230
|
continue-on-error: true
|
|
122
231
|
shell: bash
|
|
123
|
-
run: bandit -q -r
|
|
232
|
+
run: bandit -q -c pyproject.toml -r ${{ env.SRC_PATH }}/${{ env.PACKAGE_MODULE }} ${{ env.BANDIT_SKIP_FLAG }}
|
|
124
233
|
|
|
125
234
|
- name: Run pip-audit (vulnerability scan)
|
|
126
235
|
id: pipaudit
|
|
@@ -128,12 +237,9 @@ jobs:
|
|
|
128
237
|
shell: python
|
|
129
238
|
run: |
|
|
130
239
|
import subprocess, sys
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
import tomli as tomllib
|
|
135
|
-
with open("pyproject.toml", "rb") as f:
|
|
136
|
-
data = tomllib.load(f)
|
|
240
|
+
import rtoml
|
|
241
|
+
from pathlib import Path
|
|
242
|
+
data = rtoml.load(Path("pyproject.toml"))
|
|
137
243
|
vulns = data.get("tool", {}).get("pip-audit", {}).get("ignore-vulns", [])
|
|
138
244
|
cmd = ["pip-audit", "--skip-editable"]
|
|
139
245
|
for v in vulns:
|
|
@@ -164,8 +270,7 @@ jobs:
|
|
|
164
270
|
exit 1
|
|
165
271
|
fi
|
|
166
272
|
if [[ "${{ steps.pipaudit.outcome }}" != "success" ]]; then
|
|
167
|
-
echo "::
|
|
168
|
-
exit 1
|
|
273
|
+
echo "::warning::pip-audit vulnerability scan failed"
|
|
169
274
|
fi
|
|
170
275
|
echo "All checks passed!"
|
|
171
276
|
|
|
@@ -187,7 +292,7 @@ jobs:
|
|
|
187
292
|
run: uv cache prune --ci
|
|
188
293
|
|
|
189
294
|
- name: Save ruff cache
|
|
190
|
-
if: always() && steps.ruff-cache.outputs.cache-hit != 'true'
|
|
295
|
+
if: always() && runner.environment == 'github-hosted' && steps.ruff-cache.outputs.cache-hit != 'true'
|
|
191
296
|
uses: actions/cache/save@v5
|
|
192
297
|
with:
|
|
193
298
|
path: .ruff_cache
|
|
@@ -208,31 +313,9 @@ jobs:
|
|
|
208
313
|
enable-cache: true
|
|
209
314
|
prune-cache: false
|
|
210
315
|
|
|
211
|
-
- name: Install tomli (Python < 3.11)
|
|
212
|
-
shell: bash
|
|
213
|
-
run: python -c "import tomllib" 2>/dev/null || uv pip install tomli --system
|
|
214
|
-
|
|
215
316
|
- name: Extract project metadata
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
import os
|
|
219
|
-
try:
|
|
220
|
-
import tomllib
|
|
221
|
-
except ModuleNotFoundError:
|
|
222
|
-
import tomli as tomllib
|
|
223
|
-
|
|
224
|
-
with open('pyproject.toml', 'rb') as f:
|
|
225
|
-
data = tomllib.load(f)
|
|
226
|
-
project = data['project']['name']
|
|
227
|
-
module = project.replace('-', '_')
|
|
228
|
-
dash = project.replace('_', '-')
|
|
229
|
-
scripts = list(data['project'].get('scripts', {}).keys())
|
|
230
|
-
cli_bin = scripts[0] if scripts else dash
|
|
231
|
-
|
|
232
|
-
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
233
|
-
env.write(f"PROJECT_NAME={project}\n")
|
|
234
|
-
env.write(f"PACKAGE_MODULE={module}\n")
|
|
235
|
-
env.write(f"CLI_BIN={cli_bin}\n")
|
|
317
|
+
id: metadata
|
|
318
|
+
uses: ./.github/actions/extract-metadata
|
|
236
319
|
|
|
237
320
|
- name: Build wheel
|
|
238
321
|
run: uv build
|
{lib_cli_exit_tools-2.2.4 → lib_cli_exit_tools-2.3.1}/.github/workflows/default_release_public.yml
RENAMED
|
@@ -31,7 +31,7 @@ jobs:
|
|
|
31
31
|
run: uv build
|
|
32
32
|
|
|
33
33
|
- name: Upload artifacts
|
|
34
|
-
uses: actions/upload-artifact@
|
|
34
|
+
uses: actions/upload-artifact@v7
|
|
35
35
|
with:
|
|
36
36
|
name: dist
|
|
37
37
|
path: dist/*
|
|
@@ -56,7 +56,7 @@ jobs:
|
|
|
56
56
|
fi
|
|
57
57
|
|
|
58
58
|
- name: Download artifacts
|
|
59
|
-
uses: actions/download-artifact@
|
|
59
|
+
uses: actions/download-artifact@v8
|
|
60
60
|
with:
|
|
61
61
|
name: dist
|
|
62
62
|
path: dist/
|
|
@@ -2,12 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [2.3.1] - 2026-04-24
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Replaced `Iterator[...]` with `Generator[...]` in return annotations of `@contextmanager`-decorated functions (`config_overrides`, `cli_session`, `_apply_overrides_without_restore`, `_temporary_rich_click_configuration`) to satisfy pyright 1.1.409's new deprecation check that was breaking CI.
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
- Refreshed pip-audit `ignore-vulns`: dropped entries whose packages are now at fixed versions; added dev/env-only exclusions for authlib (GHSA-jj8c-mmj3-mmgv), cryptography (CVE-2026-39892), lxml (CVE-2026-41066), Pillow (CVE-2026-40192), python-multipart (CVE-2026-40347), and uv (GHSA-pjjw-68hj-v9mw). None of these packages are runtime dependencies of `lib_cli_exit_tools`.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Bumped dev dependency minimums in `pyproject.toml` and refreshed the BMK Makefile wrapper to 2.9.1 (persistent `uv tool install`).
|
|
17
|
+
|
|
18
|
+
## [2.3.0] - 2026-02-13
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- `ExitCodeStyle` enum (`str, Enum`) replacing `Literal["errno", "sysexits"]` string literals, re-exported through the public API facade.
|
|
22
|
+
- New `cli/` package structure splitting the monolithic `cli.py` into `group.py`, `commands.py`, and `styling.py` with backward-compatible re-exports.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- Replaced `Mapping[str, object]` with typed `SessionOverrides` in `cli_session` and internal helpers for stricter type safety.
|
|
26
|
+
- Removed `_CONFIG_TRACEBACK` / `_CONFIG_TRACEBACK_FORCE_COLOR` string constants in favour of direct `SessionOverrides` key access.
|
|
27
|
+
- Migrated `scripts/` to external submodule; build automation now uses `uvx bmk`.
|
|
28
|
+
- Updated GitHub Actions CI/CD workflows and removed legacy backup workflow files.
|
|
29
|
+
|
|
30
|
+
### Security
|
|
31
|
+
- Added CVE-2026-1703, CVE-2026-25990, and CVE-2026-26007 to pip-audit ignore list (transitive dev dependencies, not runtime).
|
|
5
32
|
|
|
6
33
|
## [2.2.4] - 2026-01-26
|
|
7
34
|
|
|
8
35
|
### Changed
|
|
9
36
|
- Updated dependencies.
|
|
10
37
|
- Excluded `scripts/` from pyright, pytest, and CI/CD test collection.
|
|
38
|
+
- Ctrl-C in scripts now exits with code 130 (POSIX SIGINT convention) instead of Click's default exit code 1.
|
|
11
39
|
|
|
12
40
|
## [2.2.3] - 2025-12-17
|
|
13
41
|
|