Compare commits

..

No commits in common. "develop" and "v1.11.94" have entirely different histories.

37 changed files with 1191 additions and 1289 deletions

View File

@ -1,35 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIGBzCCA++gAwIBAgIIaI6ivggL++4wDQYJKoZIhvcNAQELBQAwgZAxCzAJBgNV
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
CgwPU1NMIENvcnBvcmF0aW9uMUUwQwYDVQQDDDxTU0wuY29tIEVWIFJvb3QgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyIC0gRGV2ZWxvcG1lbnQwHhcNMTgw
MTE2MTIxNjM2WhcNNDMwMTE1MTIxNjM2WjCBkDELMAkGA1UEBhMCVVMxDjAMBgNV
BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9y
YXRpb24xRTBDBgNVBAMMPFNTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSBSU0EgUjIgLSBEZXZlbG9wbWVudDCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAK/qcD65JCkueKp0+KXG2kAw8euDHuraLR3lJoUFz4ilGK1M
t+RjSuY6dHQw8ku7TnW9ejWoSFjCBSDx7tP/fzOwOxmBW6+F1NDuV/IaUtn3G2lk
CZglVk9z3n1HuWDN10xNiLoo5nzeIlvNAoDbXDGhI4Y6Z0qouAIS607JpJMWHOqZ
OUiiOuM11gI5Kz9GtVttXCjRmwlkU8WiJVIUuVedQAQt2FChrzNQewGFFi0uIau/
wFRclx6hd4JRIImC6VMJd9lcitWsqMcM94pD3fX2ozNgWX+MVlmcDYFSN9Sv8tG4
yCj4ONS8HZGzbxeyQXJhEJSi2FnBi0j6MD/d4DNFj0hCg9wz3fgVLDGCO0pNMO0Y
oXdrzfoj1/zEv0Ibgh7zKG2JHkPfapn3ExFI5d6xi66u5tPVI8cvLxqrgybRPs7Z
y1dQA7ew3LyTPAHoGtbTMvewtx1TkTtRxxhRRm0l58owqSVbSYrixFtosNobCERo
uiknaQqoY1ZDsdKsaqFoZDbntNRYhN3Ea4OPWVqDUU5ZPz9MTIRAi3MIq854yyQo
BjX9nv+kYa+Esr19pxUW0z7BWFhbXsMVpt0QMVyhwgzXvEreaZHFwHHaGb9d5x5P
VBDhsigMmtzBk9NlbCsy+uGXWHgZA/DVefueEq0sv38VoU30uYa5Tj0FLm09AgMB
AAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUI9PCucv3G9fRoTDu
ZQ4Hw6g4PkIwHQYDVR0OBBYEFCPTwrnL9xvX0aEw7mUOB8OoOD5CMA4GA1UdDwEB
/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAk43CCrC0Zbvi7YUsSePKi+KzvyQ9
mjKa5NBU/A5/sLeZS3R+wqCX7l5euYVDsUuNgNVD/QL9jNIonuHBrvKaxkmqxE1r
IcDEaUdjy2lQ0uqD7UDoS3ctrjGkPpUahrTdr3gaKcQBtUhn9v4Y2OBm6J1hDVwI
CIKcxIzRv6AUpApOtk+++m5tzDU48t8+GzrVl1hkspSYcumA+zuHllbPDL1ADdo5
kK/bBQtZrGqzPqKzeqaB1A5Wm0Igwf++7nyzdKNdjxtv907D9vg8EB4Swavuv/Ne
5/jbpI32pz0NIzzSl5ARAHuFhILsO/cEAlloDoTHzibHqFDIeU9/59HMUsJYMOtD
Ii0/LmQ6dBE4TeukCCLJwtkFYZ2eBgDjF/LHBB+z/UBs4milRgwx+Pe5UDUEjtGe
G/XMVnTSKZTy9jMaXJD5EmfP+Cfh8EEgFgjg4AmLUbEo9gXzPxyXSLgd8JGSsjg8
EV/Ri4Mmmt4XUwlSVvEOezxxDGd17gwbottCIC+rqPHonHkGmKpLMH80Bk0uOOCs
ui1oVwSifMyIcudgCcOfRLUf/f2j2NW7N7E7Vw/Zqfn+pqp/EG0KCqOM2vfJAc0s
u3rSrOJZGtB6txgtmTjoadxApWf4U/FCi3uArt6gS5MJqZjuiRNXs/K3SlSAqLGl
5UiG52ew+VdBHzE=
-----END CERTIFICATE-----

View File

@ -62,7 +62,7 @@ jobs:
name: Windows ${{ matrix.arch }} name: Windows ${{ matrix.arch }}
strategy: strategy:
matrix: matrix:
arch: [x64, arm64] arch: [ia32, x64]
uses: ./.github/workflows/build_windows.yaml uses: ./.github/workflows/build_windows.yaml
secrets: inherit secrets: inherit
with: with:
@ -92,6 +92,7 @@ jobs:
uses: ./.github/workflows/build_linux.yaml uses: ./.github/workflows/build_linux.yaml
with: with:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
config: ${{ needs.prepare.outputs.config }}
sqlcipher: ${{ matrix.sqlcipher }} sqlcipher: ${{ matrix.sqlcipher }}
version: ${{ needs.prepare.outputs.nightly-version }} version: ${{ needs.prepare.outputs.nightly-version }}
@ -111,10 +112,8 @@ jobs:
- name: Prepare artifacts for deployment - name: Prepare artifacts for deployment
run: | run: |
set -x
# Windows # Windows
for arch in x64 arm64 for arch in x64 ia32 arm64
do do
if [ -d "win-$arch" ]; then if [ -d "win-$arch" ]; then
mkdir -p packages.element.io/{install,update}/win32/$arch mkdir -p packages.element.io/{install,update}/win32/$arch
@ -146,10 +145,8 @@ jobs:
- name: "[Nightly] Strip version from installer file" - name: "[Nightly] Strip version from installer file"
if: needs.prepare.outputs.nightly-version != '' if: needs.prepare.outputs.nightly-version != ''
run: | run: |
set -x
# Windows # Windows
for arch in x64 arm64 for arch in x64 ia32 arm64
do do
[ -d "win-$arch" ] && mv packages.element.io/install/win32/$arch/{*,"Element Nightly Setup"}.exe [ -d "win-$arch" ] && mv packages.element.io/install/win32/$arch/{*,"Element Nightly Setup"}.exe
done done
@ -164,10 +161,8 @@ jobs:
- name: "[Release] Prepare release latest symlink" - name: "[Release] Prepare release latest symlink"
if: needs.prepare.outputs.nightly-version == '' if: needs.prepare.outputs.nightly-version == ''
run: | run: |
set -x
# Windows # Windows
for arch in x64 arm64 for arch in x64 ia32 arm64
do do
if [ -d "win-$arch" ]; then if [ -d "win-$arch" ]; then
pushd packages.element.io/install/win32/$arch pushd packages.element.io/install/win32/$arch
@ -202,12 +197,18 @@ jobs:
name: packages.element.io name: packages.element.io
path: packages.element.io path: packages.element.io
# Checksum algorithm specified as per https://developers.cloudflare.com/r2/examples/aws/aws-cli/ # Workaround for https://www.cloudflarestatus.com/incidents/t5nrjmpxc1cj
- uses: unfor19/install-aws-cli-action@e8b481e524a99f37fbd39fdc1dcb3341ab091367 # v1
if: needs.prepare.outputs.deploy == 'true'
with:
version: 2.22.35
verbose: false
arch: amd64
- name: Deploy artifacts - name: Deploy artifacts
if: needs.prepare.outputs.deploy == 'true' if: needs.prepare.outputs.deploy == 'true'
run: | run: |
set -x aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/$DEPLOYMENT_DIR --endpoint-url $R2_URL --region auto
aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/$DEPLOYMENT_DIR --endpoint-url $R2_URL --region auto --checksum-algorithm CRC32
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 }}
@ -226,8 +227,6 @@ jobs:
id: deb id: deb
if: needs.linux.result == 'success' if: needs.linux.result == 'success'
run: | run: |
set -x
for arch in amd64 arm64 for arch in amd64 arm64
do do
echo "$arch=$(ls linux-$arch-sqlcipher-static/*.deb | tail -n1)" >> $GITHUB_OUTPUT echo "$arch=$(ls linux-$arch-sqlcipher-static/*.deb | tail -n1)" >> $GITHUB_OUTPUT
@ -287,8 +286,6 @@ jobs:
- name: Copy files to S3 - name: Copy files to S3
run: | run: |
set -x
PREFIX="${VERSION%.*}" PREFIX="${VERSION%.*}"
for file in win-*/*.msi; do for file in win-*/*.msi; do
filename=$(basename "$file") filename=$(basename "$file")

