Skip to content

Add trustify-cli as a subfolder with preserved history#2237

Merged
bxf12315 merged 12 commits into
guacsec:mainfrom
bxf12315:add-trustify-cli-subtree-one
Mar 3, 2026
Merged

Add trustify-cli as a subfolder with preserved history#2237
bxf12315 merged 12 commits into
guacsec:mainfrom
bxf12315:add-trustify-cli-subtree-one

Conversation

@bxf12315

@bxf12315 bxf12315 commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Add a new Trustify CLI workspace member that provides authenticated SBOM management and duplicate cleanup capabilities.

New Features:

  • Introduce a standalone trustify-cli binary crate under etc/trustify-cli for interacting with the Trustify API.
  • Support OAuth2-based authentication with automatic token retrieval and refresh via the CLI.
  • Provide SBOM management commands to get, list, and delete SBOMs with multiple output formats.
  • Add CLI workflows to detect duplicate SBOMs, export them to JSON, and delete duplicates with optional dry-run and concurrency controls.

Enhancements:

  • Extend the Cargo workspace to include the new CLI crate and share common workspace dependencies, including dotenv-based configuration loading.

Documentation:

  • Add a dedicated README for the Trustify CLI describing setup, configuration, and usage of authentication, SBOM, and duplicate-management commands.

@sourcery-ai

sourcery-ai Bot commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a new etc/trustify-cli workspace crate that implements a containerized CLI for Trustify with OAuth2-based auth, a reusable API client (with retries and token refresh), and SBOM management commands including listing, fetching, deletion, and duplicate detection/cleanup workflows, while wiring it into the Cargo workspace and documenting its usage.

Sequence diagram for sbom duplicates find workflow

sequenceDiagram
    actor User
    participant TrustifyCli as trustify_binary
    participant Commands
    participant SbomCommands
    participant DuplicatesCommands
    participant SbomApi as sbom_api
    participant ApiClient
    participant TrustifyApi as Trustify_API

    User->>TrustifyCli: invoke "trustify sbom duplicates find"
    TrustifyCli->>Commands: parse CLI and dispatch
    Commands->>SbomCommands: run(ctx)
    SbomCommands->>DuplicatesCommands: run(ctx)
    DuplicatesCommands->>SbomApi: find_duplicates(client, params, output_file)

    SbomApi->>ApiClient: list(SBOM_PATH, ListParams{limit=1,offset=0})
    ApiClient->>TrustifyApi: HTTP GET /api/v2/sbom?limit=1&offset=0
    TrustifyApi-->>ApiClient: 200 OK {total,items}
    ApiClient-->>SbomApi: JSON body

    loop for each worker page
        SbomApi->>ApiClient: get_with_query(SBOM_PATH, ListParams{limit=batch_size,offset})
        ApiClient->>TrustifyApi: HTTP GET /api/v2/sbom?limit=batch_size&offset=offset
        TrustifyApi-->>ApiClient: 200 OK page of SBOMs
        ApiClient-->>SbomApi: JSON page
        SbomApi->>SbomApi: collect SbomEntry and group by document_id
    end

    SbomApi->>SbomApi: build DuplicateGroup list
    SbomApi->>SbomApi: write duplicate_groups to output JSON file
    SbomApi-->>DuplicatesCommands: Vec<DuplicateGroup>
    DuplicatesCommands-->>SbomCommands: result summary
    SbomCommands-->>Commands: print count and output path
    Commands-->>TrustifyCli: ExitCode::SUCCESS
    TrustifyCli-->>User: summary message
Loading

Sequence diagram for API client retry and token refresh

sequenceDiagram
    actor User
    participant TrustifyCli as trustify_binary
    participant ApiClient
    participant TrustifyApi as Trustify_API
    participant SsoServer as SSO

    User->>TrustifyCli: run command requiring API call
    TrustifyCli->>ApiClient: get(path)
    ApiClient->>ApiClient: execute_with_retry(f)

    loop first attempt
        ApiClient->>TrustifyApi: HTTP GET /api/v2/sbom
        TrustifyApi-->>ApiClient: 401 Unauthorized
        ApiClient->>ApiClient: handle_response -> TokenExpired
    end

    ApiClient->>ApiClient: refresh_token()
    ApiClient->>SsoServer: POST /protocol/openid-connect/token
    SsoServer-->>ApiClient: 200 OK {access_token}
    ApiClient->>ApiClient: store new token

    ApiClient->>TrustifyApi: HTTP GET /api/v2/sbom (with new token)
    TrustifyApi-->>ApiClient: 200 OK
    ApiClient-->>TrustifyCli: JSON body
    TrustifyCli-->>User: command output
