Skip to content

ci(rust): add CI environment variables to preserve debug info in release builds #168

@WilliamBerryiii

Description

@WilliamBerryiii

OSSF Silver Criterion

build_preserve_debug (SHOULD) — The project SHOULD provide a way to generate a release build with debugging information.

Description

Add Cargo environment variable overrides to CI builds so release binaries include line-table debug information for post-mortem analysis. The root Cargo.toml has [workspace] members = [] enforcing independent microservice architecture — workspace-level [profile] sections have zero effect on individual crates. Rather than maintaining a custom [profile.release-debug] section in all 10 crate Cargo.toml files, this uses Cargo's env var override mechanism to centralize the concern in CI where it matters.

Local/production builds retain strip = true (IS019) for minimal container images. CI builds override via env vars to produce OSSF-compliant binaries with line tables.

Acceptance Criteria

  • CI builds set CARGO_PROFILE_RELEASE_DEBUG=line-tables-only and CARGO_PROFILE_RELEASE_STRIP=none
  • Release binaries built in CI contain line-table debug information
  • Local builds still produce stripped binaries (default strip = true from IS019)
  • Application-Builder.ps1 documents the env var override mechanism
  • README or build docs note how to build with debug info locally via the same env vars

Implementation Guidance

Add to Application-Builder.ps1 (which already handles per-crate detection and Cargo.lock regeneration) before the cargo build --release invocation:

$env:CARGO_PROFILE_RELEASE_DEBUG = "line-tables-only"
$env:CARGO_PROFILE_RELEASE_STRIP = "none"

Cargo environment variables override Cargo.toml profile settings at build time. This means strip = true in each crate's [profile.release] (standardized by IS019) is overridden to strip = "none" only in CI, preserving line tables in CI-built binaries while keeping local builds stripped.

To verify:

# CI build — should show "not stripped" with DWARF line tables
file target/release/<binary_name>
objdump --dwarf=decodedline target/release/<binary_name> | head

# Local build — should show "stripped"
file target/release/<binary_name>

For local debug builds when needed, developers can set the same env vars:

CARGO_PROFILE_RELEASE_DEBUG=line-tables-only CARGO_PROFILE_RELEASE_STRIP=none cargo build --release

Research: Ecosystem Precedent

GitHub-wide research across 8 major Rust projects confirmed this approach:

  • All projects with custom profiles (rspack, mullvad, deno, servo, roc) use workspace-level profiles — they all have real workspaces with populated members.
  • Azure IoT Edge — the closest architectural match (independent crates, no root workspace) — has zero custom profiles.
  • vector (Datadog) — uses external CI scripts for release optimization rather than custom profiles.
  • linkerd2-proxy — sets debug = 1 directly in [profile.release] rather than maintaining a separate profile.

The env var approach avoids maintaining per-crate custom profiles across 10 independent crates while centralizing OSSF compliance in CI.

References

  • Research: .copilot-tracking/research/2026-02-07-ossf-silver-gaps-detail-research.md — build_preserve_debug

Relationships

  • IS018 tracks this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestrustPull requests that update rust code

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions