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
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ jobs:
run: mv cmd/hx/.bin/hx.exe cmd/hx/.bin/hx_${{ matrix.goos }}_${{ matrix.goarch }}.exe

- name: Upload artifact
uses: actions/upload-artifact@ea165f8d65b6db9a8b9c8a4d5a48f8ca9897de98 # v4.6.2
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: hx-${{ matrix.goos }}-${{ matrix.goarch }}
path: cmd/hx/.bin/hx_*
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ y
cliff.toml
.todos/
cmd/hx/fixtures/hx
.ginkgo
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
HX_DIR := cmd/hx

.PHONY: build
build:
$(MAKE) -C $(HX_DIR) build

.PHONY: install
install:
$(MAKE) -C $(HX_DIR) install

.PHONY: test
test:
go test ./... -v --count=1
Expand Down
3 changes: 3 additions & 0 deletions cmd/hx/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
hx

testdata/
*.har

5 changes: 4 additions & 1 deletion cmd/hx/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build install test
.PHONY: build install test fixtures

VERSION ?= dev
LDFLAGS := -s -w -X main.version=$(VERSION)
Expand All @@ -11,3 +11,6 @@ install:

test:
go test ./... -v -count=1

fixtures:
go run github.com/flanksource/gavel/cmd/gavel@latest fixtures fixtures/hx.md
51 changes: 25 additions & 26 deletions cmd/hx/fixtures/hx.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
build: cd cmd/hx && go build -o fixtures/hx .
exec: ./hx
args: ["--quiet"]
build: go build -o hx .
exec: hx --har "{{ .name | strings.Slug }}.har"
---

# hx CLI Fixture Tests
Expand All @@ -10,52 +9,52 @@ args: ["--quiet"]

| Name | Args | CEL Validation |
|------|------|----------------|
| GET request | --quiet https://httpbin.flanksource.com/get | json.url == "https://httpbin.flanksource.com/get" |
| GET with query params | --quiet https://httpbin.flanksource.com/get search==test page==1 | json.args.search == "test" && json.args.page == "1" |
| POST JSON body | --quiet https://httpbin.flanksource.com/post name=hello count:=42 | json.json.name == "hello" && json.json.count == 42.0 |
| PUT request | --quiet PUT https://httpbin.flanksource.com/put name=updated | json.json.name == "updated" |
| DELETE request | --quiet DELETE https://httpbin.flanksource.com/delete | exitCode == 0 |
| PATCH request | --quiet PATCH https://httpbin.flanksource.com/patch name=patched | json.json.name == "patched" |
| GET request | https://httpbin.flanksource.com/get | json.url == "https://httpbin.flanksource.com/get" |
| GET with query params | https://httpbin.flanksource.com/get search==test page==1 | json.args.search == "test" && json.args.page == "1" |
| POST JSON body | https://httpbin.flanksource.com/post name=hello count:=42 | json.json.name == "hello" && json.json.count == 42.0 |
| PUT request | PUT https://httpbin.flanksource.com/put name=updated | json.json.name == "updated" |
| DELETE request | DELETE https://httpbin.flanksource.com/delete | exitCode == 0 |
| PATCH request | PATCH https://httpbin.flanksource.com/patch name=patched | json.json.name == "patched" |

## Authentication

| Name | Args | CEL Validation |
|------|------|----------------|
| Basic auth success | --quiet -u testuser:testpass https://httpbin.flanksource.com/basic-auth/testuser/testpass | json.authenticated == true && json.user == "testuser" |
| Basic auth failure | --quiet -u wrong:creds https://httpbin.flanksource.com/basic-auth/testuser/testpass | exitCode == 0 && stdout.size() == 0 |
| Bearer token | --quiet --token mytoken123 https://httpbin.flanksource.com/bearer | json.authenticated == true && json.token == "mytoken123" |
| Name | Args | ExitCode | CEL Validation |
|------|------|----------------|----------------|
| Basic auth success | -u testuser:testpass https://httpbin.flanksource.com/basic-auth/testuser/testpass | | json.authenticated == true && json.user == "testuser" |
| Basic auth failure | -u wrong:creds https://httpbin.flanksource.com/basic-auth/testuser/testpass | 1 | stdout.size() == 0 |
| Bearer token | --token mytoken123 https://httpbin.flanksource.com/bearer | | json.authenticated == true && json.token == "mytoken123" |

