[MM-55341][MM-56894] Use electron-builder to create the MSI installer, drop support for 32-bit Windows and the NSIS installer (#3028)

* Drop 32-bit windows support

* Remove unnecessary after build script

* Enable MSI build from electron-builder

* Copy MSI installers correctly

* Change script to `windows-installer`

* Revert "Remove unnecessary after build script"

This reverts commit 65b1cccb063656916a7d12c440792ad013dff826.

* Fix duplicate installers when updating to EXE version

* Inject the app-update.yml from the NSIS installer into the MSI, have the MSI uninstall the EXE if it exists

* Cleanup old MSI builder, switch actions to use new process

* Sign PR builds

* Update to use absolute paths

* Use env variable paths
This commit is contained in:
Devin Binnie 2024-05-14 12:07:45 -04:00 committed by GitHub
parent a59115b878
commit e244b2c230
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 86 additions and 1956 deletions

View file

@ -113,7 +113,6 @@ jobs:
node-gyp install node-gyp install
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64 node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
- name: ci/install-dependencies - name: ci/install-dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true' if: steps.cache-node-modules.outputs.cache-hit != 'true'
env: env:
@ -123,6 +122,10 @@ jobs:
- name: ci/build - name: ci/build
env: env:
MM_WIN_INSTALLERS: 1 MM_WIN_INSTALLERS: 1
PFX_KEY: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX_KEY }}
CSC_KEY_PASSWORD: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_KEY_PASSWORD }}
PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }}
CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }}
run: | run: |
mkdir -p ./build/win mkdir -p ./build/win
npm run package:windows npm run package:windows

View file

@ -114,7 +114,6 @@ jobs:
node-gyp install node-gyp install
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64 node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
- name: ci/install-dependencies - name: ci/install-dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true' if: steps.cache-node-modules.outputs.cache-hit != 'true'
env: env:

View file

@ -168,7 +168,6 @@ jobs:
node-gyp install node-gyp install
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64 node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
npm ci --openssl_fips='' npm ci --openssl_fips=''
npm i robotjs npm i robotjs
npx electron-rebuild --platform=win32 -f -t prod,optional,dev -w robotjs npx electron-rebuild --platform=win32 -f -t prod,optional,dev -w robotjs

View file

@ -72,19 +72,14 @@ jobs:
node-version-file: "package.json" node-version-file: "package.json"
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: package-lock.json
- name: nightly/optimize
shell: powershell
run: ./scripts/Makefile.ps1 optimize
- name: nightly/install-deps - name: nightly/install-deps
shell: powershell shell: powershell
run: | run: |
./scripts/Makefile.ps1 install-deps
choco install yq --version 4.15.1 -y choco install yq --version 4.15.1 -y
npm i -g node-gyp npm i -g node-gyp
node-gyp install node-gyp install
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64 node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
npm ci --openssl_fips='' npm ci --openssl_fips=''
- name: nightly/test - name: nightly/test
uses: ./.github/actions/test uses: ./.github/actions/test
@ -96,7 +91,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_KEY_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_KEY_PASSWORD }}
PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }} PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }}
CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }} CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }}
run: ./scripts/Makefile.ps1 build run: npm run package:windows-installers
- name: nightly/package - name: nightly/package
run: | run: |
mkdir -p ./build/win-release mkdir -p ./build/win-release

View file

@ -39,19 +39,14 @@ jobs:
node-version-file: "package.json" node-version-file: "package.json"
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: package-lock.json
- name: nightly/optimize
shell: powershell
run: ./scripts/Makefile.ps1 optimize
- name: nightly/install-deps - name: nightly/install-deps
shell: powershell shell: powershell
run: | run: |
./scripts/Makefile.ps1 install-deps
choco install yq --version 4.15.1 -y choco install yq --version 4.15.1 -y
npm i -g node-gyp npm i -g node-gyp
node-gyp install node-gyp install
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64 node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
npm ci --openssl_fips='' npm ci --openssl_fips=''
- name: nightly/test - name: nightly/test
uses: ./.github/actions/test uses: ./.github/actions/test
@ -63,7 +58,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_KEY_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_KEY_PASSWORD }}
PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }} PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }}
CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }} CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }}
run: ./scripts/Makefile.ps1 build run: npm run package:windows-installers
- name: nightly/package - name: nightly/package
run: | run: |
mkdir -p ./build/win mkdir -p ./build/win

View file

@ -84,19 +84,14 @@ jobs:
node-version-file: "package.json" node-version-file: "package.json"
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: package-lock.json
- name: release/optimize
shell: powershell
run: ./scripts/Makefile.ps1 optimize
- name: release/install-deps - name: release/install-deps
shell: powershell shell: powershell
run: | run: |
./scripts/Makefile.ps1 install-deps
choco install yq --version 4.15.1 -y choco install yq --version 4.15.1 -y
npm i -g node-gyp npm i -g node-gyp
node-gyp install node-gyp install
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64 node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="C:\Users\runneradmin\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
npm ci --openssl_fips='' npm ci --openssl_fips=''
- name: release/test - name: release/test
uses: ./.github/actions/test uses: ./.github/actions/test
@ -109,7 +104,7 @@ jobs:
PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }} PFX: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_PFX }}
CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }} CSC_LINK: ${{ secrets.MM_DESKTOP_MSI_INSTALLER_CSC_LINK }}
run: | run: |
./scripts/Makefile.ps1 build npm run package:windows-installers
- name: release/package - name: release/package
run: | run: |
mkdir -p ./build/win-release mkdir -p ./build/win-release

View file

@ -156,7 +156,8 @@
"win": { "win": {
"target": [ "target": [
"nsis", "nsis",
"zip" "zip",
"msi"
], ],
"extraFiles": [ "extraFiles": [
{ {
@ -164,13 +165,20 @@
"LICENSE.txt", "LICENSE.txt",
"NOTICE.txt" "NOTICE.txt"
] ]
},
{
"from": "resources/windows/gpo",
"to": "gpo"
} }
], ],
"signDlls": true,
"publisherName": "CN=\"Mattermost, Inc.\", O=\"Mattermost, Inc.\", L=Palo Alto, S=California, C=US" "publisherName": "CN=\"Mattermost, Inc.\", O=\"Mattermost, Inc.\", L=Palo Alto, S=California, C=US"
}, },
"nsis": { "nsis": {
"artifactName": "${version}/${name}-setup-${version}-win.${ext}", "artifactName": "${version}/${name}-setup-${version}-win.${ext}",
"packElevateHelper": false "packElevateHelper": false,
"uninstallDisplayName": "${productName}",
"include": "scripts/installer.nsh"
}, },
"rpm": { "rpm": {
"fpm": ["--rpm-rpmbuild-define", "_build_id_links none"] "fpm": ["--rpm-rpmbuild-define", "_build_id_links none"]

View file

@ -61,9 +61,10 @@
"start": "npm run create-linux-dev-shortcut && electron dist/ --disable-dev-mode", "start": "npm run create-linux-dev-shortcut && electron dist/ --disable-dev-mode",
"restart": "run-s build start", "restart": "run-s build start",
"watch": "npm run create-linux-dev-shortcut && node scripts/watch.js", "watch": "npm run create-linux-dev-shortcut && node scripts/watch.js",
"package": "run-s package:windows package:windows-nsis package:mac-with-universal package:mas package:linux", "package": "run-s package:windows package:mac-with-universal package:mas package:linux",
"package:windows": "npm run build-prod && electron-builder --win zip --x64 --ia32 --arm64 --publish=never", "package:windows": "run-s package:windows-*",
"package:windows-nsis": "npm run build-prod-upgrade && electron-builder --win zip nsis --x64 --ia32 --arm64 --publish=never", "package:windows-zip": "npm run build-prod && electron-builder --win zip --x64 --arm64 --publish=never",
"package:windows-installers": "npm run build-prod-upgrade && electron-builder --win nsis --x64 --arm64 --publish=never && node scripts/cp_msi_app_update.js && electron-builder --win msi --x64 --arm64 --publish=never",
"package:mac": "npm run build-prod && electron-builder --config.mac.provisioningProfile=./mac.provisionProfile --mac --x64 --arm64 --publish=never", "package:mac": "npm run build-prod && electron-builder --config.mac.provisioningProfile=./mac.provisionProfile --mac --x64 --arm64 --publish=never",
"package:mac-with-universal": "npm run package:mac -- --universal", "package:mac-with-universal": "npm run package:mac -- --universal",
"package:mas": "npm run build-prod-mas && electron-builder --mac mas --universal --publish=never", "package:mas": "npm run build-prod-mas && electron-builder --mac mas --universal --publish=never",

View file

@ -0,0 +1,43 @@
diff --git a/node_modules/app-builder-lib/templates/msi/template.xml b/node_modules/app-builder-lib/templates/msi/template.xml
index 2d5cd3c..04ed672 100644
--- a/node_modules/app-builder-lib/templates/msi/template.xml
+++ b/node_modules/app-builder-lib/templates/msi/template.xml
@@ -26,6 +26,11 @@
<Property Id="ARPPRODUCTICON" Value="${iconId}"/>
{{ } -}}
+ <CustomAction Id="removeExeInstaller" Directory="APPLICATIONFOLDER" ExeCommand="[APPLICATIONFOLDER]Uninstall ${productName}.exe /S" Execute="immediate" Impersonate="yes" Return="asyncWait"/>
+ <InstallExecuteSequence>
+ <Custom Action="removeExeInstaller" Before="InstallInitialize"/>
+ </InstallExecuteSequence>
+
{{ if (isRunAfterFinish) { }}
<CustomAction Id="runAfterFinish" FileKey="mainExecutable" ExeCommand="" Execute="immediate" Impersonate="yes" Return="asyncNoWait"/>
{{ if (!isAssisted) { }}
@@ -42,6 +47,7 @@
<Property Id="ALLUSERS" Secure="yes" Value="2"/>
{{ } -}}
<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="1"/>
+ <Property Id="DISABLEAUTOUPDATE" Value="0"/>
{{ if (isAssisted) { }}
<WixVariable Id="WixUISupportPerUser" Value="1" Overridable="yes"/>
@@ -80,6 +86,7 @@
</UI>
{{ } -}}
+ <Directory Id="resourcesDir" Name="APPLICATIONFOLDER:\resources\"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="${programFilesId}">
{{ if (menuCategory) { }}
@@ -110,6 +117,10 @@
{{-dirs}}
<ComponentGroup Id="ProductComponents" Directory="APPLICATIONFOLDER">
+ <Component Directory="resourcesDir">
+ <Condition>(NOT ALLUSERS = 1) AND DISABLEAUTOUPDATE = 0</Condition>
+ <File Name="app-update.yml" Source="$(var.appDir)\..\msi-app-update.yml" ReadOnly="yes" KeyPath="yes"/>
+ </Component>
{{-files}}
</ComponentGroup>
</Product>

View file

@ -1,56 +0,0 @@
{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Courier New;}}\pard\qj\f0\fs18
\b Terms of Service\b0
\par\par
The below are the Conditions of Use (End Users) for Mattermost, the software that powers the online service you are using, not for the service itself.
\par\par
\b Mattermost Conditions of Use (End Users)\b0
\par\par
This instance of the Mattermost platform is provided to you for your use by a third party entity who is not Mattermost, Inc. Mattermost, Inc. owns some of the intellectual property required for use of the Mattermost platform, and as such, the third party has agreed that your use of our IP is allowed only if you agree and comply with the following terms and conditions.
\par\par
Your promise to comply with these conditions in exchange for access to the Mattermost IP via the Mattermost platform provided by a third party entity are an Agreement by and between you and Mattermost, Inc. (the “Agreement”).
\par\par
If you do not agree to these conditions, you may not use the Mattermost platform.
\par\par
1. Your Mattermost Account
\par\par
You may not use your Account in violation of any law or policies instituted by the entity providing you access to this Service.
\par\par
2. Responsibility of Contributors
\par\par
If you choose to make content available on the Mattermost platform (“Content”), you must ensure that the following is true:
\par\par
the downloading, copying and use of the Content will not infringe the proprietary rights, including but not limited to the copyright, patent, trademark or trade secret rights, of any third party;
\par\par
if your employer has rights to intellectual property you create, you have either (i) received permission from your employer to post or make available the Content, including but not limited to any software, or (ii) secured from your employer a waiver as to all rights in or to the Content;
\par\par
you have fully complied with any third-party licenses relating to the Content, and have done all things necessary to successfully pass through to end users any required terms;
\par\par
the Content does not contain or install any viruses, worms, malware, Trojan horses or other harmful or destructive content;
\par\par
the Content is not spam, is not machine- or randomly-generated, and does not contain unethical or unwanted commercial content designed to drive traffic to third party sites or boost the search engine rankings of third party sites, or to further unlawful acts (such as phishing) or mislead recipients as to the source of the material (such as spoofing);
\par\par
the Content is not pornographic, does not contain threats or incite violence, and does not violate the privacy or publicity rights of any third party;
\par\par
your content is not getting advertised via unwanted electronic messages such as spam links on newsgroups, email lists, blogs and web sites, and similar unsolicited promotional methods;
\par\par
your content is not named in a manner that misleads your readers into thinking that you are another person or company; and
\par\par
you have, in the case of Content that includes computer code, accurately categorized and/or described the type, nature, uses and effects of the materials, whether requested to do so by Mattermost or otherwise.
\par\par
3. Intellectual Property
\par\par
Your use of the Mattermost platform does not transfer from Mattermost to you any Mattermost or third party intellectual property, and all right, title and interest in and to such property will remain (as between the parties) solely with Mattermost. Mattermost, mattermost.com, the mattermost.com logo, and all other trademarks, service marks, graphics and logos used in connection with mattermost.com, or the Mattermost platform are trademarks or registered trademarks of Mattermost or Mattermosts licensors. Other trademarks, service marks, graphics and logos used in connection with the Platform may be the trademarks of other third parties.
\par\par
4. Disclaimer of Warranties
\par\par
THE MATTERMOST PLATFORM IS PROVIDED “AS IS.” MATTERMOST AND ITS SUPPLIERS AND LICENSORS HEREBY DISCLAIM ALL WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. NEITHER MATTERMOST NOR ITS SUPPLIERS AND LICENSORS, MAKES ANY WARRANTY THAT THE MATTERMOST PLATFORM WILL BE ERROR FREE OR THAT SERVICES USING IT WILL BE CONTINUOUS OR UNINTERRUPTED.
\par\par
5. Limitation of Liability
\par\par
IN NO EVENT WILL MATTERMOST, OR ITS SUPPLIERS OR LICENSORS, BE LIABLE TO YOU UNDER ANY THEORY OF CONTRACT, NEGLIGENCE, STRICT LIABILITY OR OTHER LEGAL OR EQUITABLE THEORY FOR: (I) ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES; (II) THE COST OF PROCUREMENT FOR SUBSTITUTE PRODUCTS OR SERVICES; (III) INTERRUPTION OF USE OR LOSS OR CORRUPTION OF DATA; OR (IV) ANY AMOUNTS IN EXCESS OF $50 USD.
\par\par
6. Indemnification
\par\par
You agree to indemnify and hold harmless Mattermost, its contractors, and its licensors, and their respective directors, officers, employees and agents from and against any and all claims and expenses, including attorneys fees, arising out of your use of the Mattermost platform, including but not limited to your violation of this Agreement.
\par\par
7. This Agreement constitutes the entire agreement between Mattermost and you concerning you use of the Mattermost platform provided by a third party. Except to the extent applicable law, if any, provides otherwise, this Agreement will be governed by the laws of the state of California, U.S.A., excluding its conflict of law provisions, and the proper venue for any disputes arising out of or relating to any of the same will be the state and federal courts located in San Francisco County, California. Except for claims for injunctive or equitable relief or claims regarding intellectual property rights (which may be brought in any competent court without the posting of a bond), any dispute arising under this Agreement shall be finally settled in accordance with the Comprehensive Arbitration Rules of the Judicial Arbitration and Mediation Service, Inc. (“JAMS”) by one arbitrator appointed in accordance with such Rules. The arbitration shall take place in San Francisco, California, in the English language and the arbitral decision may be enforced in any court. The prevailing party in any action or proceeding to enforce this Agreement shall be entitled to costs and attorneys fees. If any part of this Agreement is held invalid or unenforceable, that part will be construed to reflect the parties original intent, and the remaining portions will remain in full force and effect. A waiver by either party of any term or condition of this Agreement or any breach thereof, in any one instance, will not waive such term or condition or any subsequent breach thereof.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="LANG" Overridable="yes">1033</String>
<String Id="OsRequirements" Overridable="yes">Windows 7 or higher is required to run [ProductName].</String>
<String Id="Requires64Bit" Overridable="yes">This install package only supports 64-bit operating systems</String>
<String Id="Requires32Bit" Overridable="yes">This install package only supports 32-bit operating systems</String>
<String Id="WelcomeDlgInstructions" Overridable="yes">Welcome to the [ProductName] [Installer]!
Click Install to proceed with a standard installation, or click Advanced to change the installation directory and access other customizations.</String>
<String Id="MaintenanceWelcomeDlgInstructions" Overridable="yes">[ProductName] [Installer]!
This wizard will help you install, modify, repair or uninstall the [ProductName] application on this computer.</String>
<String Id="WelcomeDlgAcceptLicenseCheckBox" Overridable="yes">I accept the terms in the License Agreement</String>
<String Id="AdvancedDlgInstructions" Overridable="yes">Change the installation directory, create application shortcuts and choose whether to launch the application after installation. Click Cancel to exit the installer.</String>
<String Id="AdvancedDlgLocationLabel" Overridable="yes">Location:</String>
<String Id="AdvancedDlgBrowse" Overridable="yes">Browse</String>
<String Id="AdvancedDlgAddDesktopShortcut" Overridable="yes">Add a shortcut to the desktop</String>
<String Id="AdvancedDlgAddStartMenuShortcut" Overridable="yes">Add a shortcut to the Start menu</String>
<String Id="AdvancedDlgLaunchAppAfterInstall" Overridable="yes">Launch [ProductName] after installation</String>
<String Id="BrowseDlgInstructions" Overridable="yes">Select the directory you want [ProductName] be installed to.</String>
<String Id="BrowseDlgNewFolder" Overridable="yes">Create a new folder</String>
<String Id="BrowseDlgUp" Overridable="yes">Go thte parent folder</String>
<String Id="BrowseDlgPathLabel" Overridable="yes">Currently defined installation directory:</String>
<String Id="CancelDlgText" Overridable="yes">Are you sure you want to cancel [ProductName] installation?</String>
<String Id="UserExitDlgInstructions" Overridable="yes">[ProductName] installation was interrupted and your system has not been modified.
To install [ProductName] in the future, please run the installer again.</String>
<String Id="ProgressDlgInstructions" Overridable="yes">[Progress1] [ProductName]. This may take several minutes.</String>
<String Id="ProgressDlgStatusLabel" Overridable="yes">Status:</String>
<String Id="SuccessDlgInstructions" Overridable="yes">[Progress2] successful. Click Finish to exit the installer.</String>
</WixLocalization>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

View file

@ -1,766 +0,0 @@
# We would have preferred to put this main section to the end of the file,
# but script arguments must be defined as the first statement in a PowerShell
# script.
Param (
[parameter(Position=0)]$makeRule
)
# While the different sections of this file may be better with import statements
# or even better with PowerShell modules, choosing this option would require
# them to be installed on CircleCI servers, which also breaks selfcontainement
# of this makefile.
################################################################################
# Logging functions
################################################################################
#Region
function Print {
Param (
[String]$message,
[Switch]$NoNewLine
)
if ($NoNewLine) {
Write-Host " $message" -NoNewLine
} else {
Write-Host " $message"
}
}
function Print-Info {
Param (
[String]$message,
[Switch]$NoNewLine
)
if ([String]::IsNullOrEmpty($message)) {
return
}
Write-Host "[" -NoNewLine
Write-Host "+" -NoNewLine -ForegroundColor Green
Write-Host "]" -NoNewLine
if ($NoNewLine) {
Write-Host " $message" -NoNewLine
} else {
Write-Host " $message"
}
}
function Print-Warning {
Param (
[String]$message,
[Switch]$NoNewLine
)
if ([String]::IsNullOrEmpty($message)) {
return
}
Write-Host "[" -NoNewLine
Write-Host "!" -NoNewLine -ForegroundColor Magenta
Write-Host "]" -NoNewLine
if ($NoNewLine) {
Write-Host " $message" -NoNewLine
} else {
Write-Host " $message"
}
}
# Avoid stacktrace to be displayed along side the error message.
# We want things simplistic.
# src.: https://stackoverflow.com/q/38064704/3514658
# src.: https://stackoverflow.com/a/38064769
# We won't use [Console]::*Write* not $host.ui.Write* statements
# as they are UI items
# src.: https://web.archive.org/web/20190720224207/https://docs.microsoft.com/en-us/powershell/developer/cmdlet/types-of-cmdlet-output
# Rewriting the error printing function in C# and calling it from Posh is not
# working either because the redirection to stderr doesn't work under Posh but
# is working when the Posh script is run from cmd.exe. We are giving up here
# and simply using Write-Host without stderr redirection.
function Print-Error {
Param (
[String]$message,
[Switch]$NoNewLine
)
if ([String]::IsNullOrEmpty($message)) {
return
}
Write-Host "[" -NoNewLine
Write-Host "-" -NoNewLine -ForegroundColor Red
Write-Host "]" -NoNewLine
if ($NoNewLine) {
Write-Host " $message" -NoNewLine
} else {
Write-Host " $message"
}
}
#EndRegion
################################################################################
# OS related functions
################################################################################
#Region
function Check-Command($cmdname) {
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}
function Refresh-Path {
$env:Path =
[System.Environment]::GetEnvironmentVariable("Path", "Machine") +
";" +
[System.Environment]::GetEnvironmentVariable("Path", "User")
}
function Get-RootDir {
return "$(Split-Path $PSCommandPath)\..\"
}
# src: https://superuser.com/a/756696/456258
function Is-Admin {
return ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent() `
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
#EndRegion
################################################################################
# Check and install of dependencies related functions
################################################################################
#Region
function Check-Deps {
Param (
[Switch]
$verbose,
[Switch]
$throwable
)
if ($PSVersionTable.PSVersion.Major -lt 5) {
Print-Error "You need at least PowerShell 5.0 to execute this Makefile. Operation aborted."
exit
}
[array]$missing = @()
if ($verbose) { Print-Info "Checking choco dependency..." }
if (!(Check-Command "choco")) {
if ($verbose) { Print-Error "choco dependency missing." }
$missing += "choco"
}
if ($verbose) { Print-Info "Checking git dependency..." }
if (!(Check-Command "git")) {
if ($verbose) { Print-Error "git dependency missing." }
$missing += "git"
}
if ($verbose) { Print-Info "Checking nodejs/npm dependency..." }
# Testing if the folder is not empty first is needed otherwise if there is
# a file called like that in the path where the makefile is invocated, the
# check will succeed while it is plain wrong.
if ([string]::IsNullOrEmpty($(Get-NpmDir)) -or
# We could have used the builtin Test-Path cmdlet instead but it is
# tested for folders as well. We need to test for a file existence
# here.
![System.IO.File]::Exists("$(Get-NpmDir)\npm.cmd") -or
![System.IO.File]::Exists("$(Get-NpmDir)\node.exe")) {
if ($verbose) { Print-Error "nodejs/npm dependency missing." }
$missing += "npm"
}
if ($verbose) { Print-Info "Checking wix dependency..." }
if ([string]::IsNullOrEmpty($(Get-WixDir)) -or
![System.IO.File]::Exists("$(Get-WixDir)\heat.exe") -or
![System.IO.File]::Exists("$(Get-WixDir)\candle.exe") -or
![System.IO.File]::Exists("$(Get-WixDir)\light.exe")) {
if ($verbose) { Print-Error "wix dependency missing." }
$missing += "wix"
}
if ($verbose) { Print-Info "Checking signtool dependency..." }
if ([string]::IsNullOrEmpty($(Get-SignToolDir)) -or
![System.IO.File]::Exists("$(Get-SignToolDir)\signtool.exe")) {
if ($verbose) { Print-Error "signtool dependency missing." }
$missing += "signtool"
}
if ($verbose) { Print-Info "Checking jq dependency..." }
if (!(Check-Command "jq")) {
if ($verbose) { Print-Error "jq dependency missing." }
$missing += "jq"
}
if ($throwable -and $missing.Count -gt 0) {
throw "com.mattermost.makefile.deps.missing"
}
return $missing
}
function Install-Deps {
[array]$missing = Check-Deps -Verbose
if ($missing -eq $null) {
Print-Info "All dependencies met; exiting dependencies installation..."
return
}
if (-not (Is-Admin)) {
throw "com.mattermost.makefile.deps.notadmin"
}
foreach ($missingItem in $missing) {
switch ($missingItem) {
"choco" {
Print-Info "Installing chocolatey..."
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
break;
}
"git" {
Print-Info "Installing git..."
choco install git --yes
break;
}
"wix" {
Install-Wix
break;
}
"signtool" {
Print-Info "Installing Windows 10 SDK (for signtool)..."
choco install windows-sdk-10.1 --yes
break;
}
"npm" {
Print-Info "Installing nodejs-lts (with npm)..."
choco install nodejs-lts --yes
break;
}
"jq" {
Print-Info "Installing jq"
choco install jq --yes
break;
}
}
Print-Info "Refreshing PATH..."
Refresh-Path
}
InstallDeps-Electron
}
function Install-Wix {
Print-Info "Downloading wixtoolset..."
# choco is using 3.11 which causes problems building on remote ssh due to dotnet3.5
# choco install wixtoolset --yes
$WebClient = New-Object System.Net.WebClient
# if they ever fix the installer we can move to 3.11
$WebClient.DownloadFile("https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311.exe",".\scripts\wix.exe")
#$WebClient.DownloadFile("https://github.com/wixtoolset/wix3/releases/download/wix3104rtm/wix310.exe",".\scripts\wix.exe")
Print-Info "Installing wixtoolset..."
# todo: check hash
.\scripts\wix.exe -q
if ($LastExitCode -ne $null) {
throw "com.mattermost.makefile.deps.wix"
}
Print-Info "wixtoolset installed!"
}
#EndRegion
################################################################################
# Research of dependencies related functions
################################################################################
#Region
function Get-WixDir {
$progFile = (${env:ProgramFiles(x86)}, ${env:ProgramFiles} -ne $null)[0]
$wixDirs = @(Get-ChildItem -Path $progFile -Recurse -Filter "*wix toolset*" -Attributes Directory -Depth 2 -ErrorAction SilentlyContinue)
if ($wixDirs[0] -eq $null) {
return $null
}
$wixDir = Join-Path -Path "$progFile" -ChildPath "$($wixDirs[0])"
$wixDir = Join-Path -Path "$wixDir" -ChildPath "bin"
return $wixDir
}
function Get-SignToolDir {
$progFile = (${env:ProgramFiles(x86)}, ${env:ProgramFiles} -ne $null)[0]
$signToolDir = Join-Path -Path "$progFile" -ChildPath "Windows Kits\10\bin\"
# Check if we are on 64 bits or not.
if ($env:PROCESSOR_ARCHITECTURE -ilike '*64*') {
$arch = "x64"
} else {
$arch = "x86"
}
[array]$signToolExes = (
Get-ChildItem -Path "$signToolDir" -Filter "signtool.exe" -Recurse -ErrorAction SilentlyContinue -Force | % {
if ($_.FullName -ilike '*x64*') {
return $_.FullName;
}
}
)
if ($signToolExes -eq $null -or
[string]::IsNullOrEmpty($signToolExes[0])) {
return $null
}
if (Test-Path $signToolExes[0]) {
return Split-Path $signToolExes[0]
}
return $null
}
function Get-NpmDir {
# npm is always installed as a nodejs dependency. 64 bits version available.
# C:\Program Files\nodejs\npm with a shortcut leading to
# C:\Program Files\nodejs\node_modules\npm\bin
$progFile = ${env:ProgramFiles}
$npmDir = Join-Path -Path "$progFile" -ChildPath "nodejs"
if ([System.IO.File]::Exists("$npmDir\npm.cmd")) {
return $npmDir
}
$progFile = ${env:ProgramW6432}
$npmDir = Join-Path -Path "$progFile" -ChildPath "nodejs"
if ([System.IO.File]::Exists("$npmDir\npm.cmd")) {
return $npmDir
}
return $null
}
#EndRegion
################################################################################
# Mattermost related functions
################################################################################
#region
function Prepare-Path {
# As we may need to install new dependencies, make sure the PATH env
# variable is not too large. Some CI envs like AppVeyor have already the
# PATH env variable defined at the maximum which prevents new strings to
# be added to it. We will remove all the stuff added for programs in
# Program Files (64 bits and 32 bits variants) except the path of our
# dependencies.
# src.: https://gist.github.com/wget/a102f89c301014836aaa49a98dd06ee2
$oldPath = $env:Path
[array]$newPath
# Cleanup the PATH from everything contained in Program Files...
$newPath = ($env:Path -split ';') | Where-Object { $_ -notlike "C:\Program Files*" }
# ...except from Git
$newPath += ($env:Path -split ';') | Where-Object { $_ -like "C:\Program Files*\*Git*" }
$env:Path = $newPath -join ';'
Print-Info "Reducing and reordering PATH from `n ""$oldPath""`n to`n ""$env:Path"""
# Prepending ensures we are using our own path here to avoid the paths the
# user might have defined to interfere.
# Prepend the PATH with npm/nodejs dir
Print-Info "Checking if npm dir is already in the PATH..."
$env:Path = "$(Get-NpmDir)" + ";" + $env:Path
# Prepend the PATH with wix dir
Print-Info "Checking if wix dir is already in the PATH..."
$env:Path = "$(Get-WixDir)" + ";" + $env:Path
# Prepend the PATH with signtool dir
Print-Info "Checking if signtool dir is already in the PATH..."
$env:Path = "$(Get-SignToolDir)" + ";" + $env:Path
}
function Catch-Interruption {
[console]::TreatControlCAsInput = $true
while ($true) {
if ([console]::KeyAvailable) {
$key = Read-Host
#$key = [system.console]::readkey($true)
if (($key.modifiers -band [consolemodifiers]"control") -and
($key.key -eq "C")) {
Print-Warning "Ctrl-C pressed. Cancelling the build process and restoring computer state..."
Restore-ComputerState
exit
}
}
}
}
function Backup-ComputerState {
$env:COM_MATTERMOST_MAKEFILE_PATH_BACKUP = $env:Path
Push-Location "$(Get-RootDir)"
# Needed because for native apps, PowerShell doesn't change the
# process current path location
#src.: https://stackoverflow.com/a/4725090/3514658
[Environment]::CurrentDirectory = $PWD
# Refresh path because it might have been made durty in the current shell
Refresh-Path
}
function Restore-ComputerState {
Print-Info "Restoring PATH..."
$env:Path = $env:COM_MATTERMOST_MAKEFILE_PATH_BACKUP
Print-Info "Restoring current working directory..."
Pop-location
[Environment]::CurrentDirectory = $PWD
# Remove all COM_MATTERMOST_MAKEFILE_ prefixed env variable
foreach ($item in (Get-Item -Path Env:*)) {
if ($item.Name -imatch 'COM_MATTERMOST_MAKEFILE_') {
Print-Info "Removing Mattermost env variable: $($item.Name)..."
Remove-Item env:\$($item.Name)
}
}
}
function Optimize-Build {
Print-Info "Checking if Windows Search is running..."
if ((Get-Service -Name "Windows Search").Status -eq "Running") {
Print-Info "Windows Search is running. Disabling it..."
Stop-Service "Windows Search"
Print-Warning "WARNING: This makefile disabled Windows Search, to reenable it, type in an administror Powershell: Start-Service ""Windows Search"""
} else {
Print-Info "Windows Search has already been disabled."
}
Print-Info "Checking if Windows Defender realtime protection is active..."
if (!(Get-MpPreference).DisableRealtimeMonitoring) {
Print-Info "Windows Defender realtime protection is active. Disabling it..."
Set-MpPreference -DisableRealtimeMonitoring $true
Print-Warning "WARNING: This makefile disabled Windows Defender realtime protection, to reenable it, type in an administror Powershell: Set-MpPreference -DisableRealtimeMonitoring `$false"
} else {
Print-Info "Windows Defender realtime protection has already been disabled."
}
}
function Run-BuildId {
Print-Info -NoNewLine "Getting build date..."
$env:COM_MATTERMOST_MAKEFILE_BUILD_DATE = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd")
Print " [$env:COM_MATTERMOST_MAKEFILE_BUILD_DATE]"
# Generate build version ids
#
# nodejs/npm does require to have semver parsable versions:
# major.minor.patch
# Non number values are allowed only if they are not starting the dot verion.
# 4.3.0-rc2 is allowed but 4.3.rc2 is not
#
# wix toolset supports semver up to the revision dot syntax:
# major.minor.patch.revision.
# ProductVersion Property is defined as
# [0-255].[0-255].[0-65535]
# 8 , 8 , 16 signed bit
# File Version is defined as
# [0-65535].[0-65535].[0-65535].[0-65535]
# 16 , 16 , 16 , 16 signed bit
#
# Other chars other than numbers should be removed.
# Versions like v4.3.0-rc0 shoud be. We are thus forcing to
# have a format like 4.3.0.rc0.
# When the last tag is not present or not a parsable semver version, we are
# taking the number of revisions reachable from the HEAD of the current branch
# (other branches are not taken into account).
# Example:
# $ git rev-list --count --first-parent HEAD
# 645
# Using the date is unreliable, because this requires to have a precision at
# seconds, leading to an overflow of the integer range supported by wix.
# 4.3.0.20190512074020 is not accepted and fails with the following error:
# candle.exe : error CNDL0001 : Value was either too large or too small for an Int32.
# Exception Type: System.OverflowException
# Add the revision only if we are not building a tag
$version = "$(jq -r '.version' package.json)"
$winVersion = "$($version -Replace '-','.' -Replace '[^0-9.]')"
Print-Info "Checking build id tag validity... [$version]"
[version]$appVersion = New-Object -TypeName System.Version
[void][version]::TryParse($winVersion, [ref]$appVersion)
if (!($appVersion)) {
# if we couldn't parse, it might be a -develop or something similar, so we just add a
# number there that will change overtime. Most likely this is a PR to be tested
$revision = "$(git rev-list --all --count)"
$winVersion = "$($version -Replace '-.*').${revision}"
[void][version]::TryParse($winVersion, [ref]$appVersion)
if (!($appVersion)) {
Print-Error "Non parsable tag detected. Fallbacking to version 0.0.0."
$version = "0.0.0"
}
}
Print-Info -NoNewLine "Getting build id version..."
$env:COM_MATTERMOST_MAKEFILE_BUILD_ID = "$version"
Print " [$env:COM_MATTERMOST_MAKEFILE_BUILD_ID]"
Print-Info -NoNewLine "Getting build id version for msi..."
$env:COM_MATTERMOST_MAKEFILE_BUILD_ID_MSI = $winVersion.Split('.')[0..3] -Join '.'
Print " [$env:COM_MATTERMOST_MAKEFILE_BUILD_ID_MSI]"
Print-Info -NoNewLine "Getting build id version for node/npm..."
$env:COM_MATTERMOST_MAKEFILE_BUILD_ID_NODE = $version
Print " [$env:COM_MATTERMOST_MAKEFILE_BUILD_ID_NODE]"
Print-Info "Patching version from msi xml descriptor..."
$msiDescriptorFileName = "scripts\msi_installer.wxs"
$msiDescriptor = [xml](Get-Content $msiDescriptorFileName)
$msiDescriptor.Wix.Product.Version = [string]$env:COM_MATTERMOST_MAKEFILE_BUILD_ID_MSI
$ComponentDownload = $msiDescriptor.CreateElement("Property", "http://schemas.microsoft.com/wix/2006/wi")
$ComponentDownload.InnerText = "https://releases.mattermost.com/desktop/$version/mattermost-desktop-$version-`$(var.Platform).msi"
$ComponentDownload.SetAttribute("Id", "ComponentDownload")
$msiDescriptor.Wix.Product.AppendChild($ComponentDownload)
$msiDescriptor.Save($msiDescriptorFileName)
Print-Info "Modified Wix XML"
}
function InstallDeps-Electron {
Print-Info "Installing nodejs/electron dependencies (running npm ci)..."
npm i -g node-gyp
node-gyp install
node-gyp install --devdir="$env:USERPROFILE\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers"
node-gyp install --devdir="$env:USERPROFILE\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch arm64
node-gyp install --devdir="$env:USERPROFILE\.electron-gyp" --target=$(jq -r .devDependencies.electron package.json) --dist-url="https://electronjs.org/headers" --arch ia32
npm ci
}
function Run-BuildElectron {
#npm install --prefix="$(Get-RootDir)" "$(Get-RootDir)"
Print-Info "Building nodejs/electron code (running npm run build)..."
npm run build
#npm run build --prefix="$(Get-RootDir)" "$(Get-RootDir)"
Print-Info "Packaging nodejs/electron for Windows (running npm run package:windows)..."
# NSIS has the upgrade flag enabled, so it must be done first
npm run package:windows-nsis
npm run package:windows
#npm run package:windows --prefix="$(Get-RootDir)" "$(Get-RootDir)"
}
function Run-BuildForceSignature {
# Only sign the executable and .dll if this is a release and not a pull request
# check.
if (Test-Path 'env:PFX') {
Print-Info "Signing"
foreach ($archPath in "release\win-unpacked", "release\win-ia32-unpacked") {
# Note: The C++ redistribuable files will be resigned again even if they have a
# correct signature from Microsoft. Windows doesn't seem to complain, but we
# don't know whether this is authorized by the Microsoft EULA.
Get-ChildItem -Path $archPath -recurse "*.dll" | ForEach-Object {
Print-Info "Signing $($_.Name) (waiting for 2 * 15 seconds)..."
# Waiting for at least 15 seconds is needed because these time
# servers usually have rate limits and signtool can fail with the
# following error message:
# "SignTool Error: The specified timestamp server either could not be reached or returned an invalid response.
# src.: https://web.archive.org/web/20190306223053/https://github.com/electron-userland/electron-builder/issues/2795#issuecomment-466831315
Start-Sleep -s 15
signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha1 /td sha1 "$($_.FullName)"
Start-Sleep -s 15
signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 /as "$($_.FullName)"
}
Print-Info "Signing Mattermost.exe (waiting for 2 * 15 seconds)..."
Start-Sleep -s 15
signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha1 /td sha1 "$archPath\Mattermost.exe"
Start-Sleep -s 15
signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 /as "$archPath\Mattermost.exe"
}
} else {
Print-Info "Certificate file not found, DLLs and executable won't be signed."
}
}
function Run-BuildLicense {
# Convert license to RTF
$licenseTxtFile = "LICENSE.txt";
$licenseRtfFile = "resources/windows/license.rtf";
$licenseNewParagraph = "\par" + [Environment]::NewLine;
$sw = [System.IO.File]::CreateText($licenseRtfFile);
$sw.WriteLine("{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Courier New;}}\pard\qj\f0\fs18");
$lineToAdd = "";
$gapDetected = 0;
# We are relying on introspected C#/.NET rather than the buggy Get-Content
# cmdlet because Get-Content considers by default a `-Delimiter` to '\n'
# and thus breaks the purpose of the parser.
foreach ($line in [System.IO.File]::ReadLines($licenseTxtFile)) {
# trim() is equivalent to .replace("\ \s+", "")
# We replace one backslash by two. Since the first arg is a regex,
# we need to escape it.
# src.: https://stackoverflow.com/a/31324570/3514658
$sanitizedLine = $line.trim().replace("\\", "\\").replace("{", "\{").replace("}", "\}");
# Print previous string gathered if gap detected.
if ([string]::IsNullOrEmpty($sanitizedLine)) {
$gapDetected++;
# For first line keep paragraph definition from document head.
if ($gapDetected -eq 1) {
$sw.Write($lineToAdd);
} elseif ($gapDetected -eq 2) {
$sw.Write($licenseNewParagraph + $lineToAdd);
} else {
$sw.Write($licenseNewParagraph + $lineToAdd + $licenseNewParagraph);
}
$lineToAdd = "";
continue;
}
# Keep carriage return for first two blocks comprising Copyright and
# license name statements.
if ($gapDetected -lt 3) {
$lineToAdd += $sanitizedLine + $licenseNewParagraph;
continue;
}
# Do not add heading space if the line begins a new paragraph.
if ($lineToAdd -eq "") {
$lineToAdd += $sanitizedLine;
continue;
}
$lineToAdd += " " + $sanitizedLine;
}
if ($lineToAdd -ne "") {
$sw.Write([Environment]::NewLine + $licenseNewParagraph + $lineToAdd + "\par");
}
$sw.Close();
}
function Run-BuildMsi {
Print-Info "Building 32 bits msi installer..."
heat.exe dir "release\win-ia32-unpacked\" -o "scripts\msi_installer_files.wxs" -scom -frag -srd -sreg -gg -cg MattermostDesktopFiles -t "scripts\msi_installer_files_replace_id.xslt" -dr INSTALLDIR
candle.exe -dPlatform=x86 "scripts\msi_installer.wxs" "scripts\msi_installer_files.wxs" -o "scripts\"
light.exe "scripts\msi_installer.wixobj" "scripts\msi_installer_files.wixobj" -loc "resources\windows\msi_i18n\en_US.wxl" -o "release\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" -b "release\win-ia32-unpacked\"
Print-Info "Building 64 bits msi installer..."
heat.exe dir "release\win-unpacked\" -o "scripts\msi_installer_files.wxs" -scom -frag -srd -sreg -gg -cg MattermostDesktopFiles -t "scripts\msi_installer_files_replace_id.xslt" -t "scripts\msi_installer_files_set_win64.xslt" -dr INSTALLDIR
candle.exe -dPlatform=x64 "scripts\msi_installer.wxs" "scripts\msi_installer_files.wxs" -o "scripts\"
light.exe "scripts\msi_installer.wixobj" "scripts\msi_installer_files.wixobj" -loc "resources\windows\msi_i18n\en_US.wxl" -o "release\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" -b "release\win-unpacked\"
# Only sign the executable and .dll if this is a release and not a pull request
# check.
if (Test-Path 'env:PFX') {
Print-Info "Signing mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi (waiting for 15 seconds)..."
Start-Sleep -s 15
# Dual signing is not supported on msi files. Is it recommended to sign with 256 hash.
# src.: https://security.stackexchange.com/a/124685/84134
# src.: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-us/d4b70ecd-a883-4289-8047-cc9cde28b492#0b3e3b80-6b3b-463f-ac1e-1bf0dc831952
signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 /d "release\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" "release\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi"
Print-Info "Signing mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi (waiting for 15 seconds)..."
Start-Sleep -s 15
signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 /d "release\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" "release\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi"
} else {
Print-Info "Certificate file not found, the msi installers won't be signed."
}
}
function Get-Cert {
if (Test-Path 'env:PFX') {
Print-Info "Getting windows certificate"
[IO.File]::WriteAllBytes("./mattermost-desktop-windows.pfx", [Convert]::FromBase64String($env:PFX))
$password = "$env:PFX_KEY" | convertto-securestring -asplaintext -force
Print-Info "Importing certificate into the machine"
Import-PfxCertificate -filepath "./mattermost-desktop-windows.pfx" cert:\localMachine\my -password $password
} else {
Print-Warning "No env:PFX environment variable found, build will not be signed."
}
}
function Remove-Cert {
if (Test-Path 'env:PFX') {
Print-Info "Removing windows certificate"
Remove-Item -path "./mattermost-desktop-windows.pfx"
}
}
function Run-Build {
Check-Deps -Verbose -Throwable
Prepare-Path
Get-Cert
Run-BuildId
Run-BuildElectron
Run-BuildForceSignature
Run-BuildLicense
Run-BuildMsi
Remove-Cert
}
function Run-Test {
Check-Deps -Verbose -Throwable
Prepare-Path
npm test
}
#EndRegion
################################################################################
# Main function
################################################################################
#Region
function Main {
try {
if ($makeRule -eq $null) {
Print-Info "No argument passed to the make file. Executing ""all"" rule."
$makeRule = "all"
}
Backup-ComputerState
switch ($makeRule.toLower()) {
"all" {
Install-Deps
Run-Build
}
"build" {
Install-Deps
Run-Build
}
"test" {
Install-Deps
Run-Test
}
"install-deps" {
Install-Deps
}
"optimize" {
Optimize-Build
}
"install-cert" {
Get-Cert
}
"remove-cert" {
Remove-Cert
}
default {
Print-Error "Makefile argument ""$_"" is invalid. Build process aborted."
}
}
$env:COM_MATTERMOST_MAKEFILE_EXECUTION_SUCCESS = $true
$exitCode = 0
} catch {
switch ($_.Exception.Message) {
"com.mattermost.makefile.deps.missing" {
Print-Error "The following dependencies are missing: $($missing -Join ', ').`n Please install dependencies as an administrator:`n # makefile.ps1 install-deps"
$exitCode = -1
}
"com.mattermost.makefile.deps.notadmin" {
Print-Error "Installing dependencies requires admin privileges. Operation aborted.`n Please reexecute this makefile as an administrator:`n # makefile.ps1 install-deps"
$exitCode = -2
}
"com.mattermost.makefile.deps.wix" {
Print-Error "There was nothing wrong with your source code,but we found a problem installing wix toolset and couldn't continue. please try re-running the job."
$exitCode = -3
}
default {
Print-Error "Another error occurred: $_"
$exitCode = -100
}
}
} finally {
if (!($env:COM_MATTERMOST_MAKEFILE_EXECUTION_SUCCESS)) {
Print-Warning "Makefile interrupted by Ctrl + C or by another interruption handler."
}
Restore-ComputerState
exit $exitCode
}
}
Main
#EndRegion

View file

@ -10,11 +10,6 @@ if [[ ! -d "${DEST}" ]]; then
mkdir -p "${DEST}" mkdir -p "${DEST}"
fi fi
if [[ -f "${SRC}/mattermost-desktop-${VERSION}-win-ia32.zip" ]]; then
echo -e "Copying Win32\n"
cp "${SRC}/mattermost-desktop-${VERSION}-win-ia32.zip" "${DEST}/mattermost-desktop-${VERSION}-win32.zip"
SOMETHING_COPIED=1
fi
if [[ -f "${SRC}/mattermost-desktop-${VERSION}-win-x64.zip" ]]; then if [[ -f "${SRC}/mattermost-desktop-${VERSION}-win-x64.zip" ]]; then
echo -e "Copying Win64\n" echo -e "Copying Win64\n"
cp "${SRC}/mattermost-desktop-${VERSION}-win-x64.zip" "${DEST}/mattermost-desktop-${VERSION}-win64.zip" cp "${SRC}/mattermost-desktop-${VERSION}-win-x64.zip" "${DEST}/mattermost-desktop-${VERSION}-win64.zip"
@ -30,14 +25,14 @@ if [[ ${MM_WIN_INSTALLERS-0} -eq 1 && -f "${SRC}/mattermost-desktop-setup-${VERS
cp "${SRC}/mattermost-desktop-setup-${VERSION}-win.exe" "${DEST}/" cp "${SRC}/mattermost-desktop-setup-${VERSION}-win.exe" "${DEST}/"
SOMETHING_COPIED=$((SOMETHING_COPIED + 3)) SOMETHING_COPIED=$((SOMETHING_COPIED + 3))
fi fi
if [[ ${MM_WIN_INSTALLERS-0} -eq 1 && -f "${SRC}/mattermost-desktop-${VERSION}-x64.msi" ]]; then if [[ ${MM_WIN_INSTALLERS-0} -eq 1 && -f "${SRC}/mattermost-desktop-${VERSION}-win-x64.msi" ]]; then
echo -e "Copying win-msi-x64\n" echo -e "Copying win-msi-x64\n"
cp "${SRC}/mattermost-desktop-${VERSION}-x64.msi" "${DEST}/" cp "${SRC}/mattermost-desktop-${VERSION}-win-x64.msi" "${DEST}/"
SOMETHING_COPIED=$((SOMETHING_COPIED + 4)) SOMETHING_COPIED=$((SOMETHING_COPIED + 4))
fi fi
if [[ ${MM_WIN_INSTALLERS-0} -eq 1 && -f "${SRC}/mattermost-desktop-${VERSION}-x86.msi" ]]; then if [[ ${MM_WIN_INSTALLERS-0} -eq 1 && -f "${SRC}/mattermost-desktop-${VERSION}-win-arm64.msi" ]]; then
echo -e "Copying win-msi-x86\n" echo -e "Copying win-msi-arm64\n"
cp "${SRC}/mattermost-desktop-${VERSION}-x86.msi" "${DEST}/" cp "${SRC}/mattermost-desktop-${VERSION}-win-arm64.msi" "${DEST}/"
SOMETHING_COPIED=$((SOMETHING_COPIED + 5)) SOMETHING_COPIED=$((SOMETHING_COPIED + 5))
fi fi

View file

@ -0,0 +1,6 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
const fs = require('fs');
fs.copyFileSync('release/win-unpacked/resources/app-update.yml', 'release/msi-app-update.yml');
fs.unlinkSync('release/win-unpacked/resources/app-update.yml');

View file

@ -21,15 +21,11 @@ Release notes can be found here: https://docs.mattermost.com/install/desktop-app
The download links can be found below. The download links can be found below.
#### Windows - msi files (beta) #### Windows - installer files
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-x64.msi") $(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win-x64.msi")
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-x86.msi") $(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win-arm64.msi") (beta)
#### Windows - setup exe files
$(print_link "${BASE_URL}/mattermost-desktop-setup-${VERSION}-win.exe")
#### Windows - zip files #### Windows - zip files
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win32.zip")
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win64.zip") $(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win64.zip")
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-arm64.zip") (beta) $(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-arm64.zip") (beta)

