-
Notifications
You must be signed in to change notification settings - Fork 82
feat: add devcontainer for VS Code and GitHub Codespaces #692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dlevy-msft-sql
wants to merge
8
commits into
microsoft:main
Choose a base branch
from
dlevy-msft-sql:feat/devcontainer
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+780
−0
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
1722239
feat: add devcontainer for VS Code and GitHub Codespaces
dlevy-msft-sql e6f43c5
fix: address Copilot review feedback
dlevy-msft-sql 08a7029
fix: improve golangci-lint install security
dlevy-msft-sql af11705
fix: address additional Copilot review feedback
dlevy-msft-sql eefc9d6
fix: apply lessons learned from go-mssqldb PR #317
dlevy-msft-sql 3407d43
fix: address Copilot review feedback round 5
dlevy-msft-sql 75cec78
docs: clarify both SA_PASSWORD vars must be updated
dlevy-msft-sql d6557ff
fix: address Copilot review feedback round 6
dlevy-msft-sql File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | | ||
dlevy-msft-sql marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| | `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 | | ||
dlevy-msft-sql marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## 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 | | ||
|
|
||
dlevy-msft-sql marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ## 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` | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.