Skip to content

Commit ab6dd02

Browse files
committed
ci: full CI setup — test matrix, release, integration, PR-title
Four workflows replacing/expanding the placeholder test.yml: - test.yml (rewrite): unit suite on every push, matrix Python 3.11-3.14 on ubuntu. 3.11 is the current Hermes runtime so we cover it; 3.12-3.14 cover forward-compat for whenever Hermes upgrades. Concurrency group cancels in-progress runs when a new commit lands on the same branch. - release.yml (new): manually triggered via workflow_dispatch. User selects a v*.*.* tag from the ref dropdown when running. Validates the ref is a real semver tag, extracts the matching CHANGELOG section via awk between '## [VERSION]' and the next '## [' heading, and publishes a GitHub Release with that section as the body. Falls back to GitHub's auto-generated release notes if no CHANGELOG section matches (so we never publish an empty body). - integration.yml (new): runs the gated integration suite (BM_INTEGRATION=1) on push to main + manual dispatch. Installs basic-memory via 'uv tool install', verifies bm on PATH, then runs pytest tests/test_integration.py against a live bm mcp subprocess. Catches BM-API drift (a bm release renaming a tool arg, etc.) before it surfaces in user runtime. - pr-title.yml (new): semantic PR title check via amannn/action-semantic-pull-request@v5. Accepts the standard conventional-commit type list. requireScope=false because this is a single-file plugin.
1 parent 7c608be commit ab6dd02

4 files changed

Lines changed: 160 additions & 4 deletions

File tree

.github/workflows/integration.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: integration
2+
3+
# Heavier than test.yml — installs the real `basic-memory` CLI via uv, runs
4+
# every bm_* tool against a live `bm mcp` subprocess. Catches BM-API drift
5+
# (e.g., a bm release renaming a tool argument) before our users see it.
6+
concurrency:
7+
group: hbm-integration-${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: true
9+
10+
on:
11+
push:
12+
branches: [main]
13+
workflow_dispatch:
14+
15+
jobs:
16+
integration:
17+
name: Integration tests (real bm + mcp)
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 15
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v3
26+
with:
27+
enable-cache: true
28+
29+
- name: Set up Python 3.12
30+
# basic-memory itself requires 3.12+; the bm install needs that.
31+
# Hermes-runtime compatibility (3.11) is covered by test.yml.
32+
run: uv python install 3.12
33+
34+
- name: Install basic-memory CLI via uv
35+
run: |
36+
uv tool install basic-memory
37+
# uv puts entry-point shims under ~/.local/bin
38+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
39+
40+
- name: Verify bm is on PATH
41+
run: |
42+
which bm
43+
bm --version
44+
45+
- name: Run integration tests
46+
env:
47+
BM_INTEGRATION: "1"
48+
run: |
49+
uv run --with pytest --with mcp --python 3.12 pytest tests/test_integration.py -v

.github/workflows/pr-title.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: pr-title
2+
3+
on:
4+
pull_request:
5+
types: [opened, edited, synchronize]
6+
7+
jobs:
8+
semantic-pr-title:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: amannn/action-semantic-pull-request@v5
12+
env:
13+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
14+
with:
15+
# Conventional-commit types we accept in PR titles + commit subjects.
16+
types: |
17+
feat
18+
fix
19+
chore
20+
docs
21+
style
22+
refactor
23+
perf
24+
test
25+
build
26+
ci
27+
# Single-file plugin — no real submodule structure. We don't require
28+
# a scope, but if a contributor uses one we accept these:
29+
scopes: |
30+
core
31+
tests
32+
ci
33+
docs
34+
deps
35+
requireScope: false
36+
requireScopeForBreakingChange: true

.github/workflows/release.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: release
2+
3+
# Manual only. Trigger from Actions → release → Run workflow,
4+
# selecting a v*.*.* tag from the ref dropdown.
5+
on:
6+
workflow_dispatch:
7+
8+
jobs:
9+
release:
10+
name: Publish GitHub Release
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: write
14+
steps:
15+
- name: Validate ref is a v*.*.* tag
16+
run: |
17+
if [ "${GITHUB_REF_TYPE}" != "tag" ]; then
18+
echo "::error::This workflow must run against a tag. Got ref_type=$GITHUB_REF_TYPE ref=$GITHUB_REF"
19+
exit 1
20+
fi
21+
if [[ ! "${GITHUB_REF_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
22+
echo "::error::Tag must match v X.Y.Z format. Got: $GITHUB_REF_NAME"
23+
exit 1
24+
fi
25+
26+
- uses: actions/checkout@v4
27+
with:
28+
ref: ${{ github.ref }}
29+
fetch-depth: 0
30+
31+
- name: Extract CHANGELOG section for this tag
32+
id: changelog
33+
run: |
34+
VERSION="${GITHUB_REF_NAME#v}"
35+
# Pull lines between `## [VERSION]` and the next `## [` heading.
36+
SECTION=$(awk -v ver="$VERSION" '
37+
$0 ~ "^## \\[" ver "\\]" { found=1; next }
38+
found && /^## \[/ { exit }
39+
found { print }
40+
' CHANGELOG.md)
41+
if [ -z "$SECTION" ]; then
42+
echo "::warning::No CHANGELOG.md section found for v$VERSION — falling back to auto-generated release notes."
43+
echo "has_section=false" >> "$GITHUB_OUTPUT"
44+
else
45+
echo "has_section=true" >> "$GITHUB_OUTPUT"
46+
{
47+
echo 'body<<EOF_CHANGELOG'
48+
echo "$SECTION"
49+
echo 'EOF_CHANGELOG'
50+
} >> "$GITHUB_OUTPUT"
51+
fi
52+
53+
- name: Create GitHub Release
54+
uses: softprops/action-gh-release@v2
55+
with:
56+
tag_name: ${{ github.ref_name }}
57+
name: ${{ github.ref_name }}
58+
body: ${{ steps.changelog.outputs.body }}
59+
# If we couldn't find a CHANGELOG section, let GitHub auto-generate
60+
# release notes from commit messages instead of publishing an empty body.
61+
generate_release_notes: ${{ steps.changelog.outputs.has_section == 'false' }}
62+
token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
name: tests
22

3+
# Cancel an in-progress run when a new commit lands on the same branch — the
4+
# latest result is the one we care about.
5+
concurrency:
6+
group: hbm-tests-${{ github.workflow }}-${{ github.ref }}
7+
cancel-in-progress: true
8+
39
on:
10+
# Branch pushes already cover PRs (the PR branch tip is what's being tested),
11+
# so we don't run the matrix twice for the same commit on push + pull_request.
412
push:
5-
branches: [main]
6-
pull_request:
7-
branches: [main]
813

914
jobs:
1015
unit:
1116
name: Unit tests (Python ${{ matrix.python-version }})
1217
runs-on: ubuntu-latest
18+
timeout-minutes: 10
1319
strategy:
1420
fail-fast: false
1521
matrix:
16-
python-version: ["3.11", "3.12"]
22+
# 3.11 is the runtime Hermes itself ships on today; 3.12-3.14 cover
23+
# forward-compat for whenever Hermes upgrades.
24+
python-version: ["3.11", "3.12", "3.13", "3.14"]
25+
1726
steps:
1827
- uses: actions/checkout@v4
1928

0 commit comments

Comments
 (0)