8
scripts/installer.nsh Normal file
View file

@ -0,0 +1,8 @@
# This macro fetches the currently install MM version via MSI (if any) and uninstalls it first
!macro customInit
nsExec::ExecToStack "$\"$%SYSTEMROOT%\system32\WindowsPowerShell\v1.0\powershell.exe$\" -command $\"$$Installer = New-Object -ComObject WindowsInstaller.Installer; $$MMProduct = $$Installer.ProductsEx('', '', 7) | Where-Object -FilterScript {$$_.InstallProperty('ProductName') -eq 'Mattermost'}; if ($$MMProduct -ne $$null) {Write-Host -NoNewline $$MMProduct.ProductCode()}$\""
Pop $0
Pop $1
StrCmp $1 "" 0 +1
ExecWait '"$%SYSTEMROOT%\system32\msiexec.exe" /x $1 /qn'
!macroend

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wi="http://schemas.microsoft.com/wix/2006/wi">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- src.: https://stackoverflow.com/a/19259647/3514658 -->
<xsl:template match="wi:ComponentGroup[@Id='MattermostDesktopFiles']/wi:Component/wi:File[contains(@Source,'Mattermost.exe')]">
<xsl:copy>
<xsl:attribute name="Id">MattermostDesktopEXE</xsl:attribute>
<xsl:copy-of select="@*[name()!='Id']"/>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,20 +0,0 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wi="http://schemas.microsoft.com/wix/2006/wi">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- src.: https://stackoverflow.com/a/4825010/3514658 -->
<xsl:template match="wi:ComponentGroup[@Id='MattermostDesktopFiles']/wi:Component">
<xsl:copy>
<xsl:attribute name="Win64">yes</xsl:attribute>
<xsl:copy-of select="@*"/>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,2 +0,0 @@
3f619089b46df893f55e58832ce442678fb0635f *./wix311.exe