View File

@ -22,7 +22,7 @@ jobs:
uses: ./.github/workflows/build_windows.yaml uses: ./.github/workflows/build_windows.yaml
strategy: strategy:
matrix: matrix:
arch: [x64, ia32, arm64] arch: [x64, ia32]
with: with:
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
@ -35,6 +35,7 @@ jobs:
sqlcipher: [system, static] sqlcipher: [system, static]
arch: [amd64, arm64] arch: [amd64, arm64]
with: with:
config: ${{ github.event.pull_request.base.ref == 'develop' && 'element.io/nightly' || 'element.io/release' }}
sqlcipher: ${{ matrix.sqlcipher }} sqlcipher: ${{ matrix.sqlcipher }}
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
@ -49,7 +50,6 @@ jobs:
- linux - linux
- windows - windows
strategy: strategy:
fail-fast: false
matrix: matrix:
include: include:
- name: macOS Universal - name: macOS Universal
@ -97,7 +97,7 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: package.json
cache: "yarn" cache: "yarn"
- name: Install Deps - name: Install Deps
@ -121,6 +121,12 @@ jobs:
# We need sudo on Linux as it is installed in /opt/ # We need sudo on Linux as it is installed in /opt/
RUN_AS: ${{ runner.os == 'Linux' && 'sudo' || '' }} RUN_AS: ${{ runner.os == 'Linux' && 'sudo' || '' }}
- name: Workaround macOS GHA permission issues
if: runner.os == 'macOS'
run: |
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/opt/off/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
- name: Run tests - name: Run tests
uses: coactions/setup-xvfb@6b00cf1889f4e1d5a48635647013c0508128ee1a uses: coactions/setup-xvfb@6b00cf1889f4e1d5a48635647013c0508128ee1a
timeout-minutes: 5 timeout-minutes: 5

View File

