hyperdx/.github/workflows/release.yml
Warren Lee d995b78c66
[HDX-3919] Add @hyperdx/cli package — terminal TUI, source map upload, and agent-friendly commands (#2043)
## Summary

Adds `packages/cli` (`@hyperdx/cli`) — a unified CLI for HyperDX that provides an interactive TUI for searching/tailing logs and traces, source map upload (migrated from `hyperdx-js`), and agent-friendly commands for programmatic access.

Ref: HDX-3919
Ref: HDX-3920

### CLI Commands

```
hdx tui -s <url>                    # Interactive TUI (main command)
hdx sources -s <url>                # List sources with ClickHouse schemas
hdx sources -s <url> --json         # JSON output for agents / scripts
hdx dashboards -s <url>             # List dashboards with tile summaries
hdx dashboards -s <url> --json      # JSON output for agents / scripts
hdx query --source "Logs" --sql "SELECT count() FROM default.otel_logs"
hdx upload-sourcemaps -k <key>      # Upload source maps (ported from hyperdx-js)
hdx auth login -s <url>             # Sign in (interactive or -e/-p flags)
hdx auth status                     # Show auth status
hdx auth logout                     # Clear saved session
```

### Key Features

**Interactive TUI (`hdx tui`)**
- Table view with dynamic columns derived from query results (percentage-based widths)
- Follow mode (live tail) enabled by default, auto-pauses when detail panel is open
- Vim-like keybindings: j/k navigation, G/g jump, Ctrl+D/U half-page scroll
- `/` for Lucene search, `s` to edit SELECT clause in `$EDITOR`, `t` to edit time range
- Tab to cycle between sources and saved searches
- `w` to toggle line wrap

**Detail Panel (3 tabs, full-screen with Ctrl+D/U scrolling)**
- **Overview** — Structured view: Top Level Attributes, Log/Span Attributes, Resource Attributes
- **Column Values** — Full `SELECT *` row data with `__hdx_*` aliased columns
- **Trace** — Waterfall chart (port of `DBTraceWaterfallChart` DAG builder) with correlated log events, j/k span navigation, inverse highlight, Event Details section

**Agent-friendly commands**
- `hdx sources --json` — Full source metadata with ClickHouse `CREATE TABLE` DDL, expression mappings, and correlated source IDs. Detailed `--help` describes the JSON schema for LLM consumption. Schema queries run in parallel.
- `hdx dashboards --json` — Dashboard metadata with simplified tile summaries (name, type, source, sql). Resolves source names for human-readable output.
- `hdx query --source <name> --sql <query>` — Raw SQL execution against any source's ClickHouse connection. Supports `--format` for ClickHouse output formats (JSON, JSONEachRow, CSV, etc.).

**Source map upload (`hdx upload-sourcemaps`)**
- Ported from `hyperdx-js/packages/cli` to consolidate on a single `@hyperdx/cli` package
- Authenticates via service account API key (`-k` / `HYPERDX_SERVICE_KEY` env var)
- Globs `.js` and `.js.map` files, handles Next.js route groups
- Uploads to presigned URLs in parallel with retry (3 attempts) and progress
- Modernized: native `fetch` (Node 22+), ESM-compatible, proper TypeScript types

### Architecture

```
packages/cli/
├── src/
│   ├── cli.tsx              # Commander CLI: tui, sources, dashboards, query,
│   │                        #   upload-sourcemaps, auth
│   ├── App.tsx              # Ink app shell (login → source picker → EventViewer)
│   ├── sourcemaps.ts        # Source map upload logic (ported from hyperdx-js)
│   ├── api/
│   │   ├── client.ts        # ApiClient + ProxyClickhouseClient
│   │   └── eventQuery.ts    # Query builders (renderChartConfig, raw SQL)
│   ├── components/
│   │   ├── EventViewer/     # Main TUI (9 files)
│   │   │   ├── EventViewer.tsx    # Orchestrator (state, hooks, render shell)
│   │   │   ├── types.ts           # Shared types & constants
│   │   │   ├── utils.ts           # Row formatting functions
│   │   │   ├── SubComponents.tsx  # Header, TabBar, SearchBar, Footer, HelpScreen, TableHeader
│   │   │   ├── TableView.tsx      # Table rows rendering
│   │   │   ├── DetailPanel.tsx    # Detail panel (overview/columns/trace tabs)
│   │   │   ├── useEventData.ts    # Data fetching hook
│   │   │   └── useKeybindings.ts  # Input handler hook
│   │   ├── TraceWaterfall/  # Trace chart (6 files)
│   │   │   ├── TraceWaterfall.tsx  # Orchestrator + render
│   │   │   ├── types.ts           # SpanRow, SpanNode, props
│   │   │   ├── utils.ts           # Duration/status/bar helpers
│   │   │   ├── buildTree.ts       # DAG builder (port of DBTraceWaterfallChart)
│   │   │   └── useTraceData.ts    # Data fetching hook
│   │   ├── RowOverview.tsx
│   │   ├── ColumnValues.tsx
│   │   ├── LoginForm.tsx
│   │   └── SourcePicker.tsx
│   ├── shared/              # Ported from packages/app (@source annotated)
│   └── utils/               # Config, editor, log silencing
├── AGENTS.md
├── CONTRIBUTING.md
└── README.md
```

### Tech Stack
- **Ink v6.8.0** (React 19 for terminals) + Commander.js
- **@clickhouse/client** via ProxyClickhouseClient (routes through `/clickhouse-proxy`)
- **@hyperdx/common-utils** for query generation (`renderChartConfig`, `chSqlToAliasMap`)
- **glob v13** for source map file discovery
- **tsup** for bundling (all deps bundled via `noExternal: [/.*/]`, zero runtime deps)
- **Bun 1.3.11** for standalone binary compilation
- Session stored at `~/.config/hyperdx/cli/session.json`

### CI/CD (`release.yml`)
- CLI binaries compiled for macOS ARM64, macOS x64, and Linux x64
- GitHub Release created with download instructions
- Version-change gate: skips release if `cli-v{version}` tag already exists
- `softprops/action-gh-release` pinned to full SHA (v2.6.1) for supply chain safety
- Bun pinned to `1.3.11` for reproducible builds
- npm publishing handled by changesets

### Keybindings

| Key | Action |
|---|---|
| `j/k` | Navigate rows (or spans in Trace tab) |
| `l/Enter` | Expand row detail |
| `h/Esc` | Close detail / blur search |
| `G/g` | Jump to newest/oldest |
| `Ctrl+D/U` | Scroll half-page (table, detail panels, Event Details) |
| `/` | Search (global or detail filter) |
| `Tab` | Cycle sources/searches or detail tabs |
| `s` | Edit SELECT clause in $EDITOR |
| `t` | Edit time range in $EDITOR |
| `f` | Toggle follow mode (live tail) |
| `w` | Toggle line wrap |
| `?` | Help screen |

### Demo
#### Main Search View
<img width="1004" height="1014" alt="image" src="https://github.com/user-attachments/assets/bb6a7f00-38c9-4281-9915-c71b65d852f8" />

#### Event Details Overview
<img width="1003" height="1024" alt="image" src="https://github.com/user-attachments/assets/57025fa5-fddb-452a-9320-93465538d5b2" />

#### Trace Waterfall
<img width="1004" height="1029" alt="image" src="https://github.com/user-attachments/assets/3443c898-ea0d-47f3-acc5-edb7cdd31946" />
2026-04-09 20:21:34 +00:00

666 lines
24 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Release
on:
push:
branches: [main]
permissions:
contents: write
packages: write
pull-requests: write
actions: read
jobs:
check_changesets:
name: Check Changesets
runs-on: ubuntu-24.04
outputs:
changeset_outputs_hasChangesets:
${{ steps.changesets.outputs.hasChangesets }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache-dependency-path: 'yarn.lock'
cache: 'yarn'
- name: Install root dependencies
run: yarn install
- name: Create Release Pull Request or Publish to npm
if: always()
continue-on-error: true
id: changesets
uses: changesets/action@v1
with:
commit: 'chore(release): bump HyperDX app/package versions'
title: 'Release HyperDX'
version: yarn run version
publish: yarn release
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# ---------------------------------------------------------------------------
# Check if version already published (skip-if-exists)
# ---------------------------------------------------------------------------
check_version:
name: Check if version exists
needs: check_changesets
runs-on: ubuntu-24.04
if:
needs.check_changesets.outputs.changeset_outputs_hasChangesets == 'false'
outputs:
should_release: ${{ steps.check.outputs.should_release }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Check if app image tag already exists
id: check
run: |
TAG_EXISTS=$(docker manifest inspect ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }} > /dev/null 2>&1 && echo "true" || echo "false")
if [ "$TAG_EXISTS" = "true" ]; then
echo "Tag ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }} already exists. Skipping release."
echo "should_release=false" >> $GITHUB_OUTPUT
else
echo "Tag does not exist. Proceeding with release."
echo "should_release=true" >> $GITHUB_OUTPUT
fi
# ---------------------------------------------------------------------------
# OTel Collector build each arch natively, then merge into multi-arch tag
# ---------------------------------------------------------------------------
build-otel-collector:
name: Build OTel Collector (${{ matrix.arch }})
needs: [check_changesets, check_version]
if: needs.check_version.outputs.should_release == 'true'
strategy:
fail-fast: true
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-latest
- arch: arm64
platform: linux/arm64
runner: ubuntu-latest-arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Build and Push
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/otel-collector/Dockerfile
platforms: ${{ matrix.platform }}
target: prod
tags: |
${{ env.OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
${{ env.NEXT_OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
push: true
cache-from: type=gha,scope=otel-collector-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=otel-collector-${{ matrix.arch }}
publish-otel-collector:
name: Publish OTel Collector Manifest
needs: [check_version, build-otel-collector]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create multi-arch manifests
run: |
VERSION="${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}"
MAJOR="${{ env.IMAGE_VERSION }}"
LATEST="${{ env.IMAGE_LATEST_TAG }}"
for IMAGE in "${{ env.OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB }}" "${{ env.NEXT_OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB }}"; do
docker buildx imagetools create \
-t "${IMAGE}:${VERSION}" \
-t "${IMAGE}:${MAJOR}" \
-t "${IMAGE}:${LATEST}" \
"${IMAGE}:${VERSION}-amd64" \
"${IMAGE}:${VERSION}-arm64"
done
# ---------------------------------------------------------------------------
# App (fullstack prod) build each arch natively, then merge
# ---------------------------------------------------------------------------
build-app:
name: Build App (${{ matrix.arch }})
needs: [check_changesets, check_version]
if: needs.check_version.outputs.should_release == 'true'
strategy:
fail-fast: true
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: Large-Runner-x64-32
- arch: arm64
platform: linux/arm64
runner: Large-Runner-ARM64-32
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Build and Push
uses: docker/build-push-action@v6
with:
file: ./docker/hyperdx/Dockerfile
platforms: ${{ matrix.platform }}
target: prod
build-contexts: |
hyperdx=./docker/hyperdx
api=./packages/api
app=./packages/app
build-args: |
CODE_VERSION=${{ env.CODE_VERSION }}
tags: |
${{ env.IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
push: true
sbom: true
provenance: true
cache-from: type=gha,scope=app-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=app-${{ matrix.arch }}
publish-app:
name: Publish App Manifest
needs: [check_version, build-app]
runs-on: ubuntu-latest
outputs:
app_was_pushed: 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create multi-arch manifest
run: |
VERSION="${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}"
MAJOR="${{ env.IMAGE_VERSION }}"
LATEST="${{ env.IMAGE_LATEST_TAG }}"
IMAGE="${{ env.IMAGE_NAME_DOCKERHUB }}"
docker buildx imagetools create \
-t "${IMAGE}:${VERSION}" \
-t "${IMAGE}:${MAJOR}" \
-t "${IMAGE}:${LATEST}" \
"${IMAGE}:${VERSION}-amd64" \
"${IMAGE}:${VERSION}-arm64"
# ---------------------------------------------------------------------------
# Local (all-in-one-noauth) build each arch natively, then merge
# ---------------------------------------------------------------------------
build-local:
name: Build Local (${{ matrix.arch }})
needs: [check_changesets, check_version]
if: needs.check_version.outputs.should_release == 'true'
strategy:
fail-fast: true
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: Large-Runner-x64-32
- arch: arm64
platform: linux/arm64
runner: Large-Runner-ARM64-32
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Build and Push
uses: docker/build-push-action@v6
with:
file: ./docker/hyperdx/Dockerfile
platforms: ${{ matrix.platform }}
target: all-in-one-noauth
build-contexts: |
clickhouse=./docker/clickhouse
otel-collector=./docker/otel-collector
hyperdx=./docker/hyperdx
api=./packages/api
app=./packages/app
build-args: |
CODE_VERSION=${{ env.CODE_VERSION }}
tags: |
${{ env.LOCAL_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
${{ env.NEXT_LOCAL_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
push: true
sbom: true
provenance: true
cache-from: type=gha,scope=local-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=local-${{ matrix.arch }}
publish-local:
name: Publish Local Manifest
needs: [check_version, build-local]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create multi-arch manifests
run: |
VERSION="${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}"
MAJOR="${{ env.IMAGE_VERSION }}"
LATEST="${{ env.IMAGE_LATEST_TAG }}"
for IMAGE in "${{ env.LOCAL_IMAGE_NAME_DOCKERHUB }}" "${{ env.NEXT_LOCAL_IMAGE_NAME_DOCKERHUB }}"; do
docker buildx imagetools create \
-t "${IMAGE}:${VERSION}" \
-t "${IMAGE}:${MAJOR}" \
-t "${IMAGE}:${LATEST}" \
"${IMAGE}:${VERSION}-amd64" \
"${IMAGE}:${VERSION}-arm64"
done
# ---------------------------------------------------------------------------
# All-in-One (all-in-one-auth) build each arch natively, then merge
# ---------------------------------------------------------------------------
build-all-in-one:
name: Build All-in-One (${{ matrix.arch }})
needs: [check_changesets, check_version]
if: needs.check_version.outputs.should_release == 'true'
strategy:
fail-fast: true
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: Large-Runner-x64-32
- arch: arm64
platform: linux/arm64
runner: Large-Runner-ARM64-32
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Build and Push
uses: docker/build-push-action@v6
with:
file: ./docker/hyperdx/Dockerfile
platforms: ${{ matrix.platform }}
target: all-in-one-auth
build-contexts: |
clickhouse=./docker/clickhouse
otel-collector=./docker/otel-collector
hyperdx=./docker/hyperdx
api=./packages/api
app=./packages/app
build-args: |
CODE_VERSION=${{ env.CODE_VERSION }}
tags: |
${{ env.ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
${{ env.NEXT_ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}-${{ matrix.arch }}
push: true
sbom: true
provenance: true
cache-from: type=gha,scope=all-in-one-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=all-in-one-${{ matrix.arch }}
publish-all-in-one:
name: Publish All-in-One Manifest
needs: [check_version, build-all-in-one]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create multi-arch manifests
run: |
VERSION="${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}"
MAJOR="${{ env.IMAGE_VERSION }}"
LATEST="${{ env.IMAGE_LATEST_TAG }}"
for IMAGE in "${{ env.ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}" "${{ env.NEXT_ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}"; do
docker buildx imagetools create \
-t "${IMAGE}:${VERSION}" \
-t "${IMAGE}:${MAJOR}" \
-t "${IMAGE}:${LATEST}" \
"${IMAGE}:${VERSION}-amd64" \
"${IMAGE}:${VERSION}-arm64"
done
# ---------------------------------------------------------------------------
# CLI compile standalone binaries and upload as GitHub Release assets
# npm publishing is handled by changesets in the check_changesets job above.
# This job only compiles platform-specific binaries and creates a GH Release.
# ---------------------------------------------------------------------------
release-cli:
name: Release CLI Binaries
needs: [check_changesets, check_version]
if: needs.check_version.outputs.should_release == 'true'
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache-dependency-path: 'yarn.lock'
cache: 'yarn'
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3.11'
- name: Install dependencies
run: yarn install
- name: Get CLI version
id: cli_version
run: |
CLI_VERSION=$(node -p "require('./packages/cli/package.json').version")
echo "version=${CLI_VERSION}" >> $GITHUB_OUTPUT
echo "CLI version: ${CLI_VERSION}"
- name: Check if CLI release already exists
id: check_cli_release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if gh release view "cli-v${{ steps.cli_version.outputs.version }}" > /dev/null 2>&1; then
echo "Release cli-v${{ steps.cli_version.outputs.version }} already exists. Skipping."
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "Release does not exist. Proceeding."
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Compile CLI binaries
if: steps.check_cli_release.outputs.exists == 'false'
working-directory: packages/cli
run: |
yarn compile:linux
yarn compile:macos
yarn compile:macos-x64
- name: Create GitHub Release
if: steps.check_cli_release.outputs.exists == 'false'
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
with:
tag_name: cli-v${{ steps.cli_version.outputs.version }}
name: '@hyperdx/cli v${{ steps.cli_version.outputs.version }}'
body: |
## @hyperdx/cli v${{ steps.cli_version.outputs.version }}
### Installation
**npm (recommended):**
```bash
npm install -g @hyperdx/cli
```
**Or run directly with npx:**
```bash
npx @hyperdx/cli tui -s <your-hyperdx-api-url>
```
**Manual download (standalone binary, no Node.js required):**
```bash
# macOS Apple Silicon
curl -L https://github.com/hyperdxio/hyperdx/releases/download/cli-v${{ steps.cli_version.outputs.version }}/hdx-darwin-arm64 -o hdx
# macOS Intel
curl -L https://github.com/hyperdxio/hyperdx/releases/download/cli-v${{ steps.cli_version.outputs.version }}/hdx-darwin-x64 -o hdx
# Linux x64
curl -L https://github.com/hyperdxio/hyperdx/releases/download/cli-v${{ steps.cli_version.outputs.version }}/hdx-linux-x64 -o hdx
chmod +x hdx && sudo mv hdx /usr/local/bin/
```
### Usage
```bash
hdx auth login -s <your-hyperdx-api-url>
hdx tui
```
draft: false
prerelease: false
files: |
packages/cli/dist/hdx-linux-x64
packages/cli/dist/hdx-darwin-arm64
packages/cli/dist/hdx-darwin-x64
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ---------------------------------------------------------------------------
# Downstream notifications
# ---------------------------------------------------------------------------
notify_helm_charts:
name: Notify Helm-Charts Downstream
needs:
[
check_changesets,
publish-app,
publish-otel-collector,
publish-local,
publish-all-in-one,
]
runs-on: ubuntu-24.04
if: |
needs.check_changesets.outputs.changeset_outputs_hasChangesets == 'false' &&
needs.publish-app.outputs.app_was_pushed == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Notify Helm-Charts Downstream
uses: actions/github-script@v7
continue-on-error: true
env:
TAG: ${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}
with:
github-token: ${{ secrets.CH_BOT_PAT }}
script: |
const { TAG } = process.env;
const result = await github.rest.actions.createWorkflowDispatch({
owner: 'ClickHouse',
repo: 'ClickStack-helm-charts',
workflow_id: '${{ secrets.DOWNSTREAM_HC_WORKFLOW_ID }}',
ref: 'main',
inputs: {
tag: TAG
}
});
notify_ch:
name: Notify CH Downstream
needs:
[
check_changesets,
publish-app,
publish-otel-collector,
publish-local,
publish-all-in-one,
]
runs-on: ubuntu-24.04
# Temporarily disabled:
if: false
# if: |
# needs.check_changesets.outputs.changeset_outputs_hasChangesets == 'false' &&
# needs.publish-app.outputs.app_was_pushed == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Get Downstream App Installation Token
id: auth
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.DOWNSTREAM_CH_APP_ID }}
private-key: ${{ secrets.DOWNSTREAM_CH_APP_PRIVATE_KEY }}
owner: ${{ secrets.DOWNSTREAM_CH_OWNER }}
- name: Notify CH Downstream
uses: actions/github-script@v7
continue-on-error: true
env:
TAG: ${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}
with:
github-token: ${{ steps.auth.outputs.token }}
script: |
const { TAG } = process.env;
const result = await github.rest.actions.createWorkflowDispatch({
owner: '${{ secrets.DOWNSTREAM_CH_OWNER }}',
repo: '${{ secrets.DOWNSTREAM_DP_REPO }}',
workflow_id: '${{ secrets.DOWNSTREAM_DP_WORKFLOW_ID }}',
ref: 'main',
inputs: {
tag: TAG
}
});
notify_clickhouse_clickstack:
needs:
[
check_changesets,
publish-app,
publish-otel-collector,
publish-local,
publish-all-in-one,
]
if: needs.publish-app.outputs.app_was_pushed == 'true'
timeout-minutes: 5
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Load Environment Variables from .env
uses: xom9ikk/dotenv@v2
- name: Notify ClickHouse/clickhouse-clickstack Downstream
uses: actions/github-script@v7
continue-on-error: true
env:
TAG: ${{ env.IMAGE_VERSION }}${{ env.IMAGE_VERSION_SUB_TAG }}
with:
github-token: ${{ secrets.CH_BOT_PAT }}
script: |
const { TAG } = process.env;
const result = await github.rest.actions.createWorkflowDispatch({
owner: 'ClickHouse',
repo: 'clickhouse-clickstack',
workflow_id: 'sync-hyperdx.yml',
ref: 'main',
inputs: {
tag: TAG,
}
});
otel-cicd-action:
if: always()
name: OpenTelemetry Export Trace
runs-on: ubuntu-latest
needs:
[
check_changesets,
publish-app,
publish-otel-collector,
publish-local,
publish-all-in-one,
release-cli,
notify_helm_charts,
notify_ch,
notify_clickhouse_clickstack,
]
steps:
- name: Export workflow
uses: corentinmusard/otel-cicd-action@v4
with:
otlpEndpoint: ${{ secrets.OTLP_ENDPOINT }}/v1/traces
otlpHeaders: ${{ secrets.OTLP_HEADERS }}
otelServiceName: 'release-hyperdx-oss-workflow'
githubToken: ${{ secrets.GITHUB_TOKEN }}