Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .azure/pipelines/build-bravo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions docs/design/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 39 additions & 2 deletions installer/wix/extensions/Bravo.Installer.Wix/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
Expand All @@ -88,6 +91,40 @@ internal static TelemetryClient GetTelemetryClient(Session session)
return telemetryClient;
}

/// <summary>
/// Maps the self-contained build flag to the publish mode reported by the application.
/// </summary>
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;
}

/// <summary>
/// Maps the WiX Package/@InstallScope value to the deployment mode reported by the application.
/// </summary>
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))
Expand Down
10 changes: 7 additions & 3 deletions installer/wix/src/Bravo/Bravo-perUser.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<?define AppName = "Bravo" ?>
<?define InstallScope = "perUser" ?>

<?if $(var.SelfContained) != "true" and $(var.SelfContained) != "false" ?>
<?error SelfContained must be "true" or "false", got "$(var.SelfContained)" ?>
<?endif ?>

<?if $(sys.BUILDARCH) = x64 ?>
<?define ProductName = "!(loc.ProductName) (User)" ?>
<?define Win64 = "yes" ?>
Expand Down Expand Up @@ -108,11 +112,11 @@
<SetProperty Action="UndefineAPPLICATIONTELEMETRYENABLED" Id="APPLICATIONTELEMETRYENABLED" Value="{}" After="AppSearch" Sequence="first"><![CDATA[APPLICATIONTELEMETRYENABLED AND APPLICATIONTELEMETRYENABLED <> "1"]]></SetProperty>

<CustomAction Id="SetPropertyTelemetryUserId" BinaryKey="CustomActionBinary" DllEntry="SetPropertyTelemetryUserId" Execute="immediate" Impersonate="yes" />
<CustomAction Id="SetPropertyValuesAfterInstall" Property="AfterInstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID]" />
<CustomAction Id="SetPropertyValuesAfterInstall" Property="AfterInstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="AfterInstall" BinaryKey="CustomActionBinary" DllEntry="AfterInstall" Execute="deferred" Impersonate="yes" />
<CustomAction Id="SetPropertyValuesDeleteUserAppLocalFolder" Property="DeleteUserAppLocalFolder" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];LOCALAPPDATASUBFOLDER=$(var.AppInstallSubfolder)" />
<CustomAction Id="SetPropertyValuesDeleteUserAppLocalFolder" Property="DeleteUserAppLocalFolder" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];LOCALAPPDATASUBFOLDER=$(var.AppInstallSubfolder);SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="DeleteUserAppLocalFolder" BinaryKey="CustomActionBinary" DllEntry="DeleteUserAppLocalFolder" Execute="deferred" Impersonate="yes" />
<CustomAction Id="SetPropertyValuesAfterUninstall" Property="AfterUninstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID]" />
<CustomAction Id="SetPropertyValuesAfterUninstall" Property="AfterUninstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="AfterUninstall" BinaryKey="CustomActionBinary" DllEntry="AfterUninstall" Execute="deferred" Impersonate="yes" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" />

Expand Down
16 changes: 10 additions & 6 deletions installer/wix/src/Bravo/Bravo.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
<?define AppName = "Bravo" ?>
<?define InstallScope = "perMachine" ?>
<?define PbitoolName = "bravo.pbitool.json" ?>


<?if $(var.SelfContained) != "true" and $(var.SelfContained) != "false" ?>
<?error SelfContained must be "true" or "false", got "$(var.SelfContained)" ?>
<?endif ?>

<?if $(sys.BUILDARCH) = x64 ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define ProductName = "!(loc.ProductName)" ?>
Expand Down Expand Up @@ -108,15 +112,15 @@
<SetProperty Action="UndefineAPPLICATIONTELEMETRYENABLED" Id="APPLICATIONTELEMETRYENABLED" Value="{}" After="AppSearch" Sequence="first"><![CDATA[APPLICATIONTELEMETRYENABLED AND APPLICATIONTELEMETRYENABLED <> "1"]]></SetProperty>

