Build & EV Sign Windows builds (#517

* Add way to provide apple ID and app password to notarise script

* Add utility to generate electron-builder.json for release & nightly builds

* Run Build & Test on staging too

* First attempt at build & deploy for macOS with signing and notarisation

* Fix quote mismatch

* use correct quotes

* add runs-on

* Fix inputs.mode usage

* remove quotes

* chmod +x

* Fix artifact paths

* Fix deploy condition

* Fix deploy condition

* Fix artifact path

* Iterate

* Fix workflow

* Fix env

* Iterate

* Fix missing env

* Fix version calculation

* Iterate

* Fix config not taking effect

* Update build_and_deploy.yaml

* Fix alignments

* delint

* Fix alignment

* Update build_macos.yaml

* Add ability to EV sign using eSigner CKA

* Initial work to build & sign Windows nightlies in CI

* Format

* Format

* Fix gha

* fix winSign

* Fix install command

* Add signtool to path

* Update build_and_deploy.yaml

* Fix quotes

* Test

* Fix comments

* Fix cmd

* Try again

* arg slashes

* Fix exe path

* Fix matrix strategy

* Use ampersand-call

* fwd slash ftw?

* ls *

* 🌲

* tree dist

* prepend path

* Specify /fd and /td to modern signtool

* /tr not /t for CKA

* Test signing

* missing comma

* 🤦‍♂️

* Fix wrong mv

* Lets sign

* Fix config gen

* Debug

* Fix typo

* Multiple drives why

* Try NVL sandbox creds

* Update

* Attempt to disable logger

* Try again

* Iterate

* Update build_macos.yaml

* Update build_and_deploy.yaml

* Update build_macos.yaml

* Update build_and_deploy.yaml

* Update build_and_deploy.yaml

* Try custom build of eSigner CKA

* Fix typos

* Update build_windows.yaml

* Update build_and_deploy.yaml

* Update build_windows.yaml

* Update build_and_deploy.yaml

* Fix symlinking

* Fix working-directory incantation

* exe

* remove debug

* Prettier

* Vendor check in SSL.com executable

* Download CKA from packages.element.io instead

* Use demo creds

* StrictMode

* Switch back to 0207 (unsigned)

* Fix call syntax

* Revert env inc

* Partial rollback

* Trace

* Trace less

* Fix CN being passed wrong

* DEBUG

* Debug 2

* Fix ConvertFrom-StringData

* 0214

* Test

* Test

* Untested

* Revert to 0207

* stash

* Try with 20230221

* Restore scripts/electron_winSign.js

* Prepare for merge

* Update build_windows.yaml

* Update build_and_deploy.yaml

* Restore .github/workflows/build_and_deploy.yaml

* Restore .github/workflows/build_and_deploy.yaml

* Fix bad restore
This commit is contained in:
Michael Telatynski 2023-02-22 13:51:19 +00:00 committed by GitHub
parent c9d7e37e09
commit a0a9ec830c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 379 additions and 219 deletions

View File

@ -1,105 +1,141 @@
name: Build and Deploy name: Build and Deploy
on: on:
# Nightly build # Nightly build
schedule: schedule:
- cron: '0 9 * * *' - cron: "0 9 * * *"
# Manual nightly & release # Manual nightly & release
workflow_dispatch: workflow_dispatch:
inputs: inputs:
mode: mode:
description: What type of build to trigger. Release builds should be ran from the `master` branch. description: What type of build to trigger. Release builds should be ran from the `master` branch.
required: true required: true
default: nightly default: nightly
type: choice type: choice
options: options:
- nightly - nightly
- release - release
macos: macos:
description: Whether to build macOS description: Whether to build macOS
required: true required: true
type: boolean type: boolean
default: true default: true
linux: windows_32bit:
description: Whether to build Linux description: Whether to build Windows 32-bit
required: true required: true
type: boolean type: boolean
default: true default: true
deploy: windows_64bit:
description: Whether to deploy artifacts description: Whether to build Windows 64-bit
required: true required: true
type: boolean type: boolean
default: true default: true
linux:
description: Whether to build Linux
required: true
type: boolean
default: true
deploy:
description: Whether to deploy artifacts
required: true
type: boolean
default: true
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env: env:
# XXX: UPDATE THIS BEFORE WHEN GOING LIVE # XXX: UPDATE THIS BEFORE WHEN GOING LIVE
R2_BUCKET: 'packages-element-io-test' R2_BUCKET: "packages-element-io-test"
jobs: jobs:
prepare: prepare:
uses: ./.github/workflows/build_prepare.yaml uses: ./.github/workflows/build_prepare.yaml
with:
config: element.io/${{ inputs.mode || 'nightly' }}
version: ${{ inputs.mode == 'release' && '' || 'develop' }}
calculate-nightly-versions: ${{ inputs.mode != 'release' }}
secrets:
CF_R2_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
CF_R2_TOKEN: ${{ secrets.CF_R2_TOKEN }}
CF_R2_S3_API: ${{ secrets.CF_R2_S3_API }}
macos:
if: github.event_name != 'workflow_dispatch' || inputs.macos
needs: prepare
name: macOS
uses: ./.github/workflows/build_macos.yaml
secrets: inherit
with:
sign: true
deploy-mode: true
base-url: https://packages.element.io/${{ inputs.mode == 'release' && 'desktop' || 'nightly' }}
version: ${{ needs.prepare.outputs.macos-version }}
linux:
if: github.event_name != 'workflow_dispatch' || inputs.linux
needs: prepare
name: Linux
uses: ./.github/workflows/build_linux.yaml
secrets: inherit
with:
sqlcipher: system
deploy-mode: true
version: ${{ needs.prepare.outputs.linux-version }}
deploy:
needs:
- macos
runs-on: ubuntu-latest
name: Deploy
if: always() && (github.event != 'workflow_dispatch' || inputs.deploy)
environment: packages.element.io
steps:
- name: Download artifacts
uses: actions/download-artifact@v3
with: with:
name: packages.element.io config: element.io/${{ inputs.mode || 'nightly' }}
path: packages.element.io version: ${{ inputs.mode == 'release' && '' || 'develop' }}
calculate-nightly-versions: ${{ inputs.mode != 'release' }}
secrets:
CF_R2_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
CF_R2_TOKEN: ${{ secrets.CF_R2_TOKEN }}
CF_R2_S3_API: ${{ secrets.CF_R2_S3_API }}
- name: Deploy debian repo windows_32bit:
if: github.event_name != 'workflow_dispatch' || inputs.linux if: github.event_name != 'workflow_dispatch' || inputs.windows_32bit
run: | needs: prepare
mv packages.element.io/debian . name: Windows 32-bit
aws s3 cp --recursive debian/ s3://$R2_BUCKET/debian --endpoint-url $R2_URL --region auto uses: ./.github/workflows/build_windows.yaml
env: secrets: inherit
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }} with:
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }} sign: true
R2_URL: ${{ secrets.CF_R2_S3_API }} deploy-mode: true
arch: x86
version: ${{ needs.prepare.outputs.win32-x86-version }}
- name: Deploy artifacts windows_64bit:
if: github.event_name != 'workflow_dispatch' || inputs.windows_64bit
needs: prepare
name: Windows 64-bit
uses: ./.github/workflows/build_windows.yaml
secrets: inherit
with:
sign: true
deploy-mode: true
arch: x64
version: ${{ needs.prepare.outputs.win32-x64-version }}
macos:
if: github.event_name != 'workflow_dispatch' || inputs.macos if: github.event_name != 'workflow_dispatch' || inputs.macos
run: | needs: prepare
aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/$DEPLOYMENT_DIR --endpoint-url $R2_URL --region auto name: macOS
env: uses: ./.github/workflows/build_macos.yaml
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }} secrets: inherit
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }} with:
R2_URL: ${{ secrets.CF_R2_S3_API }} sign: true
DEPLOYMENT_DIR: ${{ inputs.mode == 'release' && 'desktop' || 'nightly' }} deploy-mode: true
base-url: https://packages.element.io/${{ inputs.mode == 'release' && 'desktop' || 'nightly' }}
version: ${{ needs.prepare.outputs.macos-version }}
linux:
if: github.event_name != 'workflow_dispatch' || inputs.linux
needs: prepare
name: Linux
uses: ./.github/workflows/build_linux.yaml
secrets: inherit
with:
sqlcipher: system
deploy-mode: true
version: ${{ needs.prepare.outputs.linux-version }}
deploy:
needs:
- macos
- windows_32bit
- windows_64bit
runs-on: ubuntu-latest
name: Deploy
if: always() && (github.event != 'workflow_dispatch' || inputs.deploy)
environment: packages.element.io
steps:
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: packages.element.io
path: packages.element.io
- name: Deploy debian repo
if: github.event_name != 'workflow_dispatch' || inputs.linux
run: |
mv packages.element.io/debian .
aws s3 cp --recursive debian/ s3://$R2_BUCKET/debian --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
R2_URL: ${{ secrets.CF_R2_S3_API }}
- name: Deploy artifacts
if: github.event_name != 'workflow_dispatch' || inputs.macos
run: |
aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/$DEPLOYMENT_DIR --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
R2_URL: ${{ secrets.CF_R2_S3_API }}
DEPLOYMENT_DIR: ${{ inputs.mode == 'release' && 'desktop' || 'nightly' }}

