|
| 1 | +--- |
| 2 | +title: Format Strings |
| 3 | +description: Using C# format strings in GitVersion configuration |
| 4 | +--- |
| 5 | + |
| 6 | +GitVersion supports C# format strings in configuration, allowing you to apply standard .NET formatting and custom transformations to version properties. This enhancement provides more flexibility and control over how version information is displayed and used throughout your build process. |
| 7 | + |
| 8 | +## Overview |
| 9 | + |
| 10 | +The custom formatter functionality introduces several new formatters that can be used in GitVersion configuration files and templates: |
| 11 | + |
| 12 | +- **FormattableFormatter**: Supports standard .NET format strings for numeric values, dates, and implements `IFormattable` |
| 13 | +- **NumericFormatter**: Handles numeric formatting with culture-aware output |
| 14 | +- **DateTimeFormatter**: Provides date and time formatting with standard and custom format specifiers |
| 15 | +- **String Case Formatters**: Provides text case transformations with custom format specifiers |
| 16 | + |
| 17 | +## Standard .NET Format Strings |
| 18 | + |
| 19 | +### Numeric Formatting |
| 20 | + |
| 21 | +You can now use standard .NET numeric format strings with version components: |
| 22 | + |
| 23 | +```yaml |
| 24 | +# GitVersion.yml |
| 25 | +template: "{Major}.{Minor}.{Patch:F2}-{PreReleaseLabel}" |
| 26 | +``` |
| 27 | +
|
| 28 | +**Supported Numeric Formats:** |
| 29 | +
|
| 30 | +- `F` or `f` (Fixed-point): `{Patch:F2}` → `"1.23"` |
| 31 | +- `N` or `n` (Number): `{BuildMetadata:N0}` → `"1,234"` |
| 32 | +- `C` or `c` (Currency): `{Major:C}` → `"¤1.00"` |
| 33 | +- `P` or `p` (Percent): `{CommitsSinceVersionSource:P}` → `"12,345.60 %"` |
| 34 | +- `D` or `d` (Decimal): `{Major:D4}` → `"0001"` |
| 35 | +- `X` or `x` (Hexadecimal): `{Patch:X}` → `"FF"` |
| 36 | + |
| 37 | +### Date and Time Formatting |
| 38 | + |
| 39 | +When working with date-related properties like `CommitDate`: |
| 40 | + |
| 41 | +```yaml |
| 42 | +template: "Build-{SemVer}-{CommitDate:yyyy-MM-dd}" |
| 43 | +``` |
| 44 | + |
| 45 | +**Common Date Format Specifiers:** |
| 46 | + |
| 47 | +- `yyyy-MM-dd` → `"2024-03-15"` |
| 48 | +- `HH:mm:ss` → `"14:30:22"` |
| 49 | +- `MMM dd, yyyy` → `"Mar 15, 2024"` |
| 50 | +- `yyyy-MM-dd'T'HH:mm:ss'Z'` → `"2024-03-15T14:30:22Z"` |
| 51 | + |
| 52 | +## Custom String Case Formatters |
| 53 | + |
| 54 | +GitVersion introduces custom format specifiers for string case transformations that can be used in templates: |
| 55 | + |
| 56 | +### Available Case Formats |
| 57 | + |
| 58 | +| Format | Description | Example Input | Example Output | |
| 59 | +|--------|-------------|---------------|----------------| |
| 60 | +| `u` | **Uppercase** - Converts entire string to uppercase | `feature-branch` | `FEATURE-BRANCH` | |
| 61 | +| `l` | **Lowercase** - Converts entire string to lowercase | `Feature-Branch` | `feature-branch` | |
| 62 | +| `t` | **Title Case** - Capitalizes first letter of each word | `feature-branch` | `Feature-Branch` | |
| 63 | +| `s` | **Sentence Case** - Capitalizes only the first letter | `feature-branch` | `Feature-branch` | |
| 64 | +| `c` | **PascalCase** - Removes separators and capitalizes each word | `feature-branch` | `FeatureBranch` | |
| 65 | + |
| 66 | +### Usage Examples |
| 67 | + |
| 68 | +```yaml |
| 69 | +# GitVersion.yml configuration |
| 70 | +branches: |
| 71 | + feature: |
| 72 | + label: "{BranchName:c}" # Converts to PascalCase |
| 73 | + |
| 74 | +template: "{Major}.{Minor}.{Patch}-{PreReleaseLabel:l}.{CommitsSinceVersionSource:0000}" |
| 75 | +``` |
| 76 | + |
| 77 | +**Template Usage:** |
| 78 | + |
| 79 | +```yaml |
| 80 | +# Using format strings in templates |
| 81 | +assembly-informational-format: "{Major}.{Minor}.{Patch}-{CommitsSinceVersionSource:0000}" |
| 82 | +template: "{SemVer}-{BranchName:l}" |
| 83 | +``` |
| 84 | + |
| 85 | +## Examples |
| 86 | + |
| 87 | +Based on actual test cases from the implementation: |
| 88 | + |
| 89 | +### Zero-Padded Numeric Formatting |
| 90 | + |
| 91 | +```yaml |
| 92 | +# Zero-padded commit count |
| 93 | +assembly-informational-format: "{Major}.{Minor}.{Patch}-{CommitsSinceVersionSource:0000}" |
| 94 | +# Result: "1.2.3-0042" |
| 95 | +``` |
| 96 | + |
| 97 | +### String Case Transformations |
| 98 | + |
| 99 | +```yaml |
| 100 | +branches: |
| 101 | + feature: |
| 102 | + label: "{BranchName:c}" # PascalCase: "feature-branch" → "FeatureBranch" |
| 103 | + hotfix: |
| 104 | + label: "hotfix-{BranchName:l}" # Lowercase: "HOTFIX-BRANCH" → "hotfix-branch" |
| 105 | +``` |
| 106 | + |
| 107 | +### Date and Time Formatting |
| 108 | + |
| 109 | +```yaml |
| 110 | +template: "{SemVer}-build-{CommitDate:yyyy-MM-dd}" |
| 111 | +# Result: "1.2.3-build-2021-01-01" |
| 112 | +``` |
| 113 | + |
| 114 | +### Numeric Formatting |
| 115 | + |
| 116 | +```yaml |
| 117 | +# Currency format (uses InvariantCulture) |
| 118 | +template: "Cost-{Major:C}" # Result: "Cost-¤1.00" |
| 119 | +
|
| 120 | +# Percentage format |
| 121 | +template: "Progress-{Minor:P}" # Result: "Progress-200.00 %" |
| 122 | +
|
| 123 | +# Thousands separator |
| 124 | +template: "Build-{CommitsSinceVersionSource:N0}" # Result: "Build-1,234" |
| 125 | +``` |
| 126 | + |
| 127 | +## Configuration Integration |
| 128 | + |
| 129 | +The format strings are used in GitVersion configuration files through various formatting properties: |
| 130 | + |
| 131 | +### Assembly Version Formatting |
| 132 | + |
| 133 | +```yaml |
| 134 | +# GitVersion.yml |
| 135 | +assembly-informational-format: "{Major}.{Minor}.{Patch}-{CommitsSinceVersionSource:0000}" |
| 136 | +assembly-versioning-format: "{Major}.{Minor}.{Patch}.{env:BUILD_NUMBER}" |
| 137 | +assembly-file-versioning-format: "{MajorMinorPatch}.{CommitsSinceVersionSource}" |
| 138 | +``` |
| 139 | + |
| 140 | +### Template-Based Configuration |
| 141 | + |
| 142 | +```yaml |
| 143 | +# Global template for consistent formatting across all variables |
| 144 | +template: "{SemVer}-{BranchName:l}-{ShortSha}" |
| 145 | +
|
| 146 | +branches: |
| 147 | + main: |
| 148 | + label: "" |
| 149 | + feature: |
| 150 | + label: "{BranchName:c}.{CommitsSinceVersionSource}" |
| 151 | + increment: Minor |
| 152 | + release: |
| 153 | + label: "rc-{CommitsSinceVersionSource:000}" |
| 154 | + increment: None |
| 155 | +``` |
| 156 | + |
| 157 | +### Environment Variable Integration |
| 158 | + |
| 159 | +```yaml |
| 160 | +# Using environment variables with fallbacks |
| 161 | +template: "{Major}.{Minor}.{Patch}-{env:RELEASE_STAGE ?? 'dev'}" |
| 162 | +assembly-informational-format: "{SemVer}+{env:BUILD_ID ?? 'local'}" |
| 163 | +``` |
| 164 | + |
| 165 | +### Real-World Integration Examples |
| 166 | + |
| 167 | +Based on the actual test implementation: |
| 168 | + |
| 169 | +```yaml |
| 170 | +# Example from VariableProviderTests.cs |
| 171 | +assembly-informational-format: "{Major}.{Minor}.{Patch}-{CommitsSinceVersionSource:0000}" |
| 172 | +# Result: "1.2.3-0042" when CommitsSinceVersionSource = 42 |
| 173 | +
|
| 174 | +# Branch-specific formatting |
| 175 | +branches: |
| 176 | + feature: |
| 177 | + label: "{BranchName:c}" # PascalCase conversion |
| 178 | + hotfix: |
| 179 | + label: "hotfix.{CommitsSinceVersionSource:00}" |
| 180 | +``` |
| 181 | + |
| 182 | +## Invariant Culture Formatting |
| 183 | + |
| 184 | +The formatting system uses `CultureInfo.InvariantCulture` by default through the chained `TryFormat` overload implementation. This provides: |
| 185 | + |
| 186 | +- **Consistent results** across all environments and systems |
| 187 | +- **Predictable numeric formatting** with period (.) as decimal separator and comma (,) as thousands separator |
| 188 | +- **Standard date formatting** using English month names and formats |
| 189 | +- **No localization variations** regardless of system locale |
| 190 | + |
| 191 | +```csharp |
| 192 | +// All environments produce the same output: |
| 193 | +// {CommitsSinceVersionSource:N0} → "1,234" |
| 194 | +// {CommitDate:MMM dd, yyyy} → "Mar 15, 2024" |
| 195 | +// {Major:C} → "¤1.00" (generic currency symbol) |
| 196 | +``` |
| 197 | + |
| 198 | +This ensures that version strings generated by GitVersion are consistent across different build environments, developer machines, and CI/CD systems. |
| 199 | + |
| 200 | +## Verified Examples |
| 201 | + |
| 202 | +The following examples are verified by actual unit tests in the GitVersion codebase: |
| 203 | + |
| 204 | +### Zero-Padded Numeric Formatting |
| 205 | + |
| 206 | +```yaml |
| 207 | +assembly-informational-format: "{Major}.{Minor}.{Patch}-{CommitsSinceVersionSource:0000}" |
| 208 | +``` |
| 209 | + |
| 210 | +**Test**: `VariableProviderTests.Format_Allows_CSharp_FormatStrings()` |
| 211 | +**Input**: `CommitsSinceVersionSource = 42` |
| 212 | +**Output**: `"1.2.3-0042"` |
| 213 | + |
| 214 | +### String Case Transformations |
| 215 | + |
| 216 | +```csharp |
| 217 | +// From StringFormatterTests.cs |
| 218 | +[TestCase("hello world", "c", "HelloWorld")] // PascalCase |
| 219 | +[TestCase("hello", "u", "HELLO")] // Uppercase |
| 220 | +[TestCase("HELLO", "l", "hello")] // Lowercase |
| 221 | +[TestCase("hello world", "t", "Hello World")] // Title Case |
| 222 | +[TestCase("hELLO", "s", "Hello")] // Sentence Case |
| 223 | +``` |
| 224 | + |
| 225 | +### Numeric Format Specifiers |
| 226 | + |
| 227 | +```csharp |
| 228 | +// From NumericFormatterTests.cs |
| 229 | +[TestCase("1234.5678", "n", "1,234.57")] // Number format |
| 230 | +[TestCase("1234.5678", "f2", "1234.57")] // Fixed-point format |
| 231 | +[TestCase("1234.5678", "f0", "1235")] // No decimals |
| 232 | +``` |
| 233 | + |
| 234 | +### Date Formatting |
| 235 | + |
| 236 | +```csharp |
| 237 | +// From DateFormatterTests.cs |
| 238 | +[TestCase("2021-01-01", "yyyy-MM-dd", "2021-01-01")] |
| 239 | +[TestCase("2021-01-01T12:00:00Z", "yyyy-MM-ddTHH:mm:ssZ", "2021-01-01T12:00:00Z")] |
| 240 | +``` |
| 241 | + |
| 242 | +### Currency and Percentage (InvariantCulture) |
| 243 | + |
| 244 | +```csharp |
| 245 | +// From FormattableFormatterTests.cs |
| 246 | +[TestCase(123.456, "C", "¤123.46")] // Generic currency symbol |
| 247 | +[TestCase(123.456, "P", "12,345.60 %")] // Percentage format |
| 248 | +[TestCase(1234567890, "N0", "1,234,567,890")] // Thousands separators |
| 249 | +``` |
| 250 | + |
| 251 | +[reference-configuration]: /docs/reference/configuration |
| 252 | +[variables]: /docs/reference/variables |
0 commit comments