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
2 changes: 1 addition & 1 deletion .github/actions/setup-tools/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ runs:
using: composite
steps:
- name: Install declared uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
with:
version-file: pyproject.toml
enable-cache: ${{ inputs.cache }}
Expand Down
86 changes: 76 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ env:
RUST_BACKTRACE: 1

jobs:
build:
prepare:
runs-on: ${{ matrix.os }}
# Populate managed compilation caches once before the native jobs fan out.
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
Expand All @@ -51,8 +53,70 @@ jobs:
- name: Set up declared tools
uses: ./.github/actions/setup-tools # zizmor: ignore[self-repository] actionlint 1.7.12 does not accept $/...

- name: Run CI checks
run: just ci
- name: Run CI policy checks
run: just ci-policy

native:
name: native-${{ matrix.stage }} (${{ matrix.os }})
needs: prepare
runs-on: ${{ matrix.os }}
# Fresh installations verify the shared compilation cache. A cache miss
# may still rebuild tools; it must never remove a validation stage.
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
stage:
- rust
- python
- candidate
- dependencies
env:
LA_STACK_TEST_WORKERS: ${{ matrix.stage == 'candidate' && '1' || '4' }}
steps:
- name: Disable Git autocrlf on Windows
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up declared tools
uses: ./.github/actions/setup-tools # zizmor: ignore[self-repository] actionlint 1.7.12 does not accept $/...
- name: Run native validation
shell: bash
env:
CI_STAGE: ${{ matrix.stage }}
run: just "ci-$CI_STAGE"

build:
# Preserve required-check names while requiring every native stage.
needs: [prepare, native]
# A skipped required check can permit merging, including after cancellation.
if: ${{ always() }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Require complete native validation
env:
PREPARE_RESULT: ${{ needs.prepare.result }}
NATIVE_RESULT: ${{ needs.native.result }}
run: |
test "$PREPARE_RESULT" = success
test "$NATIVE_RESULT" = success

release-package:
runs-on: ubuntu-latest
Expand All @@ -66,13 +130,15 @@ jobs:
with:
cache: "false"
- name: Verify default and exact Cargo packages
run: just publish-check
run: |
just ci-dependencies
just publish-check

release-evidence:
needs: [build, release-package]
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'acgetchell/la-stack'
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 60
permissions:
contents: read
actions: read
Expand All @@ -82,18 +148,18 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
- uses: ./.github/actions/setup-tools # zizmor: ignore[self-repository] actionlint 1.7.12 does not accept $/...
with:
version-file: pyproject.toml
python-version-file: .python-version
enable-cache: false
cache: "false"
- name: Prepare native dependency provenance
run: just release-dependency-builds
- name: Capture successful native validation identities
id: evidence
env:
GH_TOKEN: ${{ github.token }}
run: |
uvx --python 3.15 \
--from 'research-repo-tools @ git+https://github.com/acgetchell/research-repo-tools@cd8594f658b5bf3ade063a685834565cc62e0cb3' \
--from 'research-repo-tools==0.2.8' \
python -I - <<'PY'
import os
import sys
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
permissions:
contents: write
pull-requests: write
uses: acgetchell/research-repo-tools/.github/workflows/dependabot-approve.yml@b972cbfd717319abaa68d9b1373711ad6f163294 # reviewed 2026-10-01
uses: acgetchell/research-repo-tools/.github/workflows/dependabot-approve.yml@4a8f53f684dee2abb7c5b8a4beab40ef29212b4c # v0.2.7
with:
repository: acgetchell/la-stack
policy: >-
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
verify:
if: github.repository == 'acgetchell/la-stack'
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 60
outputs:
commit: ${{ steps.source.outputs.commit }}
artifact-id: ${{ steps.handoff.outputs.artifact-id }}
Expand All @@ -30,12 +30,12 @@ jobs:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Install trusted package runner
uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
- name: Set up declared verification tools
uses: ./.github/actions/setup-tools # zizmor: ignore[self-repository] actionlint 1.7.12 does not accept $/...
with:
version: "0.13.7"
enable-cache: false
cache-python: false
cache: "false"
- name: Prepare native dependency provenance
run: just release-dependency-builds
- name: Verify tagged source and freeze native evidence and notes
id: source
env:
Expand All @@ -52,7 +52,7 @@ jobs:
mkdir "$RUNNER_TEMP/handoff"
cp tooling/release-evidence.toml "$RUNNER_TEMP/handoff/evidence.toml"
runtime=(uv run --no-config --no-project --isolated --no-cache --python 3.15
--with 'research-repo-tools @ git+https://github.com/acgetchell/research-repo-tools@cd8594f658b5bf3ade063a685834565cc62e0cb3'
--with 'research-repo-tools==0.2.8'
python -I -c 'import sys; from research_repo_tools.cli import main; sys.exit(main())')
"${runtime[@]}" --root "$GITHUB_WORKSPACE" release check "$RELEASE_TAG"
"${runtime[@]}" --root "$GITHUB_WORKSPACE" release evidence verify \
Expand Down Expand Up @@ -97,7 +97,7 @@ jobs:
# Run Python from the runner's script file, avoiding actionlint #651's stdin deadlock.
shell: >-
uv run --no-config --no-project --isolated --no-cache --python 3.15
--with "research-repo-tools @ git+https://github.com/acgetchell/research-repo-tools@cd8594f658b5bf3ade063a685834565cc62e0cb3"
--with "research-repo-tools==0.2.8"
python -I "{0}"
run: |
import os
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish-crates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jobs:
CANDIDATE_ACCEPTANCE: ${{ inputs.acceptance }}
run: |
set -euo pipefail
just release-dependency-builds
just release-receive "$RUNNER_TEMP/accepted-candidate" --published
just _release-notes-check "$RELEASE_TAG"

Expand Down Expand Up @@ -127,6 +128,7 @@ jobs:
CANDIDATE_ACCEPTANCE: ${{ inputs.acceptance }}
run: |
set -euo pipefail
just release-dependency-builds
just release-receive "$RUNNER_TEMP/accepted-candidate" --published --expected "$RUNNER_TEMP/approved-acceptance/acceptance.json"
just _release-notes-check "$RELEASE_TAG"
uv run --locked --no-sync research-repo-tools release registry "$RELEASE_TAG" --expect absent
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/release-benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
run: |
set -euo pipefail
uvx --python 3.15 \
--from 'research-repo-tools @ git+https://github.com/acgetchell/research-repo-tools@cd8594f658b5bf3ade063a685834565cc62e0cb3' \
--from 'research-repo-tools==0.2.8' \
python -I - <<'PY'
import hashlib, json, os
from pathlib import Path
Expand Down Expand Up @@ -136,7 +136,9 @@ jobs:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.tag }}
CANDIDATE_TRANSFER: ${{ inputs.candidate }}
run: just release-receive "$RUNNER_TEMP/accepted-candidate" --incoming "$RUNNER_TEMP/incoming-candidate"
run: |
just release-dependency-builds
just release-receive "$RUNNER_TEMP/accepted-candidate" --incoming "$RUNNER_TEMP/incoming-candidate"

