Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
1d8fc34
fix(bcp): handle 3-part table names with -d option in SQL Server
flarco Sep 14, 2026
849f986
fix(docs): update conn_property function signature and increase run_m…
flarco Sep 14, 2026
93f1e8f
fix(mongo): parse shell syntax and Extended JSON in filters
flarco Sep 16, 2026
cd86e85
feat(env): node-level env.yaml writes + validated GUI connection helpers
flarco Sep 16, 2026
6f39084
feat(env): deterministic node merge + raw env accessors for the GUI w…
flarco Sep 16, 2026
a82da32
feat(env): RemovedKeys helper for the raw-editor removal guard
flarco Sep 16, 2026
1e9fbe6
test(env): assert untouched env.yaml lines survive verbatim + block s…
flarco Sep 17, 2026
6cf4210
feat(go.mod): add open-golang dependency for enhanced functionality
flarco Sep 18, 2026
73b00ea
feat: add Databricks Unity Catalog Volume and Zerobus Arrow targets
stonefiled Sep 18, 2026
4caf284
fix(databricks): fix volume URL normalization, REST test mock, and op…
stonefiled Sep 18, 2026
2aeb28b
feat(zerobus): align Arrow Flight type mapping with official Zerobus …
stonefiled Sep 18, 2026
bcff92f
docs: add Databricks Volume and Zerobus ingestion guide in README
stonefiled Sep 18, 2026
0a1b1a0
docs: add connection configuration properties and http/ssl options to…
stonefiled Sep 18, 2026
ff58571
refactor: replace zerobus connection type with databricks copy method
flarco Sep 19, 2026
5f0dba9
Merge branch 'v1.6.4' into feature/databricks
flarco Sep 19, 2026
c1d6102
Merge pull request #803 from themulle/feature/databricks
flarco Sep 19, 2026
194cc0e
test: add Zerobus integration tests and validation functions
flarco Sep 19, 2026
958f17d
refactor: update zerobus import alias and increase sleep duration in …
flarco Sep 19, 2026
3f5f662
feat: implement volume file deletion with retry logic and add corresp…
flarco Sep 19, 2026
8666135
feat(iceberg): add merge strategies and refactor AWS config handling
flarco Sep 19, 2026
a10a946
build: promote aws-sdk-go-v2 glue service to direct dependency
flarco Sep 20, 2026
7be5b7a
feat: add support for Cloudflare R2 in icebergStorageKind function
flarco Sep 20, 2026
7001308
refactor(tests): simplify test cases for DuckDb and Iceberg databases
flarco Sep 20, 2026
b31b93c
Add --json output to sling build run
flarco Sep 21, 2026
b2d9ad3
Add LanceDB connection type backed by DuckDB lance extension
flarco Sep 21, 2026
c349c9d
add LanceDB database connection support via DuckDB lance extension
flarco Sep 21, 2026
3214b83
Merge pull request #807 from slingdata-io/flarco/lancedb-format-support
flarco Sep 21, 2026
4e5a28c
fix(gcs): pass ADC via HTTP client to avoid credential clash
flarco Sep 21, 2026
e8c34ce
Guard dev build trigger to version branches only
flarco Sep 21, 2026
b1036d7
Merge pull request #809 from slingdata-io/flarco/bigquery-with-gc_buc…
flarco Sep 21, 2026
f7afc42
Add Firebolt database connector
flarco Sep 21, 2026
3fc3db0
Merge pull request #810 from slingdata-io/flarco/add-firebolt-connector
flarco Sep 21, 2026
ecb9964
Add OpenSearch database connector support
flarco Sep 22, 2026
ea33d20
Merge pull request #811 from slingdata-io/flarco/add-support-for-open…
flarco Sep 22, 2026
ddd3771
Refactor code structure for improved readability and maintainability
flarco Sep 22, 2026
fe85613
Add DynamoDB connector with scan, batch write and delete_missing
flarco Sep 22, 2026
72c1608
Merge branch 'v1.6.4' of github.com:slingdata-io/sling-cli into flarc…
flarco Sep 22, 2026
ff86770
Merge pull request #812 from slingdata-io/flarco/dynamodb-support
flarco Sep 22, 2026
31b326e
Add read-only dBase (.dbf) database connector
flarco Sep 22, 2026
04c24d7
Merge branch 'v1.6.4' of github.com:slingdata-io/sling-cli into flarc…
flarco Sep 22, 2026
1c56208
Merge pull request #813 from slingdata-io/flarco/add-.dbf-support
flarco Sep 22, 2026
7a18790
Add Arrow-native dataflow lane for ADBC sources and sinks
flarco Sep 23, 2026
c1289d4
Merge pull request #814 from slingdata-io/flarco/fast-arrowlane
flarco Sep 23, 2026
38e419f
Add context-aware connection tests and workbench env config
flarco Sep 23, 2026
242cff1
Merge pull request #815 from slingdata-io/flarco/sling-workbench
flarco Sep 23, 2026
70e7dd6
Improve environment variable loading logic to respect existing proces…
flarco Sep 24, 2026
3af379a
Encode spaces as %20 in connection URL passwords instead of +
flarco Sep 24, 2026
5c02c07
Recover from duckdb sidecar death during parquet writes
flarco Sep 24, 2026
5f8ab01
Add ADBC support for ClickHouse and fix MySQL URI building
flarco Sep 25, 2026
5b00f49
Support schema migration for StarRocks targets
flarco Sep 25, 2026
8d6f3c2
Allow literal secret values in conns set, guard invalid env.yaml
flarco Sep 25, 2026
6dd61bf
Enable arrow lane for MySQL source and ClickHouse target
flarco Sep 25, 2026
7fa693b
Repair tab and non-breaking-space indentation in env files
flarco Sep 25, 2026
7d7cf07
Warn on repaired env file indentation and keep values intact
flarco Sep 26, 2026
fd8bc1b
Edit env.yaml line-wise to preserve comments and formatting
flarco Sep 26, 2026
a2121d2
Default DuckDB transfers to arrow via copy_format, drop copy_method
flarco Sep 26, 2026
16c68fa
Increase test timeout from 25m to 45m in test.cli.sh
flarco Sep 26, 2026
c0ddd8d
Stream duckdb arrow output through the session via a named pipe
flarco Sep 26, 2026
006a8be
Refactor checksum_decimal calculation to use truncation in DuckDB, Du…
flarco Sep 27, 2026
7c70293
test: rework CLI test group scheduling and concurrency
flarco Sep 27, 2026
920a6da
Add -extldflags=-Wl,-no_warn_duplicate_libraries to go build in scrip…
flarco Sep 27, 2026
6da42ee
Remove -extldflags from go build command in build.sh
flarco Sep 27, 2026
e5e8061
Respect limit option when streaming D1 query results
flarco Sep 27, 2026
71a8147
fix(d1): page query results to survive memory-limit resets
flarco Sep 27, 2026
f235960
Upgrade gosnowflake to v1.19.1, allow AWS IMDS lookup
flarco Sep 27, 2026
1479db4
Track assist outcomes and fix setup terminal detection
flarco Sep 27, 2026
6611dbb
Fix interrupt during SQL Server BCP load dropping tmp table
flarco Sep 27, 2026
f6cda62
Update logging arrow lane stub reasons at debug
flarco Sep 27, 2026
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
14 changes: 13 additions & 1 deletion .github/workflows/build-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ jobs:
trigger:
runs-on: ubuntu-latest
steps:


