Skip to content

Commit 2ddfe3b

Browse files
committed
Merge branch 'main' into feat/otel/span-preparations
2 parents c3e2055 + 3a3181a commit 2ddfe3b

908 files changed

Lines changed: 53694 additions & 80810 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/Dockerfile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
FROM mcr.microsoft.com/devcontainers/dotnet:10.0-noble
2+
3+
# Install .NET 8.0 and 9.0 runtimes and targeting packs (needed to build and run tests targeting these TFMs).
4+
# The base image ships the latest .NET SDK (10.0) which can build for older TFMs,
5+
# but the matching runtimes are required to *execute* those targets, and the
6+
# targeting packs (ref assemblies) are required to *compile* against them.
7+
COPY --from=mcr.microsoft.com/dotnet/sdk:8.0 /usr/share/dotnet/shared /usr/share/dotnet/shared
8+
COPY --from=mcr.microsoft.com/dotnet/sdk:9.0 /usr/share/dotnet/shared /usr/share/dotnet/shared
9+
COPY --from=mcr.microsoft.com/dotnet/sdk:8.0 /usr/share/dotnet/packs /usr/share/dotnet/packs
10+
COPY --from=mcr.microsoft.com/dotnet/sdk:9.0 /usr/share/dotnet/packs /usr/share/dotnet/packs
11+
12+
# Install jq for JSON manipulation in setup scripts.
13+
RUN apt-get update && apt-get install -y --no-install-recommends jq && rm -rf /var/lib/apt/lists/*
14+
15+
# Install go-sqlcmd (standalone binary, works on Ubuntu without dependency issues).
16+
ARG SQLCMD_VERSION=v1.9.0
17+
ARG SQLCMD_SHA256_amd64="b896bac71cf6ad8feca125bb42be61999116d8566a078ed475893372ccf8c0f2"
18+
ARG SQLCMD_SHA256_arm64="e5de98d635bfecf337acadf9d84a8f4f3cdcf38b2978b9dcd83aed20425c64ef"
19+
RUN arch="$(dpkg --print-architecture)" \
20+
&& case "$arch" in \
21+
amd64) SQLCMD_ARCH="linux-amd64" ;; \
22+
arm64) SQLCMD_ARCH="linux-arm64" ;; \
23+
*) echo "Unsupported architecture: $arch" && exit 1 ;; \
24+
esac \
25+
&& curl -fsSL "https://github.com/microsoft/go-sqlcmd/releases/download/${SQLCMD_VERSION}/sqlcmd-${SQLCMD_ARCH}.tar.bz2" \
26+
-o /tmp/sqlcmd.tar.bz2 \
27+
&& if [ "$arch" = "amd64" ]; then echo "$SQLCMD_SHA256_amd64 /tmp/sqlcmd.tar.bz2" | sha256sum -c -; fi \
28+
&& if [ "$arch" = "arm64" ]; then echo "$SQLCMD_SHA256_arm64 /tmp/sqlcmd.tar.bz2" | sha256sum -c -; fi \
29+
&& tar xjf /tmp/sqlcmd.tar.bz2 -C /usr/local/bin/ sqlcmd \
30+
&& chmod +x /usr/local/bin/sqlcmd \
31+
&& rm -f /tmp/sqlcmd.tar.bz2

.devcontainer/devcontainer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "Microsoft.Data.SqlClient",
3+
"dockerComposeFile": "docker-compose.yml",
4+
"service": "devcontainer",
5+
"workspaceFolder": "/workspaces/SqlClient",
6+
"features": {
7+
"ghcr.io/devcontainers/features/powershell:2.0.1": {}
8+
},
9+
"customizations": {
10+
"vscode": {
11+
"extensions": [
12+
"ms-azuretools.vscode-containers",
13+
"ms-dotnettools.csdevkit",
14+
"ms-dotnettools.csharp",
15+
"GitHub.copilot",
16+
"ms-mssql.mssql"
17+
],
18+
"settings": {
19+
"dotnet.defaultSolution": "src/Microsoft.Data.SqlClient.slnx"
20+
}
21+
}
22+
},
23+
"postCreateCommand": "bash .devcontainer/setup-sqlserver.sh",
24+
"remoteUser": "vscode"
25+
}

.devcontainer/docker-compose.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
services:
2+
devcontainer:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
volumes:
7+
- ..:/workspaces/SqlClient:cached
8+
- sql-config:/sql-config:ro
9+
command: sleep infinity
10+
depends_on:
11+
sqlserver:
12+
condition: service_healthy
13+
environment:
14+
- SQL_SERVER_HOST=sqlserver
15+
- SQL_SERVER_PORT=1433
16+
- SQL_SERVER_SA_PASSWORD_FILE=/sql-config/sa-password
17+
networks:
18+
- default
19+
20+
sqlserver:
21+
image: mcr.microsoft.com/mssql/server:2025-latest
22+
# Adding user: root lets the entrypoint script create the password file,
23+
# after which sqlservr internally drops privileges to the mssql user.
24+
# This is the officially supported approach for SQL Server Linux containers.
25+
# https://learn.microsoft.com/sql/linux/sql-server-linux-docker-container-security
26+
user: root
27+
entrypoint: /sql-entrypoint/sqlserver-entrypoint.sh
28+
volumes:
29+
- sql-config:/sql-config
30+
- ./sqlserver-entrypoint.sh:/sql-entrypoint/sqlserver-entrypoint.sh:ro
31+
environment:
32+
ACCEPT_EULA: "Y"
33+
MSSQL_PID: "Developer"
34+
ports:
35+
- "1433:1433"
36+
healthcheck:
37+
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$$(cat /sql-config/sa-password)" -C -Q "SELECT 1" || exit 1
38+
interval: 10s
39+
timeout: 5s
40+
retries: 10
41+
start_period: 30s
42+
networks:
43+
- default
44+
45+
volumes:
46+
sql-config:

.devcontainer/setup-sqlserver.sh

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env bash
2+
# -------------------------------------------------------------------
3+
# Initializes the SQL Server instance running in the devcontainer
4+
# companion service with the test databases required by the test suite.
5+
# -------------------------------------------------------------------
6+
set -euo pipefail
7+
8+
SQL_HOST="${SQL_SERVER_HOST:-sqlserver}"
9+
SQL_PORT="${SQL_SERVER_PORT:-1433}"
10+
SA_PASSWORD_FILE="${SQL_SERVER_SA_PASSWORD_FILE:-/sql-config/sa-password}"
11+
12+
# Wait for the auto-generated SA password file from the sqlserver service.
13+
# The sqlserver entrypoint writes this file on startup; the shared volume
14+
# may not be visible immediately when postCreateCommand begins.
15+
echo "Waiting for SA password file at ${SA_PASSWORD_FILE}..."
16+
for i in $(seq 1 30); do
17+
if [ -f "$SA_PASSWORD_FILE" ]; then
18+
break
19+
fi
20+
if [ "$i" -eq 30 ]; then
21+
echo "ERROR: SA password file not found at $SA_PASSWORD_FILE after 60 s" >&2
22+
exit 1
23+
fi
24+
sleep 2
25+
done
26+
SA_PASSWORD="$(cat "$SA_PASSWORD_FILE")"
27+
28+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
29+
30+
# Write test config file so the test suite can find the connection string.
31+
CONFIG_DIR="${REPO_ROOT}/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities"
32+
CONFIG_DEFAULT_FILE="${CONFIG_DIR}/config.default.json"
33+
CONFIG_FILE="${CONFIG_DIR}/config.json"
34+
echo "Writing test config to ${CONFIG_FILE} (based on ${CONFIG_DEFAULT_FILE})..."
35+
TCP_CONN_STR="Data Source=tcp:${SQL_HOST},${SQL_PORT};Database=Northwind;User Id=sa;Password=${SA_PASSWORD};Encrypt=false;TrustServerCertificate=true"
36+
# config.default.json contains JS-style comments (// ...) which are not valid JSON.
37+
# Strip single-line comments before feeding to jq.
38+
sed 's|//.*||' "${CONFIG_DEFAULT_FILE}" \
39+
| jq --arg cs "${TCP_CONN_STR}" \
40+
'.TCPConnectionString = $cs | .NPConnectionString = "" | .SupportsIntegratedSecurity = false' \
41+
> "${CONFIG_FILE}"
42+
echo "Test config written."
43+
44+
echo "Waiting for SQL Server at ${SQL_HOST}:${SQL_PORT} to become available..."
45+
for i in $(seq 1 30); do
46+
if sqlcmd -S "${SQL_HOST},${SQL_PORT}" -U sa -P "${SA_PASSWORD}" -C -Q "SELECT 1" &>/dev/null; then
47+
break
48+
fi
49+
if [ "$i" -eq 30 ]; then
50+
echo "ERROR: SQL Server did not become available in time." >&2
51+
exit 1
52+
fi
53+
sleep 2
54+
done
55+
echo "SQL Server is ready."
56+
57+
# Ensure Northwind database exists
58+
echo "Ensuring Northwind database exists..."
59+
DB_EXISTS_RAW="$(sqlcmd -S "${SQL_HOST},${SQL_PORT}" -U sa -P "${SA_PASSWORD}" -C -h -1 -W \
60+
-Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.databases WHERE name = N'Northwind';" | tr -d '\r')"
61+
DB_EXISTS="$(echo "$DB_EXISTS_RAW" | tr -d ' ')"
62+
if [ "$DB_EXISTS" = "0" ]; then
63+
echo "Northwind database not found, creating..."
64+
sqlcmd -S "${SQL_HOST},${SQL_PORT}" -U sa -P "${SA_PASSWORD}" -C \
65+
-i "${REPO_ROOT}/tools/testsql/createNorthwindDb.sql"
66+
echo "Northwind database created."
67+
else
68+
echo "Northwind database already exists; skipping creation script."
69+
fi
70+
71+
echo "SQL Server test database setup complete."
72+
echo ""
73+
echo "Connection info:"
74+
echo " Host: ${SQL_HOST}"
75+
echo " Port: ${SQL_PORT}"
76+
echo " User: sa"
77+
echo " Password: ${SA_PASSWORD}"
78+
echo ""
79+
echo "Example sqlcmd:"
80+
echo " sqlcmd -S ${SQL_HOST},${SQL_PORT} -U sa -P '${SA_PASSWORD}' -C"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
# -------------------------------------------------------------------
3+
# Generates a random SA password and writes it to /sql-config/sa-password
4+
# so both the devcontainer and sqlserver service can use it.
5+
#
6+
# Called as the sqlserver entrypoint (before SQL Server starts).
7+
# -------------------------------------------------------------------
8+
set -euo pipefail
9+
10+
PASSWORD_FILE="/sql-config/sa-password"
11+
12+
# -------------------------------------------------------------------
13+
#
14+
# These permissions are required for the sqlserver entrypoint to write the password file
15+
# and for the devcontainer setup script to read it. The shared volume may be owned by root,
16+
# so we set permissive permissions to ensure both sides can access it.
17+
#
18+
# The sqlserver entrypoint will overwrite the password file on startup,
19+
# so we don't need to worry about other users modifying it.
20+
#
21+
# -------------------------------------------------------------------
22+
chmod 777 /sql-config 2>/dev/null || true
23+
24+
# Generate a password only if one doesn't already exist (container restart).
25+
if [ ! -f "$PASSWORD_FILE" ]; then
26+
# 32-byte random base64 + required character classes for SQL Server policy.
27+
RAW="$(head -c 32 /dev/urandom | base64 | tr -d '/+=' | head -c 24)"
28+
# SQL Server requires uppercase, lowercase, digit, and symbol.
29+
GENERATED="A1a@${RAW}"
30+
echo -n "$GENERATED" > "$PASSWORD_FILE"
31+
fi
32+
33+
PASSWORD="$(cat "$PASSWORD_FILE")"
34+
export MSSQL_SA_PASSWORD="$PASSWORD"
35+
36+
# Hand off to the real SQL Server entrypoint.
37+
exec /opt/mssql/bin/sqlservr

.editorconfig

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,59 @@
1-
# editorconfig.org
1+
# IDE text editor configuration:
2+
#
3+
# https://editorconfig.org/
24

3-
# top-most EditorConfig file
5+
# This is the top-most EditorConfig file for our repo.
46
root = true
57

6-
# Default settings:
7-
# A newline ending every file
8-
# Use 4 spaces as indentation
8+
# =================================================================================================
9+
# Default settings for all file types.
10+
911
[*]
10-
insert_final_newline = true
11-
indent_style = space
12-
indent_size = 4
1312

14-
[*.{json,jsonc}]
13+
# Use 2 spaces for indentation.
14+
indent_style = space
1515
indent_size = 2
16+
# tab_width is irrelevant, and will default to indent_size.
1617

17-
[*.{yml,yaml}]
18-
indent_size = 2
18+
# Don't mess with line endings.
19+
end_of_line = unset
20+
21+
# UTF-8 encoding without BOM.
22+
charset = utf-8
23+
24+
# Trim trailing whitespace.
25+
trim_trailing_whitespace = true
26+
27+
# Ensure files end with a newline.
28+
insert_final_newline = true
29+
30+
# We're not enforcing a max line length via tooling because there are legitimate cases for longer
31+
# lines (e.g., long URLs in comments, long strings, etc). However, we recommend keeping lines to
32+
# a maximum of 100 characters for readability.
33+
#
34+
# See: https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length
35+
#
36+
max_line_length = unset
37+
38+
# =================================================================================================
39+
# Shell scripts typically require line endings that match the platform's native line endings.
40+
41+
# Unix-like systems (Linux, macOS) use LF.
42+
[*.sh]
43+
end_of_line = lf
44+
45+
# Windows uses CRLF.
46+
[*.{bat,cmd,ps1}]
47+
end_of_line = crlf
48+
49+
# =================================================================================================
50+
# C# files.
1951

20-
# C# files
2152
[*.cs]
53+
54+
# We use 4 spaces for C# indentation.
55+
indent_size = 4
56+
2257
# New line preferences
2358
csharp_new_line_before_open_brace = all
2459
csharp_new_line_before_else = true
@@ -75,7 +110,7 @@ dotnet_naming_symbols.static_fields.applicable_kinds = field
75110
dotnet_naming_symbols.static_fields.required_modifiers = static
76111

77112
dotnet_naming_style.static_prefix_style.required_prefix = s_
78-
dotnet_naming_style.static_prefix_style.capitalization = camel_case
113+
dotnet_naming_style.static_prefix_style.capitalization = camel_case
79114

80115
# internal and private fields should be _camelCase
81116
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
@@ -86,7 +121,7 @@ dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
86121
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
87122

88123
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
89-
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
124+
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
90125

91126
# Code style defaults
92127
dotnet_sort_system_directives_first = true
@@ -143,6 +178,9 @@ csharp_space_between_square_brackets = false
143178

144179
# Analyzers
145180

181+
# IDE0005: Remove unnecessary using directives
182+
dotnet_diagnostic.IDE0005.severity = suggestion
183+
146184
dotnet_code_quality.ca1802.api_surface = private, internal
147185

148186
# CA2000: Dispose objects before losing scope
@@ -160,16 +198,3 @@ dotnet_diagnostic.CA1416.severity = silent
160198
dotnet_code_quality.CA2100.excluded_type_names_with_derived_types = Microsoft.Data.SqlClient.ManualTesting.Tests.*
161199
dotnet_diagnostic.xUnit1031.severity=none
162200
dotnet_diagnostic.xUnit1030.severity=none
163-
164-
# Xml files
165-
[*.{xml,csproj,stylecop,resx,ruleset,props,targets,config,nuspec}]
166-
indent_size = 2
167-
168-
# Shell scripts
169-
[*.sh]
170-
indent_size = 2
171-
end_of_line = lf
172-
173-
[*.{bat,cmd,ps1}]
174-
indent_size = 2
175-
end_of_line = crlf

0 commit comments

Comments
 (0)