This document provides guidance for GitHub Copilot when working with the go-sqlcmd repository.
go-sqlcmd is a Go-based command line tool (sqlcmd) for working with Microsoft SQL Server, Azure SQL Database, and Azure Synapse. The project aims to be a complete port of the original ODBC sqlcmd to Go, utilizing the go-mssqldb driver.
/
├── cmd/ # Entry points for the application
│ ├── modern/ # Modern CLI entry point (Cobra-based)
│ │ ├── root/ # Root command and subcommands
│ │ └── sqlconfig/ # SQL configuration management
│ └── sqlcmd/ # Legacy CLI entry point (Kong-based)
├── pkg/ # Public packages consumable by other hosts
│ └── sqlcmd/ # Core sqlcmd functionality
├── internal/ # Internal packages (not for external use)
│ ├── buffer/ # Buffer management
│ ├── cmdparser/ # Command parsing utilities
│ ├── color/ # Console coloring
│ ├── config/ # Configuration management
│ ├── container/ # Docker/Podman container management
│ ├── credman/ # Credential management
│ ├── http/ # HTTP utilities
│ ├── io/ # I/O utilities
│ ├── localizer/ # Localization support
│ ├── net/ # Network utilities
│ ├── output/ # Output formatting
│ ├── pal/ # Platform abstraction layer
│ ├── secret/ # Secret/credential management
│ ├── sql/ # SQL-related utilities
│ ├── test/ # Test utilities
│ ├── tools/ # Development tools
│ └── translations/ # Localized string translations
├── build/ # Build scripts and templates
├── testdata/ # Test data files
├── release/ # Release-related files
└── .github/ # GitHub workflows and configurations
# Build the sqlcmd executable
./build/build.sh # Linux/macOS
.\build\build.cmd # Windows
# Or build directly with Go
go build -o sqlcmd ./cmd/modernThe project uses Go modules. Run go mod download to fetch dependencies.
# Run all tests
go test ./...
# Run tests with verbose output
go test -v ./...
# Run tests for a specific package
go test -v ./pkg/sqlcmd/...
go test -v ./internal/config/...Tests may require the following environment variables for database connectivity:
SQLCMDSERVER- SQL Server hostnameSQLCMDPORT- SQL Server port (default: 1433)SQLCMDUSER- Username (e.g.,sa)SQLCMDPASSWORD- PasswordSQLCMDDATABASE- Database name
- Follow standard Go conventions and idioms
- Use
gofmtfor formatting - Use tabs for indentation (as specified in
.editorconfig) - Follow effective Go guidelines: https://go.dev/doc/effective_go
All Go files should include the following copyright header:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.Each package should have a doc.go file with package-level documentation.
- Use the standard Go error handling patterns
- For user-facing errors, prefer localized error messages via the
internal/localizerpackage - Wrap errors with context when propagating
- Use camelCase for unexported identifiers
- Use PascalCase for exported identifiers
- Acronyms should be all uppercase (e.g.,
SQL,URL,HTTP) - Package names should be lowercase, single-word if possible
The modern CLI is located in cmd/modern/ and uses the Cobra library. Key points:
- Root command is in
cmd/modern/root.go - Subcommands are in
cmd/modern/root/directory - Uses dependency injection for testability
The legacy CLI is in cmd/sqlcmd/ and maintains backward compatibility with the original ODBC sqlcmd.
When adding new commands:
- Create the command in
cmd/modern/root/ - Follow the existing pattern for subcommands (see
query.go,start.go,stop.go) - Add corresponding tests with
_test.gosuffix
- Configuration files are stored in
~/.sqlcmd/sqlconfig - Use the
internal/configpackage for configuration management - Viper is used for configuration parsing (
internal/config/viper.go)
The project supports creating SQL Server instances using Docker or Podman:
- Container management is in
internal/container/ - Supports SQL Server images
- Localized strings are in
internal/translations/ - Use the
internal/localizerpackage for localized messages - Supported languages: Chinese (Simplified/Traditional), English, French, German, Italian, Japanese, Korean, Portuguese (Brazil), Russian, Spanish
When adding user-facing strings to the code, use the localizer package:
import "github.com/microsoft/go-sqlcmd/internal/localizer"
// Use localizer.Sprintf for formatted strings
message := localizer.Sprintf("This is a localizable message with %s", value)
// Use localizer.Errorf for localized errors
err := localizer.Errorf("Error: %s failed", operation)Constants that are not user-facing (like environment variable names, command names) should be placed in internal/localizer/constants.go and do not need localization.
After adding new localizable strings, you must regenerate the translation catalog files before committing. The build scripts handle this automatically.
build\build.cmdThis script:
- Installs
gotextif not already installed - Runs
go generatewhich executes the gotext command defined ininternal/translations/translations.go - Generates/updates the translation catalog in
internal/translations/catalog.go - Reports any conflicting localizable strings that need to be fixed
Run the following commands manually:
# Install gotext if not already installed
go install golang.org/x/text/cmd/gotext@latest
# Generate translation files
go generate ./...- Always run the build script after adding new user-facing strings
- Check the build output for "conflicting localizable strings" warnings and resolve them
- The
SQLCMD_LANGenvironment variable controls the runtime language (e.g.,de-de,fr-fr) - Test your changes with different language settings to ensure proper localization
- Azure AD authentication is supported via the
azidentitypackage - Authentication code is in
pkg/sqlcmd/azure_auth.go - Supports multiple authentication methods: DefaultAzureCredential, Password, Interactive, ManagedIdentity, ServicePrincipal
- Never commit secrets or credentials
- Use environment variables or secure credential stores for sensitive data
- Follow the Microsoft Security Development Lifecycle (SDL)
- Report security vulnerabilities via SECURITY.md
- Ensure all tests pass locally
- Follow the existing code style
- Update documentation if adding new features
- Add tests for new functionality
- Keep commits focused and well-described
For new commands related to context management, container operations, or configuration:
- Create a new file in
cmd/modern/root/(e.g.,mycommand.go) - Define a command struct that embeds
cmdparser.Cmd - Implement the
DefineCommandmethod to set up command options, flags, and examples - Implement the
runmethod with the command logic - Add corresponding tests in
mycommand_test.go
Example structure:
type MyCommand struct {
cmdparser.Cmd
// flags
}
func (c *MyCommand) DefineCommand(...cmdparser.CommandOptions) {
options := cmdparser.CommandOptions{
Use: "mycommand",
Short: localizer.Sprintf("Description"),
Run: c.run,
}
c.Cmd.DefineCommand(options)
// Add flags
}
func (c *MyCommand) run() {
// Command logic
}- Update the config struct in
internal/config/config.go - Add validation if needed
- Update the Viper bindings in
internal/config/viper.go - Add tests
For new features related to querying SQL Server and displaying query results, add them to the legacy CLI:
- Add new fields to the
SQLCmdArgumentsstruct incmd/sqlcmd/sqlcmd.go - Register new flags in the
setFlagsfunction - Add validation logic in the
Validatemethod if needed - Determine from existing patterns whether to add a SQLCMD variable to support it
- Update
setVarsorsetConnectfunctions to use the new arguments - Implement the feature logic in the
runfunction or related functions - Add corresponding tests in
cmd/sqlcmd/sqlcmd_test.go - Update README.md to show example usage
- Use
pkg/sqlcmdfor SQL connection management - Connection options are defined in
pkg/sqlcmd/connect.go - Support for various transports: TCP, named pipes, shared memory
- GitHub Actions workflows are in
.github/workflows/ golangci-lint.yml- Linting with golangci-lintpr-validation.yml- Build and test validation for PRs- Azure Pipelines configurations are in
.pipelines/
The project uses golangci-lint. To run locally:
golangci-lint run