- name: Check Version Branch
id: check_version_branch
run: |
# Only version branches (v<digit>...) are pushed to slingdata-io/sling
if [[ "${GITHUB_REF_NAME}" =~ ^v[0-9] ]]; then
echo "eligible=true" >> "$GITHUB_OUTPUT"
else
echo "eligible=false" >> "$GITHUB_OUTPUT"
echo "Skipping trigger: '${GITHUB_REF_NAME}' is not a version branch"
fi

- name: Trigger Dev Build on Specific Branch
if: steps.check_version_branch.outputs.eligible == 'true'
uses: benc-uk/workflow-dispatch@v1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ dist/
.DS_Store
demo/sling_commands_demo.workflow
*.screenstudio
./sling
/sling
core/dbio/filesys/test/dataset1M.csv
core/dbio/filesys/test/dataset100k.csv
tests/suite/
Expand Down Expand Up @@ -55,3 +55,5 @@ docs/
tests/evals/results/*.jsonl
tests/evals/results/*.summary.json
tests/evals/eval.duckdb

cmd/sling/sling
9 changes: 8 additions & 1 deletion .goreleaser.mac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,11 @@ brews:
branch: main

homepage: https://slingdata.io/
description: "Data Integration made simple, from the command line. Extract and load data from popular data sources to destinations with high performance and ease."
description: "Data Integration made simple, from the command line. Extract and load data from popular data sources to destinations with high performance and ease."
service: |
run [opt_bin/"sling", "serve", "workbench", "--no-browser"]
keep_alive true
working_dir Dir.home
log_path var/"log/sling-workbench.log"
error_log_path var/"log/sling-workbench.log"
environment_variables PATH: std_service_path_env
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ Example [Replication](https://docs.slingdata.io/sling-cli/run/configuration/repl
---

Available Connectors:
- **Databases**: [`adbc`](https://docs.slingdata.io/connections/database-connections/adbc) [`azuredwh`](https://docs.slingdata.io/connections/database-connections/azuredwh) [`azuresql`](https://docs.slingdata.io/connections/database-connections/azuresql) [`azuretable`](https://docs.slingdata.io/connections/database-connections/azuretable) [`bigquery`](https://docs.slingdata.io/connections/database-connections/bigquery) [`bigtable`](https://docs.slingdata.io/connections/database-connections/bigtable) [`clickhouse`](https://docs.slingdata.io/connections/database-connections/clickhouse) [`d1`](https://docs.slingdata.io/connections/database-connections/d1) [`databricks`](https://docs.slingdata.io/connections/database-connections/databricks) [`duckdb`](https://docs.slingdata.io/connections/database-connections/duckdb) [`elasticsearch`](https://docs.slingdata.io/connections/database-connections/elasticsearch) [`exasol`](https://docs.slingdata.io/connections/database-connections/exasol) [`fabric`](https://docs.slingdata.io/connections/database-connections/fabric) [`mariadb`](https://docs.slingdata.io/connections/database-connections/mariadb) [`mongodb`](https://docs.slingdata.io/connections/database-connections/mongodb) [`motherduck`](https://docs.slingdata.io/connections/database-connections/motherduck) [`mysql`](https://docs.slingdata.io/connections/database-connections/mysql) [`odbc`](https://docs.slingdata.io/connections/database-connections/odbc) [`oracle`](https://docs.slingdata.io/connections/database-connections/oracle) [`postgres`](https://docs.slingdata.io/connections/database-connections/postgres) [`prometheus`](https://docs.slingdata.io/connections/database-connections/prometheus) [`proton`](https://docs.slingdata.io/connections/database-connections/proton) [`redshift`](https://docs.slingdata.io/connections/database-connections/redshift) [`scylladb`](https://docs.slingdata.io/connections/database-connections/scylladb) [`snowflake`](https://docs.slingdata.io/connections/database-connections/snowflake) [`sqlite`](https://docs.slingdata.io/connections/database-connections/sqlite) [`sqlserver`](https://docs.slingdata.io/connections/database-connections/sqlserver) [`starrocks`](https://docs.slingdata.io/connections/database-connections/starrocks) [`trino`](https://docs.slingdata.io/connections/database-connections/trino)
- **Databases**: [`adbc`](https://docs.slingdata.io/connections/database-connections/adbc) [`azuredwh`](https://docs.slingdata.io/connections/database-connections/azuredwh) [`azuresql`](https://docs.slingdata.io/connections/database-connections/azuresql) [`azuretable`](https://docs.slingdata.io/connections/database-connections/azuretable) [`bigquery`](https://docs.slingdata.io/connections/database-connections/bigquery) [`bigtable`](https://docs.slingdata.io/connections/database-connections/bigtable) [`clickhouse`](https://docs.slingdata.io/connections/database-connections/clickhouse) [`d1`](https://docs.slingdata.io/connections/database-connections/d1) [`databricks`](https://docs.slingdata.io/connections/database-connections/databricks) [`dbase`](https://docs.slingdata.io/connections/database-connections/dbase) [`duckdb`](https://docs.slingdata.io/connections/database-connections/duckdb) [`dynamodb`](https://docs.slingdata.io/connections/database-connections/dynamodb) [`elasticsearch`](https://docs.slingdata.io/connections/database-connections/elasticsearch) [`opensearch`](https://docs.slingdata.io/connections/database-connections/opensearch) [`exasol`](https://docs.slingdata.io/connections/database-connections/exasol) [`fabric`](https://docs.slingdata.io/connections/database-connections/fabric) [`firebolt`](https://docs.slingdata.io/connections/database-connections/firebolt) [`mariadb`](https://docs.slingdata.io/connections/database-connections/mariadb) [`mongodb`](https://docs.slingdata.io/connections/database-connections/mongodb) [`motherduck`](https://docs.slingdata.io/connections/database-connections/motherduck) [`mysql`](https://docs.slingdata.io/connections/database-connections/mysql) [`odbc`](https://docs.slingdata.io/connections/database-connections/odbc) [`oracle`](https://docs.slingdata.io/connections/database-connections/oracle) [`postgres`](https://docs.slingdata.io/connections/database-connections/postgres) [`prometheus`](https://docs.slingdata.io/connections/database-connections/prometheus) [`proton`](https://docs.slingdata.io/connections/database-connections/proton) [`redshift`](https://docs.slingdata.io/connections/database-connections/redshift) [`scylladb`](https://docs.slingdata.io/connections/database-connections/scylladb) [`snowflake`](https://docs.slingdata.io/connections/database-connections/snowflake) [`sqlite`](https://docs.slingdata.io/connections/database-connections/sqlite) [`sqlserver`](https://docs.slingdata.io/connections/database-connections/sqlserver) [`starrocks`](https://docs.slingdata.io/connections/database-connections/starrocks) [`trino`](https://docs.slingdata.io/connections/database-connections/trino)

- **Data Lakes**:[`athena`](https://docs.slingdata.io/connections/datalake-connections/athena) [`Ducklake`](https://docs.slingdata.io/connections/datalake-connections/ducklake) [`iceberg`](https://docs.slingdata.io/connections/datalake-connections/iceberg) [`S3 Tables`](https://docs.slingdata.io/connections/datalake-connections/iceberg)
- **Data Lakes**:[`athena`](https://docs.slingdata.io/connections/datalake-connections/athena) [`Ducklake`](https://docs.slingdata.io/connections/datalake-connections/ducklake) [`iceberg`](https://docs.slingdata.io/connections/datalake-connections/iceberg) [`S3 Tables`](https://docs.slingdata.io/connections/datalake-connections/iceberg) [`lancedb`](https://docs.slingdata.io/connections/datalake-connections/lancedb)

- **File Systems**: [`azure`](https://docs.slingdata.io/connections/file-connections/azure) [`b2`](https://docs.slingdata.io/connections/file-connections/b2) [`dospaces`](https://docs.slingdata.io/connections/file-connections/dospaces) [`gs`](https://docs.slingdata.io/connections/file-connections/gs) [`local`](https://docs.slingdata.io/connections/file-connections/local) [`minio`](https://docs.slingdata.io/connections/file-connections/minio) [`r2`](https://docs.slingdata.io/connections/file-connections/r2) [`s3`](https://docs.slingdata.io/connections/file-connections/s3) [`sftp`](https://docs.slingdata.io/connections/file-connections/sftp) [`wasabi`](https://docs.slingdata.io/connections/file-connections/wasabi)
- **File Formats**: `csv`, `parquet`, `xlsx`, `json`, `geojson`, `avro`, `xml`, `sas7bday`
Expand Down Expand Up @@ -116,6 +116,12 @@ $ sling conns discover LOCALHOST_DEV
...
```

---

Databricks: Unity Catalog Volumes are a file connection (`type: databricks-volume`). Direct Delta ingest uses `copy_method: zerobus` on `type: databricks`. See https://docs.slingdata.io/connections/database-connections/databricks

---

## Installation

#### One-liner on Mac / Linux
Expand Down Expand Up @@ -158,6 +164,7 @@ Pre-built binaries for macOS, Linux, and Windows are available on the [releases
Requirements:
- Install Go 1.22+ (https://go.dev/doc/install)
- Install a C compiler ([gcc](https://www.google.com/search?q=install+gcc&oq=install+gcc), [tdm-gcc](https://jmeubank.github.io/tdm-gcc/), [mingw](https://www.google.com/search?q=install+mingw), etc)
- `CGO_ENABLED=1` (needed for SQLite and Databricks Zerobus; this repo's build scripts already set it)

#### Linux or Mac
```bash
Expand Down
16 changes: 11 additions & 5 deletions cmd/sling/resource/llm_CONNECTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ For database operations (queries, schema exploration) and file system operations

## 3. Connection Types Overview

Sling supports 41+ different connection types across four categories:
Sling supports 42+ different connection types across four categories:

### Database Connections (24 types)
- **Relational**: PostgreSQL, MySQL, MariaDB, SQLServer, Oracle, SQLite
### Database Connections (25 types)
- **Relational**: PostgreSQL, MySQL, MariaDB, SQLServer, Oracle, SQLite, dBase
- **Cloud Warehouses**: Snowflake, BigQuery, Redshift, Databricks
- **Analytics**: ClickHouse, DuckDB, MotherDuck, StarRocks, Trino, Proton
- **NoSQL**: MongoDB, ElasticSearch, Prometheus
Expand All @@ -122,9 +122,9 @@ Sling supports 41+ different connection types across four categories:
- **Cloud Drives**: Google Drive
- **Local**: Local file system

### Datalake Connections (4 types)
### Datalake Connections (5 types)
- **Query Engines**: Athena, DuckLake
- **Table Formats**: Iceberg
- **Table Formats**: Iceberg, LanceDB

### API Connections
- **Custom APIs**: User-defined API specifications in YAML format
Expand Down Expand Up @@ -161,10 +161,14 @@ Navigate or fetch the content of the connector from the below respective URL to

**SQLite (`sqlite`)** -> https://docs.slingdata.io/connections/database-connections/sqlite

**dBase (`dbase`)** -> https://docs.slingdata.io/connections/database-connections/dbase

**MotherDuck (`motherduck`)** -> https://docs.slingdata.io/connections/database-connections/motherduck

**ElasticSearch (`elasticsearch`)** -> https://docs.slingdata.io/connections/database-connections/elasticsearch

**OpenSearch (`opensearch`)** -> https://docs.slingdata.io/connections/database-connections/opensearch

**Prometheus (`prometheus`)** -> https://docs.slingdata.io/connections/database-connections/prometheus

**StarRocks (`starrocks`)** -> https://docs.slingdata.io/connections/database-connections/starrocks
Expand Down Expand Up @@ -223,6 +227,8 @@ Navigate or fetch the content of the connector from the below respective URL to

**DuckLake (`ducklake`)** -> https://docs.slingdata.io/connections/datalake-connections/ducklake

**LanceDB (`lancedb`)** -> https://docs.slingdata.io/connections/datalake-connections/lancedb

---

## 7. API Connections
Expand Down
2 changes: 1 addition & 1 deletion cmd/sling/resource/llm_CONNECTION_DATABASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Database operations in Sling provide comprehensive functionality for interacting

### Supported Database Types

- **Relational**: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite
- **Relational**: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, dBase
- **Cloud Warehouses**: Snowflake, BigQuery, Redshift, Databricks
- **Analytics**: ClickHouse, DuckDB, MotherDuck, StarRocks, Trino, Proton
- **NoSQL**: MongoDB, ElasticSearch, Prometheus
Expand Down
82 changes: 72 additions & 10 deletions cmd/sling/sling_assist.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"strings"
"time"

"github.com/flarco/g"
"github.com/integrii/flaggy"
Expand Down Expand Up @@ -106,13 +107,16 @@ func processAssist(c *g.CliSC) (ok bool, err error) {

switch c.UsedSC() {
case "setup":
return ok, runAssistSetup(c)
err = runAssistSetup(c)
case "error":
return ok, runAssistError(c)
err = runAssistError(c)
case "report":
return ok, runAssistReport(c)
err = runAssistReport(c)
default:
err = runAssistFlags(c)
}
return ok, runAssistFlags(c)
assistTelProps.setOutcome(err)
return ok, err
}

// runAssistFlags is the flags-only path: --resume, else first-run
Expand Down Expand Up @@ -151,8 +155,32 @@ func runAssistSession(c *g.CliSC) error {
Headless: cast.ToBool(vals["non-interactive"]),
}
applyAssistOut(&opts, cast.ToString(vals["out"]))
return launchAssist(opts)
}

// launchAssist runs the session and records launch, duration and agent exit code.
// A non-zero agent exit calls os.Exit, so the event is sent here first.
func launchAssist(opts assist.SessionOptions) error {
start := time.Now()
launched := false
opts.OnLaunch = func(agent string) {
launched = true
assistTelProps.set("agent", agent)
assistTelProps.set("launched", true)
go Track("assist_launch") // survives a closed terminal (SIGHUP)
}
_, err := assist.Session(opts)
if !launched {
if err == nil {
assistTelProps.set("outcome", "not_launched")
}
return err
}
assistTelProps.set("duration_s", int(time.Since(start).Seconds()))
if code, ok := assist.ExitCodeOf(err); ok {
assistTelProps.set("exit_code", code)
assistTelProps.set("outcome", "agent_exit")
Track(g.CliObj.Name)
os.Exit(code)
}
return err
Expand All @@ -177,6 +205,7 @@ func runAssistResume(c *g.CliSC, id string) error {
e, err := assist.PickHistoryEntry()
if err != nil {
if errors.Is(err, assist.ErrUserAborted) {
assistTelProps.set("outcome", "cancelled")
return nil
}
return err
Expand All @@ -191,11 +220,7 @@ func runAssistResume(c *g.CliSC, id string) error {
Headless: cast.ToBool(vals["non-interactive"]),
}
applyAssistOut(&opts, cast.ToString(vals["out"]))
_, err := assist.Session(opts)
if code, ok := assist.ExitCodeOf(err); ok {
os.Exit(code)
}
return err
return launchAssist(opts)
}

// padAssistResumeFlag lets flaggy accept a bare `--resume` (picker) as `--resume=`.
Expand Down Expand Up @@ -310,6 +335,10 @@ func runAssistSetup(c *g.CliSC) error {
fmt.Fprintln(os.Stdout, "")
action, err := assist.RunSetupActionForm(report)
if err != nil {
if errors.Is(err, assist.ErrUserAborted) {
assistTelProps.set("outcome", "cancelled")
return nil
}
return err
}
switch action {
Expand All @@ -327,6 +356,7 @@ func runAssistSetup(c *g.CliSC) error {
vals["reconfigure"] = true
return runSetupInstall(vals, allComponents(), profileExists, report)
case assist.SetupActionExit:
assistTelProps.set("outcome", "cancelled")
return nil
}
return nil
Expand All @@ -341,6 +371,7 @@ func runAssistSetup(c *g.CliSC) error {
result, err := assist.RunHarnessConfirmForm(prefill)
if err != nil {
if errors.Is(err, assist.ErrUserAborted) {
assistTelProps.set("outcome", "cancelled")
return nil
}
return err
Expand Down Expand Up @@ -391,6 +422,7 @@ func runSetupInstall(vals map[string]any, components []string, _ bool, _ *assist
result, err := assist.RunInstallForm(prefill)
if err != nil {
if errors.Is(err, assist.ErrUserAborted) {
assistTelProps.set("outcome", "cancelled")
return nil
}
return err
Expand Down Expand Up @@ -584,7 +616,37 @@ func setAssistTel(c *g.CliSC) {
}
tel["channel"] = channel
}
env.SetTelVal("assist", g.Marshal(tel))
assistTelProps = assistTel(tel)
assistTelProps.publish()
}

// assistTel is the `assist` telemetry prop, sent as one JSON string.
type assistTel map[string]any

var assistTelProps = assistTel{}

func (t assistTel) publish() {
env.SetTelVal("assist", g.Marshal(map[string]any(t)))
}

func (t assistTel) set(key string, val any) {
t[key] = val
t.publish()
}

// setOutcome records how the command ended, unless a path already set it.
func (t assistTel) setOutcome(err error) {
if _, ok := t["outcome"]; ok {
return
}
switch {
case errors.Is(err, assist.ErrNoTTY):
t.set("outcome", "no_tty")
case err != nil:
t.set("outcome", "error")
default:
t.set("outcome", "completed")
}
}

// flatVals returns the val map from the active subcommand. CliSC stores per-
Expand Down
52 changes: 0 additions & 52 deletions cmd/sling/sling_assist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import (
"path/filepath"
"strings"
"testing"

"github.com/flarco/g"
"github.com/slingdata-io/sling-cli/core/dbio"
"github.com/slingdata-io/sling-cli/core/dbio/connection"
)

func TestAssistBrowseFlagRemoved(t *testing.T) {
Expand Down Expand Up @@ -193,51 +189,3 @@ func TestParseKVListUnquotedStillSplits(t *testing.T) {
t.Fatalf("%v", got)
}
}

func TestOverlaySpecConn(t *testing.T) {
dir := t.TempDir()
specPath := filepath.Join(dir, "draft.yaml")
if err := os.WriteFile(specPath, []byte("name: draft\n"), 0o644); err != nil {
t.Fatal(err)
}

apiConn, err := connection.NewConnection("MY_API", dbio.TypeApi, g.M("type", "api", "spec", "baseline"))
if err != nil {
t.Fatal(err)
}
otherConn, err := connection.NewConnection("LOCAL", dbio.TypeFileLocal, g.M("type", "file"))
if err != nil {
t.Fatal(err)
}
entries := connection.ConnEntries{
{Name: "MY_API", Connection: apiConn},
{Name: "LOCAL", Connection: otherConn},
}

out, err := overlaySpecConn(entries, "MY_API", "draft.yaml", dir)
if err != nil {
t.Fatal(err)
}

got := out.Get("MY_API").Connection.Data["spec"]
want := "file://" + specPath
if got != want {
t.Fatalf("overlay spec=%q want %q", got, want)
}
// original entries stay untouched
if entries.Get("MY_API").Connection.Data["spec"] != "baseline" {
t.Fatalf("original entry was mutated")
}
if out.Get("LOCAL").Connection.Data["spec"] != nil {
t.Fatalf("unrelated entry changed")
}

// missing file errors
if _, err := overlaySpecConn(entries, "MY_API", "nope.yaml", dir); err == nil {
t.Fatal("expected error for missing spec file")
}
// unknown connection errors
if _, err := overlaySpecConn(entries, "NOPE", specPath, dir); err == nil {
t.Fatal("expected error for unknown connection")
}
}
Loading
Loading