## Status Codes

| Name | Args | CEL Validation |
|------|------|----------------|
| Status 200 | --quiet https://httpbin.flanksource.com/status/200 | exitCode == 0 |
| Status 404 | --quiet https://httpbin.flanksource.com/status/404 | exitCode == 0 |
| Status 500 | --quiet https://httpbin.flanksource.com/status/500 | exitCode == 0 |
| Name | ExitCode | Args | CEL Validation |
|------|------|----------------|----------------|
| Status 200 | 0 | https://httpbin.flanksource.com/status/200 | exitCode == 0 |
| Status 404 | 1 | https://httpbin.flanksource.com/status/404 | exitCode == 1 |
| Status 500 | 1 | https://httpbin.flanksource.com/status/500 | exitCode == 1 |

## Headers and Data

| Name | Args | CEL Validation |
|------|------|----------------|
| Custom header | --quiet https://httpbin.flanksource.com/headers X-Custom:hello | json.headers["X-Custom"] == "hello" |
| JSON response | --quiet https://httpbin.flanksource.com/get | stdout.contains('"url"') |
| UUID endpoint | --quiet https://httpbin.flanksource.com/uuid | json.uuid.size() > 0 |
| IP endpoint | --quiet https://httpbin.flanksource.com/ip | stdout.contains('"origin"') |
| Custom header | https://httpbin.flanksource.com/headers X-Custom:hello | json.headers["X-Custom"] == "hello" |
| JSON response | https://httpbin.flanksource.com/get | stdout.contains('"url"') |
| UUID endpoint | https://httpbin.flanksource.com/uuid | json.uuid.size() > 0 |
| IP endpoint | https://httpbin.flanksource.com/ip | stdout.contains('"origin"') |

## OAuth

| Name | Args | CEL Validation |
|------|------|----------------|
| OAuth client_credentials | --quiet --oauth-client-id demo-backend-client --oauth-client-secret MJlO3binatD9jk1 --oauth-token-url https://login-demo.curity.io/oauth/v2/oauth-token --oauth-scope read https://httpbin.flanksource.com/get | json.headers.Authorization.startsWith("Bearer ") |
| OAuth client_credentials | --oauth-client-id demo-backend-client --oauth-client-secret MJlO3binatD9jk1 --oauth-token-url https://login-demo.curity.io/oauth/v2/oauth-token --oauth-scope read https://httpbin.flanksource.com/get | json.headers.Authorization.startsWith("Bearer ") |

## AWS SigV4

| Name | Args | CEL Validation |
|------|------|----------------|
| AWS SigV4 signing | --quiet --aws-sigv4 --aws-service execute-api --aws-region us-east-1 https://httpbin.flanksource.com/headers | json.headers.Authorization.startsWith("AWS4-HMAC-SHA256") |
| AWS SigV4 signing | --aws-sigv4 --aws-service execute-api --aws-region us-east-1 https://httpbin.flanksource.com/headers | json.headers.Authorization.startsWith("AWS4-HMAC-SHA256") |

## Miscellaneous

| Name | Args | CEL Validation |
|------|------|----------------|
| Form data POST | --quiet -f key1=val1 -f key2=val2 https://httpbin.flanksource.com/post | json.form.key1 == "val1" && json.form.key2 == "val2" |
| Form data POST | -f key1=val1 -f key2=val2 https://httpbin.flanksource.com/post | json.form.key1 == "val1" && json.form.key2 == "val2" |
110 changes: 56 additions & 54 deletions cmd/hx/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ go 1.25.1
require (
github.com/aws/aws-sdk-go-v2/config v1.32.9
github.com/flanksource/clicky v1.17.0
github.com/flanksource/commons v1.44.1
github.com/spf13/cobra v1.9.2-0.20250831231508-51d675196729
github.com/flanksource/commons v1.46.1
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.11.1
golang.org/x/term v0.36.0
golang.org/x/term v0.40.0
)

