Skip to content

Commit 72cdb74

Browse files
feat: add devcontainer for VS Code and GitHub Codespaces
- Go 1.24 with gopls, delve, staticcheck, golangci-lint - SQL Server 2025 (Developer Edition) with health checks - go-sqlcmd installed (uses go-mssqldb - dogfooding!) - Pre-configured VS Code extensions (Go, MSSQL, Copilot, etc.) - Environment variables pre-set for integration tests - Add Development section to README with quick start guide - Add 'Open in Dev Containers' badge to README - Update CI workflow with improved SQL Server readiness checks
1 parent f49ac9b commit 72cdb74

File tree

9 files changed

+682
-11
lines changed

9 files changed

+682
-11
lines changed

.devcontainer/Dockerfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Go MSSQL Driver Development Container
2+
FROM mcr.microsoft.com/devcontainers/go:1.24-bookworm
3+
4+
# Install go-sqlcmd (uses the go-mssqldb driver - dogfooding!)
5+
# Also install Kerberos libs for integrated auth testing
6+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
7+
&& apt-get install -y curl libkrb5-dev \
8+
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
9+
10+
# Install go-sqlcmd - the Go-based sqlcmd that uses go-mssqldb
11+
# Pinned version for reproducibility; update periodically
12+
ARG SQLCMD_VERSION=v1.8.2
13+
RUN go install github.com/microsoft/go-sqlcmd/cmd/sqlcmd@${SQLCMD_VERSION}
14+
15+
# Install golangci-lint for code quality
16+
# Download pre-built binary with SHA256 checksum verification (supply chain security)
17+
# Supports both amd64 and arm64 architectures
18+
ARG GOLANGCI_LINT_VERSION=1.64.8
19+
ARG GOLANGCI_LINT_SHA256_AMD64=b6270687afb143d019f387c791cd2a6f1cb383be9b3124d241ca11bd3ce2e54e
20+
ARG GOLANGCI_LINT_SHA256_ARM64=a6ab58ebcb1c48572622146cdaec2956f56871038a54ed1149f1386e287789a5
21+
RUN ARCH=$(dpkg --print-architecture) \
22+
&& if [ "$ARCH" = "amd64" ]; then \
23+
CHECKSUM="${GOLANGCI_LINT_SHA256_AMD64}"; \
24+
elif [ "$ARCH" = "arm64" ]; then \
25+
CHECKSUM="${GOLANGCI_LINT_SHA256_ARM64}"; \
26+
else \
27+
echo "Unsupported architecture: $ARCH" && exit 1; \
28+
fi \
29+
&& curl -fsSLO "https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" \
30+
&& echo "${CHECKSUM} golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" | sha256sum -c - \
31+
&& tar -xzf "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" \
32+
&& mv "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}/golangci-lint" /usr/local/bin/ \
33+
&& rm -rf "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}" "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${ARCH}.tar.gz" \
34+
&& golangci-lint --version
35+
36+
# Install additional Go tools (pinned versions for reproducibility)
37+
RUN go install golang.org/x/tools/gopls@v0.18.1 \
38+
&& go install github.com/go-delve/delve/cmd/dlv@v1.24.1 \
39+
&& go install honnef.co/go/tools/cmd/staticcheck@v0.6.1
40+
41+
# [Optional] Uncomment this section to install additional OS packages.
42+
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
43+
# && apt-get -y install --no-install-recommends <your-package-list-here>

