Skip to content

Commit 8da41ff

Browse files
authored
Add Docker support with multi-stage build and versioning (#14)
1 parent 29cbcb8 commit 8da41ff

10 files changed

Lines changed: 1260 additions & 3 deletions

File tree

.dockerignore

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# .dockerignore for CodeMedic
2+
# Excludes unnecessary files from Docker build context
3+
4+
# Build outputs
5+
**/bin/
6+
**/obj/
7+
**/publish/
8+
9+
# Git
10+
.git/
11+
.gitignore
12+
.gitattributes
13+
14+
# IDE and editor files
15+
.vs/
16+
.vscode/
17+
*.user
18+
*.suo
19+
*.userosscache
20+
*.sln.docstates
21+
.idea/
22+
*.swp
23+
*.swo
24+
*~
25+
26+
# OS files
27+
.DS_Store
28+
Thumbs.db
29+
desktop.ini
30+
31+
# Documentation (not needed in runtime)
32+
doc/
33+
user-docs/
34+
*.md
35+
!README.md
36+
37+
# Test files
38+
test/
39+
**/Test.*/
40+
41+
# Scripts (not needed in runtime)
42+
*.ps1
43+
*.sh
44+
*.cmd
45+
!build-docker.ps1
46+
!build-docker.sh
47+
!build-docker.cmd
48+
49+
# Docker files themselves
50+
Dockerfile*
51+
.dockerignore
52+
53+
# Package restore files
54+
project.lock.json
55+
project.fragment.lock.json
56+
artifacts/
57+
58+
# NuGet packages (restored during build)
59+
*.nupkg
60+
*.snupkg
61+
.nuget/
62+
63+
# Test and coverage results
64+
[Tt]est[Rr]esult*/
65+
[Bb]uild[Ll]og.*
66+
*.trx
67+
*.coverage
68+
*.coveragexml
69+
70+
# Misc
71+
*.log
72+
*.tmp
73+
.env
74+
.env.*

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
push:
55
branches: [ main ]
66
pull_request:
7-
branches: [ main ]
87

98
jobs:
109
build-and-test:

Dockerfile

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# CodeMedic Dockerfile
2+
# Multi-stage build for optimized image size
3+
4+
# Build stage
5+
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
6+
ARG BUILD_CONFIGURATION=Release
7+
ARG VERSION=0.0.0
8+
ARG ASSEMBLY_VERSION=0.0.0.0
9+
ARG FILE_VERSION=0.0.0.0
10+
ARG INFORMATIONAL_VERSION=0.0.0
11+
WORKDIR /src
12+
13+
# Copy project files
14+
COPY ["src/CodeMedic.Abstractions/CodeMedic.Abstractions.csproj", "src/CodeMedic.Abstractions/"]
15+
COPY ["src/CodeMedic/CodeMedic.csproj", "src/CodeMedic/"]
16+
17+
# Restore dependencies
18+
RUN dotnet restore "src/CodeMedic/CodeMedic.csproj"
19+
20+
# Copy source code
21+
COPY . .
22+
23+
# Build and publish
24+
WORKDIR "/src/src/CodeMedic"
25+
RUN dotnet build "CodeMedic.csproj" \
26+
-c $BUILD_CONFIGURATION \
27+
-o /app/build \
28+
/p:Version=$VERSION \
29+
/p:AssemblyVersion=$ASSEMBLY_VERSION \
30+
/p:FileVersion=$FILE_VERSION \
31+
/p:InformationalVersion=$INFORMATIONAL_VERSION
32+
33+
RUN dotnet publish "CodeMedic.csproj" \
34+
-c $BUILD_CONFIGURATION \
35+
-o /app/publish \
36+
/p:UseAppHost=false \
37+
/p:Version=$VERSION \
38+
/p:AssemblyVersion=$ASSEMBLY_VERSION \
39+
/p:FileVersion=$FILE_VERSION \
40+
/p:InformationalVersion=$INFORMATIONAL_VERSION
41+
42+
# Runtime stage
43+
FROM mcr.microsoft.com/dotnet/runtime:10.0 AS final
44+
WORKDIR /app
45+
46+
# Copy published application
47+
COPY --from=build /app/publish .
48+
49+
# Set entrypoint
50+
ENTRYPOINT ["dotnet", "CodeMedic.dll"]
51+
52+
# Default command (shows help)
53+
CMD ["--help"]

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,24 @@ A comprehensive CLI application for analyzing the health of .NET repositories, i
44

55
## 🚀 Quick Start
66

7-
### Build
7+
### Option 1: Docker (Recommended)
8+
```bash
9+
# Build container
10+
.\build-docker.ps1 # Windows
11+
./build-docker.sh # Linux/macOS
12+
13+
# Run
14+
docker run --rm codemedic:latest --help
15+
docker run --rm -v ${PWD}:/repo codemedic:latest health /repo
16+
```
17+
18+
### Option 2: Local Build
819
```bash
920
cd src/CodeMedic
1021
dotnet build
1122
```
1223

13-
### Run
24+
### Run Locally
1425
```bash
1526
codemedic --help
1627
codemedic --version
@@ -20,15 +31,18 @@ dotnet run -- --help
2031
## 📖 Documentation
2132

2233
- **User Guide:** `user-docs/cli_quick_reference.md`
34+
- **Docker Guide:** `user-docs/docker_usage.md`
2335
- **Technical Guide:** `doc/cli_skeleton_implementation.md`
2436
- **Architecture & Extension:** `doc/cli_architecture.md`
37+
- **Docker Implementation:** `doc/docker_implementation.md`
2538
- **Test Results:** `doc/cli_skeleton_test_results.md`
2639

2740
## ✨ Features
2841

2942
- ✅ Help system with command reference
3043
- ✅ Version information display
3144
- ✅ Cross-platform support (Windows, macOS, Linux)
45+
- ✅ Docker containerization with automated versioning
3246
- ✅ Rich formatted console output
3347
- ✅ Proper error handling with exit codes
3448
- ✅ Extensible architecture for future commands

build-docker.cmd

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
@echo off
2+
REM CodeMedic Docker Build Script (Windows batch version)
3+
REM Builds the CodeMedic Docker container with versioning from Nerd Bank Git Versioning
4+
5+
setlocal EnableDelayedExpansion
6+
7+
set REGISTRY=
8+
set PUSH=0
9+
set BUILD_CONFIGURATION=Release
10+
11+
REM Parse arguments
12+
:parse_args
13+
if "%~1"=="" goto end_parse
14+
if /i "%~1"=="-r" (
15+
set REGISTRY=%~2
16+
shift
17+
shift
18+
goto parse_args
19+
)
20+
if /i "%~1"=="--registry" (
21+
set REGISTRY=%~2
22+
shift
23+
shift
24+
goto parse_args
25+
)
26+
if /i "%~1"=="-p" (
27+
set PUSH=1
28+
shift
29+
goto parse_args
30+
)
31+
if /i "%~1"=="--push" (
32+
set PUSH=1
33+
shift
34+
goto parse_args
35+
)
36+
if /i "%~1"=="-c" (
37+
set BUILD_CONFIGURATION=%~2
38+
shift
39+
shift
40+
goto parse_args
41+
)
42+
if /i "%~1"=="--configuration" (
43+
set BUILD_CONFIGURATION=%~2
44+
shift
45+
shift
46+
goto parse_args
47+
)
48+
if /i "%~1"=="-h" goto show_help
49+
if /i "%~1"=="--help" goto show_help
50+
echo Unknown option: %~1
51+
exit /b 1
52+
53+
:show_help
54+
echo Usage: %~nx0 [OPTIONS]
55+
echo.
56+
echo Options:
57+
echo -r, --registry REGISTRY Docker registry prefix (e.g., ghcr.io/owner)
58+
echo -p, --push Push images to registry after build
59+
echo -c, --configuration CONFIG Build configuration (Release or Debug)
60+
echo -h, --help Show this help message
61+
echo.
62+
echo Examples:
63+
echo %~nx0
64+
echo %~nx0 --registry ghcr.io/csharpfritz --push
65+
exit /b 0
66+
67+
:end_parse
68+
69+
echo.
70+
echo 🏥 CodeMedic Docker Build Script
71+
echo =================================
72+
echo.
73+
74+
REM Change to script directory
75+
cd /d "%~dp0"
76+
77+
REM Check if Docker is available
78+
docker --version >nul 2>&1
79+
if errorlevel 1 (
80+
echo ❌ Error: Docker is not installed or not in PATH
81+
exit /b 1
82+
)
83+
84+
REM Check if nbgv is available
85+
where nbgv >nul 2>&1
86+
if errorlevel 1 (
87+
echo 📦 Installing Nerd Bank Git Versioning CLI tool...
88+
dotnet tool install -g nbgv
89+
if errorlevel 1 (
90+
echo ❌ Error: Failed to install nbgv
91+
exit /b 1
92+
)
93+
)
94+
95+
REM Get version information from NBGv2
96+
echo 🔢 Retrieving version information from NBGv2...
97+
98+
REM Use PowerShell to parse JSON (more reliable than batch)
99+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty SemVer2}"`) do set SEMVER2=%%v
100+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty Version}"`) do set VERSION=%%v
101+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty AssemblyVersion}"`) do set ASSEMBLY_VERSION=%%v
102+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty AssemblyFileVersion}"`) do set FILE_VERSION=%%v
103+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty AssemblyInformationalVersion}"`) do set INFORMATIONAL_VERSION=%%v
104+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty VersionMajor}"`) do set VERSION_MAJOR=%%v
105+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty VersionMinor}"`) do set VERSION_MINOR=%%v
106+
for /f "usebackq delims=" %%v in (`powershell -NoProfile -Command "& {nbgv get-version -f json | ConvertFrom-Json | Select-Object -ExpandProperty GitCommitIdShort}"`) do set COMMIT=%%v
107+
108+
set MAJOR_MINOR=%VERSION_MAJOR%.%VERSION_MINOR%
109+
110+
echo Version: %VERSION%
111+
echo SemVer2: %SEMVER2%
112+
echo Assembly Version: %ASSEMBLY_VERSION%
113+
echo File Version: %FILE_VERSION%
114+
echo Informational: %INFORMATIONAL_VERSION%
115+
echo Commit: %COMMIT%
116+
echo.
117+
118+
REM Construct image name
119+
set IMAGE_NAME=codemedic
120+
if not "%REGISTRY%"=="" set IMAGE_NAME=%REGISTRY%/%IMAGE_NAME%
121+
122+
REM Build tags
123+
set TAG1=%IMAGE_NAME%:%SEMVER2%
124+
set TAG2=%IMAGE_NAME%:%MAJOR_MINOR%
125+
set TAG3=%IMAGE_NAME%:latest
126+
set TAG4=%IMAGE_NAME%:%SEMVER2%-%COMMIT%
127+
128+
echo 🐳 Building Docker image...
129+
echo Image name: %IMAGE_NAME%
130+
echo Tags:
131+
echo - %TAG1%
132+
echo - %TAG2%
133+
echo - %TAG3%
134+
echo - %TAG4%
135+
echo.
136+
137+
REM Build the Docker image
138+
echo 🔨 Building...
139+
docker build -f Dockerfile ^
140+
--build-arg BUILD_CONFIGURATION=%BUILD_CONFIGURATION% ^
141+
--build-arg VERSION=%SEMVER2% ^
142+
--build-arg ASSEMBLY_VERSION=%ASSEMBLY_VERSION% ^
143+
--build-arg FILE_VERSION=%FILE_VERSION% ^
144+
--build-arg INFORMATIONAL_VERSION=%INFORMATIONAL_VERSION% ^
145+
-t "%TAG1%" -t "%TAG2%" -t "%TAG3%" -t "%TAG4%" .
146+
147+
if errorlevel 1 (
148+
echo ❌ Error: Docker build failed
149+
exit /b 1
150+
)
151+
152+
echo.
153+
echo ✅ Docker image built successfully!
154+
echo.
155+
156+
REM Push if requested
157+
if %PUSH%==1 (
158+
if "%REGISTRY%"=="" (
159+
echo ❌ Error: Cannot push without specifying a registry. Use --registry parameter.
160+
exit /b 1
161+
)
162+
163+
echo 📤 Pushing images to registry...
164+
165+
echo Pushing: %TAG1%
166+
docker push "%TAG1%"
167+
if errorlevel 1 exit /b 1
168+
169+
echo Pushing: %TAG2%
170+
docker push "%TAG2%"
171+
if errorlevel 1 exit /b 1
172+
173+
echo Pushing: %TAG3%
174+
docker push "%TAG3%"
175+
if errorlevel 1 exit /b 1
176+
177+
echo Pushing: %TAG4%
178+
docker push "%TAG4%"
179+
if errorlevel 1 exit /b 1
180+
181+
echo.
182+
echo ✅ All images pushed successfully!
183+
echo.
184+
)
185+
186+
REM Display usage examples
187+
echo 📋 Usage Examples:
188+
echo Run health check:
189+
echo docker run --rm -v %%cd%%:/repo %TAG1% health /repo
190+
echo.
191+
echo Show help:
192+
echo docker run --rm %TAG1% --help
193+
echo.
194+
echo Interactive shell:
195+
echo docker run --rm -it --entrypoint /bin/bash %TAG1%
196+
echo.
197+
198+
endlocal

0 commit comments

Comments
 (0)