Skip to content

ci: add release size audit and native backend checks - #55

Merged
meashgrey merged 3 commits into
feat/chemdraw-sketcherfrom
ci/release-size-20261027
Oct 27, 2026
Merged

meashgrey merged 3 commits into
feat/chemdraw-sketcherfrom
ci/release-size-20261027

Conversation

@meashgrey

@meashgrey meashgrey commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add a release audit tool to measure and report build/release sizes.
  • Update weekly release build workflow and native backend verification.
  • Add a native frame benchmark and adjust Cargo manifests, lockfile, and build configuration.

Scope

Merge 3 commits from ci/release-size-20261027 into feat/chemdraw-sketcher (branch is ahead by 3 commits and behind by 0).

Validation

CI and checks have not been independently executed as part of creating this PR.

Summary by Sourcery

Add release size and performance auditing with native backend verification to the release build pipeline.

New Features:

  • Add a release-audit tool that compares executable size and benchmark performance across release profiles.
  • Add a native offscreen molecule-rendering benchmark for release performance validation.

Enhancements:

  • Configure platform-specific native graphics backends and explicit desktop UI feature forwarding.
  • Enforce release size and runtime performance budgets in the weekly release build, with paired measurements and uploaded reports.
  • Add Linux checks that verify resolved windowing and graphics backend features.

Build:

  • Add a stripped standard release profile and an optimized release-size profile, and update release packaging to use frozen production artifacts.

CI:

  • Run release audits, native backend checks, and optimized scientific and renderer tests in weekly release workflows, including release-audit branches.

Tests:

  • Add unit coverage for release measurement parsing, timing comparisons, paired benchmarks, and fail-closed budget enforcement.

Chores:

  • Update Cargo dependencies, lockfile, manifests, and build configuration for the new audit and backend setup.

@sourcery-ai

sourcery-ai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

This PR adds CI-enforced release size and performance auditing through frozen production binaries, paired native benchmarks, and a new audit tool, while restructuring backend feature selection and validating Linux native dependency graphs across supported windowing variants.

Sequence diagram for the release size and performance audit

sequenceDiagram
    participant CI as Weekly release workflow
    participant Cargo
    participant Audit as chitin-release-audit
    participant Criterion
    participant Artifacts as Frozen executables

    CI->>Cargo: cargo build -p chitin-desktop --release --locked
    CI->>Cargo: just build-desktop-release
    CI->>Artifacts: Freeze production executables
    CI->>Cargo: cargo test -p chitin-release-audit --locked
    CI->>Cargo: cargo test -p chitin-bio -p chitin-molecule-renderer --lib --profile release-size --locked
    CI->>Audit: just benchmark-release-profiles
    Audit->>Cargo: cargo bench --no-run --profile release
    Audit->>Cargo: cargo bench --no-run --profile release-size
    Audit->>Criterion: Run baseline/optimized/optimized/baseline phases
    Criterion-->>Audit: Saved medians and raw samples
    CI->>Audit: cargo run -- --paired
    Audit->>Artifacts: Read executable sizes
    Audit->>Criterion: Read paired medians
    Audit-->>CI: comparison.json and budget result
Loading

Sequence diagram for the native offscreen frame benchmark

sequenceDiagram
    participant Criterion
    participant Benchmark as native_frame
    participant Parser as PdbParser
    participant Adapter as Native wgpu adapter
    participant Renderer as MoleculeRenderer
    participant GPU as Device and queue

    Criterion->>Benchmark: native_structure_parse_512_atoms
    Benchmark->>Parser: parse_bytes
    Parser-->>Benchmark: Parsed structure
    Criterion->>Benchmark: native_molecule_frame_512_atoms
    Benchmark->>Adapter: request_adapter
    Adapter-->>Benchmark: Native adapter
    Benchmark->>GPU: request_device
    Benchmark->>Renderer: MoleculeRenderer::new
    loop Each measured frame
        Benchmark->>Renderer: render
        Renderer->>GPU: Submit render commands
        Benchmark->>GPU: poll
        GPU-->>Benchmark: Completed submission
    end
Loading

Flow diagram for Linux native backend verification

flowchart TD
    Start[Linux host check]
    Variants[Check default, wayland, and x11 variants]
    Tree[cargo tree feature inspection]
    Vulkan{Vulkan enabled only}
    Window{Selected window backend matches variant}
    Wayland{Wayland variant excludes X11 pointer polling}
    Compile[cargo check]
    Pass[Backend verification passes]
    Fail[Fail with dependency or feature diagnostic]

    Start --> Variants
    Variants --> Tree
    Tree --> Vulkan
    Vulkan -->|no| Fail
    Vulkan -->|yes| Window
    Window -->|no| Fail
    Window -->|yes| Wayland
    Wayland -->|invalid| Fail
    Wayland -->|valid or not applicable| Compile
    Compile -->|failure| Fail
    Compile -->|success| Pass
