Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# CI for the public OpSentry repository.
#
# Self-contained on purpose. The rest of the org calls a reusable workflow that
# lives in a private repository; this one cannot, because a public repo should
# not depend on a private repo's workflow to verify itself -- a contributor
# opening a PR must be able to read every step that gates it, and the private
# workflow would be invisible to them.
#
# This repository is what `brew install opsentry` and `git clone` actually pull
# from, so until now the two most-used install paths had nothing checking them.

name: ci

on:
pull_request:
push:
branches: [develop, main]

jobs:
test:
name: hooks + lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Install jq
# The hooks parse Claude Code's PreToolUse JSON with jq; the suite
# cannot run without it. Ubuntu runners ship it, but pinning the install
# keeps the requirement visible rather than inherited.
run: sudo apt-get install -y jq

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Hook test suite
# 168 assertions across the 8 guardrail hooks, simulating the JSON
# Claude Code sends on PreToolUse.
run: bash test.sh

- name: Lint
run: |
# Pinned: ruff's default rule set grows between releases, and an
# unpinned upgrade would fail CI on a commit that changed nothing.
pip install ruff==0.16.1
ruff check opsentry

- name: Verify the installer is self-consistent
# install.sh is the git-clone install path. A broken shebang or syntax
# error here breaks the documented install for everyone who does not use
# brew or pip, and no test would otherwise catch it.
run: |
bash -n install.sh
bash -n opsentry/install.sh
for hook in opsentry/claude/hooks/*.sh; do bash -n "$hook"; done
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.8.4] - 2026-08-03

### Added
- **CI.** This repository is what `brew install opsentry` and `git clone` pull
from, and until now nothing verified it — there were no workflows at all, only
issue and PR templates. Every push and pull request now runs the 168-assertion
hook suite, lints the Python, and syntax-checks `install.sh` and all eight
guardrail hooks so a broken installer cannot ship.

The workflow is **self-contained** rather than calling the organisation's
shared one, which lives in a private repository: a contributor opening a pull
request must be able to read every step that gates it, and a private workflow
would be invisible to them.

### Fixed
- `baseline.py` and `blocklog_audit.py` carried `#!/usr/bin/env python3` but were
tracked non-executable, so neither could be run directly despite advertising
that it could. Found by CI on its first run.

## [1.8.3] - 2026-08-03
### Changed
- **Version aligned with the OpSentry release line.** This repository had been
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.8.3
1.8.4
Empty file modified opsentry/baseline.py
100644 → 100755
Empty file.
Empty file modified opsentry/blocklog_audit.py
100644 → 100755
Empty file.