View File

@ -1,107 +1,107 @@
name: Build and Test name: Build and Test
on: on:
pull_request: {} pull_request: {}
push: push:
branches: [develop, staging, master] branches: [develop, staging, master]
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
fetch: fetch:
uses: ./.github/workflows/build_prepare.yaml uses: ./.github/workflows/build_prepare.yaml
with:
config: ${{ github.event.pull_request.base.ref == 'develop' && 'element.io/nightly' || 'element.io/release' }}
version: ${{ github.event.pull_request.base.ref == 'develop' && 'develop' || '' }}
windows:
needs: fetch
name: Windows
uses: ./.github/workflows/build_windows.yaml
strategy:
matrix:
arch: [x64, x86]
with:
arch: ${{ matrix.arch }}
linux:
needs: fetch
name: Linux
uses: ./.github/workflows/build_linux.yaml
strategy:
matrix:
sqlcipher: [system, static]
with:
sqlcipher: ${{ matrix.sqlcipher }}
macos:
needs: fetch
name: macOS
uses: ./.github/workflows/build_macos.yaml
test:
needs:
- macos
- linux
- windows
strategy:
matrix:
include:
- name: macOS Universal
os: macos
artifact: macos
executable: "./dist/mac-universal/Element.app/Contents/MacOS/Element"
prepare_cmd: "find ./dist/mac-universal/Element.app -type f | perl -lne 'print if -B' | tr '\\n' '\\0' | xargs -0 -n1 chmod 755"
- name: "Linux (sqlcipher: system)"
os: ubuntu
artifact: linux-sqlcipher-system
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: "Linux (sqlcipher: static)"
os: ubuntu
artifact: linux-sqlcipher-static
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: Windows (x86)
os: windows
artifact: win-x86
executable: "./dist/win-ia32-unpacked/Element.exe"
- name: Windows (x64)
os: windows
artifact: win-x64
executable: "./dist/win-unpacked/Element.exe"
name: Test ${{ matrix.name }}
runs-on: ${{ matrix.os }}-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with: with:
cache: "yarn" config: ${{ github.event.pull_request.base.ref == 'develop' && 'element.io/nightly' || 'element.io/release' }}
version: ${{ github.event.pull_request.base.ref == 'develop' && 'develop' || '' }}
- name: Install Deps windows:
run: "yarn install --pure-lockfile" needs: fetch
name: Windows
- uses: actions/download-artifact@v3 uses: ./.github/workflows/build_windows.yaml
strategy:
matrix:
arch: [x64, x86]
with: with:
name: ${{ matrix.artifact }} arch: ${{ matrix.arch }}
path: dist
- name: Prepare for tests linux:
run: ${{ matrix.prepare_cmd }} needs: fetch
if: matrix.prepare_cmd name: Linux
uses: ./.github/workflows/build_linux.yaml
- name: Run tests strategy:
uses: GabrielBB/xvfb-action@v1 matrix:
timeout-minutes: 5 sqlcipher: [system, static]
with: with:
run: "yarn test" sqlcipher: ${{ matrix.sqlcipher }}
env:
ELEMENT_DESKTOP_EXECUTABLE: ${{ matrix.executable }}
- name: Upload Artifacts macos:
uses: actions/upload-artifact@v3 needs: fetch
if: always() name: macOS
with: uses: ./.github/workflows/build_macos.yaml
name: ${{ matrix.artifact }}
path: test_artifacts test:
retention-days: 1 needs:
- macos
- linux
- windows
strategy:
matrix:
include:
- name: macOS Universal
os: macos
artifact: macos
executable: "./dist/mac-universal/Element.app/Contents/MacOS/Element"
prepare_cmd: "find ./dist/mac-universal/Element.app -type f | perl -lne 'print if -B' | tr '\\n' '\\0' | xargs -0 -n1 chmod 755"
- name: "Linux (sqlcipher: system)"
os: ubuntu
artifact: linux-sqlcipher-system
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: "Linux (sqlcipher: static)"
os: ubuntu
artifact: linux-sqlcipher-static
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: Windows (x86)
os: windows
artifact: win-x86
executable: "./dist/win-ia32-unpacked/Element.exe"
- name: Windows (x64)
os: windows
artifact: win-x64
executable: "./dist/win-unpacked/Element.exe"
name: Test ${{ matrix.name }}
runs-on: ${{ matrix.os }}-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Install Deps
run: "yarn install --pure-lockfile"
- uses: actions/download-artifact@v3
with:
name: ${{ matrix.artifact }}
path: dist
- name: Prepare for tests
run: ${{ matrix.prepare_cmd }}
if: matrix.prepare_cmd
- name: Run tests
uses: GabrielBB/xvfb-action@v1
timeout-minutes: 5
with:
run: "yarn test"
env:
ELEMENT_DESKTOP_EXECUTABLE: ${{ matrix.executable }}
- name: Upload Artifacts
uses: actions/upload-artifact@v3
if: always()
with:
name: ${{ matrix.artifact }}
path: test_artifacts
retention-days: 1