<CustomAction Id="SetPropertyTelemetryUserId" BinaryKey="CustomActionBinary" DllEntry="SetPropertyTelemetryUserId" Execute="immediate" Impersonate="yes" />
<CustomAction Id="SetPropertyValuesRegisterExternalTool" Property="RegisterExternalTool" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];PRODUCTEXECUTABLEPATH=[INSTALLFOLDER]$(var.AppExecutableName);PBITOOLPATH=[POWERBIEXTERNALTOOLSFOLDER]$(var.PbitoolName)" />
<CustomAction Id="SetPropertyValuesRegisterExternalTool" Property="RegisterExternalTool" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];PRODUCTEXECUTABLEPATH=[INSTALLFOLDER]$(var.AppExecutableName);PBITOOLPATH=[POWERBIEXTERNALTOOLSFOLDER]$(var.PbitoolName);SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="RegisterExternalTool" BinaryKey="CustomActionBinary" DllEntry="RegisterExternalTool" Execute="deferred" Impersonate="no" />
<CustomAction Id="SetPropertyValuesAfterInstall" Property="AfterInstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID]" />
<CustomAction Id="SetPropertyValuesAfterInstall" Property="AfterInstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="AfterInstall" BinaryKey="CustomActionBinary" DllEntry="AfterInstall" Execute="deferred" Impersonate="no" />
<CustomAction Id="SetPropertyValuesUnregisterExternalTool" Property="UnregisterExternalTool" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];PRODUCTEXECUTABLEPATH=[INSTALLFOLDER]$(var.AppExecutableName);PBITOOLPATH=[POWERBIEXTERNALTOOLSFOLDER]$(var.PbitoolName)" />
<CustomAction Id="SetPropertyValuesUnregisterExternalTool" Property="UnregisterExternalTool" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];PRODUCTEXECUTABLEPATH=[INSTALLFOLDER]$(var.AppExecutableName);PBITOOLPATH=[POWERBIEXTERNALTOOLSFOLDER]$(var.PbitoolName);SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="UnregisterExternalTool" BinaryKey="CustomActionBinary" DllEntry="UnregisterExternalTool" Execute="deferred" Impersonate="no" />
<CustomAction Id="SetPropertyValuesDeleteUserAppLocalFolder" Property="DeleteUserAppLocalFolder" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];LOCALAPPDATASUBFOLDER=$(var.AppInstallSubfolder)" />
<CustomAction Id="SetPropertyValuesDeleteUserAppLocalFolder" Property="DeleteUserAppLocalFolder" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];LOCALAPPDATASUBFOLDER=$(var.AppInstallSubfolder);SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="DeleteUserAppLocalFolder" BinaryKey="CustomActionBinary" DllEntry="DeleteUserAppLocalFolder" Execute="deferred" Impersonate="no" />
<CustomAction Id="SetPropertyValuesAfterUninstall" Property="AfterUninstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID]" />
<CustomAction Id="SetPropertyValuesAfterUninstall" Property="AfterUninstall" Value="INSTALLSCOPE=$(var.InstallScope);PRODUCTNAME=$(var.AppName);PRODUCTVERSION=$(var.ProductVersion);PRODUCTBUILD=$(var.ProductBuild);INSTALLERTELEMETRYENABLED=[INSTALLERTELEMETRYENABLED];TELEMETRYUSERID=[TELEMETRYUSERID];SELFCONTAINED=$(var.SelfContained)" />
<CustomAction Id="AfterUninstall" BinaryKey="CustomActionBinary" DllEntry="AfterUninstall" Execute="deferred" Impersonate="no" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" />

Expand Down
Binary file modified installer/wix/src/assets/Bravo.Installer.Wix.CA.dll
Binary file not shown.
4 changes: 2 additions & 2 deletions publish.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading