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
15 changes: 15 additions & 0 deletions .github/settings/actions-selected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"github_owned_allowed": true,
"verified_allowed": false,
"patterns_allowed": [
"github/codeql-action@*",
"actions-rust-lang/setup-rust-toolchain@*",
"astral-sh/setup-uv@*",
"codecov/codecov-action@*",
"zizmorcore/zizmor-action@*",
"taiki-e/cache-cargo-install-action@*",
"swatinem/rust-cache@*",
"dependabot/fetch-metadata@*",
"acgetchell/research-repo-tools/.github/workflows/dependabot-approve.yml@*"
]
}
4 changes: 4 additions & 0 deletions .github/settings/actions-workflow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"default_workflow_permissions": "read",
"can_approve_pull_request_reviews": true
}
78 changes: 78 additions & 0 deletions .github/settings/main-ruleset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"name": "main",
"target": "branch",
"enforcement": "active",
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "always"
}
],
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"~DEFAULT_BRANCH"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
},
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 1,
"dismiss_stale_reviews_on_push": true,
"required_reviewers": [],
"require_code_owner_review": false,
"require_last_push_approval": false,
"required_review_thread_resolution": true,
"require_extra_approval_for_unattributed_changes": true,
"allowed_merge_methods": [
"merge",
"squash",
"rebase"
]
}
},
{
"type": "required_status_checks",
"parameters": {
"strict_required_status_checks_policy": true,
"do_not_enforce_on_create": true,
"required_status_checks": [
{
"context": "build (macos-latest)",
"integration_id": 15368
},
{
"context": "build (ubuntu-latest)",
"integration_id": 15368
},
{
"context": "build (windows-latest)",
"integration_id": 15368
},
{
"context": "Clippy SARIF Analysis",
"integration_id": 15368
},
{
"context": "CodeRabbit",
"integration_id": 347564
},
{
"context": "Repository Rule SARIF Analysis",
"integration_id": 15368
}
]
}
}
]
}
90 changes: 36 additions & 54 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -1,66 +1,48 @@
name: Dependabot review and auto-merge
name: Dependabot approval and auto-merge

on:
pull_request:
# Trusted base-branch policy only; the reusable job never checks out or runs PR code.
on: # zizmor: ignore[dangerous-triggers]
pull_request_target: # nosemgrep: la-stack.github-actions.no-pull-request-target
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
types:
- opened
- reopened
- ready_for_review
- synchronize
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
group: dependabot-auto-merge-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
contents: write
pull-requests: write
permissions: {}

jobs:
review-and-enable-auto-merge:
if: >-
github.event.pull_request.user.login == 'dependabot[bot]' &&
github.repository == 'acgetchell/la-stack'
runs-on: ubuntu-latest
steps:
- name: Request CodeRabbit review
env:
# Dependabot-triggered workflows receive Dependabot secrets.
GH_TOKEN: ${{ secrets.CODERABBIT_REVIEW_TOKEN }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPOSITORY: ${{ github.repository }}
run: |
if [[ -z "$GH_TOKEN" ]]; then
echo "::error::CODERABBIT_REVIEW_TOKEN is not configured."
exit 1
fi

token_owner="$(gh api user --jq '.login')"
if [[ "$token_owner" != "acgetchell" ]]; then
echo "::error::CODERABBIT_REVIEW_TOKEN must belong to acgetchell."
exit 1
fi

marker="<!-- coderabbit-review-request:${PR_HEAD_SHA} -->"
comments="$(
gh api --paginate \
"repos/${REPOSITORY}/issues/${PR_NUMBER}/comments" \
--jq '.[] | select(.user.login == "acgetchell") | .body'
)"
if grep -Fxq -- "$marker" <<< "$comments"; then
echo "CodeRabbit review already requested for ${PR_HEAD_SHA}."
exit 0
fi
body="$(printf '@coderabbitai review\n\n%s' "$marker")"
gh api \
--method POST \
"repos/${REPOSITORY}/issues/${PR_NUMBER}/comments" \
--raw-field body="$body"

- name: Enable auto-merge
env:
GH_TOKEN: ${{ github.token }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: gh pr merge --auto --squash --match-head-commit "$PR_HEAD_SHA" "$PR_URL"
approve-and-enable-auto-merge:
permissions:
contents: write
pull-requests: write
uses: acgetchell/research-repo-tools/.github/workflows/dependabot-approve.yml@cbb2ea6dee8866b3f0547bca935aef48fdd71707 # reviewed 2026-10-01
with:
repository: acgetchell/la-stack
policy: >-
{"cargo": {
"files": ["Cargo.toml", "Cargo.lock", "benches/comparison/Cargo.toml"]
}, "uv": {
"files": ["pyproject.toml", "uv.lock"]
}, "github_actions": {
"files": [
".github/actions/prepare-release-benchmarks/action.yml",
".github/actions/setup-tools/action.yml",
".github/workflows/audit.yml",
".github/workflows/benchmarks.yml",
".github/workflows/ci.yml",
".github/workflows/codecov.yml",
".github/workflows/codeql.yml",
".github/workflows/dependabot-auto-merge.yml",
".github/workflows/release-benchmarks.yml",
".github/workflows/rust-clippy.yml",
".github/workflows/semgrep-sarif.yml",
".github/workflows/zizmor.yml"
]
}}
5 changes: 4 additions & 1 deletion .github/workflows/semgrep-sarif.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ jobs:
--timeout 30 \
--config semgrep.yaml \
--sarif \
--output semgrep-results.sarif \
--output semgrep-raw.sarif \
.
status=$?
set -e
# GitHub ignores SARIF suppression metadata; honor reviewed inline exceptions.
jq '.runs[].results |= map(select(any(.suppressions[]?; .kind == "inSource") | not))' semgrep-raw.sarif > semgrep-results.sarif
echo "exit_code=$status" >> "$GITHUB_OUTPUT"
exit 0

Expand Down
29 changes: 16 additions & 13 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
analyze:
name: GitHub Actions Security Analysis
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
actions: read
contents: read
Expand All @@ -35,24 +36,26 @@ jobs:
- name: Set up declared tools
uses: ./.github/actions/setup-tools # zizmor: ignore[self-repository] actionlint 1.7.12 does not accept $/...

- name: Run declared zizmor with SARIF output
- name: Fail on workflow findings
id: audit
env:
GH_TOKEN: ${{ github.token }}
run: |
scan_status=0
uv run --locked --no-sync --no-python-downloads research-repo-tools \
toolchain run -- zizmor --persona regular --format sarif .github > zizmor-results.sarif || scan_status=$?
if [[ ! -s zizmor-results.sarif ]] || ! jq -e '.version == "2.1.0" and (.runs | type == "array")' zizmor-results.sarif > /dev/null; then
rm -f zizmor-results.sarif
fi
exit "$scan_status"
ZIZMOR_GITHUB_TOKEN: ${{ github.token }}
run: just zizmor --require-online

- name: Produce SARIF even when the finding gate fails
id: sarif
if: ${{ !cancelled() && steps.audit.outcome != 'skipped' }}
env:
ZIZMOR_GITHUB_TOKEN: ${{ github.token }}
run: just zizmor --require-online --format sarif > "$RUNNER_TEMP/zizmor.sarif"

- name: Upload SARIF results
if: >-
always() && hashFiles('zizmor-results.sarif') != '' &&
(github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
!cancelled() && steps.sarif.outcome == 'success' &&
(github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) &&
github.actor != 'dependabot[bot]'
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
sarif_file: zizmor-results.sarif
sarif_file: ${{ runner.temp }}/zizmor.sarif
category: zizmor
wait-for-processing: true
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ Favor the invariant over a convenient edit or faster implementation.
- Read [Documentation guidance](docs/dev/docs.md) for README inclusion in
rustdoc, guide placement, feature-gated doctests, link destinations,
scientific notation, and generated-file rules.
The [command policy](docs/dev/docs.md#command-discovery-and-placement) owns
recipe naming, generated help, and README/contributor command placement.

## Validation

Expand Down
32 changes: 26 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ just ci # run the comprehensive local CI path
```

Use `just fix` when you intentionally want formatters and automatic fixes to
change files. Run `just --list` for the full command surface.
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.1.7` package,
locked in the `tooling` dependency group and included by `dev`. Normal setup
Expand Down Expand Up @@ -76,17 +78,20 @@ an explicit allowlist, and kept with readable version comments for review.

`just zizmor` uses the same pinned scanner and `regular` persona as the SARIF
workflow. It runs online audits using `ZIZMOR_GITHUB_TOKEN`, `GH_TOKEN`,
`GITHUB_TOKEN`, or an authenticated `gh auth token`, in that order, without
or an authenticated `gh auth token`, in that order, without
printing the token. Without authentication it reports an offline fallback;
SHA/version-comment resolution and other online findings are then unchecked.
Use `ZIZMOR_OFFLINE=true just zizmor` to request offline audits explicitly.
Use `just zizmor --offline` for deliberate offline audits, or
`just zizmor --require-online` to require authentication, as hosted CI does.
Zizmor owns remote action SHA/tag resolution; Semgrep guards managed scanner
execution and cache isolation in release workflows. The local authentication
adapter and its tests remain consumer-owned security policy.
adapter and authentication regressions belong to research-repo-tools. Hosted
CI runs a blocking finding check before a separate SARIF export; native SARIF
output alone does not fail on findings.

`just security` runs the shared OSV dependency audit for `uv.lock` and `Cargo.lock`,
then the Gitleaks scan of reachable Git history and current tracked/nonignored
files. Run either gate separately with `just security-osv` or
files. Run either gate separately with `just audit` or
`just security-secrets`. Setup installs both declared managed binaries. OSV needs
network access, and Gitleaks requires a complete Git checkout. JSON/SARIF reports
are retained under `target/security`, with secret findings redacted. These gates
Expand Down Expand Up @@ -127,6 +132,21 @@ live CodeRabbit only on an explicit maintainer request. Consumer integration
tests use local stubs and never contact CodeRabbit. This local workflow is
separate from hosted GitHub review and Dependabot auto-merge.

### Dependabot approvals

Hosted dependency updates use the same pinned research-repo-tools approval
workflow as markov-chain-monte-carlo. Trusted base-branch policy verifies signed
Dependabot commits, complete changed-file allowlists, and the current head
before a deduplicated `github-actions[bot]` approval. Native squash auto-merge
still requires the configured approvals, strict checks (including CodeRabbit's
status), resolved threads, and dismissal of stale approvals.

This replaces owner-authored CodeRabbit requests and their personal token.
CodeRabbit's successful status on a skipped bot review is not an approval.
The [rollout guide](docs/dev/MANAGING_CHANGES.md#dependabot-approval-rollout)
owns GitHub settings and post-merge verification. The workflow never executes
PR code; dependency eligibility remains in `.github/dependabot.yml`.

### Rust Toolchain Policy

The `bench-compile` recipe uses Cargo's `CARGO_BUILD_WARNINGS=deny` policy for
Expand Down Expand Up @@ -213,7 +233,7 @@ For individual edited file formats, use these focused checks and formatters:
| Surface | Commands |
|---------|----------|
| JSON | `jq empty <file>.json` or `just validate-json` |
| TOML | `just toml-lint`, `just toml-fmt-check`; format with `just toml-fmt` |
| TOML | `just toml-lint`, `just toml-fmt-check`; format with `just toml-fix` |
| GitHub Actions | `just action-lint` |
| Shell scripts | `just shell-fix`, then `just shell-check` |
| YAML | `just yaml-fix`, then `just yaml-lint` |
Expand Down
Loading
Loading