diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..a944f693 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,46 @@ +# go-sqlcmd Development Container +FROM mcr.microsoft.com/devcontainers/go:1.24-bookworm + +# Install additional OS packages +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get install -y curl libkrb5-dev gnupg2 \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install Microsoft ODBC driver and mssql-tools18 (legacy ODBC sqlcmd/bcp for compatibility testing) +RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \ + && curl -fsSL https://packages.microsoft.com/config/debian/12/prod.list | tee /etc/apt/sources.list.d/mssql-release.list \ + && apt-get update \ + && ACCEPT_EULA=Y apt-get install -y msodbcsql18 mssql-tools18 unixodbc-dev \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* +ENV PATH="/opt/mssql-tools18/bin:${PATH}" + +# Install golangci-lint for code quality +# Download pre-built binary with SHA256 checksum verification (supply chain security) +# Supports both amd64 and arm64 architectures +ARG GOLANGCI_LINT_VERSION=1.64.8 +ARG GOLANGCI_LINT_SHA256_AMD64=b6270687afb143d019f387c791cd2a6f1cb383be9b3124d241ca11bd3ce2e54e +ARG GOLANGCI_LINT_SHA256_ARM64=a6ab58ebcb1c48572622146cdaec2956f56871038a54ed1149f1386e287789a5 +RUN ARCH=$(dpkg --print-architecture) \ + && if [ "$ARCH" = "amd64" ]; then \ + CHECKSUM="${GOLANGCI_LINT_SHA256_AMD64}"; \ + elif [ "$ARCH" = "arm64" ]; then \ + CHECKSUM="${GOLANGCI_LINT_SHA256_ARM64}"; \ + else \ + echo "Unsupported architecture: $ARCH" && exit 1; \ + fi \ + && curl -fsSLO "https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" \ + && echo "${CHECKSUM} golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" | sha256sum -c - \ + && tar -xzf "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" \ + && mv "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}/golangci-lint" /usr/local/bin/ \ + && rm -rf "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}" "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" \ + && golangci-lint --version + +# Install additional Go tools (pinned versions for reproducibility) +RUN go install golang.org/x/tools/gopls@v0.18.1 \ + && go install github.com/go-delve/delve/cmd/dlv@v1.24.1 \ + && go install honnef.co/go/tools/cmd/staticcheck@v0.6.1 \ + && go install golang.org/x/text/cmd/gotext@v0.22.0 + +# Create bin directory for local sqlcmd builds +RUN mkdir -p /home/vscode/bin && chown vscode:vscode /home/vscode/bin +ENV PATH="/home/vscode/bin:${PATH}" diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 00000000..30d855df --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,276 @@ +# go-sqlcmd Development Container + +This folder contains the configuration for a VS Code Dev Container / GitHub Codespaces development environment for go-sqlcmd. + +## What's Included + +- **Go 1.24** development environment with all necessary tools +- **SQL Server 2025** (Developer Edition) running in a sidecar container +- **Pre-configured VS Code extensions**: + - Go (official extension) + - MS SQL (for database management) + - Docker + - GitHub Copilot + - GitLens +- **Go quality tools**: golangci-lint, gopls, delve debugger, staticcheck +- **Locally built sqlcmd** added to PATH automatically + +## Quick Start + +### Using VS Code (Recommended) + +1. Install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +2. Open this repository in VS Code +3. When prompted, click **"Reopen in Container"**, or: + - Press `F1` and select **"Dev Containers: Reopen in Container"** +4. Wait for the container to build (first time takes ~5 minutes) +5. Start developing! + +### Using GitHub Codespaces + +1. Click the green **"Code"** button on the repository +2. Select **"Codespaces"** tab +3. Click **"Create codespace on main"** (or your preferred branch) +4. Wait for the environment to start + +## Running Tests + +Environment variables are pre-configured for running tests: + +```bash +# Run all tests +go test ./... + +# Run short tests +go test -short ./... + +# Run tests with verbose output +go test -v ./... +``` + +### Helpful Aliases + +After the container starts, these aliases are available: + +| Alias | Command | +|-------|---------| +| `gtest` | Run all tests | +| `gtest-short` | Run short tests | +| `gtest-v` | Run tests with verbose output | +| `gbuild` | Build sqlcmd locally | +| `ginstall` | Build and install sqlcmd to ~/bin | +| `gfmt` | Format code | +| `gvet` | Run go vet | +| `glint` | Run golangci-lint | +| `ggen` | Run go generate (for translations) | +| `test-db` | Test database connection | +| `sql` | Connect to SQL Server (go-sqlcmd) | +| `sql-legacy` | Connect using legacy ODBC sqlcmd | +| `rebuild` | Rebuild sqlcmd | + +## SQL Server Connection + +The SQL Server instance is accessible at: + +- **Server**: `localhost,1433` +- **Username**: `sa` +- **Password**: Available via `$SQLCMDPASSWORD` environment variable +- **Database**: `master` (default) or `SqlCmdTest` (created for testing) + +> **Note**: The SQL Server password for this devcontainer is provided via the `$SQLCMDPASSWORD` environment variable and is a non-production, development-only default. +> For the default devcontainer setup, the password value (`SqlCmd@2025!`) is checked into this repository for convenience; override it via environment variables or Codespaces/CI secrets for non-local use. +> When using VS Code's MSSQL extension, copy the value from `$SQLCMDPASSWORD` when prompted. + +### Using the Built-in sqlcmd + +The container has **two versions** of sqlcmd available: + +1. **go-sqlcmd** (this project) - the modern Go-based sqlcmd, built from source at `~/bin/sqlcmd` +2. **Legacy ODBC sqlcmd** - the classic version from mssql-tools18 at `/opt/mssql-tools18/bin/sqlcmd` + +Since go-sqlcmd is first in PATH, the `sqlcmd` command runs the modern version. Use the aliases or full paths to choose which version: + +```bash +# go-sqlcmd (this project) - default in PATH +sql # alias for go-sqlcmd with connection args +sqlcmd -S localhost -U sa -P "$SQLCMDPASSWORD" -C + +# Legacy ODBC sqlcmd (for compatibility testing) +sql-legacy # alias for legacy sqlcmd with connection args +/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SQLCMDPASSWORD" -C + +# Run a query with go-sqlcmd +sql -Q "SELECT @@VERSION" + +# Compare behavior between versions +sql -Q "SELECT 1 AS test" +sql-legacy -Q "SELECT 1 AS test" +``` + +### VS Code SQL Extension + +The MSSQL extension is pre-configured with a connection profile named **"sqlcmd-container (use SQLCMDPASSWORD env var)"**. Click the SQL Server icon in the Activity Bar to connect. + +### Connecting from Host Machine Tools + +The SQL Server port (1433) is forwarded to your host machine, so you can connect using tools installed locally: + +#### Azure Data Studio + +1. Open Azure Data Studio on your host machine +2. Create a new connection: + - Server: `localhost,1433` + - Authentication: SQL Login + - User: `sa` + - Password: `SqlCmd@2025!` + - Trust server certificate: Yes + +#### SQL Server Management Studio (Windows) + +1. Open SSMS on your Windows host +2. Connect to Server: + - Server name: `localhost,1433` + - Authentication: SQL Server Authentication + - Login: `sa` + - Password: `SqlCmd@2025!` + - Check "Trust server certificate" + +## Environment Variables + +The following environment variables are set automatically: + +| Variable | Value | +|----------|-------| +| `SQLCMDSERVER` | `localhost` | +| `SQLCMDUSER` | `sa` | +| `SQLCMDPASSWORD` | `SqlCmd@2025!` | +| `SQLCMDDATABASE` | `master` | +| `SQLCMDDBNAME` | `master` | + +These use the same environment variable names as the CI pipeline to ensure local tests behave similarly, although the actual password and SQL Server version in CI may differ. + +## Working with sqlcmd + +### Build and Test Workflow + +```bash +# Build sqlcmd from source +ginstall + +# Test the build +~/bin/sqlcmd --version + +# Run a query against the local SQL Server +sql -Q "SELECT name FROM sys.databases" + +# Run the test suite +gtest +``` + +### Rebuilding After Changes + +```bash +# Quick rebuild +rebuild + +# Or full rebuild with install +ginstall +``` + +## Customization + +### Adding SQL Setup Scripts + +The `setup.sql` script in `.devcontainer/mssql/` is executed automatically when the container starts. To run additional SQL scripts, either add them to `setup.sql` or update `post-create.sh` to execute them explicitly. + +### Modifying the SA Password + +To change the SQL Server password: + +1. Update both `SA_PASSWORD` and `MSSQL_SA_PASSWORD` in `docker-compose.yml` (these must match) +2. Update `SQLCMDPASSWORD` in `devcontainer.json` (both `remoteEnv` and `go.testEnvVars` sections) +3. Update the password in the `mssql.connections` settings in `devcontainer.json` + +### Using a Different SQL Server Version + +Edit `docker-compose.yml` and change the image tag: + +```yaml +db: + image: mcr.microsoft.com/mssql/server:2022-latest # or 2019-latest +``` + +> **Note:** SQL Server 2025 is the default as it includes the latest features. + +## Troubleshooting + +### ARM64 (Apple Silicon) Users + +SQL Server container images may have issues on ARM64 architecture. If you encounter problems: + +1. Edit `docker-compose.yml` to use SQL Server 2022: + ```yaml + db: + image: mcr.microsoft.com/mssql/server:2022-latest + ``` +2. Ensure Rosetta is enabled in Docker Desktop: **Settings > General > "Use Rosetta for x86_64/amd64 emulation on Apple Silicon"** + +### SQL Server not starting + +Check the Docker logs: +```bash +docker logs $(docker ps -qf "name=db") +``` + +Common issues: +- Insufficient memory (SQL Server requires at least 2GB RAM) +- Port 1433 already in use +- ARM64 architecture issues (see above) + +### Connection refused + +Wait a few seconds after the container starts. SQL Server takes ~30 seconds to become ready. The health check should handle this automatically. + +### Tests failing with connection errors + +Ensure the environment variables are set: +```bash +echo $SQLCMDSERVER +echo $SQLCMDPASSWORD +``` + +If empty, try restarting the terminal or running: +```bash +source ~/.bashrc +``` + +### sqlcmd not found + +Run the install command: +```bash +ginstall +``` + +Or manually: +```bash +go build -o ~/bin/sqlcmd ./cmd/modern +``` + +## Files Reference + +| File | Purpose | +|------|---------| +| `devcontainer.json` | Main configuration file | +| `docker-compose.yml` | Container orchestration (Go + SQL Server) | +| `Dockerfile` | Go development container image | +| `post-create.sh` | Setup script (runs after container creation) | +| `mssql/setup.sql` | Initial database setup script | + +## Contributing + +When modifying the devcontainer: + +1. Test locally with `Dev Containers: Rebuild Container` +2. Ensure all tests pass: `go test ./...` +3. Verify SQL connection works: `test-db` +4. Verify sqlcmd builds: `ginstall && ~/bin/sqlcmd --version` diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..41021397 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,91 @@ +{ + "name": "go-sqlcmd Development", + "dockerComposeFile": "docker-compose.yml", + "service": "devcontainer", + "workspaceFolder": "/workspaces/go-sqlcmd", + "shutdownAction": "stopCompose", + + // Configure tool-specific properties + "customizations": { + "vscode": { + "extensions": [ + "golang.go", + "ms-mssql.mssql", + "ms-azuretools.vscode-docker", + "GitHub.copilot", + "GitHub.copilot-chat", + "eamodio.gitlens", + "EditorConfig.EditorConfig", + "streetsidesoftware.code-spell-checker" + ], + "settings": { + "go.toolsManagement.autoUpdate": false, + "go.useLanguageServer": true, + "go.lintTool": "golangci-lint", + "go.lintFlags": ["--fast"], + "go.testEnvVars": { + "SQLCMDSERVER": "localhost", + "SQLCMDUSER": "sa", + "SQLCMDPASSWORD": "${env:SQLCMDPASSWORD}", + "SQLCMDDATABASE": "master" + }, + "mssql.connections": [ + { + "server": "localhost,1433", + "database": "master", + "authenticationType": "SqlLogin", + "user": "sa", + "password": "", + "savePassword": false, + "profileName": "sqlcmd-container (use SQLCMDPASSWORD env var)", + "encrypt": "Optional", + "trustServerCertificate": true + } + ], + "editor.formatOnSave": true, + "editor.defaultFormatter": "golang.go", + "[go]": { + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + } + }, + "terminal.integrated.defaultProfile.linux": "bash" + } + } + }, + + // Forward the SQL Server port + "forwardPorts": [1433], + "portsAttributes": { + "1433": { + "label": "SQL Server", + "onAutoForward": "silent" + } + }, + + // Use 'postCreateCommand' to run commands after the container is created + "postCreateCommand": "bash .devcontainer/post-create.sh", + + // Environment variables for tests - password must match docker-compose.yml + // This is a development-only container credential, not a production secret. + // For GitHub Codespaces, you can override SQLCMDPASSWORD via Codespaces Secrets. + "remoteEnv": { + "SQLCMDSERVER": "localhost", + "SQLCMDUSER": "sa", + "SQLCMDPASSWORD": "${localEnv:SQLCMDPASSWORD:SqlCmd@2025!}", + "SQLCMDDATABASE": "master", + "SQLCMDDBNAME": "master" + }, + + // Features to add to the dev container + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "moby": true + }, + "ghcr.io/devcontainers/features/github-cli:1": { + "version": "latest" + } + } +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..010fd74f --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,37 @@ +version: '3.8' + +services: + devcontainer: + build: + context: . + dockerfile: Dockerfile + volumes: + - ..:/workspaces/go-sqlcmd:cached + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db + depends_on: + db: + condition: service_healthy + + db: + image: mcr.microsoft.com/mssql/server:2025-latest + restart: unless-stopped + environment: + ACCEPT_EULA: "Y" + # Password can be overridden via SQLCMDPASSWORD environment variable + SA_PASSWORD: "${SQLCMDPASSWORD:-SqlCmd@2025!}" + MSSQL_SA_PASSWORD: "${SQLCMDPASSWORD:-SqlCmd@2025!}" + MSSQL_PID: "Developer" + volumes: + - mssql-data:/var/opt/mssql + healthcheck: + test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P \"$$MSSQL_SA_PASSWORD\" -C -Q \"SELECT 1\" || exit 1"] + interval: 10s + timeout: 5s + retries: 15 + start_period: 45s + +volumes: + mssql-data: diff --git a/.devcontainer/mssql/setup.sql b/.devcontainer/mssql/setup.sql new file mode 100644 index 00000000..79aac446 --- /dev/null +++ b/.devcontainer/mssql/setup.sql @@ -0,0 +1,69 @@ +-- go-sqlcmd Development Database Setup +-- This script runs automatically when the devcontainer starts + +USE master; +GO + +-- Create a test database for development +IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'SqlCmdTest') +BEGIN + CREATE DATABASE SqlCmdTest; + PRINT 'Created database: SqlCmdTest'; +END +GO + +-- Enable contained database authentication for testing +-- Use TRY/CATCH in case this fails on certain SQL Server configurations +BEGIN TRY + EXEC sp_configure 'contained database authentication', 1; + RECONFIGURE; +END TRY +BEGIN CATCH + PRINT 'Note: Could not enable contained database authentication (may already be enabled or not supported)'; +END CATCH; +GO + +-- Make SqlCmdTest a contained database for testing +BEGIN TRY + ALTER DATABASE SqlCmdTest SET CONTAINMENT = PARTIAL; +END TRY +BEGIN CATCH + PRINT 'Note: Could not set database containment (may not be supported)'; +END CATCH; +GO + +USE SqlCmdTest; +GO + +-- Create a sample table for quick testing +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'TestTable') +BEGIN + CREATE TABLE TestTable ( + ID INT IDENTITY(1,1) PRIMARY KEY, + Name NVARCHAR(100) NOT NULL, + Value NVARCHAR(MAX), + CreatedAt DATETIME2 DEFAULT GETUTCDATE() + ); + + INSERT INTO TestTable (Name, Value) VALUES + ('Test1', 'Sample value 1'), + ('Test2', 'Sample value 2'), + ('Test3', 'Sample value 3'); + + PRINT 'Created table: TestTable with sample data'; +END +GO + +-- Create a view for testing +IF NOT EXISTS (SELECT * FROM sys.views WHERE name = 'TestView') +BEGIN + EXEC('CREATE VIEW TestView AS SELECT ID, Name, CreatedAt FROM TestTable'); + PRINT 'Created view: TestView'; +END +GO + +PRINT 'go-sqlcmd development database setup complete!'; +PRINT 'Test database: SqlCmdTest'; +PRINT 'Sample table: TestTable (3 rows)'; +PRINT 'Sample view: TestView'; +GO diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100644 index 00000000..364281ef --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,141 @@ +#!/bin/bash +set -e + +echo "=== go-sqlcmd Development Container Setup ===" + +# Dynamic workspace detection with fallback +if [ -n "${WORKSPACE_FOLDER}" ] && [ -d "${WORKSPACE_FOLDER}" ]; then + cd "${WORKSPACE_FOLDER}" +elif [ -d "/workspaces/go-sqlcmd" ]; then + cd /workspaces/go-sqlcmd +else + # Find workspace by looking for go.mod + workspace_go_mod="$(find /workspaces -maxdepth 2 -name 'go.mod' -type f -print -quit 2>/dev/null)" + if [ -n "$workspace_go_mod" ]; then + cd "$(dirname "$workspace_go_mod")" + else + echo "Error: Could not determine workspace directory" >&2 + exit 1 + fi +fi +echo "πŸ“ Working in: $(pwd)" + +# Download Go dependencies +echo "πŸ“¦ Downloading Go dependencies..." +go mod download + +# Build sqlcmd and add to PATH +echo "πŸ”¨ Building sqlcmd..." +go build -o ~/bin/sqlcmd ./cmd/modern +echo "βœ… sqlcmd built and added to PATH at ~/bin/sqlcmd" + +# Verify build works +echo "πŸ”¨ Verifying full build..." +go build ./... + +# Wait for SQL Server to be ready (health check should have done this, but let's verify) +echo "πŸ”„ Verifying SQL Server connection..." +max_attempts=30 +attempt=1 +sql_ready=false +while [ $attempt -le $max_attempts ]; do + if ~/bin/sqlcmd -S localhost -U sa -P "${SQLCMDPASSWORD}" -C -Q "SELECT 1" > /dev/null 2>&1; then + echo "βœ… SQL Server is ready!" + sql_ready=true + break + fi + echo " Waiting for SQL Server... (attempt $attempt/$max_attempts)" + sleep 2 + attempt=$((attempt + 1)) +done + +if [ "$sql_ready" = false ]; then + echo "⚠️ Warning: Could not verify SQL Server connection. Tests may fail." +fi + +# Run initial setup SQL if it exists and SQL Server is ready +if [ -f ".devcontainer/mssql/setup.sql" ]; then + if [ "$sql_ready" = true ]; then + echo "πŸ“‹ Running setup.sql..." + ~/bin/sqlcmd -S localhost -U sa -P "${SQLCMDPASSWORD}" -C -i .devcontainer/mssql/setup.sql + else + echo "⚠️ Skipping setup.sql because SQL Server connection could not be verified." + fi +fi + +# Create useful aliases in a dedicated directory (safe and idempotent) +echo "πŸ”§ Setting up helpful aliases..." +mkdir -p ~/.bash_aliases.d +cat > ~/.bash_aliases.d/go-sqlcmd << 'EOF' +# go-sqlcmd development aliases +alias gtest='go test ./...' +alias gtest-short='go test -short ./...' +alias gtest-v='go test -v ./...' +alias gbuild='go build ./cmd/modern && echo "Built: ./modern"' +alias ginstall='go build -o ~/bin/sqlcmd ./cmd/modern && echo "Installed to ~/bin/sqlcmd"' +alias gfmt='go fmt ./...' +alias gvet='go vet ./...' +alias glint='golangci-lint run' +alias ggen='go generate ./...' + +# sqlcmd shortcut - uses the locally built version +alias sql='~/bin/sqlcmd -S localhost -U sa -P "$SQLCMDPASSWORD" -C' + +# Legacy ODBC sqlcmd for compatibility testing +alias sql-legacy='/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SQLCMDPASSWORD" -C' + +# Quick test connection +alias test-db='~/bin/sqlcmd -S localhost -U sa -P "$SQLCMDPASSWORD" -C -Q "SELECT @@VERSION"' + +# Rebuild and test +alias rebuild='go build -o ~/bin/sqlcmd ./cmd/modern && echo "Rebuilt sqlcmd"' +EOF + +# Ensure aliases are sourced from .bashrc +if ! grep -q 'go-sqlcmd aliases' ~/.bashrc 2>/dev/null; then + { + echo '' + echo '# go-sqlcmd aliases' + echo 'if [ -f ~/.bash_aliases ]; then' + echo ' # Source traditional aliases file if present' + echo ' . ~/.bash_aliases' + echo 'fi' + echo '' + echo 'if [ -d ~/.bash_aliases.d ]; then' + echo ' # Source all alias snippets from ~/.bash_aliases.d' + echo ' for f in ~/.bash_aliases.d/*; do' + echo ' [ -r "$f" ] && . "$f"' + echo ' done' + echo 'fi' + } >> ~/.bashrc +fi + +echo "" +echo "=== Setup Complete! ===" +echo "" +echo "πŸ“– Quick Reference:" +echo " gtest - Run all tests" +echo " gtest-short - Run short tests" +echo " gtest-v - Run tests with verbose output" +echo " gbuild - Build sqlcmd locally" +echo " ginstall - Build and install sqlcmd to ~/bin" +echo " gfmt - Format code" +echo " gvet - Run go vet" +echo " glint - Run golangci-lint" +echo " ggen - Run go generate (for translations)" +echo " test-db - Test database connection" +echo " sql - Connect to SQL Server (go-sqlcmd)" +echo " sql-legacy - Connect using legacy ODBC sqlcmd" +echo " rebuild - Rebuild sqlcmd" +echo "" +echo "πŸ”§ Your locally built sqlcmd is at ~/bin/sqlcmd and in PATH" +echo "" +echo "πŸ”— SQL Server Connection:" +echo " Server: localhost,1433" +echo " User: sa" +echo " Password: (from SQLCMDPASSWORD environment variable)" +echo " Database: master (or SqlCmdTest)" +echo "" +echo "πŸ§ͺ Environment variables are pre-configured for tests." +echo " Run 'go test ./...' to execute the full test suite." +echo "" diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..329bd7a0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,72 @@ +# go-sqlcmd Docker Ignore File +# Exclude files not needed in the container build context + +# Git +.git/ +.gitignore + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Go build artifacts +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.test +*.out + +# Pre-built binaries (we build from source in the container) +darwin-amd64/ +darwin-arm64/ +linux-amd64/ +linux-arm64/ +linux-s390x/ +windows-amd64/ +windows-arm/ +windows-arm64/ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Test coverage +*.cover +*.coverprofile +coverage.out +coverage.html + +# Dependency directories +vendor/ + +# Documentation and non-essential files (keep devcontainer docs) +LICENSE* +SECURITY* +CONTRIBUTING* +CHANGELOG* + +# CI/CD files (not needed in container) +.github/ +.pipelines/ +appveyor.yml + +# Dev container configuration (not needed in image build) +.devcontainer/ + +# Test output and temporary files +*.log +*.tmp +tmp/ + +# Release files +release/ diff --git a/README.md b/README.md index e4a1e35d..576439da 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # SQLCMD CLI +[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](.devcontainer/README.md) + This repo contains the `sqlcmd` command line tool and Go packages for working with Microsoft SQL Server, Azure SQL Database, and Azure Synapse. Learn more about how `sqlcmd` is used from a articles/posts written by the community: [Community Buzz][]. @@ -307,6 +309,52 @@ e.g. sqlcmd.exe: error: sqlcmd.exe: '-w 4': Der Wert muss grâßer als 8 und kleiner als 65536 sein. ``` +## Development + +### Quick Start with Dev Containers + +The easiest way to develop and test sqlcmd is to use the included [Dev Container](.devcontainer/README.md), which works with: + +- **VS Code**: Install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), open this repo, and click "Reopen in Container" +- **GitHub Codespaces**: Click the "Code" button on GitHub and select "Create codespace" + +The dev container includes: +- Go 1.24 with all development tools (golangci-lint, gopls, delve) +- SQL Server 2025 ready for integration tests +- Your locally built `sqlcmd` added to PATH automatically +- Pre-configured environment variables for tests + +Once inside the container: +```bash +# Build sqlcmd from source +ginstall + +# Run the test suite +gtest + +# Connect to SQL Server +sql -Q "SELECT @@VERSION" +``` + +### Manual Setup + +If you prefer to set up your environment manually: + +1. Install Go 1.24 or higher +2. Clone this repository +3. Set up a SQL Server instance (2017 or later) +4. Configure environment variables: + - `SQLCMDSERVER` - Server hostname (e.g., `localhost`) + - `SQLCMDUSER` - Username (e.g., `sa`) + - `SQLCMDPASSWORD` - Password + - `SQLCMDDATABASE` - Database name (optional) + +5. Build and run: + ```bash + go build -o sqlcmd ./cmd/modern + ./sqlcmd --version + ``` + ## Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a