@ -8,6 +8,10 @@ on:
type: string type: string
required: true required: true
description: "The architecture to build for, one of 'amd64' | 'arm64'" description: "The architecture to build for, one of 'amd64' | 'arm64'"
config:
type: string
required: true
description: "The config directory to use"
version: version:
type: string type: string
required: false required: false
@ -72,7 +76,7 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: package.json
cache: "yarn" cache: "yarn"
env: env:
# Workaround for https://github.com/actions/setup-node/issues/317 # Workaround for https://github.com/actions/setup-node/issues/317
@ -84,17 +88,17 @@ jobs:
- name: "Get modified files" - name: "Get modified files"
id: changed_files id: changed_files
if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request' if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request'
uses: tj-actions/changed-files@48d8f15b2aaa3d255ca5af3eba4870f807ce6b3c # v45 uses: tj-actions/changed-files@d6e91a2266cdb9d62096cebf1e8546899c6aa18f # v45
with: with:
files: | files: |
dockerbuild/** dockerbuild/**
# This allows contributors to test changes to the dockerbuild image within a pull request # This allows contributors to test changes to the dockerbuild image within a pull request
- name: Build docker image - name: Build docker image
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6 uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
if: steps.changed_files.outputs.any_modified == 'true' if: steps.changed_files.outputs.any_modified == 'true'
with: with:
file: dockerbuild/Dockerfile context: dockerbuild
load: true load: true
platforms: linux/${{ inputs.arch }} platforms: linux/${{ inputs.arch }}
tags: ${{ env.HAK_DOCKER_IMAGE }} tags: ${{ env.HAK_DOCKER_IMAGE }}
@ -119,6 +123,11 @@ jobs:
./scripts/glibc-check.sh $filename ./scripts/glibc-check.sh $filename
done done
- name: "[Nightly] Resolve version"
if: inputs.version != ''
run: |
echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV
- name: Generate debian files and arguments - name: Generate debian files and arguments
run: | run: |
if [ -f changelog.Debian ]; then if [ -f changelog.Debian ]; then
@ -135,9 +144,6 @@ jobs:
- name: Build App - name: Build App
run: yarn build --publish never -l ${{ steps.config.outputs.build-args }} run: yarn build --publish never -l ${{ steps.config.outputs.build-args }}
env:
# Only set for Nightly builds
ED_NIGHTLY: ${{ inputs.version }}
- name: Check native libraries - name: Check native libraries
run: | run: |
@ -176,10 +182,3 @@ jobs:
dist dist
!dist/*-unpacked/** !dist/*-unpacked/**
retention-days: 1 retention-days: 1
- name: Assert all required files are present
run: |
test -f ./dist/element-desktop*$ARCH.deb
test -f ./dist/element-desktop*.tar.gz
env:
ARCH: ${{ inputs.arch }}

View File

@ -58,23 +58,28 @@ jobs:
# M1 macos-14 comes without Python preinstalled # M1 macos-14 comes without Python preinstalled
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: "3.13" python-version: "3.12"
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: package.json
cache: "yarn" cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps - name: Install Deps
run: "yarn install --frozen-lockfile" run: "yarn install --frozen-lockfile"
# Python 3.12 drops distutils which keytar relies on
- name: Install setuptools
run: pip3 install setuptools
- name: Build Natives - name: Build Natives
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: yarn build:native:universal run: |
# Python 3.12 drops distutils which keytar relies on
pip3 install setuptools
yarn build:native:universal
- name: "[Nightly] Resolve version"
if: inputs.version != ''
run: |
echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV
# 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"
@ -87,8 +92,6 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
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 }}
# Only set for Nightly builds
ED_NIGHTLY: ${{ inputs.version }}
- name: Check app was signed & notarised successfully - name: Check app was signed & notarised successfully
if: inputs.sign != '' if: inputs.sign != ''
@ -140,8 +143,3 @@ jobs:
dist dist
!dist/mac-universal/** !dist/mac-universal/**
retention-days: 1 retention-days: 1
- name: Assert all required files are present
run: |
test -f ./dist/Element*.dmg
test -f ./dist/Element*-mac.zip

View File

@ -34,9 +34,12 @@ on:
packages-dir: packages-dir:
description: "The directory non-deb packages for this run should live in within packages.element.io" description: "The directory non-deb packages for this run should live in within packages.element.io"
value: ${{ inputs.nightly && 'nightly' || 'desktop' }} value: ${{ inputs.nightly && 'nightly' || 'desktop' }}
# This is just a simple pass-through of the input to simplify reuse of complex inline conditions # These are just simple pass-throughs of the input to simplify reuse of complex inline conditions
config:
description: "The relative path to the config file for this run"
value: ${{ inputs.config }}
deploy: deploy:
description: "Whether the build should be deployed to production" description: "The relative path to the config file for this run"
value: ${{ inputs.deploy }} value: ${{ inputs.deploy }}
permissions: {} permissions: {}
jobs: jobs:
@ -53,7 +56,7 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: package.json
cache: "yarn" cache: "yarn"
- name: Install Deps - name: Install Deps
@ -80,7 +83,7 @@ jobs:
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' >> VERSIONS 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' >> VERSIONS
aws s3 cp s3://$R2_BUCKET/debian/dists/default/main/binary-arm64/Packages - --endpoint-url $R2_URL --region auto | grep "Package: element-nightly" -A 50 | grep Version -m1 | sed -n 's/Version: //p' >> VERSIONS aws s3 cp s3://$R2_BUCKET/debian/dists/default/main/binary-arm64/Packages - --endpoint-url $R2_URL --region auto | grep "Package: element-nightly" -A 50 | grep Version -m1 | sed -n 's/Version: //p' >> VERSIONS
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- >> VERSIONS 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- >> VERSIONS
aws s3 cp s3://$R2_BUCKET/nightly/update/win32/arm64/RELEASES - --endpoint-url $R2_URL --region auto | awk '{print $2}' | cut -d "-" -f 5 | cut -c 8- >> VERSIONS 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- >> VERSIONS
# Pick the greatest one # Pick the greatest one
VERSION=$(cat VERSIONS | sort -uf | tail -n1) VERSION=$(cat VERSIONS | sort -uf | tail -n1)
@ -90,6 +93,8 @@ jobs:
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 }}
# Workaround for https://www.cloudflarestatus.com/incidents/t5nrjmpxc1cj
AWS_REQUEST_CHECKSUM_CALCULATION: when_required
R2_BUCKET: ${{ vars.R2_BUCKET }} R2_BUCKET: ${{ vars.R2_BUCKET }}
R2_URL: ${{ vars.CF_R2_S3_API }} R2_URL: ${{ vars.CF_R2_S3_API }}

View File

@ -56,8 +56,7 @@ jobs:
"ia32": { "ia32": {
"target": "i686-pc-windows-msvc", "target": "i686-pc-windows-msvc",
"build-args": "--ia32", "build-args": "--ia32",
"arch": "x86", "arch": "x86"
"extra_config": "{\"user_notice\": {\"title\": \"Your desktop environment is unsupported.\",\"description\": \"Support for 32-bit Windows installations has ended. Transition to the web or mobile app for continued access.\"}}"
} }
} }
@ -75,6 +74,11 @@ jobs:
path: | path: |
./.hak ./.hak
- name: Set up build tools
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: ${{ steps.config.outputs.arch || inputs.arch }}
# 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
@ -100,38 +104,13 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: package.json
cache: "yarn" cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps - name: Install Deps
run: "yarn install --frozen-lockfile" run: "yarn install --frozen-lockfile"
- name: Insert config snippet
if: steps.config.outputs.extra_config != ''
shell: bash
run: |
mkdir config-edit
yarn asar extract webapp.asar config-edit
cd config-edit
mv config.json old-config.json
echo '${{ steps.config.outputs.extra_config }}' | jq -s '.[0] * .[1]' old-config.json - > config.json
rm old-config.json
cd ..
rm webapp.asar
yarn asar pack config-edit/ webapp.asar
- name: Set up sqlcipher macros
if: steps.cache.outputs.cache-hit != 'true' && contains(inputs.arch, 'arm')
shell: pwsh
run: |
echo "NCC=${{ github.workspace }}\scripts\cl.bat" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Set up build tools
if: steps.cache.outputs.cache-hit != 'true'
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: ${{ steps.config.outputs.arch || inputs.arch }}
- name: Build Natives - name: Build Natives
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: | run: |
@ -181,25 +160,24 @@ jobs:
INSTALL_DIR: C:\Users\runneradmin\eSignerCKA INSTALL_DIR: C:\Users\runneradmin\eSignerCKA
MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key
- name: Build App - name: "[Nightly] Resolve version"
run: yarn build --publish never -w ${{ steps.config.outputs.build-args }} if: inputs.version != ''
env: shell: bash
# Only set for Nightly builds
ED_NIGHTLY: ${{ inputs.version }}
- name: Trust eSigner sandbox cert
if: inputs.sign == ''
run: | run: |
Set-StrictMode -Version 'Latest' echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV
Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath .github/SSLcom-sandbox.crt
# XXX: For whatever reason if we use `yarn build ...` it freezes, but splitting it into parts it is fine
- run: yarn run build:ts
- run: yarn run build:res
- name: Build App
run: |
yarn electron-builder --publish never -w ${{ steps.config.outputs.build-args }}
- name: Check app was signed successfully - name: Check app was signed successfully
if: inputs.sign
run: | run: |
Set-StrictMode -Version 'Latest' . "$env:SIGNTOOL_PATH" verify /pa (get-item ./dist/squirrel-windows*/*.exe)
Get-ChildItem `
-Recurse dist `
-Include *.exe, *.msi `
| ForEach-Object -Process {. $env:SIGNTOOL_PATH verify /pa $_.FullName; if(!$?) { throw }}
- name: Upload Artifacts - name: Upload Artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@ -208,11 +186,3 @@ jobs:
path: | path: |
dist dist
retention-days: 1 retention-days: 1
- name: Assert all required files are present
run: |
Test-Path './dist/win-*unpacked/Element*.exe'
Test-Path './dist/squirrel-windows*/Element Setup*.exe'
Test-Path './dist/squirrel-windows*/element-desktop-*-full.nupkg'
Test-Path './dist/squirrel-windows*/RELEASES'
Test-Path './dist/Element*.msi'

View File

@ -22,17 +22,17 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3 uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3 uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
with: with:
install: true install: true
- name: Build test image - name: Build test image
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6 uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
with: with:
file: dockerbuild/Dockerfile context: dockerbuild
push: false push: false
load: true load: true
tags: element-desktop-dockerbuild tags: element-desktop-dockerbuild
@ -42,7 +42,7 @@ jobs:
run: docker run -v $PWD:/project element-desktop-dockerbuild yarn install run: docker run -v $PWD:/project element-desktop-dockerbuild yarn install
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 uses: docker/login-action@327cd5a69de6c009b9ce71bce8395f28e651bf99
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
@ -52,7 +52,7 @@ jobs:
- name: Extract metadata for Docker - name: Extract metadata for Docker
id: meta id: meta
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5 uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: | tags: |
@ -61,9 +61,9 @@ jobs:
- name: Build and push Docker image - name: Build and push Docker image
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6 uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
with: with:
file: dockerbuild/Dockerfile context: dockerbuild
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}

View File

@ -19,7 +19,6 @@ jobs:
contents: write contents: write
issues: write issues: write
pull-requests: read pull-requests: read
id-token: write
secrets: secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}

View File

@ -14,9 +14,7 @@ jobs:
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v9
with: with:
operations-per-run: 250 operations-per-run: 100
days-before-issue-stale: -1
days-before-issue-close: -1
days-before-pr-stale: 180 days-before-pr-stale: 180
days-before-pr-close: 0 days-before-pr-close: 0
close-pr-message: "This PR has been automatically closed because it has been stale for 180 days. If you wish to continue working on this PR, please ping a maintainer to reopen it." close-pr-message: "This PR has been automatically closed because it has been stale for 180 days. If you wish to continue working on this PR, please ping a maintainer to reopen it."

View File

@ -1 +0,0 @@
v22.14.0

View File

@ -1,73 +1,3 @@
Changes in [1.11.96](https://github.com/element-hq/element-desktop/releases/tag/v1.11.96) (2025-03-25)
======================================================================================================
## ✨ Features
* RoomListViewModel: Track the index of the active room in the list ([#29519](https://github.com/element-hq/element-web/pull/29519)). Contributed by @MidhunSureshR.
* New room list: add empty state ([#29512](https://github.com/element-hq/element-web/pull/29512)). Contributed by @florianduros.
* Implement `MessagePreviewViewModel` ([#29514](https://github.com/element-hq/element-web/pull/29514)). Contributed by @MidhunSureshR.
* RoomListViewModel: Add functionality to toggle message preview setting ([#29511](https://github.com/element-hq/element-web/pull/29511)). Contributed by @MidhunSureshR.
* New room list: add more options menu on room list item ([#29445](https://github.com/element-hq/element-web/pull/29445)). Contributed by @florianduros.
* RoomListViewModel: Provide a way to resort the room list and track the active sort method ([#29499](https://github.com/element-hq/element-web/pull/29499)). Contributed by @MidhunSureshR.
* Change \*All rooms\* meta space name to \*All Chats\* ([#29498](https://github.com/element-hq/element-web/pull/29498)). Contributed by @florianduros.
* Add setting to hide avatars of rooms you have been invited to. ([#29497](https://github.com/element-hq/element-web/pull/29497)). Contributed by @Half-Shot.
* Room List Store: Save preferred sorting algorithm and use that on app launch ([#29493](https://github.com/element-hq/element-web/pull/29493)). Contributed by @MidhunSureshR.
* Add key storage toggle to Encryption settings ([#29310](https://github.com/element-hq/element-web/pull/29310)). Contributed by @dbkr.
* New room list: add primary filters ([#29481](https://github.com/element-hq/element-web/pull/29481)). Contributed by @florianduros.
* Implement MSC4142: Remove unintentional intentional mentions in replies ([#28209](https://github.com/element-hq/element-web/pull/28209)). Contributed by @tulir.
* White background for 'They do not match' button ([#29470](https://github.com/element-hq/element-web/pull/29470)). Contributed by @andybalaam.
* RoomListViewModel: Support secondary filters in the view model ([#29465](https://github.com/element-hq/element-web/pull/29465)). Contributed by @MidhunSureshR.
* RoomListViewModel: Support primary filters in the view model ([#29454](https://github.com/element-hq/element-web/pull/29454)). Contributed by @MidhunSureshR.
* Room List Store: Implement secondary filters ([#29458](https://github.com/element-hq/element-web/pull/29458)). Contributed by @MidhunSureshR.
* Room List Store: Implement rest of the primary filters ([#29444](https://github.com/element-hq/element-web/pull/29444)). Contributed by @MidhunSureshR.
* Room List Store: Support filters by implementing just the favourite filter ([#29433](https://github.com/element-hq/element-web/pull/29433)). Contributed by @MidhunSureshR.
* Move toggle switch for integration manager for a11y ([#29436](https://github.com/element-hq/element-web/pull/29436)). Contributed by @Half-Shot.
* New room list: basic flat list ([#29368](https://github.com/element-hq/element-web/pull/29368)). Contributed by @florianduros.
* Improve rageshake upload experience by providing useful error information ([#29378](https://github.com/element-hq/element-web/pull/29378)). Contributed by @Half-Shot.
* Add more functionality to the room list vm ([#29402](https://github.com/element-hq/element-web/pull/29402)). Contributed by @MidhunSureshR.
## 🐛 Bug Fixes
* Fix `--no-update` command line flag ([#2210](https://github.com/element-hq/element-desktop/pull/2210)). Contributed by @t3chguy.
* New room list: fix compose menu action in space ([#29500](https://github.com/element-hq/element-web/pull/29500)). Contributed by @florianduros.
* Change ToggleHiddenEventVisibility \& GoToHome KeyBindingActions ([#29374](https://github.com/element-hq/element-web/pull/29374)). Contributed by @gy-mate.
* Fix Docker Healthcheck ([#29471](https://github.com/element-hq/element-web/pull/29471)). Contributed by @benbz.
* Room List Store: Fetch rooms after space store is ready + attach store to window ([#29453](https://github.com/element-hq/element-web/pull/29453)). Contributed by @MidhunSureshR.
* Room List Store: Fix bug where left rooms appear in room list ([#29452](https://github.com/element-hq/element-web/pull/29452)). Contributed by @MidhunSureshR.
* Add space to the bottom of the room summary actions below leave room ([#29270](https://github.com/element-hq/element-web/pull/29270)). Contributed by @langleyd.
* Show error screens in group calls ([#29254](https://github.com/element-hq/element-web/pull/29254)). Contributed by @robintown.
* Prevent user from accidentally triggering multiple identity resets ([#29388](https://github.com/element-hq/element-web/pull/29388)). Contributed by @uhoreg.
* Remove buggy tooltip on room intro \& homepage ([#29406](https://github.com/element-hq/element-web/pull/29406)). Contributed by @t3chguy.
Changes in [1.11.95](https://github.com/element-hq/element-desktop/releases/tag/v1.11.95) (2025-03-11)
======================================================================================================
## ✨ Features
* Switch to shiftkey/node-keytar as it has NAPI 10 updates ([#2172](https://github.com/element-hq/element-desktop/pull/2172)). Contributed by @t3chguy.
* Add support for Windows arm64 ([#624](https://github.com/element-hq/element-desktop/pull/624)). Contributed by @t3chguy.
* Room List Store: Filter rooms by active space ([#29399](https://github.com/element-hq/element-web/pull/29399)). Contributed by @MidhunSureshR.
* Room List - Update the room list store on actions from the dispatcher ([#29397](https://github.com/element-hq/element-web/pull/29397)). Contributed by @MidhunSureshR.
* Room List - Implement a minimal view model ([#29357](https://github.com/element-hq/element-web/pull/29357)). Contributed by @MidhunSureshR.
* New room list: add space menu in room header ([#29352](https://github.com/element-hq/element-web/pull/29352)). Contributed by @florianduros.
* Room List - Store sorted rooms in skip list ([#29345](https://github.com/element-hq/element-web/pull/29345)). Contributed by @MidhunSureshR.
* New room list: add dial to search section ([#29359](https://github.com/element-hq/element-web/pull/29359)). Contributed by @florianduros.
* New room list: add compose menu for spaces in header ([#29347](https://github.com/element-hq/element-web/pull/29347)). Contributed by @florianduros.
* Use EditInPlace control for Identity Server picker to improve a11y ([#29280](https://github.com/element-hq/element-web/pull/29280)). Contributed by @Half-Shot.
* First step to add header to new room list ([#29320](https://github.com/element-hq/element-web/pull/29320)). Contributed by @florianduros.
* Add Windows 64-bit arm link and remove 32-bit link on compatibility page ([#29312](https://github.com/element-hq/element-web/pull/29312)). Contributed by @t3chguy.
* Honour the backup disable flag from Element X ([#29290](https://github.com/element-hq/element-web/pull/29290)). Contributed by @dbkr.
## 🐛 Bug Fixes
* Fix edited code block width ([#29394](https://github.com/element-hq/element-web/pull/29394)). Contributed by @florianduros.
* new room list: keep space name in one line in header ([#29369](https://github.com/element-hq/element-web/pull/29369)). Contributed by @florianduros.
* Dismiss "Key storage out of sync" toast when secrets received ([#29348](https://github.com/element-hq/element-web/pull/29348)). Contributed by @richvdh.
* Minor CSS fixes for the new room list ([#29334](https://github.com/element-hq/element-web/pull/29334)). Contributed by @florianduros.
* Add padding to room header icon ([#29271](https://github.com/element-hq/element-web/pull/29271)). Contributed by @langleyd.
Changes in [1.11.94](https://github.com/element-hq/element-desktop/releases/tag/v1.11.94) (2025-02-27) Changes in [1.11.94](https://github.com/element-hq/element-desktop/releases/tag/v1.11.94) (2025-02-27)
====================================================================================================== ======================================================================================================
* No changes * No changes

View File

@ -2,7 +2,7 @@
# with broader compatibility, down to Debian bullseye & Ubuntu focal. # with broader compatibility, down to Debian bullseye & Ubuntu focal.
FROM rust:bullseye FROM rust:bullseye
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND noninteractive
RUN curl --proto "=https" -L https://yarnpkg.com/latest.tar.gz | tar xvz && mv yarn-* /yarn && ln -s /yarn/bin/yarn /usr/bin/yarn RUN curl --proto "=https" -L https://yarnpkg.com/latest.tar.gz | tar xvz && mv yarn-* /yarn && ln -s /yarn/bin/yarn /usr/bin/yarn
RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \ RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
@ -16,12 +16,13 @@ RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/* apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
RUN ln -s /usr/bin/python3 /usr/bin/python & ln -s /usr/bin/pip3 /usr/bin/pip RUN ln -s /usr/bin/python3 /usr/bin/python & ln -s /usr/bin/pip3 /usr/bin/pip
ENV DEBUG_COLORS=true ENV DEBUG_COLORS true
ENV FORCE_COLOR=true ENV FORCE_COLOR true
WORKDIR /project WORKDIR /project
ENV NODE_VERSION 20.18.2
ARG TARGETOS ARG TARGETOS
ARG TARGETARCH ARG TARGETARCH
COPY .node-version dockerbuild/setup.sh / COPY setup.sh /setup.sh
RUN /setup.sh RUN /setup.sh

View File

@ -3,6 +3,5 @@
set -x set -x
declare -A archMap=(["amd64"]="x64" ["arm64"]="arm64") declare -A archMap=(["amd64"]="x64" ["arm64"]="arm64")
ARCH="${archMap["$TARGETARCH"]}" ARCH="${archMap["$TARGETARCH"]}"
NODE_VERSION=$(cat /.node-version) curl --proto "=https" -L "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
curl --proto "=https" -L "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md

View File

@ -12,13 +12,6 @@ If you want to build native modules, make sure that the following tools are inst
- [Strawberry Perl](https://strawberryperl.com/) - [Strawberry Perl](https://strawberryperl.com/)
- [Rustup](https://rustup.rs/) - [Rustup](https://rustup.rs/)
- [NASM](https://www.nasm.us/) - [NASM](https://www.nasm.us/)
You can install the above tools using [Chocolatey](https://chocolatey.org/install):
```cmd
choco install --no-progress -y git nodejs-lts yarn python StrawberryPerl rustup.install nasm magicsplat-tcl-tk
```
- [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) with the following configuration: - [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) with the following configuration:
- On the Workloads tab: - On the Workloads tab:
- Desktop & Mobile -> C++ build tools - Desktop & Mobile -> C++ build tools

View File

@ -174,9 +174,6 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
schemes: ["io.element.desktop", "element"], schemes: ["io.element.desktop", "element"],
}, },
], ],
nativeRebuilder: "sequential",
nodeGypRebuild: false,
npmRebuild: true,
}; };
/** /**

26
hak/keytar/build.ts Normal file
View File

@ -0,0 +1,26 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const env = hakEnv.makeGypEnv();
console.log("Running yarn with env", env);
await hakEnv.spawn(
path.join(moduleInfo.nodeModuleBinDir, "node-gyp"),
["rebuild", "--arch", hakEnv.getTargetArch()],
{
cwd: moduleInfo.moduleBuildDir,
env,
},
);
}

15
hak/keytar/check.ts Normal file
View File

@ -0,0 +1,15 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
// node-gyp uses python for reasons beyond comprehension
await hakEnv.checkTools([["python", "--version"]]);
}

10
hak/keytar/hak.json Normal file
View File

@ -0,0 +1,10 @@
{
"scripts": {
"check": "check.ts",
"build": "build.ts"
},
"copy": "build/Release/keytar.node",
"dependencies": {
"libsecret": "0.20.3"
}
}

View File

@ -5,6 +5,7 @@ export default {
project: ["**/*.{js,ts}"], project: ["**/*.{js,ts}"],
ignoreDependencies: [ ignoreDependencies: [
// Brought in via hak scripts // Brought in via hak scripts
"keytar",
"matrix-seshat", "matrix-seshat",
// Required for `action-validator` // Required for `action-validator`
"@action-validator/*", "@action-validator/*",

View File

@ -3,7 +3,7 @@
"productName": "Element", "productName": "Element",
"main": "lib/electron-main.js", "main": "lib/electron-main.js",
"exports": "./lib/electron-main.js", "exports": "./lib/electron-main.js",
"version": "1.11.96", "version": "1.11.94",
"description": "Element: the future of secure communication", "description": "Element: the future of secure communication",
"author": "Element", "author": "Element",
"homepage": "https://element.io", "homepage": "https://element.io",
@ -44,7 +44,7 @@
"build": "yarn run build:ts && yarn run build:res && electron-builder", "build": "yarn run build:ts && yarn run build:res && electron-builder",
"build:ts": "tsc", "build:ts": "tsc",
"build:res": "tsx scripts/copy-res.ts", "build:res": "tsx scripts/copy-res.ts",
"docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild -f dockerbuild/Dockerfile .", "docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild dockerbuild",
"docker:build:native": "scripts/in-docker.sh yarn run hak", "docker:build:native": "scripts/in-docker.sh yarn run hak",
"docker:build": "scripts/in-docker.sh yarn run build", "docker:build": "scripts/in-docker.sh yarn run build",
"docker:install": "scripts/in-docker.sh yarn install", "docker:install": "scripts/in-docker.sh yarn install",
@ -53,17 +53,15 @@
"test": "playwright test", "test": "playwright test",
"test:open": "yarn test --ui", "test:open": "yarn test --ui",
"test:screenshots:build": "docker build playwright -t element-desktop-playwright --platform linux/amd64", "test:screenshots:build": "docker build playwright -t element-desktop-playwright --platform linux/amd64",
"test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright", "test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright"
"postinstall": "electron-builder install-app-deps"
}, },
"dependencies": { "dependencies": {
"@sentry/electron": "^6.0.0", "@sentry/electron": "^5.0.0",
"@standardnotes/electron-clear-data": "^1.0.5", "@standardnotes/electron-clear-data": "^1.0.5",
"auto-launch": "^5.0.5", "auto-launch": "^5.0.5",
"counterpart": "^0.18.6", "counterpart": "^0.18.6",
"electron-store": "^10.0.0", "electron-store": "^10.0.0",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"keytar-forked": "7.10.0",
"minimist": "^1.2.6", "minimist": "^1.2.6",
"png-to-ico": "^2.1.1", "png-to-ico": "^2.1.1",
"uuid": "^11.0.0" "uuid": "^11.0.0"
@ -74,22 +72,22 @@
"@babel/core": "^7.18.10", "@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10", "@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6", "@babel/preset-typescript": "^7.18.6",
"@electron/asar": "3.3.1", "@electron/asar": "3.2.18",
"@playwright/test": "1.51.1", "@playwright/test": "1.50.1",
"@stylistic/eslint-plugin": "^3.0.0", "@stylistic/eslint-plugin": "^3.0.0",
"@types/auto-launch": "^5.0.1", "@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1", "@types/counterpart": "^0.18.1",
"@types/minimist": "^1.2.1", "@types/minimist": "^1.2.1",
"@types/node": "18.19.84", "@types/node": "18.19.74",
"@types/pacote": "^11.1.1", "@types/pacote": "^11.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",
"app-builder-lib": "26.0.12", "app-builder-lib": "26.0.1",
"chokidar": "^4.0.0", "chokidar": "^4.0.0",
"detect-libc": "^2.0.0", "detect-libc": "^2.0.0",
"electron": "35.1.2", "electron": "34.0.2",
"electron-builder": "26.0.12", "electron-builder": "26.0.1",
"electron-builder-squirrel-windows": "26.0.12", "electron-builder-squirrel-windows": "26.0.1",
"electron-devtools-installer": "^4.0.0", "electron-devtools-installer": "^4.0.0",
"eslint": "^8.26.0", "eslint": "^8.26.0",
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
@ -110,13 +108,14 @@
"rimraf": "^6.0.0", "rimraf": "^6.0.0",
"tar": "^7.0.0", "tar": "^7.0.0",
"tsx": "^4.19.2", "tsx": "^4.19.2",
"typescript": "5.8.2" "typescript": "5.7.3"
}, },
"hakDependencies": { "hakDependencies": {
"matrix-seshat": "^4.0.1" "matrix-seshat": "^4.0.0",
"keytar": "^7.9.0"
}, },
"resolutions": { "resolutions": {
"@types/node": "18.19.84", "@types/node": "18.19.74",
"config-file-ts": "0.2.8-rc1" "config-file-ts": "0.2.8-rc1"
} }
} }

View File

@ -1,4 +1,4 @@
FROM mcr.microsoft.com/playwright:v1.51.1-jammy FROM mcr.microsoft.com/playwright:v1.50.1-jammy
WORKDIR /work/element-desktop WORKDIR /work/element-desktop

View File

@ -55,16 +55,4 @@ test.describe("App launch", () => {
}), }),
).resolves.not.toBeNull(); ).resolves.not.toBeNull();
}); });
test.describe("--no-update", () => {
test.use({
extraArgs: ["--no-update"],
});
// XXX: this test works fine locally but in CI the app start races with the test plumbing up the stdout/stderr pipes
// which means the logs are missed, disabling for now.
test.skip("should respect option", async ({ page, stdout }) => {
expect(stdout.data.toString()).toContain("Auto update disabled via command line flag");
});
});
}); });

View File

@ -11,37 +11,12 @@ import fs from "node:fs/promises";
import path, { dirname } from "node:path"; import path, { dirname } from "node:path";
import os from "node:os"; import os from "node:os";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { PassThrough } from "node:stream";
/**
* A PassThrough stream that captures all data written to it.
*/
class CapturedPassThrough extends PassThrough {
private _chunks = [];
public constructor() {
super();
super.on("data", this.onData);
}
private onData = (chunk): void => {
this._chunks.push(chunk);
};
public get data(): Buffer {
return Buffer.concat(this._chunks);
}
}
interface Fixtures { interface Fixtures {
app: ElectronApplication; app: ElectronApplication;
tmpDir: string; tmpDir: string;
extraEnv: Record<string, string>; extraEnv: Record<string, string>;
extraArgs: string[]; extraArgs: string[];
// Utilities to capture stdout and stderr for tests to make assertions against
stdout: CapturedPassThrough;
stderr: CapturedPassThrough;
} }
const __dirname = dirname(fileURLToPath(import.meta.url)); const __dirname = dirname(fileURLToPath(import.meta.url));
@ -49,16 +24,6 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
export const test = base.extend<Fixtures>({ export const test = base.extend<Fixtures>({
extraEnv: {}, extraEnv: {},
extraArgs: [], extraArgs: [],
// eslint-disable-next-line no-empty-pattern
stdout: async ({}, use) => {
await use(new CapturedPassThrough());
},
// eslint-disable-next-line no-empty-pattern
stderr: async ({}, use) => {
await use(new CapturedPassThrough());
},
// eslint-disable-next-line no-empty-pattern // eslint-disable-next-line no-empty-pattern
tmpDir: async ({}, use) => { tmpDir: async ({}, use) => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-")); const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-"));
@ -66,7 +31,7 @@ export const test = base.extend<Fixtures>({
await use(tmpDir); await use(tmpDir);
await fs.rm(tmpDir, { recursive: true }); await fs.rm(tmpDir, { recursive: true });
}, },
app: async ({ tmpDir, extraEnv, extraArgs, stdout, stderr }, use) => { app: async ({ tmpDir, extraEnv, extraArgs }, use) => {
const args = ["--profile-dir", tmpDir]; const args = ["--profile-dir", tmpDir];
const executablePath = process.env["ELEMENT_DESKTOP_EXECUTABLE"]; const executablePath = process.env["ELEMENT_DESKTOP_EXECUTABLE"];
@ -84,8 +49,8 @@ export const test = base.extend<Fixtures>({
args: [...args, ...extraArgs], args: [...args, ...extraArgs],
}); });
app.process().stdout.pipe(stdout).pipe(process.stdout); app.process().stdout.pipe(process.stdout);
app.process().stderr.pipe(stderr).pipe(process.stderr); app.process().stderr.pipe(process.stderr);
await app.firstWindow(); await app.firstWindow();

View File

@ -1,7 +0,0 @@
REM Batch file to aid in cross-compiling sqlcipher for Windows ARM64
REM Full path should be passed to Makefile.msc as NCC env var
setlocal
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %VSCMD_ARG_HOST_ARCH%
cl.exe %*
endlocal

View File

@ -67,14 +67,14 @@ Hak is divided into lifecycle stages, in order:
# hak.json # hak.json
The scripts section contains scripts used for lifecycle stages that need them (fetch, build). The scripts section contains scripts used for lifecycle stages that need them (fetch, fetchDeps, build).
It also contains 'prune' and 'copy' which are globs of files to delete from the output module directory It also contains 'prune' and 'copy' which are globs of files to delete from the output module directory
and copy over from the module build directory to the output module directory, respectively. and copy over from the module build directory to the output module directory, respectively.
# Shortcomings # Shortcomings
Hak doesn't know about dependencies between lifecycle stages, ie. it doesn't know that you need to Hak doesn't know about dependencies between lifecycle stages, ie. it doesn't know that you need to
'fetch' before you can 'build', etc. You get to run each individually, and remember 'fetch' and 'fetchDeps' before you can 'build', etc. You get to run each individually, and remember
the right order. the right order.
There is also a _lot_ of duplication in the command execution: we should abstract away There is also a _lot_ of duplication in the command execution: we should abstract away

View File

@ -10,5 +10,7 @@ import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js"; import type HakEnv from "./hakEnv.js";
export default async function check(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> { export default async function check(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await moduleInfo.scripts.check?.(hakEnv, moduleInfo); if (moduleInfo.scripts.check) {
await moduleInfo.scripts.check(hakEnv, moduleInfo);
}
} }

View File

@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
import path from "node:path"; import path from "node:path";
import fsProm from "node:fs/promises"; import fsProm from "node:fs/promises";
import childProcess from "node:child_process"; import childProcess from "node:child_process";
import { rimraf } from "rimraf";
import { glob } from "glob"; import { glob } from "glob";
import { mkdirp } from "mkdirp"; import { mkdirp } from "mkdirp";
@ -16,6 +17,20 @@ import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js"; import type { DependencyInfo } from "./dep.js";
export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> { export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (moduleInfo.cfg.prune) {
console.log("Removing " + moduleInfo.cfg.prune + " from " + moduleInfo.moduleOutDir);
// rimraf doesn't have a 'cwd' option: it always uses process.cwd()
// (and if you set glob.cwd it just breaks because it can't find the files)
const oldCwd = process.cwd();
try {
await mkdirp(moduleInfo.moduleOutDir);
process.chdir(moduleInfo.moduleOutDir);
await rimraf(moduleInfo.cfg.prune);
} finally {
process.chdir(oldCwd);
}
}
if (moduleInfo.cfg.copy) { if (moduleInfo.cfg.copy) {
// If there are multiple moduleBuildDirs, singular moduleBuildDir // If there are multiple moduleBuildDirs, singular moduleBuildDir
// is the same as moduleBuildDirs[0], so we're just listing the contents // is the same as moduleBuildDirs[0], so we're just listing the contents

19
scripts/hak/fetchDeps.ts Normal file
View File

@ -0,0 +1,19 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { mkdirp } from "mkdirp";
import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
export default async function fetchDeps(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await mkdirp(moduleInfo.moduleDotHakDir);
if (moduleInfo.scripts.fetchDeps) {
await moduleInfo.scripts.fetchDeps(hakEnv, moduleInfo);
}
}

View File

@ -19,7 +19,7 @@ import packageJson from "../../package.json";
const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "clean"]; const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "clean"];
// Shortcuts for multiple commands at once (useful for building universal binaries // Shortcuts for multiple commands at once (useful for building universal binaries
// because you can run the fetch/build for each arch and then copy/link once) // because you can run the fetch/fetchDeps/build for each arch and then copy/link once)
const METACOMMANDS: Record<string, string[]> = { const METACOMMANDS: Record<string, string[]> = {
fetchandbuild: ["check", "fetch", "build"], fetchandbuild: ["check", "fetch", "build"],
copyandlink: ["copy", "link"], copyandlink: ["copy", "link"],

54
src/@types/keytar.d.ts vendored Normal file
View File

@ -0,0 +1,54 @@
// Based on https://github.com/atom/node-keytar/blob/master/keytar.d.ts because keytar is a hak-dependency and not a normal one
// Definitions by: Milan Burda <https://github.com/miniak>, Brendan Forster <https://github.com/shiftkey>, Hari Juturu <https://github.com/juturu>
// Adapted from DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/keytar/index.d.ts
declare module "keytar" {
/**
* Get the stored password for the service and account.
*
* @param service The string service name.
* @param account The string account name.
*
* @returns A promise for the password string.
*/
export function getPassword(service: string, account: string): Promise<string | null>;
/**
* Add the password for the service and account to the keychain.
*
* @param service The string service name.
* @param account The string account name.
* @param password The string password.
*
* @returns A promise for the set password completion.
*/
export function setPassword(service: string, account: string, password: string): Promise<void>;
/**
* Delete the stored password for the service and account.
*
* @param service The string service name.
* @param account The string account name.
*
* @returns A promise for the deletion status. True on success.
*/
export function deletePassword(service: string, account: string): Promise<boolean>;
/**
* Find a password for the service in the keychain.
*
* @param service The string service name.
*
* @returns A promise for the password string.
*/
export function findPassword(service: string): Promise<string | null>;
/**
* Find all accounts and passwords for `service` in the keychain.
*
* @param service The string service name.
*
* @returns A promise for the array of found credentials.
*/
export function findCredentials(service: string): Promise<Array<{ account: string; password: string }>>;
}

View File

@ -22,6 +22,7 @@ import { URL, fileURLToPath } from "node:url";
import minimist from "minimist"; import minimist from "minimist";
import "./ipc.js"; import "./ipc.js";
import "./keytar.js";
import "./seshat.js"; import "./seshat.js";
import "./settings.js"; import "./settings.js";
import * as tray from "./tray.js"; import * as tray from "./tray.js";
@ -436,9 +437,8 @@ app.on("ready", async () => {
}); });
}); });
// Minimist parses `--no-`-prefixed arguments as booleans with value `false` rather than verbatim. if (argv["no-update"]) {
if (argv["update"] === false) { console.log('Auto update disabled via command line flag "--no-update"');
console.log("Auto update disabled via command line flag");
} else if (global.vectorConfig["update_base_url"]) { } else if (global.vectorConfig["update_base_url"]) {
console.log(`Starting auto update with base URL: ${global.vectorConfig["update_base_url"]}`); console.log(`Starting auto update with base URL: ${global.vectorConfig["update_base_url"]}`);
void updater.start(global.vectorConfig["update_base_url"]); void updater.start(global.vectorConfig["update_base_url"]);

View File

@ -9,7 +9,7 @@
"edit": "Golygu", "edit": "Golygu",
"minimise": "Lleihau", "minimise": "Lleihau",
"paste": "Gludo", "paste": "Gludo",
"paste_match_style": "Arddull Gludo a Chyfateb", "paste_match_style": "Gludo a Chyfateb Arddull",
"quit": "Gadael", "quit": "Gadael",
"redo": "Ail-wneud", "redo": "Ail-wneud",
"select_all": "Dewis y Cyfan", "select_all": "Dewis y Cyfan",
@ -20,7 +20,7 @@
}, },
"common": { "common": {
"about": "Ynghylch", "about": "Ynghylch",
"brand_help": "Cymorth %(brand)s", "brand_help": "%(brand)s Cymorth",
"help": "Cymorth", "help": "Cymorth",
"preferences": "Dewisiadau" "preferences": "Dewisiadau"
}, },
@ -40,18 +40,18 @@
"unhide": "Datguddio" "unhide": "Datguddio"
}, },
"right_click_menu": { "right_click_menu": {
"add_to_dictionary": "Ychwanegu at y geiriadur", "add_to_dictionary": "Ychwanegu i'r Geiriadur",
"copy_email": "Copïo cyfeiriad e-bost", "copy_email": "Copïo cyfeiriad e-bost",
"copy_image": "Copïo delwedd", "copy_image": "Copïo delwedd",
"copy_image_url": "Copïo cyfeiriad delwedd", "copy_image_url": "Copïo cyfeiriad delwedd",
"copy_link_url": "Copïo cyfeiriad y ddolen", "copy_link_url": "Copïo cyfeiriad y ddolen",
"save_image_as": "Cadw delwedd fel...", "save_image_as": "Cadw delwedd fel...",
"save_image_as_error_description": "Methodd cadw'r ddelwedd", "save_image_as_error_description": "Methodd y ddelwedd â chadw",
"save_image_as_error_title": "Methodd cadw'r ddelwedd" "save_image_as_error_title": "Wedi methu cadw'r ddelwedd"
}, },
"view_menu": { "view_menu": {
"actual_size": "Maint Gwirioneddol", "actual_size": "Maint Gwirioneddol",
"toggle_developer_tools": "Toglo Offer Datblygwyr", "toggle_developer_tools": "Toggle Developer Tools",
"toggle_full_screen": "Toglo Sgrin Lawn", "toggle_full_screen": "Toglo Sgrin Lawn",
"view": "Golwg" "view": "Golwg"
}, },

View File

@ -7,12 +7,12 @@ Please see LICENSE files in the repository root for full details.
import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron"; import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
import { relaunchApp } from "@standardnotes/electron-clear-data"; import { relaunchApp } from "@standardnotes/electron-clear-data";
import keytar from "keytar-forked";
import IpcMainEvent = Electron.IpcMainEvent; import IpcMainEvent = Electron.IpcMainEvent;
import { recordSSOSession } from "./protocol.js"; import { recordSSOSession } from "./protocol.js";
import { randomArray } from "./utils.js"; import { randomArray } from "./utils.js";
import { Settings } from "./settings.js"; import { Settings } from "./settings.js";
import { keytar } from "./keytar.js";
import { getDisplayMediaCallback, setDisplayMediaCallback } from "./displayMediaCallback.js"; import { getDisplayMediaCallback, setDisplayMediaCallback } from "./displayMediaCallback.js";
ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void { ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
@ -141,11 +141,11 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
case "getPickleKey": case "getPickleKey":
try { try {
ret = await keytar.getPassword("element.io", `${args[0]}|${args[1]}`); ret = await keytar?.getPassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be // migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im) // logins from the time of riot.im)
if (ret === null) { if (ret === null) {
ret = await keytar.getPassword("riot.im", `${args[0]}|${args[1]}`); ret = await keytar?.getPassword("riot.im", `${args[0]}|${args[1]}`);
} }
} catch { } catch {
// if an error is thrown (e.g. keytar can't connect to the keychain), // if an error is thrown (e.g. keytar can't connect to the keychain),
@ -161,18 +161,17 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
// rather than sending them a pickle key we did not store on their behalf. // rather than sending them a pickle key we did not store on their behalf.
await keytar!.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey); await keytar!.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
ret = pickleKey; ret = pickleKey;
} catch (e) { } catch {
console.error("Failed to create pickle key", e);
ret = null; ret = null;
} }
break; break;
case "destroyPickleKey": case "destroyPickleKey":
try { try {
await keytar.deletePassword("element.io", `${args[0]}|${args[1]}`); await keytar?.deletePassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be // migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im) // logins from the time of riot.im)
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`); await keytar?.deletePassword("riot.im", `${args[0]}|${args[1]}`);
} catch {} } catch {}
break; break;
case "getDesktopCapturerSources": case "getDesktopCapturerSources":

