Skip to content
Draft
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
149 changes: 149 additions & 0 deletions .github/actions/test-report/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
name: Surfpool Report
description: >
Post a single PR comment with code coverage table and a link to the
Surfpool transaction report on GitHub Pages.

inputs:
rust-coverage-json:
description: Path to cargo-llvm-cov JSON output
required: false
ts-coverage-json:
description: Path to vitest coverage-summary.json
required: false
report-path:
description: Path to the Surfpool HTML report file
required: false
pages-path:
description: Path prefix on GitHub Pages (e.g. "pr/1")
default: pr/${{ github.event.pull_request.number }}
green-threshold:
description: Line coverage % for green badge
default: "90"
yellow-threshold:
description: Line coverage % for yellow badge
default: "80"
comment-header:
description: Sticky comment header ID
default: surfpool

runs:
using: composite
steps:
# ── Deploy report to GitHub Pages ──
- name: Deploy report
if: inputs.report-path != '' && github.event_name == 'pull_request'
shell: bash
env:
REPORT_FILE: ${{ inputs.report-path }}
PAGES_PATH: ${{ inputs.pages-path }}
run: |
if [ ! -f "${REPORT_FILE}" ]; then
echo "No report file at ${REPORT_FILE}, skipping deploy"
exit 0
fi

git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

cp "${REPORT_FILE}" /tmp/surfpool-report.html

if git ls-remote --exit-code origin gh-pages >/dev/null 2>&1; then
git fetch origin gh-pages
git checkout gh-pages
else
git checkout --orphan gh-pages
git rm -rf . 2>/dev/null || true
echo "# GitHub Pages" > README.md
git add README.md
git commit -m "init: gh-pages branch"
fi

mkdir -p "${PAGES_PATH}"
cp /tmp/surfpool-report.html "${PAGES_PATH}/index.html"

git add "${PAGES_PATH}/index.html"
git commit -m "deploy: surfpool report for ${PAGES_PATH}" || true
git push origin gh-pages
git checkout -

- name: Upload report artifact
if: inputs.report-path != ''
uses: actions/upload-artifact@v4
with:
name: surfpool-report
path: ${{ inputs.report-path }}

# ── Build the unified comment ──
- name: Build comment
id: comment
shell: bash
env:
RS_JSON: ${{ inputs.rust-coverage-json }}
TS_JSON: ${{ inputs.ts-coverage-json }}
GREEN: ${{ inputs.green-threshold }}
YELLOW: ${{ inputs.yellow-threshold }}
REPORT_FILE: ${{ inputs.report-path }}
PAGES_PATH: ${{ inputs.pages-path }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}
run: |
badge() {
local val=$1
if [ "$(echo "$val >= $GREEN" | bc -l 2>/dev/null)" = "1" ]; then echo "🟢"
elif [ "$(echo "$val >= $YELLOW" | bc -l 2>/dev/null)" = "1" ]; then echo "🟡"
else echo "🔴"; fi
}

{
echo "body<<EOFCOMMENT"

# ── Coverage table ──
HAS_COV=false
ROWS=""

if [ -n "$TS_JSON" ] && [ -f "$TS_JSON" ]; then
HAS_COV=true
TS_STMTS=$(jq -r '.total.statements.pct' "$TS_JSON")
TS_BRANCH=$(jq -r '.total.branches.pct' "$TS_JSON")
TS_FUNC=$(jq -r '.total.functions.pct' "$TS_JSON")
TS_LINES=$(jq -r '.total.lines.pct' "$TS_JSON")
TS_BADGE=$(badge "$TS_LINES")
ROWS="${ROWS}| ${TS_BADGE} **TypeScript** | ${TS_STMTS}% | ${TS_BRANCH}% | ${TS_FUNC}% | ${TS_LINES}% |
"
fi

if [ -n "$RS_JSON" ] && [ -f "$RS_JSON" ]; then
HAS_COV=true
RS_LINES=$(jq -r '[.data[0].totals.lines.percent] | .[0] | . * 10 | round / 10' "$RS_JSON")
RS_FUNC=$(jq -r '[.data[0].totals.functions.percent] | .[0] | . * 10 | round / 10' "$RS_JSON")
RS_REGIONS=$(jq -r '[.data[0].totals.regions.percent] | .[0] | . * 10 | round / 10' "$RS_JSON")
RS_BADGE=$(badge "$RS_LINES")
ROWS="${ROWS}| ${RS_BADGE} **Rust** | ${RS_REGIONS}% | — | ${RS_FUNC}% | ${RS_LINES}% |
"
fi

if [ "$HAS_COV" = "true" ]; then
echo "## Test Coverage"
echo ""
echo "| | Statements | Branches | Functions | Lines |"
echo "|---|---|---|---|---|"
echo "$ROWS"
fi

# ── Report link ──
if [ -n "$REPORT_FILE" ] && [ -f "$REPORT_FILE" ]; then
echo ""
echo "---"
echo ""
echo "**[Surfpool Report](https://${REPO_OWNER}.github.io/${REPO_NAME}/${PAGES_PATH}/)** — transaction profiling, account state diffs, byte comparison"
fi

echo "EOFCOMMENT"
} >> "$GITHUB_OUTPUT"

