mnesis 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.
- mnesis-0.1.0/.github/dependabot.yml +16 -0
- mnesis-0.1.0/.github/workflows/ci.yml +95 -0
- mnesis-0.1.0/.github/workflows/dependency-review.yml +24 -0
- mnesis-0.1.0/.github/workflows/docs.yml +67 -0
- mnesis-0.1.0/.github/workflows/publish.yml +309 -0
- mnesis-0.1.0/.github/workflows/scorecard.yml +46 -0
- mnesis-0.1.0/.gitignore +217 -0
- mnesis-0.1.0/CONTRIBUTING.md +169 -0
- mnesis-0.1.0/LICENSE +201 -0
- mnesis-0.1.0/NOTICE +13 -0
- mnesis-0.1.0/PKG-INFO +312 -0
- mnesis-0.1.0/README.md +283 -0
- mnesis-0.1.0/SECURITY.md +61 -0
- mnesis-0.1.0/codecov.yml +15 -0
- mnesis-0.1.0/docs/LCM.pdf +0 -0
- mnesis-0.1.0/docs/byo-llm.md +124 -0
- mnesis-0.1.0/docs/changelog.md +48 -0
- mnesis-0.1.0/docs/concepts.md +66 -0
- mnesis-0.1.0/docs/configuration.md +102 -0
- mnesis-0.1.0/docs/examples.md +82 -0
- mnesis-0.1.0/docs/gen_ref_pages.py +53 -0
- mnesis-0.1.0/docs/getting-started.md +94 -0
- mnesis-0.1.0/docs/images/benchmark_improvement.png +0 -0
- mnesis-0.1.0/docs/images/benchmark_scores.png +0 -0
- mnesis-0.1.0/docs/images/logo.png +0 -0
- mnesis-0.1.0/docs/images/logo_icon.png +0 -0
- mnesis-0.1.0/docs/images/logo_wordmark.png +0 -0
- mnesis-0.1.0/docs/images/rlm_vs_lcm.png +0 -0
- mnesis-0.1.0/docs/index.md +46 -0
- mnesis-0.1.0/docs/providers.md +95 -0
- mnesis-0.1.0/examples/01_basic_session.py +84 -0
- mnesis-0.1.0/examples/02_long_running_agent.py +107 -0
- mnesis-0.1.0/examples/03_tool_use.py +143 -0
- mnesis-0.1.0/examples/04_large_files.py +196 -0
- mnesis-0.1.0/examples/05_parallel_processing.py +156 -0
- mnesis-0.1.0/examples/06_byo_llm.py +143 -0
- mnesis-0.1.0/mkdocs.yml +74 -0
- mnesis-0.1.0/pyproject.toml +124 -0
- mnesis-0.1.0/src/mnesis/__init__.py +76 -0
- mnesis-0.1.0/src/mnesis/compaction/__init__.py +19 -0
- mnesis-0.1.0/src/mnesis/compaction/engine.py +335 -0
- mnesis-0.1.0/src/mnesis/compaction/levels.py +307 -0
- mnesis-0.1.0/src/mnesis/compaction/pruner.py +252 -0
- mnesis-0.1.0/src/mnesis/context/__init__.py +5 -0
- mnesis-0.1.0/src/mnesis/context/builder.py +216 -0
- mnesis-0.1.0/src/mnesis/events/__init__.py +5 -0
- mnesis-0.1.0/src/mnesis/events/bus.py +138 -0
- mnesis-0.1.0/src/mnesis/files/__init__.py +5 -0
- mnesis-0.1.0/src/mnesis/files/handler.py +445 -0
- mnesis-0.1.0/src/mnesis/models/__init__.py +63 -0
- mnesis-0.1.0/src/mnesis/models/config.py +233 -0
- mnesis-0.1.0/src/mnesis/models/message.py +326 -0
- mnesis-0.1.0/src/mnesis/models/summary.py +70 -0
- mnesis-0.1.0/src/mnesis/operators/__init__.py +6 -0
- mnesis-0.1.0/src/mnesis/operators/agentic_map.py +240 -0
- mnesis-0.1.0/src/mnesis/operators/llm_map.py +270 -0
- mnesis-0.1.0/src/mnesis/session.py +708 -0
- mnesis-0.1.0/src/mnesis/store/__init__.py +29 -0
- mnesis-0.1.0/src/mnesis/store/immutable.py +916 -0
- mnesis-0.1.0/src/mnesis/store/pool.py +162 -0
- mnesis-0.1.0/src/mnesis/store/schema.sql +121 -0
- mnesis-0.1.0/src/mnesis/store/summary_dag.py +291 -0
- mnesis-0.1.0/src/mnesis/tokens/__init__.py +5 -0
- mnesis-0.1.0/src/mnesis/tokens/estimator.py +155 -0
- mnesis-0.1.0/tests/__init__.py +0 -0
- mnesis-0.1.0/tests/conftest.py +134 -0
- mnesis-0.1.0/tests/test_compaction.py +210 -0
- mnesis-0.1.0/tests/test_context_builder.py +237 -0
- mnesis-0.1.0/tests/test_files.py +106 -0
- mnesis-0.1.0/tests/test_operators.py +173 -0
- mnesis-0.1.0/tests/test_pruner.py +201 -0
- mnesis-0.1.0/tests/test_session.py +277 -0
- mnesis-0.1.0/tests/test_store.py +243 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: "uv"
|
|
9
|
+
directory: "/"
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
|
12
|
+
|
|
13
|
+
- package-ecosystem: "github-actions"
|
|
14
|
+
directory: "/"
|
|
15
|
+
schedule:
|
|
16
|
+
interval: "weekly"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
paths:
|
|
9
|
+
- "src/**"
|
|
10
|
+
- "tests/**"
|
|
11
|
+
- "pyproject.toml"
|
|
12
|
+
pull_request:
|
|
13
|
+
branches: [main]
|
|
14
|
+
paths:
|
|
15
|
+
- "src/**"
|
|
16
|
+
- "tests/**"
|
|
17
|
+
- "pyproject.toml"
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
lint:
|
|
21
|
+
name: Lint & Format
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: true
|
|
30
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
31
|
+
python-version: "3.12"
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: uv sync --dev
|
|
35
|
+
|
|
36
|
+
- name: Ruff lint
|
|
37
|
+
run: uv run ruff check src/ tests/
|
|
38
|
+
|
|
39
|
+
- name: Ruff format check
|
|
40
|
+
run: uv run ruff format --check src/ tests/
|
|
41
|
+
|
|
42
|
+
typecheck:
|
|
43
|
+
name: Type Check
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
47
|
+
|
|
48
|
+
- name: Install uv
|
|
49
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
50
|
+
with:
|
|
51
|
+
enable-cache: true
|
|
52
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
53
|
+
python-version: "3.12"
|
|
54
|
+
|
|
55
|
+
- name: Install dependencies
|
|
56
|
+
run: uv sync --dev
|
|
57
|
+
|
|
58
|
+
- name: mypy
|
|
59
|
+
run: uv run mypy src/mnesis
|
|
60
|
+
|
|
61
|
+
test:
|
|
62
|
+
name: Tests (Python ${{ matrix.python-version }})
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
permissions:
|
|
65
|
+
contents: read
|
|
66
|
+
id-token: write
|
|
67
|
+
strategy:
|
|
68
|
+
fail-fast: false
|
|
69
|
+
matrix:
|
|
70
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
73
|
+
|
|
74
|
+
- name: Install uv
|
|
75
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
76
|
+
with:
|
|
77
|
+
enable-cache: true
|
|
78
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
79
|
+
python-version: ${{ matrix.python-version }}
|
|
80
|
+
|
|
81
|
+
- name: Install dependencies
|
|
82
|
+
run: uv sync --dev
|
|
83
|
+
|
|
84
|
+
- name: Run tests
|
|
85
|
+
env:
|
|
86
|
+
MNESIS_MOCK_LLM: "1"
|
|
87
|
+
run: uv run pytest
|
|
88
|
+
|
|
89
|
+
- name: Upload coverage report
|
|
90
|
+
if: matrix.python-version == '3.12'
|
|
91
|
+
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5
|
|
92
|
+
with:
|
|
93
|
+
files: coverage.xml
|
|
94
|
+
fail_ci_if_error: false
|
|
95
|
+
use_oidc: true
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Dependency Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pull-requests: write # post inline comments on vulnerable deps
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
dependency-review:
|
|
13
|
+
name: Dependency Review
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
17
|
+
|
|
18
|
+
- name: Dependency Review
|
|
19
|
+
uses: actions/dependency-review-action@ce3cf9537a52e8119d91fd484ab5b8a807627bf8 # v4.6.0
|
|
20
|
+
with:
|
|
21
|
+
# Fail on any vulnerability severity
|
|
22
|
+
fail-on-severity: low
|
|
23
|
+
# Post a summary comment on the PR
|
|
24
|
+
comment-summary-in-pr: always
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
- "src/**"
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [main]
|
|
12
|
+
paths:
|
|
13
|
+
- "docs/**"
|
|
14
|
+
- "mkdocs.yml"
|
|
15
|
+
- "src/**"
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
pages: write
|
|
21
|
+
id-token: write
|
|
22
|
+
|
|
23
|
+
# Only one deployment at a time; don't cancel in-progress runs
|
|
24
|
+
concurrency:
|
|
25
|
+
group: pages
|
|
26
|
+
cancel-in-progress: false
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
build:
|
|
30
|
+
name: Build Docs
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
34
|
+
with:
|
|
35
|
+
fetch-depth: 0
|
|
36
|
+
|
|
37
|
+
- name: Install uv
|
|
38
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
39
|
+
with:
|
|
40
|
+
enable-cache: true
|
|
41
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
42
|
+
python-version: "3.12"
|
|
43
|
+
|
|
44
|
+
- name: Install docs dependencies
|
|
45
|
+
run: uv sync --group docs
|
|
46
|
+
|
|
47
|
+
- name: Build docs
|
|
48
|
+
run: uv run mkdocs build
|
|
49
|
+
|
|
50
|
+
- name: Upload pages artifact
|
|
51
|
+
if: github.event_name != 'pull_request'
|
|
52
|
+
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
|
|
53
|
+
with:
|
|
54
|
+
path: site/
|
|
55
|
+
|
|
56
|
+
deploy:
|
|
57
|
+
name: Deploy to GitHub Pages
|
|
58
|
+
if: github.event_name != 'pull_request'
|
|
59
|
+
needs: build
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
environment:
|
|
62
|
+
name: github-pages
|
|
63
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
64
|
+
steps:
|
|
65
|
+
- name: Deploy
|
|
66
|
+
id: deployment
|
|
67
|
+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: "Version to release (e.g. 0.2.0)"
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
notes:
|
|
11
|
+
description: "Release notes (markdown bullet points). Leave blank to auto-generate from git log."
|
|
12
|
+
required: false
|
|
13
|
+
type: string
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
id-token: write # PyPI OIDC + Sigstore signing
|
|
18
|
+
attestations: write # build provenance attestations
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
# ── 1. Validate inputs ────────────────────────────────────────────────────
|
|
22
|
+
validate:
|
|
23
|
+
name: Validate version
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
outputs:
|
|
26
|
+
version: ${{ steps.check.outputs.version }}
|
|
27
|
+
tag: ${{ steps.check.outputs.tag }}
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Check version format, ordering, and uniqueness
|
|
34
|
+
id: check
|
|
35
|
+
run: |
|
|
36
|
+
VERSION="${{ inputs.version }}"
|
|
37
|
+
|
|
38
|
+
# Must be X.Y.Z (no leading v)
|
|
39
|
+
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
40
|
+
echo "::error::Version '$VERSION' is not valid semver (expected X.Y.Z)"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
TAG="v${VERSION}"
|
|
45
|
+
|
|
46
|
+
# Tag must not already exist
|
|
47
|
+
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
|
48
|
+
echo "::error::Tag '$TAG' already exists"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Changelog must not already have an entry for this version
|
|
53
|
+
if grep -q "^## ${VERSION}" docs/changelog.md; then
|
|
54
|
+
echo "::error::docs/changelog.md already has an entry for ${VERSION}"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Version must be strictly greater than the latest release tag
|
|
59
|
+
LAST_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
|
|
60
|
+
if [ -n "$LAST_TAG" ]; then
|
|
61
|
+
LAST_VERSION="${LAST_TAG#v}"
|
|
62
|
+
python3 - <<PYEOF
|
|
63
|
+
import sys
|
|
64
|
+
|
|
65
|
+
def parse(v):
|
|
66
|
+
return tuple(int(x) for x in v.split('.'))
|
|
67
|
+
|
|
68
|
+
new = parse("${VERSION}")
|
|
69
|
+
last = parse("${LAST_VERSION}")
|
|
70
|
+
if new <= last:
|
|
71
|
+
print(f"::error::Version ${VERSION} is not greater than last release ${LAST_VERSION}")
|
|
72
|
+
sys.exit(1)
|
|
73
|
+
print(f"Version ${VERSION} > ${LAST_VERSION} ✓")
|
|
74
|
+
PYEOF
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
78
|
+
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
79
|
+
|
|
80
|
+
# ── 2. Full CI gate ───────────────────────────────────────────────────────
|
|
81
|
+
lint:
|
|
82
|
+
name: Lint & Format
|
|
83
|
+
needs: validate
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
87
|
+
|
|
88
|
+
- name: Install uv
|
|
89
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
90
|
+
with:
|
|
91
|
+
enable-cache: true
|
|
92
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
93
|
+
python-version: "3.12"
|
|
94
|
+
|
|
95
|
+
- name: Install dependencies
|
|
96
|
+
run: uv sync --dev
|
|
97
|
+
|
|
98
|
+
- name: Ruff lint
|
|
99
|
+
run: uv run ruff check src/ tests/
|
|
100
|
+
|
|
101
|
+
- name: Ruff format check
|
|
102
|
+
run: uv run ruff format --check src/ tests/
|
|
103
|
+
|
|
104
|
+
typecheck:
|
|
105
|
+
name: Type Check
|
|
106
|
+
needs: validate
|
|
107
|
+
runs-on: ubuntu-latest
|
|
108
|
+
steps:
|
|
109
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
110
|
+
|
|
111
|
+
- name: Install uv
|
|
112
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
113
|
+
with:
|
|
114
|
+
enable-cache: true
|
|
115
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
116
|
+
python-version: "3.12"
|
|
117
|
+
|
|
118
|
+
- name: Install dependencies
|
|
119
|
+
run: uv sync --dev
|
|
120
|
+
|
|
121
|
+
- name: mypy
|
|
122
|
+
run: uv run mypy src/mnesis
|
|
123
|
+
|
|
124
|
+
test:
|
|
125
|
+
name: Tests (Python ${{ matrix.python-version }})
|
|
126
|
+
needs: validate
|
|
127
|
+
runs-on: ubuntu-latest
|
|
128
|
+
strategy:
|
|
129
|
+
fail-fast: false
|
|
130
|
+
matrix:
|
|
131
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
132
|
+
steps:
|
|
133
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
134
|
+
|
|
135
|
+
- name: Install uv
|
|
136
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
137
|
+
with:
|
|
138
|
+
enable-cache: true
|
|
139
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
140
|
+
python-version: ${{ matrix.python-version }}
|
|
141
|
+
|
|
142
|
+
- name: Install dependencies
|
|
143
|
+
run: uv sync --dev
|
|
144
|
+
|
|
145
|
+
- name: Run tests
|
|
146
|
+
env:
|
|
147
|
+
MNESIS_MOCK_LLM: "1"
|
|
148
|
+
run: uv run pytest
|
|
149
|
+
|
|
150
|
+
# ── 3. Release ────────────────────────────────────────────────────────────
|
|
151
|
+
release:
|
|
152
|
+
name: Release v${{ needs.validate.outputs.version }}
|
|
153
|
+
needs: [validate, lint, typecheck, test]
|
|
154
|
+
runs-on: ubuntu-latest
|
|
155
|
+
environment: pypi
|
|
156
|
+
steps:
|
|
157
|
+
- name: Generate release token
|
|
158
|
+
id: app-token
|
|
159
|
+
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
|
160
|
+
with:
|
|
161
|
+
app-id: ${{ secrets.RELEASE_APP_ID }}
|
|
162
|
+
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
|
|
163
|
+
|
|
164
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
165
|
+
with:
|
|
166
|
+
fetch-depth: 0
|
|
167
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
168
|
+
|
|
169
|
+
- name: Install uv
|
|
170
|
+
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
|
171
|
+
with:
|
|
172
|
+
enable-cache: true
|
|
173
|
+
cache-dependency-glob: "**/pyproject.toml"
|
|
174
|
+
python-version: "3.12"
|
|
175
|
+
|
|
176
|
+
- name: Configure git identity
|
|
177
|
+
run: |
|
|
178
|
+
git config user.name "Mnesis Release Bot"
|
|
179
|
+
git config user.email "mnesis-release-bot[bot]@users.noreply.github.com"
|
|
180
|
+
|
|
181
|
+
# ── 3a. Resolve release notes ────────────────────────────────────────
|
|
182
|
+
- name: Resolve release notes
|
|
183
|
+
id: notes
|
|
184
|
+
run: |
|
|
185
|
+
NOTES="${{ inputs.notes }}"
|
|
186
|
+
|
|
187
|
+
if [ -z "$NOTES" ]; then
|
|
188
|
+
LAST_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
|
|
189
|
+
if [ -n "$LAST_TAG" ]; then
|
|
190
|
+
NOTES=$(git log "${LAST_TAG}..HEAD" --pretty=format:"- %s" --no-merges)
|
|
191
|
+
else
|
|
192
|
+
NOTES=$(git log HEAD --pretty=format:"- %s" --no-merges)
|
|
193
|
+
fi
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
printf '%s' "$NOTES" > /tmp/release_notes.md
|
|
197
|
+
|
|
198
|
+
echo "notes<<EOF" >> "$GITHUB_OUTPUT"
|
|
199
|
+
printf '%s\n' "$NOTES" >> "$GITHUB_OUTPUT"
|
|
200
|
+
echo "EOF" >> "$GITHUB_OUTPUT"
|
|
201
|
+
|
|
202
|
+
# ── 3b. Bump version in pyproject.toml ──────────────────────────────
|
|
203
|
+
- name: Bump version in pyproject.toml
|
|
204
|
+
run: |
|
|
205
|
+
VERSION="${{ needs.validate.outputs.version }}"
|
|
206
|
+
sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
|
|
207
|
+
grep '^version = ' pyproject.toml
|
|
208
|
+
|
|
209
|
+
# ── 3c. Prepend changelog entry ──────────────────────────────────────
|
|
210
|
+
- name: Update docs/changelog.md
|
|
211
|
+
env:
|
|
212
|
+
VERSION: ${{ needs.validate.outputs.version }}
|
|
213
|
+
NOTES: ${{ steps.notes.outputs.notes }}
|
|
214
|
+
run: |
|
|
215
|
+
python3 - <<'PYEOF'
|
|
216
|
+
import pathlib, os, datetime
|
|
217
|
+
|
|
218
|
+
path = pathlib.Path("docs/changelog.md")
|
|
219
|
+
text = path.read_text()
|
|
220
|
+
lines = text.splitlines(keepends=True)
|
|
221
|
+
version = os.environ["VERSION"]
|
|
222
|
+
date = datetime.date.today().strftime("%Y-%m-%d")
|
|
223
|
+
notes = os.environ["NOTES"].strip()
|
|
224
|
+
|
|
225
|
+
insert = 1
|
|
226
|
+
for i, line in enumerate(lines):
|
|
227
|
+
if i == 0:
|
|
228
|
+
continue
|
|
229
|
+
if line.strip() == "" and i == 1:
|
|
230
|
+
insert = 2
|
|
231
|
+
break
|
|
232
|
+
|
|
233
|
+
new_section = f"## {version} — {date}\n\n{notes}\n\n"
|
|
234
|
+
lines.insert(insert, new_section)
|
|
235
|
+
path.write_text("".join(lines))
|
|
236
|
+
print(f"Prepended changelog entry for {version}")
|
|
237
|
+
PYEOF
|
|
238
|
+
|
|
239
|
+
# ── 3d. Build distribution ───────────────────────────────────────────
|
|
240
|
+
# Build before pushing so a build failure leaves the repo untouched.
|
|
241
|
+
- name: Build package
|
|
242
|
+
run: uv build
|
|
243
|
+
|
|
244
|
+
# ── 3e. Attest build provenance ──────────────────────────────────────
|
|
245
|
+
# Generates a Sigstore-signed SLSA provenance attestation for the
|
|
246
|
+
# built artifacts. Attestations are stored in GitHub's attestation
|
|
247
|
+
# store and uploaded to PyPI alongside the package. Users can verify
|
|
248
|
+
# with: gh attestation verify <wheel> --repo Lucenor/mnesis
|
|
249
|
+
- name: Attest build provenance
|
|
250
|
+
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
|
|
251
|
+
with:
|
|
252
|
+
subject-path: dist/*
|
|
253
|
+
|
|
254
|
+
# ── 3f. Generate and attest SBOM ─────────────────────────────────────
|
|
255
|
+
# Generates an SPDX SBOM listing every dependency in the release
|
|
256
|
+
# artifacts, then attests it with Sigstore. Complements provenance
|
|
257
|
+
# ("who built it") with a full dependency inventory ("what's in it").
|
|
258
|
+
- name: Generate SBOM
|
|
259
|
+
uses: anchore/sbom-action@28d71544de8eaf1b958d335707167c5f783590ad # v0.17.0
|
|
260
|
+
with:
|
|
261
|
+
path: dist/
|
|
262
|
+
format: spdx-json
|
|
263
|
+
output-file: sbom.spdx.json
|
|
264
|
+
upload-artifact: false
|
|
265
|
+
|
|
266
|
+
- name: Attest SBOM
|
|
267
|
+
uses: actions/attest-sbom@bd218ad0dbcb3e146bd073d1d9c6d78e08aa8a0b # v2.0.0
|
|
268
|
+
with:
|
|
269
|
+
subject-path: dist/*
|
|
270
|
+
sbom-path: sbom.spdx.json
|
|
271
|
+
|
|
272
|
+
# ── 3g. Commit, tag, push ────────────────────────────────────────────
|
|
273
|
+
- name: Commit and tag release
|
|
274
|
+
run: |
|
|
275
|
+
VERSION="${{ needs.validate.outputs.version }}"
|
|
276
|
+
TAG="${{ needs.validate.outputs.tag }}"
|
|
277
|
+
|
|
278
|
+
git add pyproject.toml docs/changelog.md
|
|
279
|
+
git commit -m "chore: release ${VERSION}"
|
|
280
|
+
git tag -a "$TAG" -m "Release ${VERSION}"
|
|
281
|
+
git push origin main
|
|
282
|
+
git push origin "$TAG"
|
|
283
|
+
|
|
284
|
+
# ── 3h. Create GitHub Release (draft) ───────────────────────────────
|
|
285
|
+
# Created as a draft so it is not subject to release immutability rules.
|
|
286
|
+
# Promoted to published only after PyPI succeeds.
|
|
287
|
+
- name: Create GitHub Release (draft)
|
|
288
|
+
env:
|
|
289
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
290
|
+
run: |
|
|
291
|
+
TAG="${{ needs.validate.outputs.tag }}"
|
|
292
|
+
gh release create "$TAG" dist/* \
|
|
293
|
+
--title "mnesis ${TAG}" \
|
|
294
|
+
--notes-file /tmp/release_notes.md \
|
|
295
|
+
--draft
|
|
296
|
+
|
|
297
|
+
# ── 3i. Publish to PyPI ──────────────────────────────────────────────
|
|
298
|
+
- name: Publish to PyPI
|
|
299
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
|
|
300
|
+
with:
|
|
301
|
+
packages-dir: dist/
|
|
302
|
+
|
|
303
|
+
# ── 3j. Publish GitHub Release ───────────────────────────────────────
|
|
304
|
+
- name: Publish GitHub Release
|
|
305
|
+
env:
|
|
306
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
307
|
+
run: |
|
|
308
|
+
TAG="${{ needs.validate.outputs.tag }}"
|
|
309
|
+
gh release edit "$TAG" --draft=false
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: OpenSSF Scorecard
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
schedule:
|
|
7
|
+
# Weekly on Monday at 06:00 UTC
|
|
8
|
+
- cron: "0 6 * * 1"
|
|
9
|
+
|
|
10
|
+
# Restrict default token to read-only; scorecard job elevates as needed.
|
|
11
|
+
permissions: read-all
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
scorecard:
|
|
15
|
+
name: Scorecard analysis
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
security-events: write # upload SARIF to GitHub code scanning
|
|
19
|
+
id-token: write # publish results to OpenSSF database
|
|
20
|
+
contents: read
|
|
21
|
+
actions: read
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
|
|
28
|
+
- name: Run Scorecard analysis
|
|
29
|
+
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
|
30
|
+
with:
|
|
31
|
+
results_file: scorecard.sarif
|
|
32
|
+
results_format: sarif
|
|
33
|
+
# Publish results to OpenSSF database for the badge to work
|
|
34
|
+
publish_results: true
|
|
35
|
+
|
|
36
|
+
- name: Upload SARIF artifact
|
|
37
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.4.3
|
|
38
|
+
with:
|
|
39
|
+
name: scorecard-sarif
|
|
40
|
+
path: scorecard.sarif
|
|
41
|
+
retention-days: 5
|
|
42
|
+
|
|
43
|
+
- name: Upload SARIF to GitHub code scanning
|
|
44
|
+
uses: github/codeql-action/upload-sarif@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.25.10
|
|
45
|
+
with:
|
|
46
|
+
sarif_file: scorecard.sarif
|