21
src/keytar.ts Normal file
View File

@ -0,0 +1,21 @@
/*
Copyright 2022-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type * as Keytar from "keytar"; // Hak dependency type
let keytar: typeof Keytar | undefined;
try {
({ default: keytar } = await import("keytar"));
} catch (e) {
if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
console.log("Keytar isn't installed; secure key storage is disabled.");
} else {
console.warn("Keytar unexpected error:", e);
}
}
export { keytar };

View File

@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
import { app, ipcMain } from "electron"; import { app, ipcMain } from "electron";
import { promises as afs } from "node:fs"; import { promises as afs } from "node:fs";
import path from "node:path"; import path from "node:path";
import keytar from "keytar-forked";
import type { import type {
Seshat as SeshatType, Seshat as SeshatType,
@ -17,6 +16,7 @@ import type {
} from "matrix-seshat"; // Hak dependency type } from "matrix-seshat"; // Hak dependency type
import IpcMainEvent = Electron.IpcMainEvent; import IpcMainEvent = Electron.IpcMainEvent;
import { randomArray } from "./utils.js"; import { randomArray } from "./utils.js";
import { keytar } from "./keytar.js";
let seshatSupported = false; let seshatSupported = false;
let Seshat: typeof SeshatType; let Seshat: typeof SeshatType;

1851
yarn.lock

File diff suppressed because it is too large Load Diff