diff --git a/.azure/pipelines/build-bravo.yaml b/.azure/pipelines/build-bravo.yaml
index 89f3e83a..20b569b9 100644
--- a/.azure/pipelines/build-bravo.yaml
+++ b/.azure/pipelines/build-bravo.yaml
@@ -73,13 +73,13 @@ steps:
- task: CmdLine@2
displayName: 'WiX compile app'
inputs:
- script: '"%WIX%bin\candle.exe" Bravo.wxs -dPublishFolder="$(Build.BinariesDirectory)" -dVersion="$(NBGV_SimpleVersion)" -arch "$(arch)"'
+ script: '"%WIX%bin\candle.exe" Bravo.wxs -dPublishFolder="$(Build.BinariesDirectory)" -dVersion="$(NBGV_SemVer2)" -dSelfContained="$(selfcontained)" -arch "$(arch)"'
workingDirectory: '$(installerSourcesDirectory)'
failOnStderr: true
- task: CmdLine@2
displayName: 'WiX compile app (perUser)'
inputs:
- script: '"%WIX%bin\candle.exe" Bravo-perUser.wxs -dPublishFolder="$(Build.BinariesDirectory)" -dVersion="$(NBGV_SimpleVersion)" -arch "$(arch)"'
+ script: '"%WIX%bin\candle.exe" Bravo-perUser.wxs -dPublishFolder="$(Build.BinariesDirectory)" -dVersion="$(NBGV_SemVer2)" -dSelfContained="$(selfcontained)" -arch "$(arch)"'
workingDirectory: '$(installerSourcesDirectory)'
failOnStderr: true
- task: CmdLine@2
diff --git a/docs/design/versioning.md b/docs/design/versioning.md
index 4fb611af..595ddb33 100644
--- a/docs/design/versioning.md
+++ b/docs/design/versioning.md
@@ -22,18 +22,18 @@ Do not set `Version`, `FileVersion` or `InformationalVersion` in `Bravo.csproj`:
| `AssemblyFileVersion` | `X.Y.Z.{height}` | ordering two builds; MSI `ProductVersion` |
| `AssemblyInformationalVersion` | `X.Y.Z.{height}[-tag]+{commit}` | diagnostics |
| `AssemblyVersion` | `X.Y.0.0` | assembly identity (`assemblyVersion.precision: minor`) |
-| `NBGV_SimpleVersion` | `X.Y.Z` | WiX `-dVersion` |
-| `NBGV_SemVer2` | `X.Y.Z[-tag]` | artifact names, git tag, `AppVersion.SemanticVersion` |
+| `NBGV_SemVer2` | `X.Y.Z[-tag]` | artifact names, git tag, `AppVersion.SemanticVersion`, WiX `-dVersion` |
`{height}` is the number of commits since the numeric `X.Y.Z` last changed. It is a build counter: it makes
every build uniquely identifiable and orders builds that share the same `X.Y.Z`.
## Rules
-- **The prerelease tag never reaches a numeric field.** `AssemblyFileVersion` and `NBGV_SimpleVersion` stay
-numeric in every state, so Windows Installer and `System.Version` keep working unchanged.
+- **The prerelease tag never reaches a numeric field.** `AssemblyFileVersion` stays numeric in every state, so
+Windows Installer and `System.Version` keep working unchanged. WiX `-dVersion` carries the tag but feeds the
+installer telemetry only: the MSI `ProductVersion` is bound to the file version of `Bravo.exe`.
-- **`SemVer2` is the version that the application and the artifacts report.** The
+- **`SemVer2` is the version that the application, the installer and the artifacts report.** The
application reads it as `ThisAssembly.NuGetPackageVersion`, which equals `SemVer2` only while
`nuGetPackageVersion.semVer` is `2` in `version.json` and `NBGV_ThisAssemblyIncludesPackageVersion` is set in
`Bravo.csproj`. Without the first, the application reports the SemVer1 form `X.Y.Z-tag-0001-g{commit}`; without
diff --git a/installer/wix/extensions/Bravo.Installer.Wix/Helpers.cs b/installer/wix/extensions/Bravo.Installer.Wix/Helpers.cs
index 3c399663..624225af 100644
--- a/installer/wix/extensions/Bravo.Installer.Wix/Helpers.cs
+++ b/installer/wix/extensions/Bravo.Installer.Wix/Helpers.cs
@@ -15,6 +15,7 @@ internal static class Helpers
internal const string PropertyProductName = "PRODUCTNAME";
internal const string PropertyProductVersion = "PRODUCTVERSION";
internal const string PropertyProductBuild = "PRODUCTBUILD";
+ internal const string PropertySelfContained = "SELFCONTAINED";
internal const string PropertyProductExecutablePath = "PRODUCTEXECUTABLEPATH";
internal const string PropertyInstallerTelemetryEnabled = "INSTALLERTELEMETRYENABLED";
internal const string PropertyTelemetryUserId = "TELEMETRYUSERID";
@@ -68,18 +69,20 @@ internal static TelemetryClient GetTelemetryClient(Session session)
var productVersion = session.CustomActionData[PropertyProductVersion];
var productBuild = session.CustomActionData[PropertyProductBuild];
var userId = session.CustomActionData[PropertyTelemetryUserId];
- var installScope = session.CustomActionData[PropertyInstallScope];
+ var installScope = GetInstallScope(session.CustomActionData[PropertyInstallScope]);
+ var publishMode = GetPublishMode(session.CustomActionData[PropertySelfContained]);
var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.InstrumentationKey = "47a8970c-6293-408a-9cce-5b7b311574d3";
telemetryConfiguration.DisableTelemetry = false;
- // Keep telemetry context configuration synchronized with Sqlbi.Bravo.Infrastructure.Helpers.ContextTelemetryInitializer
+ // Keep telemetry context configuration synchronized with Sqlbi.Bravo.Infrastructure.Telemetry.TelemetrySessionInfo
var telemetryClient = new TelemetryClient(telemetryConfiguration);
telemetryClient.Context.Device.OperatingSystem = Environment.OSVersion.ToString();
telemetryClient.Context.Component.Version = productVersion;
telemetryClient.Context.Session.Id = Guid.NewGuid().ToString();
telemetryClient.Context.User.Id = userId;
+ telemetryClient.Context.GlobalProperties.Add("PublishMode", publishMode);
telemetryClient.Context.GlobalProperties.Add("InstallScope", installScope);
telemetryClient.Context.GlobalProperties.Add("ProductName", productName);
telemetryClient.Context.GlobalProperties.Add("Version", productVersion);
@@ -88,6 +91,40 @@ internal static TelemetryClient GetTelemetryClient(Session session)
return telemetryClient;
}
+ ///
+ /// Maps the self-contained build flag to the publish mode reported by the application.
+ ///
+ internal static string GetPublishMode(string selfContained)
+ {
+ // This method must not throw because it can be called while reporting exceptions from
+ // custom actions. An exception here would fail the custom action and roll back the installation.
+ if (bool.TryParse(selfContained, out var value))
+ return value ? "SelfContained" : "FrameworkDependent";
+
+ // Unexpected values are reported as received, so that the telemetry shows what the build passed in
+ return selfContained;
+ }
+
+ ///
+ /// Maps the WiX Package/@InstallScope value to the deployment mode reported by the application.
+ ///
+ internal static string GetInstallScope(string installScope)
+ {
+ // The installer telemetry used to send the raw WiX values 'perMachine' and 'perUser'. The values are now
+ // mapped to 'PerMachine' and 'PerUser', the AppDeploymentMode names sent by the application telemetry,
+ // so that the InstallScope property has the same set of values for both sources.
+ //
+ // See GetPublishMode for why this method must not throw.
+ if (string.Equals(installScope, "perMachine", StringComparison.OrdinalIgnoreCase))
+ return "PerMachine";
+
+ if (string.Equals(installScope, "perUser", StringComparison.OrdinalIgnoreCase))
+ return "PerUser";
+
+ // Unexpected values are reported as received, so that the telemetry shows what the build passed in
+ return installScope;
+ }
+
internal static bool IsTelemetryEnabled(Session session)
{
if (session.CustomActionData.TryGetValue(PropertyInstallerTelemetryEnabled, out var value))
diff --git a/installer/wix/src/Bravo/Bravo-perUser.wxs b/installer/wix/src/Bravo/Bravo-perUser.wxs
index d6dbbb65..d2617903 100644
--- a/installer/wix/src/Bravo/Bravo-perUser.wxs
+++ b/installer/wix/src/Bravo/Bravo-perUser.wxs
@@ -11,6 +11,10 @@
+
+
+
+
@@ -108,11 +112,11 @@
"1"]]>
-
+
-
+
-
+
diff --git a/installer/wix/src/Bravo/Bravo.wxs b/installer/wix/src/Bravo/Bravo.wxs
index fcb2a820..fe0add27 100644
--- a/installer/wix/src/Bravo/Bravo.wxs
+++ b/installer/wix/src/Bravo/Bravo.wxs
@@ -11,7 +11,11 @@
-
+
+
+
+
+
@@ -108,15 +112,15 @@
"1"]]>
-
+
-
+
-
+
-
+
-
+
diff --git a/installer/wix/src/assets/Bravo.Installer.Wix.CA.dll b/installer/wix/src/assets/Bravo.Installer.Wix.CA.dll
index 32a2418a..477dbd83 100644
Binary files a/installer/wix/src/assets/Bravo.Installer.Wix.CA.dll and b/installer/wix/src/assets/Bravo.Installer.Wix.CA.dll differ
diff --git a/publish.cmd b/publish.cmd
index f19f8c6e..20b8b5b5 100644
--- a/publish.cmd
+++ b/publish.cmd
@@ -46,8 +46,8 @@ IF EXIST *.wixobj DEL *.wixobj
IF EXIST *.wixpdb DEL *.wixpdb
%wixheat% dir "%publishfolder%" -gg -scom -srd -sreg -sfrag -templatefragment -cg ComponentsAutogenerated -dr INSTALLFOLDER -var var.PublishFolder -t Bravo.xslt -out Components.wxs -nologo || GOTO :error
%wixcandle% Components.wxs -dPublishFolder="%publishfolder%" -arch "%arch%" -nologo || GOTO :error
-%wixcandle% Bravo.wxs -arch "%arch%" -dPublishFolder="%publishfolder%" -dVersion="%version%" -nologo || GOTO :error
-%wixcandle% Bravo-perUser.wxs -arch "%arch%" -dPublishFolder="%publishfolder%" -dVersion="%version%" -nologo || GOTO :error
+%wixcandle% Bravo.wxs -arch "%arch%" -dPublishFolder="%publishfolder%" -dVersion="%version%" -dSelfContained="%selfcontained%" -nologo || GOTO :error
+%wixcandle% Bravo-perUser.wxs -arch "%arch%" -dPublishFolder="%publishfolder%" -dVersion="%version%" -dSelfContained="%selfcontained%" -nologo || GOTO :error
%wixlight% Bravo.wixobj Components.wixobj -ext WixUIExtension.dll -ext WixUtilExtension.dll -cultures:en-us -loc Bravo-en-us.wxl -out "Bravo-%arch%-en-us.msi" -sice:ICE03 -sice:ICE60 -sice:ICE61 -sice:ICE80 -nologo || GOTO :error
%wixlight% Bravo-perUser.wixobj Components.wixobj -ext WixUIExtension.dll -ext WixUtilExtension.dll -cultures:en-us -loc Bravo-en-us.wxl -out "Bravo-%arch%-en-us-userinstaller.msi" -sice:ICE57 -sice:ICE60 -sice:ICE61 -sice:ICE80 -nologo || GOTO :error