.devcontainer/README.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# go-mssqldb Development Container
2+
3+
This folder contains the configuration for a VS Code Dev Container / GitHub Codespaces development environment for the go-mssqldb driver.
4+
5+
> **⚠️ Security Note**: The SQL Server password for this devcontainer is provided via the `$SQLPASSWORD` environment variable and is a non-production, development-only default.
6+
> For the default devcontainer setup, the password value (`MssqlDriver@2025!`) is checked into this repository for convenience; override it via environment variables or Codespaces/CI secrets for non-local use.
7+
> When using VS Code's MSSQL extension, copy the value from `$SQLPASSWORD` when prompted.
8+
> Never expose port 1433 outside of localhost or use these credentials in any production or shared environment.
9+
10+
## What's Included
11+
12+
- **Go 1.24** development environment with all necessary tools
13+
- **SQL Server 2025** (Developer Edition) running in a sidecar container with AI/vector capabilities
14+
- **Pre-configured VS Code extensions**:
15+
- Go (official extension)
16+
- MS SQL (for database management)
17+
- Docker
18+
- GitHub Copilot
19+
- GitLens
20+
- **SQL Server tools**: go-sqlcmd (uses this driver - dogfooding!)
21+
- **Go quality tools**: golangci-lint, gopls, delve debugger, staticcheck
22+
23+
## Quick Start
24+
25+
### Using VS Code (Recommended)
26+
27+
1. Install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
28+
2. Open this repository in VS Code
29+
3. When prompted, click **"Reopen in Container"**, or:
30+
- Press `F1` and select **"Dev Containers: Reopen in Container"**
31+
4. Wait for the container to build (first time takes ~5 minutes)
32+
5. Start developing!
33+
34+
### Using GitHub Codespaces
35+
36+
1. Click the green **"Code"** button on the repository
37+
2. Select **"Codespaces"** tab
38+
3. Click **"Create codespace on main"** (or your preferred branch)
39+
4. Wait for the environment to start
40+
41+
## Running Tests
42+
43+
Environment variables are pre-configured for running integration tests:
44+
45+
```bash
46+
# Run all tests (includes SQL Server integration tests)
47+
go test ./...
48+
49+
# Run unit tests only (no SQL Server required)
50+
go test ./msdsn ./internal/... ./integratedauth ./azuread -v
51+
52+
# Run short tests
53+
go test -short ./...
54+
```
55+
56+
### Helpful Aliases
57+
58+
After the container starts, these aliases are available:
59+
60+
| Alias | Command |
61+
|-------|---------|
62+
| `gtest` | Run all tests |
63+
| `gtest-unit` | Run unit tests only |
64+
| `gtest-short` | Run short tests |
65+
| `gbuild` | Build all packages |
66+
| `gfmt` | Format code |
67+
| `gvet` | Run go vet |
68+
| `glint` | Run golangci-lint |
69+
| `test-db` | Test database connection |
70+
| `sql` | Connect to SQL Server (using go-sqlcmd) |
71+
72+
## SQL Server Connection
73+
74+
The SQL Server instance is accessible at:
75+
76+
- **Server**: `localhost,1433`
77+
- **Username**: `sa`
78+
- **Password**: `MssqlDriver@2025!`
79+
- **Database**: `master` (default) or `GoDriverTest` (created for testing)
80+
81+
### Connecting with go-sqlcmd
82+
83+
The container includes [go-sqlcmd](https://github.com/microsoft/go-sqlcmd), which is built on this driver (dogfooding!):
84+
85+
```bash
86+
# Using the alias
87+
sql
88+
89+
# Or explicitly (-C trusts the self-signed certificate used by the devcontainer SQL Server)
90+
sqlcmd -S localhost -U sa -P "MssqlDriver@2025!" -C
91+
```
92+
93+
### VS Code SQL Extension
94+
95+
The MSSQL extension is pre-configured with a connection profile named **"mssql-container"**. Click the SQL Server icon in the Activity Bar to connect.
96+
97+
## Environment Variables
98+
99+
The following environment variables are set automatically:
100+
101+
| Variable | Value |
102+
|----------|-------|
103+
| `HOST` | `localhost` |
104+
| `SQLUSER` | `sa` |
105+
| `SQLPASSWORD` | `MssqlDriver@2025!` (default, overridable via Codespaces Secrets) |
106+
| `DATABASE` | `master` |
107+
| `SQLSERVER_DSN` | Full connection string |
108+
109+
## Customization
110+
111+
### Adding SQL Setup Scripts
112+
113+
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.
114+
115+
### Modifying the SA Password
116+
117+
The devcontainer uses environment variable substitution for the password. To change it:
118+
119+
**Option 1: Environment Variable Override (Recommended)**
120+
121+
Set `SQLPASSWORD` in your environment before opening the devcontainer:
122+
- **GitHub Codespaces**: Add `SQLPASSWORD` as a [Codespaces Secret](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-encrypted-secrets-for-your-codespaces)
123+
- **VS Code**: Set `SQLPASSWORD` in your shell before opening VS Code
124+
125+
**Option 2: Edit Configuration Files**
126+
127+
1. Update both `SA_PASSWORD` and `MSSQL_SA_PASSWORD` defaults in `docker-compose.yml` (these must match)
128+
2. Update `SQLPASSWORD` default in `devcontainer.json` (remoteEnv section)
129+
3. Update the password in the `mssql.connections` settings in `devcontainer.json`
130+
131+
### Using a Different SQL Server Version
132+
133+
Edit `docker-compose.yml` and change the image tag:
134+
135+
```yaml
136+
db:
137+
image: mcr.microsoft.com/mssql/server:2022-latest # or 2019-latest
138+
```
139+
140+
> **Note:** SQL Server 2025 is the default as it includes the latest features like JSON type support, vector search, and AI capabilities that this driver supports.
141+
142+
## Troubleshooting
143+
144+
### ARM64 (Apple Silicon) Users
145+
146+
SQL Server does not have native ARM64 container images. **Use GitHub Codespaces** instead - it runs on x86_64 infrastructure where SQL Server works natively.
147+
148+
### SQL Server not starting
149+
150+
Check the Docker logs:
151+
```bash
152+
docker logs $(docker ps -qf "name=db")
153+
```
154+
155+
Common issues:
156+
- Insufficient memory (SQL Server requires at least 2GB RAM)
157+
- Port 1433 already in use
158+
- ARM64 architecture issues (see above)
159+
160+
### Connection refused
161+
162+
Wait a few seconds after the container starts. SQL Server takes ~30 seconds to become ready. The health check should handle this automatically.
163+
164+
### Tests failing with "no database connection string"
165+
166+
Ensure the environment variables are set:
167+
```bash
168+
echo $SQLSERVER_DSN
169+
```
170+
171+
If empty, try restarting the terminal or running:
172+
```bash
173+
source ~/.bashrc
174+
```
175+
176+
## Files Reference
177+
178+
| File | Purpose |
179+
|------|---------|
180+
| `devcontainer.json` | Main configuration file |
181+
| `docker-compose.yml` | Container orchestration (Go + SQL Server) |
182+
| `Dockerfile` | Go development container image |
183+
| `post-create.sh` | Setup script (runs after container creation) |
184+
| `mssql/setup.sql` | Initial database setup script |
185+
186+
## Contributing
187+
188+
When modifying the devcontainer:
189+
190+
1. Test locally with `Dev Containers: Rebuild Container`
191+
2. Ensure all tests pass: `go test ./...`
192+
3. Verify SQL connection works: `test-db`

.devcontainer/devcontainer.json

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"name": "Go MSSQL Driver Development",
3+
"dockerComposeFile": "docker-compose.yml",
4+
"service": "devcontainer",
5+
"workspaceFolder": "/workspaces/go-mssqldb",
6+
"shutdownAction": "stopCompose",
7+
8+
// Configure tool-specific properties
9+
"customizations": {
10+
"vscode": {
11+
"extensions": [
12+
"golang.go",
13+
"ms-mssql.mssql",
14+
"ms-azuretools.vscode-docker",
15+
"GitHub.copilot",
16+
"GitHub.copilot-chat",
17+
"eamodio.gitlens",
18+
"EditorConfig.EditorConfig",
19+
"streetsidesoftware.code-spell-checker"
20+
],
21+
"settings": {
22+
"go.toolsManagement.autoUpdate": true,
23+
"go.useLanguageServer": true,
24+
"go.lintTool": "golangci-lint",
25+
"go.lintFlags": ["--fast"],
26+
"go.testEnvVars": {
27+
"HOST": "localhost",
28+
"SQLUSER": "sa",
29+
"SQLPASSWORD": "${env:SQLPASSWORD}",
30+
"DATABASE": "master"
31+
},
32+
// Note: The MSSQL extension doesn't support env var substitution in passwords.
33+
// This default password matches the devcontainer default. To change it,
34+
// override SQLPASSWORD env var and update this value to match.
35+
"mssql.connections": [
36+
{
37+
"server": "localhost,1433",
38+
"database": "master",
39+
"authenticationType": "SqlLogin",
40+
"user": "sa",
41+
"password": "MssqlDriver@2025!",
42+
"savePassword": true,
43+
"profileName": "mssql-container"
44+
}
45+
],
46+
"editor.formatOnSave": true,
47+
"editor.defaultFormatter": "golang.go",
48+
"[go]": {
49+
"editor.formatOnSave": true,
50+
"editor.codeActionsOnSave": {
51+
"source.organizeImports": "explicit"
52+
}
53+
},
54+
"terminal.integrated.defaultProfile.linux": "bash"
55+
}
56+
}
57+
},
58+
59+
// Forward the SQL Server port
60+
"forwardPorts": [1433],
61+
"portsAttributes": {
62+
"1433": {
63+
"label": "SQL Server",
64+
"onAutoForward": "silent"
65+
}
66+
},
67+
68+
// Use 'postCreateCommand' to run commands after the container is created
69+
"postCreateCommand": "bash .devcontainer/post-create.sh",
70+
71+
// Environment variables for tests - password must match docker-compose.yml
72+
// This is a development-only container credential, not a production secret.
73+
// For GitHub Codespaces, you can override SQLPASSWORD via Codespaces Secrets.
74+
"remoteEnv": {
75+
"HOST": "localhost",
76+
"SQLUSER": "sa",
77+
"SQLPASSWORD": "${localEnv:SQLPASSWORD:MssqlDriver@2025!}",
78+
"DATABASE": "master",
79+
"SQLSERVER_DSN": "sqlserver://sa:${localEnv:SQLPASSWORD:MssqlDriver@2025!}@localhost:1433?database=master"
80+
},
81+
82+
// Features to add to the dev container
83+
"features": {
84+
"ghcr.io/devcontainers/features/docker-in-docker:2": {
85+
"version": "latest",
86+
"moby": true
87+
},
88+
"ghcr.io/devcontainers/features/github-cli:1": {
89+
"version": "latest"
90+
}
91+
}
92+
}

