Skip to content
Closed
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
18 changes: 15 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0

- name: Validate tracked files are not ignored
shell: bash
Expand All @@ -80,6 +82,12 @@ jobs:
fi
echo "No tracked files match .gitignore rules."

- name: Validate newly introduced commit subjects
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: python3 scripts/validate_release_commit_subjects.py "$BASE_SHA" "$HEAD_SHA"

python-contract:
runs-on: ubuntu-latest
steps:
Expand All @@ -90,10 +98,14 @@ jobs:
python-version: "3.11"

- name: Install pytest
run: python -m pip install --upgrade pip pytest
run: python -m pip install --upgrade pip pytest PyYAML

- name: Validate Python provenance stubs and documentation
run: python -m pytest -q python/tests/test_relation_provenance_contract.py
- name: Validate Python provenance, documentation, and release contracts
run: >-
python -m pytest -q
python/tests/test_relation_provenance_contract.py
python/tests/test_docs_contract.py
python/tests/test_release_changelog_generation.py

# The CAVIAR and maritime example suites on CPU (review follow-up:
# previously no workflow ran any of them; the maritime suites were
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/release-plz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ jobs:
python3 \
python3-dev \
python3-pip
python3 -m pip install --no-cache-dir tomli==2.2.1

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
Expand Down Expand Up @@ -158,6 +159,22 @@ jobs:
if: github.event_name == 'workflow_dispatch'
run: bash scripts/preflight_release_publish.sh

- name: Prepare unpublished changelog regeneration
if: github.event_name != 'workflow_dispatch'
run: |
set -euo pipefail
python3 scripts/prepare_release_changelog.py

unexpected=()
while IFS= read -r entry; do
[[ "$entry" == " M CHANGELOG.md" ]] || unexpected+=("$entry")
done < <(git status --porcelain=v1 --untracked-files=all)
if ((${#unexpected[@]} != 0)); then
echo "Changelog preparation changed unexpected repository paths:" >&2
printf ' %s\n' "${unexpected[@]}" >&2
exit 1
fi

- name: Run release-plz
id: release
run: |
Expand Down Expand Up @@ -209,6 +226,7 @@ jobs:
--git-token "$GITHUB_TOKEN" \
--repo-url "https://github.com/${GITHUB_REPOSITORY}" \
--config release-plz.toml \
--allow-dirty \
-o json)
echo "release_pr_output: $release_pr_output"

Expand Down
318 changes: 96 additions & 222 deletions CHANGELOG.md

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions docs/architecture/release-process.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,36 @@ Workspace packages that are not published to crates.io:

`pyxlog` ships as a Python package on PyPI, not as a crates.io Rust crate.

## Release Automation Ownership

XLOG versions the publishable crates and the Python package together, so release
worthiness is a whole-workspace release-worthiness gate. The
`.github/workflows/release-plz.yml` owns this gate: on a push to `main`, it looks
for release-worthy Conventional Commits since the latest CLI tag before creating
or updating the rolling release pull request.
`release-plz.toml` does not decide release worthiness; it describes the shared
version group, publication targets, generated changelog, release pull request,
and tag formats after the workflow has admitted the workspace release.

The workspace has a single authoritative Git tag, owned by `xlog-cli` and named
`xlog-cli-v{{ version }}`. The shared changelog therefore uses package-labelled
headings for all generated crate sections, while only the `xlog-cli` heading has
a compare link. The preparation step removes unpublished sections for the
current workspace version before regeneration, including sections written with
the earlier unlabelled heading format. This keeps repeated automation runs
convergent without changing sections once the authoritative tag exists.
Release-plz attributes commits from the packaged file set for each crate, so a
commit that changes a shared packaged file can appear in several package
sections. Repeated appearances reflect package attribution; regeneration does
not append another copy of an existing current-version section.

A push to `main` can prepare a release pull request, but it cannot publish a
release. Publication is a manual `workflow_dispatch` from the reviewed release
commit. The operator must set `confirm_gpu_validation` and provide the GPU host,
commit, and evidence after the complete release validation command has passed.
Only that manual path invokes registry publication and creates the CLI tag; the
Python wheel and GitHub release assets then use the same tag.

## CUDA Artifact Model

XLOG runs GPU kernels, and those compiled kernels are not checked into the tree.
Expand Down
14 changes: 14 additions & 0 deletions python/tests/test_docs_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,17 @@ def compile(source: str, device: int = 0) -> CompiledLogicProgram: ...
)
assert "## LogicProgram" in result.stdout
assert "compile(source: str, device: int = 0)" in result.stdout


def test_release_process_documents_automation_ownership_and_single_tag_policy() -> None:
page = read("docs/architecture/release-process.mdx")

assert "whole-workspace release-worthiness gate" in page
assert "`.github/workflows/release-plz.yml` owns this gate" in page
assert "`release-plz.toml` does not decide release worthiness" in page
assert "single authoritative Git tag" in page
assert "`xlog-cli-v{{ version }}`" in page
assert "package-labelled" in page
assert "manual `workflow_dispatch`" in page
assert "confirm_gpu_validation" in page
assert "docs-internal" not in page
Loading
Loading