require (
cel.dev/expr v0.24.0 // indirect
cel.dev/expr v0.25.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Snawoot/go-http-digest-auth-client v1.1.3 // indirect
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect
github.com/alecthomas/chroma/v2 v2.20.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.9 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect
Expand All @@ -34,61 +34,63 @@ require (
github.com/aws/smithy-go v1.24.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cert-manager/cert-manager v1.16.1 // indirect
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
github.com/cert-manager/cert-manager v1.19.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/x/ansi v0.10.1 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/flanksource/gomplate/v3 v3.24.60 // indirect
github.com/flanksource/is-healthy v1.0.79 // indirect
github.com/flanksource/gomplate/v3 v3.24.68 // indirect
github.com/flanksource/is-healthy v1.0.82 // indirect
github.com/flanksource/kubectl-neat v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/cel-go v0.22.1 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/google/cel-go v0.27.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gosimple/slug v1.13.1 // indirect
github.com/gosimple/slug v1.15.0 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/hairyhenderson/toml v0.4.2-0.20210923231440-40456b8e66cf // indirect
github.com/hairyhenderson/yaml v0.0.0-20220618171115-2d35fca545ce // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/itchyny/gojq v0.12.17 // indirect
github.com/itchyny/timefmt-go v0.1.6 // indirect
github.com/jeremywohl/flatten v0.0.0-20180923035001-588fe0d4c603 // indirect
github.com/itchyny/gojq v0.12.18 // indirect
github.com/itchyny/timefmt-go v0.1.7 // indirect
github.com/jeremywohl/flatten v1.0.1 // indirect
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lmittmann/tint v1.1.2 // indirect
github.com/lmittmann/tint v1.1.3 // indirect
github.com/lrita/cmap v0.0.0-20231108122212-cb084a67f554 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ohler55/ojg v1.25.0 // indirect
github.com/ohler55/ojg v1.28.0 // indirect
github.com/oklog/ulid/v2 v2.1.1 // indirect
github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.0.9 // indirect
Expand All @@ -98,34 +100,33 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/playwright-community/playwright-go v0.4702.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/prometheus/common v0.67.5 // indirect
github.com/prometheus/procfs v0.20.0 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/robertkrimen/otto v0.3.0 // indirect
github.com/robertkrimen/otto v0.5.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/samber/lo v1.52.0 // indirect
github.com/samber/oops v1.19.3 // indirect
github.com/samber/oops v1.21.0 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/tiendc/go-deepcopy v1.6.0 // indirect
github.com/timberio/go-datemath v0.1.0 // indirect
github.com/tj/go-naturaldate v1.3.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect
github.com/vadimi/go-http-ntlm v1.0.3 // indirect
github.com/vadimi/go-http-ntlm/v2 v2.5.0 // indirect
github.com/vadimi/go-ntlm v1.2.1 // indirect
Expand All @@ -136,37 +137,38 @@ require (
github.com/xuri/nfp v0.0.1 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.40.0 // indirect
go.opentelemetry.io/otel/metric v1.40.0 // indirect
go.opentelemetry.io/otel/trace v1.40.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
google.golang.org/protobuf v1.36.10 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
golang.org/x/net v0.51.0 // indirect
golang.org/x/oauth2 v0.34.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260223185530-2f722ef697dc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260223185530-2f722ef697dc // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.34.1 // indirect
k8s.io/apiextensions-apiserver v0.31.1 // indirect
k8s.io/apimachinery v0.34.1 // indirect
k8s.io/client-go v0.34.1 // indirect
k8s.io/api v0.35.1 // indirect
k8s.io/apiextensions-apiserver v0.35.1 // indirect
k8s.io/apimachinery v0.35.1 // indirect
k8s.io/client-go v0.35.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 // indirect
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf // indirect
sigs.k8s.io/gateway-api v1.1.0 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/gateway-api v1.4.1 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)

Expand Down
Loading
Loading