.devcontainer/docker-compose.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
services:
2+
devcontainer:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
volumes:
7+
- ..:/workspaces/go-mssqldb:cached
8+
# Overrides default command so things don't shut down after the process ends.
9+
command: sleep infinity
10+
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
11+
network_mode: service:db
12+
depends_on:
13+
db:
14+
condition: service_healthy
15+
16+
db:
17+
image: mcr.microsoft.com/mssql/server:2025-latest
18+
restart: unless-stopped
19+
environment:
20+
ACCEPT_EULA: "Y"
21+
# Password can be overridden via SQLPASSWORD environment variable
22+
SA_PASSWORD: "${SQLPASSWORD:-MssqlDriver@2025!}"
23+
MSSQL_SA_PASSWORD: "${SQLPASSWORD:-MssqlDriver@2025!}"
24+
MSSQL_PID: "Developer"
25+
volumes:
26+
- mssql-data:/var/opt/mssql
27+
healthcheck:
28+
# Healthcheck runs inside SQL Server container using its bundled sqlcmd (mssql-tools18)
29+
# Uses $$SA_PASSWORD to reference env var (Docker Compose escapes $ as $$)
30+
test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P \"$$SA_PASSWORD\" -C -Q \"SELECT 1\" || exit 1"]
31+
interval: 10s
32+
timeout: 5s
33+
retries: 15
34+
start_period: 45s
35+
# Note: The devcontainer uses go-sqlcmd (github.com/microsoft/go-sqlcmd) for user
36+
# interactions, which is built on this driver (dogfooding!). The healthcheck above
37+
# uses the SQL Server container's bundled sqlcmd since go-sqlcmd isn't installed there.
38+
39+
volumes:
40+
mssql-data:

0 commit comments

Comments
 (0)