- name: Upload verified inert archive
id: upload
Expand Down Expand Up @@ -193,7 +195,7 @@ jobs:
run: |
set -euo pipefail
uvx --python 3.15 \
--from 'research-repo-tools @ git+https://github.com/acgetchell/research-repo-tools@cd8594f658b5bf3ade063a685834565cc62e0cb3' \
--from 'research-repo-tools==0.2.8' \
python -I - <<'PY'
import hashlib, json, os
from pathlib import Path
Expand Down
35 changes: 24 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ change files. Run bare `just` for the complete generated command list, including
arguments and descriptions. The [command policy](docs/dev/docs.md#command-discovery-and-placement)
owns recipe naming and documentation placement.

Setup, tool checks, updates, changelog, and opt-in CodeRabbit review use the published `research-repo-tools==0.2.6` package,
Setup, tool checks, updates, changelog, and opt-in CodeRabbit review use the published `research-repo-tools==0.2.8` package,
locked in the `tooling` dependency group and included by `dev`. Its `python-tools`
extra owns the pytest, Ruff and Ty versions.
`toolchain.inherit-python-tools` checks those versions against the lock and
selected executables. Keep repository lint policy local and omit duplicate
version pins for these tools from `dev`.

Normal setup and CI install it from PyPI through `uv sync --locked --group dev`; a sibling
checkout is unnecessary. To upgrade it deliberately, review the exact
`tooling` and project runtime requirements and refresh `uv.lock` together, then run the consumer
integration tests and `just ci`. See the [Tooling guide](tooling/README.md#changelog-and-release-tooling)
for the retained changelog policy and ownership boundary.
checkout is unnecessary. To upgrade it deliberately, use the published target's
adoption command and reconcile isolated pins as described in
[Shared capability adoption](tooling/README.md#shared-capability-adoption), then
run the consumer integration tests and `just ci`.

The shared setup contract requires an existing uv and does not generate bootstrap
installers. `.python-version` selects Python; `rust-toolchain.toml` selects Rust
Expand Down Expand Up @@ -135,8 +135,13 @@ network access, and Gitleaks requires a complete Git checkout. JSON/SARIF report
are retained under `target/security`, with secret findings redacted. These gates
run separately from `just ci`; the hosted RustSec audit remains in place.

CI runs `just ci` on Ubuntu, macOS, and Windows to keep platform coverage
aligned with the local comprehensive validation path.
CI runs the [staged validation graph](#validation-workflow) on Ubuntu, macOS, and
Windows, covering the complete local `just ci` path. The dedicated
`just ci-dependencies` stage prepares authenticated native
dependency builds and verifies installed bytes when tooling is published.
Verified development tooling remains eligible for ordinary checks; release
evidence still requires a published supplier. See the
[source-build adoption contract](tooling/README.md#shared-capability-adoption).

### CodeRabbit review

Expand Down Expand Up @@ -303,15 +308,23 @@ because nextest does not execute them. The test, example, and benchmark buckets
retain their execution or compile-contract roles because ordinary compilation
does not execute Clippy lints.

Native CI retains the same `build (OS)` and `Run CI checks` identities. Ordinary
setup caches only managed Cargo compilation by OS, architecture and exact tool
declarations; exact-version tool installations are freshly verified. GitHub's
Hosted CI prepares each native OS and runs `just ci-policy`, then starts separate
`just ci-rust`, `just ci-python`, `just ci-candidate`, and `just ci-dependencies`
jobs. The two Python jobs partition the complete suite: candidate capture and
acceptance has a dedicated runner, and every other test runs in `ci-python`.
The existing `build (OS)` required-check names are aggregate gates: each requires
every preparation and native job to succeed. Release evidence records the actual
native jobs, their validation steps, and their OS labels.

Preparation populates the managed compilation cache before the native jobs start.
Ordinary setup caches only managed Cargo compilation by OS, architecture and exact
tool declarations; exact-version tool installations are freshly verified. GitHub's
cache ref scopes separate PR entries from protected main. Release packaging and
publication keep caches disabled. The shared local build cache defaults to the
tooling home's `cargo-build/<host>/<Rust version>`; an absolute
`RESEARCH_REPO_TOOLS_CARGO_BUILD_HOME` selects separate compilation storage.
This cache does not replace project builds or validation. See the
[integration record](docs/dev/release-flow-integration.md) for graph ownership,
[integration record](docs/dev/release-flow-integration.md#hosted-ci-stages) for graph ownership,
baseline timings and remaining native/published-package evidence.

`la-stack` intentionally has no notebook validation bucket: the repository has
Expand Down
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading