# This workflow relies on actions/cache to store the hak dependency artifacts as they take a long time to build # Due to this extra care must be taken to only ever run all build_* scripts against the same branch to ensure # the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch. on: workflow_call: inputs: ref: type: string required: false description: "The git ref to checkout, defaults to the default branch" arch: type: string required: true description: "The architecture to build for, one of 'amd64' | 'arm64'" version: type: string required: false description: "Version string to override the one in package.json, used for non-release builds" sqlcipher: type: string required: true description: "How to link sqlcipher, one of 'system' | 'static'" blob_report: type: boolean required: false description: "Whether to run the blob report" prepare-artifact-name: type: string required: false description: | The name of the prepare artifact to use, defaults to 'webapp'. The artifact must contain the following: + webapp.asar - the asar archive of the webapp to embed in the desktop app + electronVersion - the version of electron to use for cache keying + hakHash - the hash of the .hak directory to use for cache keying + changelog.Debian - the changelog file to embed in the Debian package + variant.json - the variant configuration to use for the build The artifact can also contain any additional files which will be applied as overrides to the checkout root before building, for example icons in the `build/` directory to override the app icons. default: "webapp" test: type: boolean required: false default: true description: "Whether to run the test stage after building" test-args: type: string required: false description: "Additional arguments to pass to playwright" runs-on: type: string required: false description: "The runner image to use, normally set for you, may be needed for running in private repos." artifact-prefix: type: string required: false description: "An optional prefix to add to the artifact name, useful for distinguishing builds in private repos." default: "" targets: type: string required: false description: "List of targets to build" default: "tar.gz deb" env: SQLCIPHER_BUNDLED: ${{ inputs.sqlcipher == 'static' && '1' || '' }} MAX_GLIBC: 2.31 # bullseye-era glibc, used by glibc-check.sh permissions: {} # No permissions required jobs: build: name: Build Linux ${{ inputs.arch }} SQLCipher ${{ inputs.sqlcipher }} # We build on native infrastructure as matrix-seshat fails to cross-compile properly # https://github.com/matrix-org/seshat/issues/135 runs-on: ${{ inputs.runs-on || (inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04') }} env: HAK_DOCKER_IMAGE: ghcr.io/element-hq/element-desktop-dockerbuild steps: - name: Resolve docker image tag for push if: github.event_name == 'push' run: echo "HAK_DOCKER_IMAGE=$HAK_DOCKER_IMAGE:$REF" >> $GITHUB_ENV env: REF: ${{ inputs.ref || github.ref_name }} - name: Resolve docker image tag for release if: github.event_name == 'release' run: echo "HAK_DOCKER_IMAGE=$HAK_DOCKER_IMAGE:staging" >> $GITHUB_ENV - name: Resolve docker image tag for other triggers if: github.event_name != 'push' && github.event_name != 'release' run: echo "HAK_DOCKER_IMAGE=$HAK_DOCKER_IMAGE:develop" >> $GITHUB_ENV - uses: nbucic/variable-mapper@0673f6891a0619ba7c002ecfed0f9f4f39017b6f id: config with: key: "${{ inputs.arch }}" export_to: output map: | { "amd64": { "target": "x86_64-unknown-linux-gnu", "arch": "x86-64" }, "arm64": { "target": "aarch64-unknown-linux-gnu", "arch": "aarch64", "build-args": "--arm64" } } - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: repository: element-hq/element-desktop ref: ${{ inputs.ref }} - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 with: name: ${{ inputs.prepare-artifact-name }} - name: Cache .hak id: cache uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: key: ${{ runner.os }}-${{ github.ref_name }}-${{ inputs.sqlcipher }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion', 'dockerbuild/*') }} path: | ./.hak - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 with: node-version-file: .node-version cache: "yarn" env: # Workaround for https://github.com/actions/setup-node/issues/317 FORCE_COLOR: 0 - name: Install Deps run: "yarn install --frozen-lockfile" - name: "Get modified files" id: changed_files if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request' && github.repository == 'element-hq/element-desktop' uses: tj-actions/changed-files@823fcebdb31bb35fdf2229d9f769b400309430d0 # v46 with: files: | dockerbuild/** # This allows contributors to test changes to the dockerbuild image within a pull request - name: Build docker image uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 if: steps.changed_files.outputs.any_modified == 'true' with: file: dockerbuild/Dockerfile load: true platforms: linux/${{ inputs.arch }} tags: ${{ env.HAK_DOCKER_IMAGE }} - name: Build Natives if: steps.cache.outputs.cache-hit != 'true' run: | docker run \ -v ${{ github.workspace }}:/work -w /work \ -e SQLCIPHER_BUNDLED \ $HAK_DOCKER_IMAGE \ yarn build:native - name: Fix permissions on .hak run: sudo chown -R $USER:$USER .hak - name: Check native libraries in hak dependencies run: | shopt -s globstar for filename in ./.hak/hakModules/**/*.node; do ./scripts/glibc-check.sh $filename done - name: Generate debian files and arguments run: | if [ -f changelog.Debian ]; then echo "ED_DEBIAN_CHANGELOG=changelog.Debian" >> $GITHUB_ENV fi - name: Build App run: yarn build --publish never ${{ steps.config.outputs.build-args }} -l ${{ inputs.targets }} env: VARIANT_PATH: variant.json # Only set for Nightly builds VERSION: ${{ inputs.version }} # Workaround for https://github.com/electron-userland/electron-builder/issues/5721 USE_HARD_LINKS: false - name: Check native libraries run: | set -x shopt -s globstar FILES=$(file dist/**/*.node) echo $FILES ! echo "$FILES" | grep -v "$ARCH" LIBS=$(readelf -d dist/**/*.node | grep NEEDED) echo "$LIBS" set +x assert_contains_string() { [[ "$1" == *"$2"* ]]; } ! assert_contains_string "$LIBS" "libcrypto.so.1.1" if [ "$SQLCIPHER_BUNDLED" == "1" ]; then ! assert_contains_string "$LIBS" "libsqlcipher.so.0" else assert_contains_string "$LIBS" "libsqlcipher.so.0" fi ./scripts/glibc-check.sh dist/linux-*unpacked/element-desktop* env: ARCH: ${{ steps.config.outputs.arch }} # We exclude *-unpacked as it loses permissions and the tarball contains it with correct permissions - name: Upload Artifacts uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: ${{ inputs.artifact-prefix }}linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }} path: | dist !dist/*-unpacked/** retention-days: 1 - name: Assert deb is present and valid if: contains(inputs.targets, 'deb') run: | test -f ./dist/element-desktop*$ARCH.deb DEB_LISTING=$(dpkg-deb --fsys-tarfile ./dist/element-desktop*.deb | tar -tv) echo "deb listing: " echo "$DEB_LISTING" ! echo "$DEB_LISTING" | grep '^h' env: ARCH: ${{ inputs.arch }} - name: Assert tar.gz is present if: contains(inputs.targets, 'tar.gz') run: | test -f ./dist/element-desktop*.tar.gz TAR_GZ_LISTING=$(tar -tvf ./dist/element-desktop*.tar.gz) echo "tar.gz listing: " echo "$TAR_GZ_LISTING" ! echo "$TAR_GZ_LISTING" | grep '^h' test: name: Test Linux ${{ inputs.arch }} SQLCipher ${{ inputs.sqlcipher }} needs: build if: inputs.test && contains(inputs.targets, 'deb') uses: ./.github/workflows/build_test.yaml with: project: linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }} artifact: ${{ inputs.artifact-prefix }}linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }} runs-on: ${{ inputs.runs-on || (inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04') }} executable: /opt/Element*/element-desktop* prepare_cmd: | sudo apt-get -qq update sudo apt install ./dist/*.deb blob_report: ${{ inputs.blob_report }} args: ${{ inputs.test-args }}