Loading

File-Level Changes

Change Details Files
Adds a release-audit tool and integrates size/performance gating into the weekly release workflow.
  • Builds stripped and optimized desktop profiles, freezes production binaries before benchmark builds, and compares artifact sizes.
  • Runs order-balanced Criterion benchmarks across desktop, UI, biology, and native molecule-rendering workloads.
  • Fails releases unless the optimized executable is smaller and runtime benchmark medians stay within a 5% slowdown budget; uploads JSON and measurement artifacts.
.github/workflows/weekly-release-build.yml
Cargo.toml
justfile
tools/chitin-release-audit/Cargo.toml
tools/chitin-release-audit/src/main.rs
tools/chitin-release-audit/src/measure.rs
Cargo.lock
Introduces a deterministic native offscreen rendering benchmark and expands optimized-profile test coverage.
  • Adds a 512-atom synthetic fixture and measures parsing plus GPU submission/completion at a fixed render size.
  • Uses configurable software adapters for headless CI and treats missing native GPU support as a benchmark failure.
  • Adds Criterion and release-size profile support for renderer benchmarking.
crates/chitin-molecule-renderer/benches/native_frame.rs
crates/chitin-molecule-renderer/Cargo.toml
crates/chitin-molecule-renderer/src/molecule.rs
Makes graphics and window-system backends explicitly feature- and target-selected.
  • Forwards x11 and Wayland features through desktop and UI crates while disabling unintended default features.
  • Selects Vulkan, DX12, Metal, or WebGPU by target, with optional Windows Vulkan support.
  • Adds a Linux script that validates resolved Cargo feature graphs and checks default, Wayland-only, and X11-only builds.
crates/chitin-desktop/Cargo.toml
crates/chitin-ui/Cargo.toml
crates/chitin-wgpu/Cargo.toml
tools/check-native-backends.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@meashgrey
meashgrey merged commit 5f1a240 into feat/chemdraw-sketcher Oct 27, 2026
4 checks passed
@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f8343091-90e1-4c19-bf0b-b26083a0c549

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path=".github/workflows/weekly-release-build.yml" line_range="99" />
<code_context>
+            target/release-frozen/optimized/${{ matrix.desktop_executable }} \
+            | tee target/release-audit/executable-bytes.txt
+
+      - name: Check release audit tests
+        run: cargo test -p chitin-release-audit --locked
+
</code_context>
<issue_to_address>
**Backend regressions pass CI**

When the workflow runs after a native backend feature change, `weekly-release-build.yml` and the regular CI workflow never invoke `tools/check-native-backends.sh`, so its feature-graph assertions and Linux configuration checks do not run; backend regressions pass CI unnoticed and an unexpected or unusable Linux build can ship.

Invoke `tools/check-native-backends.sh` from the weekly release workflow and regular CI.

Also at `.github/workflows/weekly-release-build.yml:102`, `tools/check-native-backends.sh:1`, `tools/check-native-backends.sh:53`.
</issue_to_address>