Loading

Class diagram for new trustify-cli core types

classDiagram
    class Cli {
        +Config config
        +Commands command
    }

    class Config {
        +String url
        +Option~String~ sso_url
        +Option~String~ client_id
        +Option~String~ client_secret
        +bool has_auth()
        +Option~(str,str,str)~ auth_credentials()
    }

    class Context {
        +Config config
        +ApiClient client
    }

    class Commands {
        <<enum>>
        Sbom
        Auth
        +run(ctx: Context) Result~ExitCode~
    }

    class SbomCommands {
        <<enum>>
        Get
        List
        Delete
        Duplicates
        +run(ctx: Context) Result~ExitCode~
    }

    class DuplicatesCommands {
        <<enum>>
        Find
        Delete
        +run(ctx: Context) Result~ExitCode~
    }

    class AuthCommands {
        <<enum>>
        Token
        +run(ctx: Context) Result~ExitCode~
    }

    class ApiClient {
        -Client client
        -String base_url
        -Arc~RwLock~Option~String~~ token
        -Option~AuthCredentials~ auth_credentials
        +new(base_url: str, token: Option~String~, auth_credentials: Option~AuthCredentials~) ApiClient
        +url(path: str) String
        +get(path: str) Result~String,ApiError~
        +get_with_query(path: str, query: T) Result~String,ApiError~
        +delete(path: str) Result~String,ApiError~
        +authorize(request: RequestBuilder) RequestBuilder
        +refresh_token() Result~(),ApiError~
        +execute_with_retry(f: F) Result~String,ApiError~
        +handle_response(response: Response) Result~String,ApiError~
    }

    class ApiError {
        <<enum>>
        NetworkError
        HttpError
        NotFound
        Unauthorized
        TokenExpired
        Timeout
        ServerError
        InternalError
        TemplateError
    }

    class AuthCredentials {
        +String token_url
        +String client_id
        +String client_secret
        +new(sso_url: str, client_id: str, client_secret: str) AuthCredentials
        +get_token() Result~String,AuthError~
    }

    class AuthError {
        <<enum>>
        ConnectionError
        AuthenticationFailed
        ServerError
    }

    class ListParams {
        +Option~String~ q
        +Option~u32~ limit
        +Option~u32~ offset
        +Option~String~ sort
    }

    class FindDuplicatesParams {
        +u32 batch_size
        +usize concurrency
    }

    class DuplicateGroup {
        +String document_id
        +Option~String~ published
        +String id
        +Vec~String~ duplicates
    }

    class DeleteResult {
        +u32 deleted
        +u32 skipped
        +u32 failed
        +u32 total
    }

    class DeleteEntry {
        +String id
        +String document_id
    }

    class ListFormat {
        <<enum>>
        Id
        Name
        Short
        Full
    }

    Cli --> Config
    Cli --> Commands
    Context --> Config
    Context --> ApiClient

    Commands --> SbomCommands
    Commands --> AuthCommands

    SbomCommands --> DuplicatesCommands
    SbomCommands --> ListFormat

    ApiClient --> ApiError
    ApiClient --> AuthCredentials

    AuthCredentials --> AuthError

    ListParams ..> ApiClient
    FindDuplicatesParams ..> ApiClient
    DuplicateGroup ..> FindDuplicatesParams

    DeleteResult ..> DeleteEntry
    DeleteEntry ..> DuplicateGroup
Loading

File-Level Changes

Change Details Files
Add trustify-cli as a new workspace member with its own binary, configuration, and CLI wiring.
  • Register etc/trustify-cli as a workspace member in the root Cargo.toml and add dotenvy as a shared workspace dependency.
  • Define the trustify-cli package (bin target trustify) with dependencies on clap, tokio, reqwest, indicatif, dotenvy, serde, and others.
  • Introduce a top-level Context struct and main entrypoint that loads .env, parses CLI args, initializes OAuth2 credentials and an ApiClient, then dispatches to subcommands.
Cargo.toml
etc/trustify-cli/Cargo.toml
etc/trustify-cli/src/main.rs
etc/trustify-cli/src/cli.rs
etc/trustify-cli/src/config.rs
Implement a reusable API layer with OAuth2 client-credentials auth, token refresh, retry logic, and SBOM-specific operations.
  • Add auth module that builds a Keycloak-style token endpoint from an SSO URL and performs client-credentials token retrieval with structured error reporting.
  • Add ApiClient wrapper over reqwest that normalizes base URLs, injects bearer tokens, auto-refreshes tokens on 401 using stored AuthCredentials, and retries transient errors with backoff.
  • Implement SBOM API helpers to get, list, and delete SBOMs; fetch all SBOMs concurrently in batches; compute duplicate groups by document_id; and drive concurrent deletion with progress bars and dry-run support.
etc/trustify-cli/src/api/mod.rs
etc/trustify-cli/src/api/auth.rs
etc/trustify-cli/src/api/client.rs
etc/trustify-cli/src/api/sbom.rs
Expose user-facing CLI commands for auth and SBOM management, including duplicate detection and cleanup, with multiple output formats.
  • Define global CLI surface (trustify) with shared connection/auth configuration and subcommands grouped under sbom and auth.
  • Add auth token command that prints an access token using configured SSO/client credentials, with validation of required inputs.
  • Add sbom subcommands: get, list (id/name/short/full formats), delete (by id or query with concurrency and dry-run), and nested duplicates find/delete commands that read/write JSON files, support interactive overwrite handling, and report summary stats.
etc/trustify-cli/src/commands/mod.rs
etc/trustify-cli/src/commands/auth.rs
etc/trustify-cli/src/commands/sbom.rs
Document the Trustify CLI usage and add licensing and ignore/auxiliary file changes.
  • Add a dedicated README for the CLI with configuration guidance, example workflows, and detailed command usage.
  • Add a LICENSE file for the trustify-cli crate and adjust repo-level ignore/docker-related files as part of integrating the new tool.
  • Fix minor whitespace-only changes in the top-level README and Cargo.toml without functional impact.
etc/trustify-cli/README.md
etc/trustify-cli/LICENSE
README.md
Cargo.toml
.gitignore

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

@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch from e0e8819 to d0a3feb Compare February 6, 2026 12:42
@codecov

codecov Bot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 759 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.30%. Comparing base (ccf67ed) to head (57524c5).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
etc/trustify-cli/src/api/sbom.rs 0.00% 334 Missing ⚠️
etc/trustify-cli/src/commands/sbom.rs 0.00% 203 Missing ⚠️
etc/trustify-cli/src/api/client.rs 0.00% 129 Missing ⚠️
etc/trustify-cli/src/api/auth.rs 0.00% 52 Missing ⚠️
etc/trustify-cli/src/main.rs 0.00% 16 Missing ⚠️
etc/trustify-cli/src/commands/auth.rs 0.00% 11 Missing ⚠️
etc/trustify-cli/src/config.rs 0.00% 9 Missing ⚠️
etc/trustify-cli/src/commands/mod.rs 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2237      +/-   ##
==========================================
- Coverage   70.44%   68.30%   -2.15%     
==========================================
  Files         414      422       +8     
  Lines       23917    24676     +759     
  Branches    23917    24676     +759     
==========================================
+ Hits        16849    16854       +5     
- Misses       6152     6900     +748     
- Partials      916      922       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bxf12315

bxf12315 commented Feb 6, 2026

Copy link
Copy Markdown
Contributor Author

After rebasing, I encountered a large number of conflicts, so I created a new PR. Is that reasonable? @ruromero @dejanb

@dejanb

dejanb commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

I don't see particular need for this, but if it's OK with @ruromero (as original PR author), I'm OK with it.

I'll take a deeper look into it on Monday. One thing that stands out at the moment is the test coverage. Is there anything we can do to improve that?

@ruromero

ruromero commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

fine by me

Comment thread etc/trustify-cli/src/api/test.rs Outdated
@bxf12315 bxf12315 requested review from dejanb and ruromero February 9, 2026 07:36

@dejanb dejanb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we're close to finish this phase. Just a few comments.

Comment thread Cargo.lock
Comment thread etc/trustify-cli/README.md Outdated
@bxf12315 bxf12315 changed the title Add trustify cli subtree one Add trustify-cli as a subfolder with preserved history Feb 9, 2026
@bxf12315 bxf12315 closed this Feb 10, 2026
@github-project-automation github-project-automation Bot moved this to Done in Trustify Feb 10, 2026
@bxf12315 bxf12315 reopened this Feb 10, 2026
@bxf12315

Copy link
Copy Markdown
Contributor Author

I think we're close to finish this phase. Just a few comments.

Done

@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch from 9769c27 to cc611f2 Compare February 10, 2026 06:36
@bxf12315 bxf12315 marked this pull request as ready for review February 10, 2026 06:41

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 4 issues, and left some high level feedback:

  • In sbom::delete_by_query you only act on the first page of results (whatever fits in the limit), so large result sets will leave many matching SBOMs undeleted; consider iterating pages until all matching items are processed or making that limitation explicit in the interface.
  • The trustify-cli crate is set to edition = "2024", which is not yet stable and may not match the rest of the workspace; aligning the edition with the workspace (e.g. 2021) will avoid toolchain and build issues.
  • Both find_duplicates and delete_list load all SBOM metadata or delete entries into memory (Vec<SbomEntry> / Vec<DeleteEntry>); if this CLI is used against very large datasets you may want to switch to a streaming/chunked approach to avoid excessive memory usage.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `sbom::delete_by_query` you only act on the first page of results (whatever fits in the `limit`), so large result sets will leave many matching SBOMs undeleted; consider iterating pages until all matching items are processed or making that limitation explicit in the interface.
- The `trustify-cli` crate is set to `edition = "2024"`, which is not yet stable and may not match the rest of the workspace; aligning the edition with the workspace (e.g. 2021) will avoid toolchain and build issues.
- Both `find_duplicates` and `delete_list` load all SBOM metadata or delete entries into memory (`Vec<SbomEntry>` / `Vec<DeleteEntry>`); if this CLI is used against very large datasets you may want to switch to a streaming/chunked approach to avoid excessive memory usage.

## Individual Comments

### Comment 1
<location> `etc/trustify-cli/src/api/client.rs:21-22` </location>
<code_context>
+    #[error("HTTP {0}: {1}")]
+    HttpError(u16, String),
+
+    #[error("HTTP 404: Resource not found")]
+    NotFound(String),
+
+    #[error("HTTP 401: Please check your authentication credentials")]
</code_context>

<issue_to_address>
**suggestion:** The `NotFound` variant carries a `String` that is never surfaced in the error message.

`NotFound` is defined as `NotFound(String)` but always constructed with the same string and the error is hard-coded as `"HTTP 404: Resource not found"`, so the inner `String` is effectively unused. Consider removing the payload (i.e. `NotFound`) or incorporating it into the `#[error]` format string so any extra context is surfaced.

```suggestion
    #[error("HTTP 404: Resource not found: {0}")]
    NotFound(String),
```
</issue_to_address>

### Comment 2
<location> `etc/trustify-cli/src/api/client.rs:30-31` </location>
<code_context>
+    #[error("HTTP 401: Token expired")]
+    TokenExpired,
+
+    #[error("HTTP {0}: Server timeout")]
+    Timeout(u16),
+
+    #[error("HTTP {0}: {1}")]
</code_context>

<issue_to_address>
**issue:** Using code `0` for network-level timeouts leads to confusing error messages like `HTTP 0: Server timeout`.

In `impl From<reqwest::Error> for ApiError`, network timeouts (no HTTP response) are converted to `ApiError::Timeout(0)`, which then renders as `"HTTP 0: Server timeout"`. This conflates network and server timeouts and can mislead users. Either introduce a separate variant for network timeouts (e.g. `NetworkTimeout`) or special-case `0` in the display implementation to show a more accurate message like `"Network timeout"`.
</issue_to_address>

### Comment 3
<location> `etc/trustify-cli/src/commands/sbom.rs:138-127` </location>
<code_context>
+                format_list_output(&json, format)?;
+                Ok(ExitCode::SUCCESS)
+            }
+            SbomCommands::Delete {
+                id,
+                query,
+                dry_run,
+                concurrency,
+                limit,
+            } => {
+                if let Some(i) = id {
+                    sbom_api::delete(&ctx.client, i).await?;
</code_context>

<issue_to_address>
**issue:** Delete command silently succeeds when neither `id` nor `query` is provided.

When both `id` and `query` are `None`, this branch is a no-op but still returns `ExitCode::SUCCESS`, which can mislead users (e.g., on a mistyped or missing flag). Please add a check that requires at least one of `id` or `query` and return an error or clear message if both are absent.
</issue_to_address>

### Comment 4
<location> `etc/trustify-cli/src/commands/sbom.rs:283-292` </location>
<code_context>
+            }
+            Ok(ExitCode::SUCCESS)
+        }
+        ListFormat::Name => {
+            let result: Vec<Value> = items
+                .iter()
+                .map(|item| {
+                    serde_json::json!({
+                        "id": item.get("id"),
+                        "name": item.get("name"),
+                        "document_id": item.get("document_id")
+                    })
+                })
+                .collect();
+            println!("{}", serde_json::to_string(&result).unwrap_or_default());
+            Ok(ExitCode::SUCCESS)
+        }
</code_context>

<issue_to_address>
**issue (bug_risk):** JSON serialization failures in list formatting are silently swallowed.

Using `serde_json::to_string(&result).unwrap_or_default()` in both branches hides serialization errors by printing an empty string with no diagnostics. Please handle the `Result` explicitly (e.g., log the error and return a non-success `ExitCode`, or fall back to printing the raw `json` input) so failures are visible instead of silently ignored.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread etc/trustify-cli/src/api/client.rs Outdated
Comment thread etc/trustify-cli/src/api/client.rs
Comment thread etc/trustify-cli/src/commands/sbom.rs
Comment thread etc/trustify-cli/src/commands/sbom.rs

@dejanb dejanb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me. Thanks @bxf12315

@ruromero Can you give it one more look as well

Note: it would be great to use conventional commits as for the rest of the project (https://www.conventionalcommits.org/en/v1.0.0/) and be a bit more descriptive, but I don't want to hold this on that

@ruromero ruromero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great improvements. Thanks @bxf12315

@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch 2 times, most recently from cd6b4ea to e3a8a50 Compare February 10, 2026 14:52
@bxf12315

Copy link
Copy Markdown
Contributor Author

Looks good to me. Thanks @bxf12315

@ruromero Can you give it one more look as well

Note: it would be great to use conventional commits as for the rest of the project (https://www.conventionalcommits.org/en/v1.0.0/) and be a bit more descriptive, but I don't want to hold this on that

Done

@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch 3 times, most recently from f8421af to a776548 Compare February 27, 2026 00:26
Comment thread Cargo.toml Outdated
@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch 2 times, most recently from 5163375 to d7ab7dc Compare March 2, 2026 05:30
Comment thread .dockerignore
@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch from d7ab7dc to a468e9c Compare March 2, 2026 14:54
@dejanb

dejanb commented Mar 2, 2026

Copy link
Copy Markdown
Contributor

I think it looks good now @bxf12315 . Can you rebase it and add it to the merge queue?

ruromero and others added 11 commits March 3, 2026 07:21
Signed-off-by: Ruben Romero Montes <rromerom@redhat.com>
Assisted by: Cursor
Signed-off-by: Ruben Romero Montes <rromerom@redhat.com>
Assisted-by: Cursor
Signed-off-by: Ruben Romero Montes <rromerom@redhat.com>
Assisted-by: Cursor
Signed-off-by: Ruben Romero Montes <rromerom@redhat.com>
Assisted-by: Cursor
… format the code, and replace unwrap to make clippy happy.
@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch 2 times, most recently from f62b6bf to f287610 Compare March 3, 2026 02:40
@bxf12315 bxf12315 force-pushed the add-trustify-cli-subtree-one branch from f287610 to 57524c5 Compare March 3, 2026 02:51
@bxf12315 bxf12315 enabled auto-merge March 3, 2026 03:42
@bxf12315

bxf12315 commented Mar 3, 2026

Copy link
Copy Markdown
Contributor Author

I think it looks good now @bxf12315 . Can you rebase it and add it to the merge queue?

ok

@bxf12315 bxf12315 requested a review from dejanb March 3, 2026 05:33

@dejanb dejanb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@bxf12315 bxf12315 added this pull request to the merge queue Mar 3, 2026
Merged via the queue into guacsec:main with commit 7c72b6b Mar 3, 2026
5 of 7 checks passed
@bxf12315 bxf12315 deleted the add-trustify-cli-subtree-one branch March 3, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants