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
29 changes: 29 additions & 0 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Stylus Performance Check

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]

jobs:
performance-regression:
name: Gas Regression Check
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Prepare Dummy Profiles
run: |
mkdir -p artifacts/capture
cp tests/fixtures/baseline.json artifacts/capture/baseline.json
cp tests/fixtures/baseline.json artifacts/capture/current_profile.json

- name: Run Stylus Performance Check
uses: ./
with:
tx_hash: "0xaaf333656d069068844d17f175fa5b73534c0b71599100bee2153791c3e81edc"
rpc_url: "https://sepolia-rollup.arbitrum.io/rpc"
threshold: "10"
skip_capture: "true"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ target
.DS_Store
*.svg
*.json
!tests/fixtures/*.json
profiles/
flamegraphs.svg
profile.json
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Before you begin, ensure you have:
# Fork the repository on GitHub
# Clone your fork
git clone https://github.com/Timi16/stylus-trace.git
cd stylus-trace-studio
cd Stylus-Trace

# Add upstream remote
git remote add upstream https://github.com/Timi16/stylus-trace.git
Expand Down
24 changes: 12 additions & 12 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[workspace]
resolver = "2"
members = [
"bin/stylus-trace",
"crates/stylus-trace-studio",
"bin/stylus-trace-studio",
"crates/stylus-trace-core",
]

[workspace.package]
Expand All @@ -15,7 +15,7 @@ repository = "https://github.com/CreativesOnchain/Stylus-Trace"
homepage = "https://github.com/CreativesOnchain/Stylus-Trace"

[workspace.dependencies]
stylus-trace-studio = { version = "0.1.6", path = "crates/stylus-trace-studio" }
stylus-trace-core = { version = "0.1.6", path = "crates/stylus-trace-core" }
clap = { version = "4.5", features = ["derive", "env"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,37 @@ This feature will be enabled automatically once upstream tracer support is avail
| `--output` | Path to write the diff report JSON | `artifacts/diff/diff_report.json` |
| `--flamegraph` | Path to write visual diff flamegraph SVG | `artifacts/diff/diff.svg` |

### `ci init`
| Flag | Description | Default |
|------|-------------|---------|
| `--tx` | **(Required)** Transaction hash to profile in CI | - |
| `--rpc` | RPC endpoint URL | `http://localhost:8547` |
| `--threshold` | Percentage threshold for regressions | `1.0` |
| `--force` | Overwrite existing workflow files | `false` |

---

## 🤖 CI/CD Integration

Stylus Trace is built for automated performance tracking. You can integrate it into your project to **strictly block merges** that cause gas regressions.

### Quick Setup (Zero Config)
Run this in your repository to auto-generate a GitHub Actions workflow:
```bash
stylus-trace ci init --tx 0x...
```

### Manual Integration
You can use the [Stylus Trace Action](https://github.com/CreativesOnchain/Stylus-Trace) directly in your workflows:

```yaml
- name: Gas Regression Check
uses: CreativesOnchain/Stylus-Trace@main
with:
tx_hash: "0x..."
threshold: "1.0" # Fail if gas increases by > 1%
```

---

## 🤝 Contributing
Expand Down
78 changes: 78 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: 'Stylus Performance Regression Check'
description: 'Automated performance regression detection for Arbitrum Stylus transactions'
author: 'Creatives Onchain'

inputs:
rpc_url:
description: 'Arbitrum Nitro RPC endpoint'
required: false
default: 'http://localhost:8547'
tx_hash:
description: 'Transaction hash to profile'
required: true
baseline:
description: 'Path to baseline profile JSON'
required: false
default: 'artifacts/capture/baseline.json'
threshold:
description: 'Percentage threshold for allowed increase (e.g. 1.0 for 1%)'
required: false
default: '1.0'
ink:
description: 'Use Stylus Ink units instead of Gas'
required: false
default: 'false'
skip_capture:
description: 'Skip the capture step (useful for testing with pre-existing profiles)'
required: false
default: 'false'

runs:
using: "composite"
steps:
- name: Setup Tool
shell: bash
run: |
if [ -f "bin/stylus-trace-studio/Cargo.toml" ]; then
echo "Local Stylus-Trace detected. Building from source..."
cargo build --release --bin stylus-trace
echo "$(pwd)/target/release" >> $GITHUB_PATH
elif ! command -v stylus-trace &> /dev/null; then
echo "Installing stylus-trace-studio..."
cargo install stylus-trace-studio
else
echo "stylus-trace already installed."
fi

- name: Capture Current Profile
shell: bash
run: |
if [ "${{ inputs.skip_capture }}" = "true" ]; then
echo "Skipping capture as requested. Ensuring profile exists..."
mkdir -p artifacts/capture
if [ ! -f "artifacts/capture/current_profile.json" ]; then
echo "Error: current_profile.json not found but skip_capture is true"
exit 1
fi
exit 0
fi

INK_FLAG=""
if [ "${{ inputs.ink }}" = "true" ]; then
INK_FLAG="--ink"
fi

stylus-trace capture \
--rpc "${{ inputs.rpc_url }}" \
--tx "${{ inputs.tx_hash }}" \
--output current_profile.json \
$INK_FLAG

- name: Compare with Baseline
shell: bash
run: |
stylus-trace diff \
"${{ inputs.baseline }}" \
artifacts/capture/current_profile.json \
--threshold-percent "${{ inputs.threshold }}" \
--summary
19 changes: 19 additions & 0 deletions bin/stylus-trace-studio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "stylus-trace-studio"
version = { workspace = true }
authors = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
description = { workspace = true }

[[bin]]
name = "stylus-trace"
path = "src/main.rs"

[dependencies]
stylus-trace-core = { workspace = true }
clap.workspace = true
anyhow.workspace = true
env_logger.workspace = true
log.workspace = true
serde_json.workspace = true
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use clap::{Args, Parser, Subcommand};
use env_logger::Env;
use std::path::PathBuf;

use stylus_trace_studio::commands::{
use stylus_trace_core::commands::{
display_schema, display_version, execute_capture, validate_args, validate_profile_file,
CaptureArgs,
};
use stylus_trace_studio::flamegraph::FlamegraphConfig;
use stylus_trace_core::flamegraph::FlamegraphConfig;

/// Stylus Trace Studio - Performance profiling for Arbitrum Stylus
#[derive(Parser, Debug)]
Expand Down Expand Up @@ -100,6 +100,12 @@ pub enum Commands {
file: PathBuf,
},

/// CI configuration and management
Ci {
#[command(subcommand)]
subcommand: CiSubcommands,
},

/// Display schema information
Schema {
/// Show full schema details
Expand Down Expand Up @@ -158,13 +164,58 @@ fn main() -> Result<()> {
Commands::Validate { file } => {
validate_profile_file(file).context("Failed to validate profile")?
}
Commands::Ci { subcommand } => handle_ci(subcommand)?,
Commands::Schema { show } => display_schema(show),
Commands::Version => display_version(),
}

Ok(())
}

#[derive(Subcommand, Debug)]
pub enum CiSubcommands {
/// Initialize CI/CD performance regression checks
Init {
/// Transaction hash to profile in CI
#[arg(short, long)]
tx: String,

/// RPC endpoint URL
#[arg(short, long, default_value = "http://localhost:8547")]
rpc: Option<String>,

/// Percentage threshold for regressions (e.g., 1.0)
#[arg(short = 'p', long, default_value = "1.0")]
threshold: f64,

/// Force overwrite existing workflow files
#[arg(long)]
force: bool,
},
}

/// Handle CI command logic
fn handle_ci(subcommand: CiSubcommands) -> Result<()> {
match subcommand {
CiSubcommands::Init {
tx,
rpc,
threshold,
force,
} => {
let args = stylus_trace_core::commands::models::CiInitArgs {
transaction_hash: tx,
rpc_url: rpc,
threshold,
force,
};
stylus_trace_core::commands::execute_ci_init(args)
.context("CI initialization failed")?;
}
}
Ok(())
}

/// Setup logging based on verbosity level
fn setup_logging(verbose: bool) {
let log_level = if verbose { "debug" } else { "info" };
Expand Down Expand Up @@ -235,7 +286,7 @@ fn handle_capture(command: Commands) -> Result<()> {

/// Handle the diff command logic
fn handle_diff(args: &DiffSubArgs) -> Result<()> {
let studio_args = stylus_trace_studio::commands::models::DiffArgs {
let studio_args = stylus_trace_core::commands::models::DiffArgs {
baseline: resolve_artifact_path(args.baseline.clone(), "capture"),
target: resolve_artifact_path(args.target.clone(), "capture"),
threshold_file: args.threshold.clone(),
Expand All @@ -253,7 +304,7 @@ fn handle_diff(args: &DiffSubArgs) -> Result<()> {
hostio_threshold: args.hostio_threshold,
};

stylus_trace_studio::commands::diff::execute_diff(studio_args)
stylus_trace_core::commands::diff::execute_diff(studio_args)
.context("Diff execution failed")?;
Ok(())
}
Expand Down
15 changes: 0 additions & 15 deletions bin/stylus-trace/Cargo.toml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "stylus-trace-studio"
name = "stylus-trace-core"
version.workspace = true
edition.workspace = true
authors.workspace = true
Expand All @@ -9,7 +9,6 @@ repository.workspace = true
homepage.workspace = true
documentation = "https://docs.rs/stylus-trace-studio"

# EITHER use a crate-local README (recommended)
readme = "README.md"

# OR point to root README (works too)
Expand Down
Loading