View File

@ -70,7 +70,7 @@ jobs:
env: env:
SQLCIPHER_STATIC: ${{ inputs.sqlcipher == 'static' && '1' || '' }} SQLCIPHER_STATIC: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
- name: '[Nightly] Resolve version' - name: "[Nightly] Resolve version"
id: nightly id: nightly
if: inputs.version != '' if: inputs.version != ''
run: | run: |
@ -101,17 +101,17 @@ jobs:
run: | run: |
# Clear out the template packages.element.io directory, it has a dedicated deploy workflow # Clear out the template packages.element.io directory, it has a dedicated deploy workflow
rm -R packages.element.io/* rm -R packages.element.io/*
# Install reprepro # Install reprepro
sudo apt-get install -y reprepro sudo apt-get install -y reprepro
# Fetch reprepro database # Fetch reprepro database
aws s3 cp --recursive s3://$R2_BUCKET debian/db/ --endpoint-url $R2_URL --region auto aws s3 cp --recursive s3://$R2_BUCKET debian/db/ --endpoint-url $R2_URL --region auto
grep Codename debian/conf/distributions | sed -n 's/Codename: //p' | while read -r target ; do grep Codename debian/conf/distributions | sed -n 's/Codename: //p' | while read -r target ; do
reprepro -b debian includedeb "$target" ./dist/*.deb reprepro -b debian includedeb "$target" ./dist/*.deb
done done
# Store reprepro database # Store reprepro database
aws s3 cp --recursive debian/db/ s3://$R2_BUCKET --endpoint-url $R2_URL --region auto aws s3 cp --recursive debian/db/ s3://$R2_BUCKET --endpoint-url $R2_URL --region auto
env: env:

View File

@ -69,14 +69,14 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: "yarn build:native:universal" run: "yarn build:native:universal"
- name: '[Nightly] Resolve version' - name: "[Nightly] Resolve version"
id: nightly id: nightly
if: inputs.version != '' if: inputs.version != ''
run: | run: |
echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT
# We split these because electron-builder gets upset if we set CSC_LINK even to an empty string # We split these because electron-builder gets upset if we set CSC_LINK even to an empty string
- name: '[Signed] Build App' - name: "[Signed] Build App"
if: inputs.sign != '' if: inputs.sign != ''
run: | run: |
scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }}
@ -88,7 +88,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.APPLE_CSC_LINK }} CSC_LINK: ${{ secrets.APPLE_CSC_LINK }}
- name: '[Unsigned] Build App' - name: "[Unsigned] Build App"
if: inputs.sign == '' if: inputs.sign == ''
run: | run: |
scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }}
@ -103,11 +103,11 @@ jobs:
mkdir -p dist/install/macos dist/update/macos mkdir -p dist/install/macos dist/update/macos
mv _dist/*-mac.zip dist/update/macos/ mv _dist/*-mac.zip dist/update/macos/
mv _dist/*.dmg dist/install/macos/ mv _dist/*.dmg dist/install/macos/
PKG_JSON_VERSION=$(cat package.json | jq -r .version) PKG_JSON_VERSION=$(cat package.json | jq -r .version)
LATEST=$(find dist -type f -iname "*-mac.zip" | xargs -0 -n1 -- basename) LATEST=$(find dist -type f -iname "*-mac.zip" | xargs -0 -n1 -- basename)
URL="${{ inputs.base-url }}/update/macos/$LATEST" URL="${{ inputs.base-url }}/update/macos/$LATEST"
jq -n --arg version "${VERSION:-$PKG_JSON_VERSION}" --arg url "$URL" ' jq -n --arg version "${VERSION:-$PKG_JSON_VERSION}" --arg url "$URL" '
{ {
currentRelease: $version, currentRelease: $version,
@ -127,12 +127,12 @@ jobs:
VERSION: ${{ inputs.version }} VERSION: ${{ inputs.version }}
# We don't wish to store the installer for every nightly ever, so we only keep the latest # We don't wish to store the installer for every nightly ever, so we only keep the latest
- name: '[Nightly] Strip version from installer file' - name: "[Nightly] Strip version from installer file"
if: inputs.deploy-mode && inputs.version != '' if: inputs.deploy-mode && inputs.version != ''
run: | run: |
mv dist/install/macos/*.dmg "dist/install/macos/Element Nightly.dmg" mv dist/install/macos/*.dmg "dist/install/macos/Element Nightly.dmg"
- name: '[Release] Prepare release latest symlink' - name: "[Release] Prepare release latest symlink"
if: inputs.deploy-mode && inputs.version == '' if: inputs.deploy-mode && inputs.version == ''
run: | run: |
ln -s "$(find . -type f -iname "*.dmg" | xargs -0 -n1 -- basename)" "Element.dmg" ln -s "$(find . -type f -iname "*.dmg" | xargs -0 -n1 -- basename)" "Element.dmg"

View File

@ -31,6 +31,12 @@ on:
linux-version: linux-version:
description: "The version string the next Linux Nightly should use, only output for calculate-nightly-versions" description: "The version string the next Linux Nightly should use, only output for calculate-nightly-versions"
value: ${{ jobs.prepare.outputs.linux-version }} value: ${{ jobs.prepare.outputs.linux-version }}
win32-x64-version:
description: "The version string the next Windows x64 Nightly should use, only output for calculate-nightly-versions"
value: ${{ jobs.prepare.outputs.win32-x64-version }}
win32-x86-version:
description: "The version string the next Windows x86 Nightly should use, only output for calculate-nightly-versions"
value: ${{ jobs.prepare.outputs.win32-x86-version }}
jobs: jobs:
prepare: prepare:
name: Prepare name: Prepare
@ -39,6 +45,8 @@ jobs:
outputs: outputs:
macos-version: ${{ steps.versions.outputs.macos }} macos-version: ${{ steps.versions.outputs.macos }}
linux-version: ${{ steps.versions.outputs.linux }} linux-version: ${{ steps.versions.outputs.linux }}
win32-x64-version: ${{ steps.versions.outputs.win_x64 }}
win32-x86-version: ${{ steps.versions.outputs.win_x86 }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -77,9 +85,14 @@ jobs:
LINUX=$(aws s3 cp s3://$R2_BUCKET/debian/dists/default/main/binary-amd64/Packages - --endpoint-url $R2_URL --region auto | grep "Package: element-nightly" -A 50 | grep Version -m1 | sed -n 's/Version: //p') LINUX=$(aws s3 cp s3://$R2_BUCKET/debian/dists/default/main/binary-amd64/Packages - --endpoint-url $R2_URL --region auto | grep "Package: element-nightly" -A 50 | grep Version -m1 | sed -n 's/Version: //p')
echo "linux=$(scripts/generate-nightly-version.ts --latest $LINUX)" >> $GITHUB_OUTPUT echo "linux=$(scripts/generate-nightly-version.ts --latest $LINUX)" >> $GITHUB_OUTPUT
WINx64=$(aws s3 cp s3://$R2_BUCKET/nightly/update/win32/x64/RELEASES - --endpoint-url $R2_URL --region auto | awk '{print $2}' | cut -d "-" -f 5 | cut -c 8-)
echo "win_x64=$(scripts/generate-nightly-version.ts --latest $WINx64)" >> $GITHUB_OUTPUT
WINx86=$(aws s3 cp s3://$R2_BUCKET/nightly/update/win32/ia32/RELEASES - --endpoint-url $R2_URL --region auto | awk '{print $2}' | cut -d "-" -f 5 | cut -c 8-)
echo "win_x86=$(scripts/generate-nightly-version.ts --latest $WINx86)" >> $GITHUB_OUTPUT
env: env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }} AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
# XXX: UPDATE THIS BEFORE WHEN GOING LIVE # XXX: UPDATE THIS BEFORE WHEN GOING LIVE
R2_BUCKET: 'packages-element-io-test' R2_BUCKET: "packages-element-io-test"
R2_URL: ${{ secrets.CF_R2_S3_API }} R2_URL: ${{ secrets.CF_R2_S3_API }}

View File

@ -3,14 +3,34 @@
# the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch. # the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch.
on: on:
workflow_call: workflow_call:
secrets:
ESIGNER_USER_NAME:
required: false
ESIGNER_USER_PASSWORD:
required: false
ESIGNER_USER_TOTP:
required: false
inputs: inputs:
arch: arch:
type: string type: string
required: true required: true
description: "The architecture to build for, one of 'x64' | 'x86'" description: "The architecture to build for, one of 'x64' | 'x86'"
version:
type: string
required: false
description: "Version string to override the one in package.json, used for non-release builds"
sign:
type: string
required: false
description: "Whether to sign & notarise the build, requires 'packages.element.io' environment"
deploy-mode:
type: string
required: false
description: "Whether to arrange artifacts in the arrangement needed for deployment, skipping unrelated ones"
jobs: jobs:
build: build:
runs-on: windows-latest runs-on: windows-latest
environment: ${{ inputs.sign && 'packages.element.io' || '' }}
steps: steps:
- uses: kanga333/variable-mapper@master - uses: kanga333/variable-mapper@master
id: config id: config
@ -50,12 +70,14 @@ jobs:
# ActiveTCL package on choco is from 2015, # ActiveTCL package on choco is from 2015,
# this one is newer but includes more than we need # this one is newer but includes more than we need
- name: Choco install tclsh - name: Choco install tclsh
if: steps.cache.outputs.cache-hit != 'true'
shell: pwsh shell: pwsh
run: | run: |
choco install -y magicsplat-tcl-tk --no-progress choco install -y magicsplat-tcl-tk --no-progress
echo "${HOME}/AppData/Local/Apps/Tcl86/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "${HOME}/AppData/Local/Apps/Tcl86/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Choco install NetWide Assembler - name: Choco install NetWide Assembler
if: steps.cache.outputs.cache-hit != 'true'
shell: pwsh shell: pwsh
run: | run: |
choco install -y nasm --no-progress choco install -y nasm --no-progress
@ -82,12 +104,86 @@ jobs:
refreshenv refreshenv
yarn build:native --target ${{ steps.config.outputs.target }} yarn build:native --target ${{ steps.config.outputs.target }}
- name: Install and configure eSigner CKA
id: esigner
if: inputs.sign
run: |
Set-StrictMode -Version 'Latest'
# Download
Invoke-WebRequest -OutFile eSigner_CKA.exe "https://packages.element.io/tools/SSL.COM%20eSigner%20CKA_1.0.4-build-20230221_signed.exe"
# Install
New-Item -ItemType Directory -Force -Path "$env:INSTALL_DIR"
./eSigner_CKA.exe /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES /DIR="${{ env.INSTALL_DIR }}" | Out-Null
# Disable logger
$LogConfig = Get-Content -Path ${{ env.INSTALL_DIR }}/log4net.config
$LogConfig[0] = '<log4net threshold="OFF">'
$LogConfig | Set-Content -Path ${{ env.INSTALL_DIR }}/log4net.config
# Configure
${{ env.INSTALL_DIR }}/eSignerCKATool.exe config -mode "${{ env.MODE }}" -user "${{ secrets.ESIGNER_USER_NAME }}" -pass "${{ secrets.ESIGNER_USER_PASSWORD }}" -totp "${{ secrets.ESIGNER_USER_TOTP }}" -key "${{ env.MASTER_KEY_FILE }}" -r
${{ env.INSTALL_DIR }}/eSignerCKATool.exe unload
${{ env.INSTALL_DIR }}/eSignerCKATool.exe load
# Find certificate
$CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
echo Certificate: $CodeSigningCert
# Extract thumbprint and subject name
$Thumbprint = $CodeSigningCert.Thumbprint
$SubjectName = ($CodeSigningCert.Subject -replace ", ?", "`n" | ConvertFrom-StringData).CN
echo "config-args=--signtool-thumbprint '$Thumbprint' --signtool-subject-name '$SubjectName'" >> $env:GITHUB_OUTPUT
env:
# XXX: UPDATE THIS BEFORE WHEN GOING LIVE
MODE: sandbox
INSTALL_DIR: C:\Users\runneradmin\eSignerCKA
MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key
- name: "[Nightly] Resolve version"
id: nightly
if: inputs.version != ''
shell: bash
run: |
echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT
- name: Build App - name: Build App
run: "yarn build --publish never -w ${{ steps.config.outputs.build-args }}" run: |
yarn ts-node scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} ${{ steps.esigner.outputs.config-args }}
yarn build --publish never -w --config electron-builder.json ${{ steps.config.outputs.build-args }}
env:
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22000.0/x86/signtool.exe"
- name: Prepare artifacts for deployment
if: inputs.deploy-mode
shell: bash
run: |
mv dist _dist
mkdir -p dist/install/win32/${{ inputs.arch }}/msi dist/update/win32/${{ inputs.arch }}
mv _dist/squirrel-windows*/*.exe dist/install/win32/${{ inputs.arch }}/
mv _dist/squirrel-windows*/*.nupkg dist/update/win32/${{ inputs.arch }}/
mv _dist/squirrel-windows*/RELEASES dist/update/win32/${{ inputs.arch }}/
# mv _dist/*.msi dist/install/win32/${{ inputs.arch }}/msi/
# We don't wish to store the installer for every nightly ever, so we only keep the latest
- name: "[Nightly] Strip version from installer file"
if: inputs.deploy-mode && inputs.version != ''
shell: bash
run: |
mv dist/install/win32/${{ inputs.arch }}/*.exe "dist/install/win32/${{ inputs.arch }}/Element Nightly Setup.exe"
# mv dist/install/win32/${{ inputs.arch }}/msi/*.msi "dist/install/win32/${{ inputs.arch }}/msi/Element Nightly Setup.msi"
- name: "[Release] Prepare release latest symlink"
if: inputs.deploy-mode && inputs.version == ''
shell: bash
run: |
ln -s "$(find . -type f -iname "*.exe" | xargs -0 -n1 -- basename)" "Element Setup.exe"
working-directory: "dist/install/win32/${{ inputs.arch }}"
- name: Upload Artifacts - name: Upload Artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: win-${{ inputs.arch }} name: ${{ inputs.deploy-mode && 'packages.element.io' || format('win-{0}', inputs.arch) }}
path: dist path: dist
retention-days: 1 retention-days: 1

View File

@ -8,9 +8,9 @@ on:
# Trigger a daily rebuild for (mac-mini built) Nightly builds # Trigger a daily rebuild for (mac-mini built) Nightly builds
schedule: schedule:
- cron: "0 11 * * *" - cron: "0 11 * * *"
# Trigger after Nightly builds are deployed # Trigger after Nightly builds are deployed
workflow_run: workflow_run:
workflows: [ "Build and Deploy" ] workflows: ["Build and Deploy"]
types: types:
- completed - completed
# Manual trigger for rebuilding for releases # Manual trigger for rebuilding for releases

View File

@ -22,10 +22,12 @@ const NIGHTLY_APP_ID = "im.riot.nightly";
const NIGHTLY_APP_NAME = "element-desktop-nightly"; const NIGHTLY_APP_NAME = "element-desktop-nightly";
const argv = parseArgs<{ const argv = parseArgs<{
nightly?: string; "nightly"?: string;
"signtool-thumbprint"?: string;
"signtool-subject-name"?: string;
"deb-custom-control"?: string; "deb-custom-control"?: string;
}>(process.argv.slice(2), { }>(process.argv.slice(2), {
string: ["nightly", "deb-custom-control"], string: ["nightly", "deb-custom-control", "signtool-thumbprint", "signtool-subject-name"],
}); });
interface File { interface File {
@ -54,7 +56,10 @@ interface PackageBuild {
target: { target: {
target: string; target: string;
}; };
sign: string; sign?: string;
signingHashAlgorithms?: string[];
certificateSubjectName?: string;
certificateSha1?: string;
}; };
deb?: { deb?: {
fpm?: string[]; fpm?: string[];
@ -108,6 +113,13 @@ async function main(): Promise<number | void> {
cfg.extraMetadata!.version = version; cfg.extraMetadata!.version = version;
} }
if (argv["signtool-thumbprint"] && argv["signtool-subject-name"]) {
delete cfg.win.sign;
cfg.win.signingHashAlgorithms = ["sha256"];
cfg.win.certificateSubjectName = argv["signtool-subject-name"];
cfg.win.certificateSha1 = argv["signtool-thumbprint"];
}
if (os.platform() === "linux") { if (os.platform() === "linux") {
// Electron crashes on debian if there's a space in the path. // Electron crashes on debian if there's a space in the path.
// https://github.com/vector-im/element-web/issues/13171 // https://github.com/vector-im/element-web/issues/13171
@ -123,9 +135,11 @@ async function main(): Promise<number | void> {
await fsProm.writeFile(ELECTRON_BUILDER_CFG_FILE, JSON.stringify(cfg, null, 4)); await fsProm.writeFile(ELECTRON_BUILDER_CFG_FILE, JSON.stringify(cfg, null, 4));
} }
main().then((ret) => { main()
process.exit(ret!); .then((ret) => {
}).catch((e) => { process.exit(ret!);
console.error(e); })
process.exit(1); .catch((e) => {
}); console.error(e);
process.exit(1);
});

View File

@ -8,6 +8,7 @@ const HIDDEN_FILES = [
".DS_Store", ".DS_Store",
"index.html", "index.html",
"/fonts/", "/fonts/",
"/tools/",
"/nginx-theme/", "/nginx-theme/",
".~tmp~/", ".~tmp~/",
"msi/", "msi/",