Skip to content
Draft
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: 53 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ concurrency:
cancel-in-progress: true

jobs:
ci:
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [ "3.11", "3.12" ]
python-version: [ "3.10", "3.11", "3.12" ]

steps:
- name: Checkout
Expand All @@ -46,3 +46,54 @@ jobs:
- name: Tests (pytest)
run: |
pytest -q

protected-file-guard:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fail if protected paths are modified
run: |
PROTECTED_PATHS=(
"authority_gate.py"
"stop_machine.py"
"commit_gate/"
".github/workflows/"
)
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}..HEAD)
VIOLATIONS=""
for path in "${PROTECTED_PATHS[@]}"; do
if echo "$CHANGED" | grep -q "^${path}"; then
VIOLATIONS="${VIOLATIONS}\n - ${path}"
fi
done
if [ -n "$VIOLATIONS" ]; then
echo "::error::Protected paths modified — triple-lock review required:${VIOLATIONS}"
exit 1
fi
echo "No protected paths modified."

build-artefact:
runs-on: ubuntu-latest
needs: tests
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build source artefact
run: |
zip -r constraint-workshop-${{ github.sha }}.zip \
authority_gate.py stop_machine.py mgtp/ commit_gate/ registry/ \
--exclude "*/__pycache__/*" --exclude "*/.git/*"

- name: Upload artefact
uses: actions/upload-artifact@v4
with:
name: constraint-workshop-${{ github.sha }}
path: constraint-workshop-${{ github.sha }}.zip
retention-days: 90
92 changes: 92 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Release

on:
push:
tags:
- "v[0-9]*.[0-9]*.[0-9]*"

permissions:
contents: write

jobs:
verify-protected-branch:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Verify tag is reachable from main
run: |
git fetch origin main
TAG_SHA=$(git rev-parse HEAD)
if ! git merge-base --is-ancestor "$TAG_SHA" "origin/main"; then
echo "::error::Tag ${{ github.ref_name }} (${TAG_SHA}) is not on the protected main branch."
exit 1
fi
echo "Tag ${TAG_SHA} is on main. Proceeding."

tests:
runs-on: ubuntu-latest
needs: verify-protected-branch
strategy:
fail-fast: false
matrix:
python-version: [ "3.10", "3.11", "3.12" ]
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff pytest

- name: Lint (ruff)
run: ruff check .

- name: Tests (pytest)
run: pytest -q

build-release-artefact:
runs-on: ubuntu-latest
needs: tests
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Record commit SHA
id: meta
run: |
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"

- name: Build release artefact
run: |
zip -r constraint-workshop-${{ github.ref_name }}.zip \
authority_gate.py stop_machine.py mgtp/ commit_gate/ registry/ \
--exclude "*/__pycache__/*" --exclude "*/.git/*"
sha256sum constraint-workshop-${{ github.ref_name }}.zip \
> constraint-workshop-${{ github.ref_name }}.zip.sha256

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: "Release ${{ github.ref_name }}"
body: |
## Release ${{ github.ref_name }}

**Commit SHA:** `${{ steps.meta.outputs.sha }}`
**Branch:** `main` (verified)

All CI checks (Python 3.10, 3.11, 3.12) passed before this release was built.
files: |
constraint-workshop-${{ github.ref_name }}.zip
constraint-workshop-${{ github.ref_name }}.zip.sha256