- name: Post comment
if: github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: ${{ inputs.comment-header }}
message: ${{ steps.comment.outputs.body }}
236 changes: 236 additions & 0 deletions .github/workflows/release_sdk_node_npm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
name: Publish SDK Node Package

on:
workflow_dispatch:
inputs:
dry_run:
description: "Dry run (do not actually publish to npm)"
required: false
type: boolean
default: false

env:
CARGO_TERM_COLOR: always
SURFPOOL_REPORT_UI_DIR: ${{ github.workspace }}/surfpool-web-ui/apps/report-viewer/dist

jobs:
prepare_release:
name: Prepare Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.package.outputs.version }}
should_publish: ${{ steps.package.outputs.should_publish }}
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org

- name: Read package version
id: package
working-directory: crates/sdk-node
shell: bash
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

if npm view "surfpool-sdk@${VERSION}" version --registry=https://registry.npmjs.org >/dev/null 2>&1; then
echo "should_publish=false" >> "$GITHUB_OUTPUT"
echo "surfpool-sdk@${VERSION} is already published"
else
echo "should_publish=true" >> "$GITHUB_OUTPUT"
echo "surfpool-sdk@${VERSION} is ready to publish"
fi

build_artifacts:
name: Build (${{ matrix.name }})
needs: prepare_release
if: needs.prepare_release.outputs.should_publish == 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: linux-x64
os: ubuntu-22.04
upload_metadata: true
platform_dir: linux-x64-gnu
- name: macos-x64
os: macos-13
upload_metadata: false
platform_dir: darwin-x64
- name: macos-arm64
os: macos-14
upload_metadata: false
platform_dir: darwin-arm64

steps:
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libudev-dev clang libclang-dev

- name: Checkout repository
uses: actions/checkout@v4

- name: Checkout report viewer repository
uses: actions/checkout@v4
with:
repository: solana-foundation/surfpool-web-ui
path: surfpool-web-ui

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: crates/sdk-node/package-lock.json

- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 10.14.0

- name: Install npm dependencies
working-directory: crates/sdk-node
run: npm ci

- name: Install report viewer dependencies
working-directory: surfpool-web-ui
run: pnpm install --frozen-lockfile

- name: Build report viewer
working-directory: surfpool-web-ui
run: pnpm --filter @surfpool/report-viewer build

- name: Build npm package
working-directory: crates/sdk-node
run: npm run build

- name: Smoke test package
working-directory: crates/sdk-node
run: npm run smoke

- name: Upload native binary
uses: actions/upload-artifact@v4
with:
name: sdk-node-${{ matrix.name }}-binary
path: crates/sdk-node/surfpool-sdk.*.node
if-no-files-found: error

- name: Upload package metadata
if: matrix.upload_metadata
uses: actions/upload-artifact@v4
with:
name: sdk-node-package-metadata
path: |
crates/sdk-node/surfpool-sdk/internal.js
crates/sdk-node/surfpool-sdk/internal.d.ts
if-no-files-found: error

publish:
name: Publish To npm
needs:
- prepare_release
- build_artifacts
if: needs.prepare_release.outputs.should_publish == 'true'
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Install Linux dependencies
run: sudo apt-get update && sudo apt-get install -y libudev-dev clang libclang-dev

- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
cache: npm
cache-dependency-path: crates/sdk-node/package-lock.json

- name: Install npm dependencies
working-directory: crates/sdk-node
run: npm ci

- name: Download native binaries
uses: actions/download-artifact@v4
with:
pattern: sdk-node-*-binary
path: crates/sdk-node/artifacts

- name: Download package metadata
uses: actions/download-artifact@v4
with:
name: sdk-node-package-metadata
path: crates/sdk-node/surfpool-sdk

- name: Create npm platform package directories
working-directory: crates/sdk-node
run: npm run create-npm-dir

- name: Copy artifacts into npm platform packages
working-directory: crates/sdk-node
run: npm run artifacts

- name: Build TypeScript wrapper
working-directory: crates/sdk-node
run: npm run build:ts

- name: Pack root npm tarball
working-directory: crates/sdk-node
run: NPM_CONFIG_CACHE=$(mktemp -d) npm pack --dry-run

- name: Pack platform npm tarballs
working-directory: crates/sdk-node
run: |
cd npm/darwin-x64 && NPM_CONFIG_CACHE=$(mktemp -d) npm pack --dry-run
cd ../darwin-arm64 && NPM_CONFIG_CACHE=$(mktemp -d) npm pack --dry-run
cd ../linux-x64-gnu && NPM_CONFIG_CACHE=$(mktemp -d) npm pack --dry-run

- name: Publish platform packages
if: inputs.dry_run != true
working-directory: crates/sdk-node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx napi prepublish -t npm --skip-gh-release

- name: Dry run platform publish
if: inputs.dry_run == true
working-directory: crates/sdk-node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx napi prepublish -t npm --skip-gh-release --dry-run

- name: Publish root package
if: inputs.dry_run != true
working-directory: crates/sdk-node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish --access public --provenance

- name: Dry run root publish
if: inputs.dry_run == true
working-directory: crates/sdk-node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish --dry-run --access public
Loading
Loading