### Comment 2
<location path="tools/chitin-release-audit/src/measure.rs" line_range="103-105" />
<code_context>
+/// Success only after all four phases of all workloads finish. Their raw samples
+/// and executable paths remain available for independent inspection.
+pub(super) fn run(root: &Path) -> Result<()> {
+  fs::create_dir_all(root)?;
+  ensure!(
+    fs::read_dir(root)?.next().is_none(),
+    "measurement directory must be empty: {}",
+    root.display()
</code_context>
<issue_to_address>
**Concurrent audits mix measurements**

When two `measure` invocations use the same root concurrently, both `measure` processes can observe the same empty root, then run Criterion with identical phase labels and write into the same result directories. Their outputs can interleave or overwrite one another, so the later comparison can pass using mixed measurements.

Acquire an exclusive lock or atomically claim the measurement root before checking or writing it, and fail the second invocation if the claim already exists.
</issue_to_address>

### Comment 3
<location path="tools/chitin-release-audit/src/main.rs" line_range="224-225" />
<code_context>
+  let timings = compare_timings(&read(Path::new(root), baseline)?, &read(Path::new(root), candidate)?)?;
+  // A partially executed benchmark script must not produce a passing release.
+  for required in ["native_structure_parse_512_atoms", "native_molecule_frame_512_atoms"] {
+    ensure!(
+      timings.iter().any(|timing| timing.benchmark == required),
+      "missing benchmark {required}"
+    );
+  }
+  for prefix in [
+    "sequence_columns/visible_columns_after/",
+    "sequence_box_hit/row_interval_after/",
+    "sequence_wrapped_row_lookup_",
+    "kit_tree_",
+    "molecular_surface",
+  ] {
+    ensure!(
+      timings.iter().any(|timing| timing.benchmark.starts_with(prefix)),
+      "missing benchmark family {prefix}"
+    );
</code_context>
<issue_to_address>
**Missing benchmark cases pass the audit**

When an individual benchmark case is removed or omitted from both profile runs while another case in its family remains, the prefix check accepts any single result in a benchmark family, while `compare_timings` only requires both profiles to have matching sets. Removing or disabling a case such as the 100,000-residue workload from both profiles therefore leaves that workload ungated while the audit can pass.

Validate the full expected benchmark-name set, including every scale and variant, rather than only requiring one result per prefix.
</issue_to_address>

Sourcery assessment

Approval pending. 3 findings to address first.

Blocking findings: .github/workflows/weekly-release-build.yml:99, tools/chitin-release-audit/src/measure.rs:105, tools/chitin-release-audit/src/main.rs:225


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

target/release-frozen/optimized/${{ matrix.desktop_executable }} \
| tee target/release-audit/executable-bytes.txt

- name: Check release audit tests

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Backend regressions pass CI

When the workflow runs after a native backend feature change, weekly-release-build.yml and the regular CI workflow never invoke tools/check-native-backends.sh, so its feature-graph assertions and Linux configuration checks do not run; backend regressions pass CI unnoticed and an unexpected or unusable Linux build can ship.

Invoke tools/check-native-backends.sh from the weekly release workflow and regular CI.

Also at .github/workflows/weekly-release-build.yml:102, tools/check-native-backends.sh:1, tools/check-native-backends.sh:53.

Prompt for AI agents
In `.github/workflows/weekly-release-build.yml` at line 99:

**Backend regressions pass CI**

When the workflow runs after a native backend feature change, `weekly-release-build.yml` and the regular CI workflow never invoke `tools/check-native-backends.sh`, so its feature-graph assertions and Linux configuration checks do not run; backend regressions pass CI unnoticed and an unexpected or unusable Linux build can ship.

Invoke `tools/check-native-backends.sh` from the weekly release workflow and regular CI.

Also at `.github/workflows/weekly-release-build.yml:102`, `tools/check-native-backends.sh:1`, `tools/check-native-backends.sh:53`.

Comment on lines +103 to +105
fs::create_dir_all(root)?;
ensure!(
fs::read_dir(root)?.next().is_none(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Concurrent audits mix measurements

When two measure invocations use the same root concurrently, both measure processes can observe the same empty root, then run Criterion with identical phase labels and write into the same result directories. Their outputs can interleave or overwrite one another, so the later comparison can pass using mixed measurements.

Acquire an exclusive lock or atomically claim the measurement root before checking or writing it, and fail the second invocation if the claim already exists.

Prompt for AI agents
In `tools/chitin-release-audit/src/measure.rs` at lines 103-105:

**Concurrent audits mix measurements**

When two `measure` invocations use the same root concurrently, both `measure` processes can observe the same empty root, then run Criterion with identical phase labels and write into the same result directories. Their outputs can interleave or overwrite one another, so the later comparison can pass using mixed measurements.

Acquire an exclusive lock or atomically claim the measurement root before checking or writing it, and fail the second invocation if the claim already exists.

Comment on lines +224 to +225
ensure!(
timings.iter().any(|timing| timing.benchmark.starts_with(prefix)),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Missing benchmark cases pass the audit

When an individual benchmark case is removed or omitted from both profile runs while another case in its family remains, the prefix check accepts any single result in a benchmark family, while compare_timings only requires both profiles to have matching sets. Removing or disabling a case such as the 100,000-residue workload from both profiles therefore leaves that workload ungated while the audit can pass.

Validate the full expected benchmark-name set, including every scale and variant, rather than only requiring one result per prefix.

Prompt for AI agents
In `tools/chitin-release-audit/src/main.rs` at lines 224-225:

**Missing benchmark cases pass the audit**

When an individual benchmark case is removed or omitted from both profile runs while another case in its family remains, the prefix check accepts any single result in a benchmark family, while `compare_timings` only requires both profiles to have matching sets. Removing or disabling a case such as the 100,000-residue workload from both profiles therefore leaves that workload ungated while the audit can pass.

Validate the full expected benchmark-name set, including every scale and variant, rather than only requiring one result per prefix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant