Files
simplex-chat/.github/workflows/build.yml
T

1406 lines
57 KiB
YAML

name: build
on:
push:
branches:
- master
- stable
tags:
- "v*"
- "!*-fdroid"
- "!*-armv7a"
pull_request:
paths:
- "src/**"
- "apps/simplex-chat/**"
- "apps/simplex-bot/**"
- "apps/simplex-bot-advanced/**"
- "apps/simplex-badge-service/**"
- "apps/simplex-broadcast-bot/**"
- "apps/simplex-directory-service/**"
- "tests/**"
- "bots/src/**"
- "simplex-chat.cabal"
- "cabal.project"
- "Dockerfile*"
- "scripts/ci/**"
- "scripts/desktop/**"
- ".github/**"
env:
opt: ${{ github.event_name == 'pull_request' && 'O0' || 'O2' }}
ghc_options: ${{ github.event_name == 'pull_request' && '--ghc-options=-O0' || '' }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}
branch: ${{ github.base_ref || github.ref_name }}
cache_o0: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/stable') }}
ZSTD_CLEVEL: 9
# This workflow uses custom actions (prepare-build and prepare-release) defined in:
#
# .github/actions/
# ├── prepare-build
# │ └── action.yml
# └── prepare-release
# └── action.yml
# Important!
# Do not use always(), it makes build unskippable.
# See: https://github.com/actions/runner/issues/1846#issuecomment-1246102753
jobs:
# =============================
# Global variables
# =============================
# That is the only and less hacky way to setup global variables
# to use in strategy matrix (env:/YAML anchors doesn't work).
# See: https://github.com/orgs/community/discussions/56787#discussioncomment-6041789
# https://github.com/actions/runner/issues/1182
# https://stackoverflow.com/a/77549656
variables:
runs-on: ubuntu-latest
outputs:
GHC_VER: 9.6.3
JAVA_VER: 17
steps:
- name: Dummy job when we have just simple variables
if: false
run: echo
# =============================
# Create release
# =============================
# Create release, but only if it's triggered by tag push.
# Create simplex-chat-libs release core-<version>, but only if the head commit of a push to master or stable changes the version in simplex-chat.cabal.
# On pull requests and other pushes, this job will always complete.
# Secrets:
# -------
# NODEJS_REPO_TOKEN
# Only select repositories: simplex-chat-libs
# Permissions:
# * Contents (Read and Write)
maybe-release:
runs-on: ubuntu-latest
outputs:
libs_tag: ${{ steps.libs_commit.outputs.tag }}
core_changed: ${{ steps.core.outputs.core }}
steps:
- name: Clone project
if: github.event_name == 'push' || github.event_name == 'pull_request'
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Check chat core change
id: core
if: github.event_name == 'pull_request'
env:
BASE: ${{ github.event.pull_request.base.sha }}
run: |
git fetch -q --depth=1 origin "$BASE"
python3 scripts/ci/packages_release.py changes "$BASE" | grep '^core=' >> "$GITHUB_OUTPUT"
- name: Build changelog
id: build_changelog
if: startsWith(github.ref, 'refs/tags/v')
uses: simplex-chat/release-changelog-builder-action@v5
with:
configuration: .github/changelog_conf.json
failOnError: true
ignorePreReleases: true
commitMode: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
if: startsWith(github.ref, 'refs/tags/v')
uses: simplex-chat/action-gh-release@v2
with:
body: ${{ steps.build_changelog.outputs.changelog }}
prerelease: true
files: |
LICENSE
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check version change
id: check_version
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/stable'
shell: bash
run: |
version=$(sed -n 's/^version: *//p' simplex-chat.cabal)
prev_version=$(git show HEAD^1:simplex-chat.cabal | sed -n 's/^version: *//p')
if [ "$version" != "$prev_version" ]; then
echo "version=$version" >> $GITHUB_OUTPUT
fi
- name: Record libs release
id: libs_commit
if: steps.check_version.outputs.version
env:
GH_TOKEN: ${{ secrets.NODEJS_REPO_TOKEN }}
LIBS_REPOSITORY: ${{ github.repository }}-libs
VERSION: ${{ steps.check_version.outputs.version }}
run: |
commit=$(python3 scripts/ci/packages_release.py record --core "$VERSION" --commit "$GITHUB_SHA")
echo "tag=core-$VERSION" >> "$GITHUB_OUTPUT"
echo "commit=$commit" >> "$GITHUB_OUTPUT"
# creates the tag on the commit that recorded the release
- name: Create libs release
if: steps.check_version.outputs.version
uses: softprops/action-gh-release@v2
with:
repository: ${{ github.repository }}-libs
tag_name: ${{ steps.libs_commit.outputs.tag }}
target_commitish: ${{ steps.libs_commit.outputs.commit }}
token: ${{ secrets.NODEJS_REPO_TOKEN }}
# =========================
# Linux Build
# =========================
build-linux:
name: "ubuntu-${{ matrix.os }}-${{ matrix.arch }} (CLI,Desktop), GHC: ${{ matrix.ghc }}"
needs: [maybe-release, variables]
runs-on: ${{ matrix.runner }}
permissions:
contents: write
packages: write
env:
image_cache: ghcr.io/simplex-chat/simplex-chat-build-cache:${{ matrix.os }}-${{ matrix.arch }}-ghc${{ matrix.ghc }}
source_hashes: dist-newstyle/sources.sha256
concurrency: &linux-concurrency
group: ${{ github.workflow }}-${{ github.ref }}-linux-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.ghc }}-${{ needs.maybe-release.outputs.libs_tag }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
strategy:
fail-fast: false
matrix:
include:
- os: 22.04
os_underscore: 22_04
arch: x86_64
runner: "ubuntu-22.04"
ghc: "8.10.7"
hash: 'sha256:5c8b2c0a6c745bc177669abfaa716b4bc57d58e2ea3882fb5da67f4d59e3dda5'
should_run: ${{ !(github.ref == 'refs/heads/stable' || startsWith(github.ref, 'refs/tags/v')) }}
- os: 22.04
os_underscore: 22_04
arch: x86_64
runner: "ubuntu-22.04"
should_run: true
ghc: ${{ needs.variables.outputs.GHC_VER }}
hash: 'sha256:5c8b2c0a6c745bc177669abfaa716b4bc57d58e2ea3882fb5da67f4d59e3dda5'
libs: true
- os: 24.04
os_underscore: 24_04
arch: x86_64
runner: "ubuntu-24.04"
should_run: true
ghc: ${{ needs.variables.outputs.GHC_VER }}
hash: 'sha256:98ff7968124952e719a8a69bb3cccdd217f5fe758108ac4f21ad22e1df44d237'
steps: &linux-steps
- name: Checkout Code
if: matrix.should_run == true
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup swap
if: matrix.ghc == '8.10.7' && matrix.should_run == true
uses: ./.github/actions/swap
with:
swap-size-gb: 30
- name: Get UID and GID
id: ids
run: |
echo "uid=$(id -u)" >> $GITHUB_OUTPUT
echo "gid=$(id -g)" >> $GITHUB_OUTPUT
# Otherwise we run out of disk space with Docker build
- name: Free disk space
if: matrix.should_run == true
shell: bash
run: ./scripts/ci/linux_util_free_space.sh
- name: Set up Docker Buildx
if: matrix.should_run == true
uses: simplex-chat/docker-setup-buildx-action@v3
- name: Log in to GitHub Container Registry
if: matrix.should_run == true && env.release != 'true'
shell: bash
env:
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: echo "$GHCR_TOKEN" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
- name: Compute image cache week
id: week
if: matrix.should_run == true && env.release != 'true'
run: echo "week=$(date -u +%G-W%V)" >> "$GITHUB_OUTPUT"
- name: Build and cache Docker image
if: matrix.should_run == true
uses: simplex-chat/docker-build-push-action@v6
with:
context: .
load: true
file: Dockerfile.build
tags: build/${{ matrix.os }}:latest
build-args: |
TAG=${{ matrix.os }}
HASH=${{ matrix.hash }}
GHC=${{ matrix.ghc }}
USER_UID=${{ steps.ids.outputs.uid }}
USER_GID=${{ steps.ids.outputs.gid }}
cache-from: ${{ env.release != 'true' && format('type=registry,ref={0}-{1}', env.image_cache, steps.week.outputs.week) || '' }}
cache-to: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && format('type=registry,ref={0}-{1},mode=max,ignore-error=true', env.image_cache, steps.week.outputs.week) || '' }}
# Docker needs these flags for AppImage build:
# --device /dev/fuse
# --cap-add SYS_ADMIN
# --security-opt apparmor:unconfined
- name: Start container
if: matrix.should_run == true
shell: bash
run: |
mkdir -p ~/.cabal
docker run -t -d \
--device /dev/fuse \
--cap-add SYS_ADMIN \
--security-opt apparmor:unconfined \
--name builder \
-e CABAL_DIR=/home/builder/.cabal \
-v ~/.cabal:/home/builder/.cabal \
-v /home/runner/work/_temp:/home/runner/work/_temp \
-v ${{ github.workspace }}:/project \
build/${{ matrix.os }}:latest
- name: Compute cache key prefixes
id: keys
if: matrix.should_run == true && env.release != 'true'
run: |
toolchain=$(docker exec builder dpkg-query -W -f '${db:Status-Status} ${binary:Package} ${Version}\n' 'binutils*' 'cpp*' 'gcc*' '*-dev' | grep '^installed ' | sha256sum | cut -c1-16)
target=ubuntu-${{ matrix.os }}-${{ matrix.arch }}-ghc${{ matrix.ghc }}-$toolchain
echo "deps=deps-$target" >> "$GITHUB_OUTPUT"
echo "dist=dist-$target" >> "$GITHUB_OUTPUT"
echo "dist_lib=dist-lib-$target" >> "$GITHUB_OUTPUT"
- name: Restore dependencies from cache
id: restore-deps
if: matrix.should_run == true && env.release != 'true'
uses: actions/cache/restore@v4
with:
path: ~/.cabal/store
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.deps }}-${{ env.branch }}-
${{ steps.keys.outputs.deps }}-
- name: Warn if dependencies not in cache
if: matrix.should_run == true && env.release != 'true' && steps.restore-deps.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.deps }}-${{ env.branch }}"
- name: Restore source repositories from cache
id: restore-src
if: matrix.should_run == true && env.release != 'true'
uses: actions/cache/restore@v4
with:
path: dist-newstyle/src
key: src-${{ runner.os }}-${{ hashFiles('cabal.project') }}
restore-keys: src-${{ runner.os }}-
- name: Warn if source repositories not in cache
if: matrix.should_run == true && env.release != 'true' && steps.restore-src.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::src-${{ runner.os }}"
- name: Restore build directory from cache
id: restore-build
if: matrix.should_run == true && env.release != 'true'
uses: actions/cache/restore@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-
${{ steps.keys.outputs.dist }}-${{ env.opt }}-
- name: Warn if build directory not in cache
if: matrix.should_run == true && env.release != 'true' && steps.restore-build.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}"
- name: Restore library build directory from cache
id: restore-build-lib
if: env.release != 'true' && matrix.libs && needs.maybe-release.outputs.core_changed && matrix.arch == 'x86_64'
uses: actions/cache/restore@v4
with:
path: |
dist-lib/*
!dist-lib/src
key: ${{ steps.keys.outputs.dist_lib }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist_lib }}-${{ env.branch }}-
${{ steps.keys.outputs.dist_lib }}-
- name: Warn if library build directory not in cache
if: steps.restore-build-lib.outcome == 'success' && steps.restore-build-lib.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.dist_lib }}-${{ env.branch }}"
- name: Set old timestamps on unchanged sources (GHC 8.10.7)
if: matrix.ghc == '8.10.7' && steps.restore-build.outputs.cache-matched-key != '' && hashFiles(env.source_hashes) != ''
run: scripts/ci/source-timestamps.sh restore ${{ env.source_hashes }}
- name: Prepare cabal.project.local
if: matrix.should_run == true
shell: bash
run: |
echo "ignore-project: False" >> cabal.project.local
echo "package direct-sqlcipher" >> cabal.project.local
echo " flags: +openssl" >> cabal.project.local
- name: Build CLI
id: build-cli
if: matrix.should_run == true
shell: docker exec -t builder sh -eu {0}
run: |
scripts/ci/prune-old-builds.sh dist-newstyle
cabal update
cabal build -j --enable-tests ${{ env.ghc_options }}
mkdir -p /out
for i in simplex-chat simplex-chat-test; do
bin=$(find /project/dist-newstyle -name "$i" -type f -executable)
chmod +x "$bin"
cp "$bin" /out/
done
strip /out/simplex-chat
# Also for pull requests that change the chat core, for the package tests.
- name: Build library
id: build-lib
if: matrix.libs && (needs.maybe-release.outputs.libs_tag || (needs.maybe-release.outputs.core_changed && matrix.arch == 'x86_64'))
shell: docker exec -t builder sh -eu {0}
run: |
scripts/ci/prune-old-builds.sh dist-lib
mkdir -p dist-lib
rm -rf dist-lib/src
ln -s ../dist-newstyle/src dist-lib/src
DIST_DIR=dist-lib SKIP_VLC=1 scripts/desktop/build-lib-linux.sh
name=simplex-chat-libs-linux-${{ matrix.arch }}
mkdir -p release-libs/$name/libs
find apps/multiplatform/common/src/commonMain/cpp/desktop/libs/linux-${{ matrix.arch }} -maxdepth 1 -type f -exec cp {} release-libs/$name/libs/ \;
(cd release-libs/$name && zip -r ../$name.zip libs)
- name: Record source hashes (GHC 8.10.7)
if: matrix.should_run == true && matrix.ghc == '8.10.7'
shell: docker exec -t builder sh -eu {0}
run: scripts/ci/source-timestamps.sh record ${{ env.source_hashes }}
- name: Compute dependency cache key
id: hash-deps
if: matrix.should_run == true && env.release != 'true'
shell: bash
run: echo "hash=$(ls ~/.cabal/store/ghc-*/ | sha256sum | cut -c1-16)" >> "$GITHUB_OUTPUT"
- name: Save dependencies to cache
if: matrix.should_run == true && env.release != 'true' && steps.restore-deps.outputs.cache-matched-key != format('{0}-{1}-{2}', steps.keys.outputs.deps, env.branch, steps.hash-deps.outputs.hash)
uses: actions/cache/save@v4
with:
path: ~/.cabal/store
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ steps.hash-deps.outputs.hash }}
- name: Save source repositories to cache
if: matrix.should_run == true && env.release != 'true' && matrix.libs && matrix.arch == 'x86_64' && steps.restore-src.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: dist-newstyle/src
key: src-${{ runner.os }}-${{ hashFiles('cabal.project') }}
- name: Save build directory to cache
if: matrix.should_run == true && env.release != 'true' && steps.restore-build.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-${{ github.sha }}
- name: Save library build directory to cache
if: steps.build-lib.outcome == 'success' && env.release != 'true' && steps.restore-build-lib.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
dist-lib/*
!dist-lib/src
key: ${{ steps.keys.outputs.dist_lib }}-${{ env.branch }}-${{ github.sha }}
- name: Upload library
if: needs.maybe-release.outputs.libs_tag && matrix.libs
uses: softprops/action-gh-release@v2
with:
repository: ${{ github.repository }}-libs
tag_name: ${{ needs.maybe-release.outputs.libs_tag }}
files: release-libs/*.zip
token: ${{ secrets.NODEJS_REPO_TOKEN }}
- name: Build CLI deb
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
shell: docker exec -t builder sh -eu {0}
run: |
version=${{ github.ref }}
version=${version#refs/tags/v}
version=${version%-*}
./scripts/desktop/build-cli-deb.sh "$version"
- name: Copy tests from container
if: matrix.should_run == true
shell: bash
run: |
docker cp builder:/out/simplex-chat-test .
- name: Copy CLI from container and prepare it
id: linux_cli_prepare
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
shell: bash
run: |
cli_name="simplex-chat-ubuntu-${{ matrix.os_underscore }}-${{ matrix.arch }}"
cli_deb_name="${cli_name}.deb"
cli_path="${{ github.workspace }}"
docker cp builder:/out/simplex-chat "./${cli_name}"
docker cp builder:/out/deb-build/simplex-chat.deb "./${cli_deb_name}"
echo "bin_name=${cli_name}" >> $GITHUB_OUTPUT
echo "bin_path=${cli_path}/${cli_name}" >> $GITHUB_OUTPUT
echo "bin_hash=$(echo SHA2-256\(${cli_name}\)= $(openssl sha256 "${cli_path}/${cli_name}" | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
echo "deb_name=${cli_deb_name}" >> $GITHUB_OUTPUT
echo "deb_path=${cli_path}/${cli_deb_name}" >> $GITHUB_OUTPUT
echo "deb_hash=$(echo SHA2-256\(${cli_deb_name}\)= $(openssl sha256 "${cli_path}/${cli_deb_name}" | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Upload CLI
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
uses: ./.github/actions/prepare-release
with:
bin_name: ${{ steps.linux_cli_prepare.outputs.bin_name }}
bin_path: ${{ steps.linux_cli_prepare.outputs.bin_path }}
bin_hash: ${{ steps.linux_cli_prepare.outputs.bin_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload CLI deb
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
uses: ./.github/actions/prepare-release
with:
bin_name: ${{ steps.linux_cli_prepare.outputs.deb_name }}
bin_path: ${{ steps.linux_cli_prepare.outputs.deb_path }}
bin_hash: ${{ steps.linux_cli_prepare.outputs.deb_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Desktop
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
shell: docker exec -t builder sh -eu {0}
run: |
export ASSETS_DIR='../../assets'
scripts/desktop/make-deb-linux.sh
- name: Prepare Desktop
id: linux_desktop_build
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
shell: bash
run: |
path=$(echo ${{ github.workspace }}/apps/multiplatform/release/main/deb/simplex_${{ matrix.arch }}.deb )
echo "package_path=$path" >> $GITHUB_OUTPUT
echo "package_hash=$(echo SHA2-256\(simplex-desktop-ubuntu-${{ matrix.os_underscore }}-${{ matrix.arch }}.deb\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Upload Desktop
uses: ./.github/actions/prepare-release
if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true
with:
bin_path: ${{ steps.linux_desktop_build.outputs.package_path }}
bin_name: simplex-desktop-ubuntu-${{ matrix.os_underscore }}-${{ matrix.arch }}.deb
bin_hash: ${{ steps.linux_desktop_build.outputs.package_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Build AppImage
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == '22.04' && matrix.should_run == true
shell: docker exec -t builder sh -eu {0}
run: |
export ASSETS_DIR='../../assets'
scripts/desktop/make-appimage-linux.sh
- name: Prepare AppImage
id: linux_appimage_build
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == '22.04' && matrix.should_run == true
shell: bash
run: |
path=$(echo ${{ github.workspace }}/apps/multiplatform/release/main/*imple*.AppImage)
echo "appimage_path=$path" >> $GITHUB_OUTPUT
echo "appimage_hash=$(echo SHA2-256\(simplex-desktop-${{ matrix.arch }}.AppImage\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Upload AppImage
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == '22.04' && matrix.should_run == true
uses: ./.github/actions/prepare-release
with:
bin_path: ${{ steps.linux_appimage_build.outputs.appimage_path }}
bin_name: "simplex-desktop-${{ matrix.arch }}.AppImage"
bin_hash: ${{ steps.linux_appimage_build.outputs.appimage_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Mount RAM disk for tests
if: matrix.should_run == true && matrix.arch == 'x86_64'
shell: bash
run: |
mkdir -p tests/tmp
sudo mount -t tmpfs -o size=512M tmpfs tests/tmp
sudo chown $(id -u):$(id -g) tests/tmp
- name: Run tests
if: matrix.should_run == true && matrix.arch == 'x86_64'
timeout-minutes: 120
shell: bash
run: |
i=1
attempts=1
${{ (github.ref == 'refs/heads/stable' || startsWith(github.ref, 'refs/tags/v')) }} && attempts=3
while [ "$i" -le "$attempts" ]; do
if ./simplex-chat-test; then
break
else
echo "Attempt $i failed, retrying..."
i=$((i + 1))
sleep 1
fi
done
if [ "$i" -gt "$attempts" ]; then
echo "All "$attempts" attempts failed."
exit 1
fi
- name: Setup Node.js
id: setup-node
if: ${{ !cancelled() && needs.maybe-release.outputs.core_changed && steps.build-lib.outcome == 'success' }}
uses: actions/setup-node@v7
with:
node-version: 22
- name: Setup Python
id: setup-python
if: ${{ !cancelled() && steps.setup-node.outcome == 'success' }}
uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Build simplex-chat (npm) and add-on
id: build-nodejs
if: ${{ !cancelled() && steps.setup-python.outcome == 'success' }}
shell: bash
working-directory: packages/simplex-chat-nodejs
run: |
(cd ../simplex-chat-client/types/typescript && npm install --no-audit --no-fund && npx tsc)
npm install --ignore-scripts --no-save --no-audit --no-fund ../simplex-chat-client/types/typescript
npx --yes node-gyp rebuild
npx tsc && cp src/simplex.* dist
- name: Test simplex-chat (npm)
id: test-nodejs
if: ${{ !cancelled() && steps.build-nodejs.outcome == 'success' }}
timeout-minutes: 30
shell: bash
working-directory: packages/simplex-chat-nodejs
env:
SIMPLEX_LIBS_DIR: ${{ github.workspace }}/release-libs/simplex-chat-libs-linux-${{ matrix.arch }}/libs
run: npx jest --forceExit --testNamePattern '^(?!.*use preset servers)'
- name: Test simplex-chat (PyPI)
if: ${{ !cancelled() && steps.test-nodejs.outcome == 'success' }}
timeout-minutes: 30
shell: bash
working-directory: packages/simplex-chat-python
run: |
python -m pip install -e ".[test]"
python -m pytest -q
- name: Remove -O2 build directory
id: remove-o2
if: env.cache_o0 == 'true' && !cancelled() && steps.build-cli.outcome == 'success'
shell: docker exec -t builder sh -eu {0}
run: find dist-newstyle -mindepth 1 -maxdepth 1 ! -name src -exec rm -rf {} +
- name: Restore -O0 build directory from cache
id: restore-build-o0
if: ${{ !cancelled() && steps.remove-o2.outcome == 'success' }}
uses: actions/cache/restore@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-
${{ steps.keys.outputs.dist }}-O0-
- name: Set old timestamps on unchanged sources for -O0 build (GHC 8.10.7)
if: ${{ !cancelled() && matrix.ghc == '8.10.7' && steps.restore-build-o0.outputs.cache-matched-key != '' && hashFiles(env.source_hashes) != '' }}
run: scripts/ci/source-timestamps.sh restore ${{ env.source_hashes }}
- name: Build at -O0 for pull request caches
id: build-o0
if: ${{ !cancelled() && steps.remove-o2.outcome == 'success' }}
shell: docker exec -t builder sh -eu {0}
run: |
scripts/ci/prune-old-builds.sh dist-newstyle
cabal build -j --enable-tests --ghc-options=-O0
- name: Record source hashes for -O0 build (GHC 8.10.7)
if: ${{ !cancelled() && matrix.ghc == '8.10.7' && steps.build-o0.outcome == 'success' }}
shell: docker exec -t builder sh -eu {0}
run: scripts/ci/source-timestamps.sh record ${{ env.source_hashes }}
- name: Save -O0 build directory to cache
if: ${{ !cancelled() && steps.build-o0.outcome == 'success' && steps.restore-build-o0.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-${{ github.sha }}
build-linux-push:
name: "ubuntu-${{ matrix.os }}-${{ matrix.arch }} (CLI,Desktop), GHC: ${{ matrix.ghc }}"
needs: [maybe-release, variables]
if: github.event_name != 'pull_request'
runs-on: ${{ matrix.runner }}
permissions:
contents: write
packages: write
env:
image_cache: ghcr.io/simplex-chat/simplex-chat-build-cache:${{ matrix.os }}-${{ matrix.arch }}-ghc${{ matrix.ghc }}
source_hashes: dist-newstyle/sources.sha256
cache_o0: false
concurrency: *linux-concurrency
strategy:
fail-fast: false
matrix:
include:
- os: 22.04
os_underscore: 22_04
arch: aarch64
runner: "ubuntu-22.04-arm"
should_run: true
ghc: ${{ needs.variables.outputs.GHC_VER }}
hash: 'sha256:6a62a4157b8775eaf4959cb629e757d32d39d1f4c8ac1b0ddc2510b555cf72f3'
libs: true
- os: 24.04
os_underscore: 24_04
arch: aarch64
runner: "ubuntu-24.04-arm"
should_run: true
ghc: ${{ needs.variables.outputs.GHC_VER }}
hash: 'sha256:68434214381cb38287104e629fe8ee720167dd98cbb36ab1cbbab342515fa6ab'
steps: *linux-steps
# =================================
# Linux PostgreSQL Library Build
# =================================
build-linux-postgres:
name: "ubuntu-22.04-x86_64 (Postgres lib), GHC: ${{ needs.variables.outputs.GHC_VER }}"
needs: [maybe-release, variables]
runs-on: ubuntu-22.04
if: needs.maybe-release.outputs.libs_tag
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Get UID and GID
id: ids
run: |
echo "uid=$(id -u)" >> $GITHUB_OUTPUT
echo "gid=$(id -g)" >> $GITHUB_OUTPUT
- name: Free disk space
shell: bash
run: ./scripts/ci/linux_util_free_space.sh
- name: Set up Docker Buildx
uses: simplex-chat/docker-setup-buildx-action@v3
- name: Build and cache Docker image
uses: simplex-chat/docker-build-push-action@v6
with:
context: .
load: true
file: Dockerfile.build
tags: build/22.04:latest
build-args: |
TAG=22.04
HASH=sha256:5c8b2c0a6c745bc177669abfaa716b4bc57d58e2ea3882fb5da67f4d59e3dda5
GHC=${{ needs.variables.outputs.GHC_VER }}
USER_UID=${{ steps.ids.outputs.uid }}
USER_GID=${{ steps.ids.outputs.gid }}
- name: Start container
shell: bash
run: |
mkdir -p ~/.cabal
docker run -t -d \
--name builder \
-e CABAL_DIR=/home/builder/.cabal \
-v ~/.cabal:/home/builder/.cabal \
-v /home/runner/work/_temp:/home/runner/work/_temp \
-v ${{ github.workspace }}:/project \
build/22.04:latest
- name: Compute cache key prefix
id: keys
run: |
toolchain=$(docker exec builder dpkg-query -W -f '${db:Status-Status} ${binary:Package} ${Version}\n' 'binutils*' 'cpp*' 'gcc*' '*-dev' | grep '^installed ' | sha256sum | cut -c1-16)
echo "deps=deps-ubuntu-22.04-x86_64-postgres-ghc${{ needs.variables.outputs.GHC_VER }}-$toolchain" >> "$GITHUB_OUTPUT"
- name: Restore dependencies from cache
id: restore-deps
uses: actions/cache/restore@v4
with:
path: ~/.cabal/store
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.deps }}-${{ env.branch }}-
${{ steps.keys.outputs.deps }}-
- name: Warn if dependencies not in cache
if: steps.restore-deps.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.deps }}-${{ env.branch }}"
- name: Prepare cabal.project.local
shell: bash
run: |
echo "ignore-project: False" >> cabal.project.local
echo "package direct-sqlcipher" >> cabal.project.local
echo " flags: +openssl" >> cabal.project.local
- name: Build postgres library
shell: docker exec -t builder sh -eu {0}
run: |
cabal update
scripts/desktop/build-lib-linux.sh postgres
- name: Compute dependency cache key
id: hash-deps
shell: bash
run: echo "hash=$(ls ~/.cabal/store/ghc-*/ | sha256sum | cut -c1-16)" >> "$GITHUB_OUTPUT"
- name: Save dependencies to cache
if: steps.restore-deps.outputs.cache-matched-key != format('{0}-{1}-{2}', steps.keys.outputs.deps, env.branch, steps.hash-deps.outputs.hash)
uses: actions/cache/save@v4
with:
path: ~/.cabal/store
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ steps.hash-deps.outputs.hash }}
- name: Copy libs from container
shell: bash
run: |
ARCH=x86_64
GHC_VER=${{ needs.variables.outputs.GHC_VER }}
BUILD_DIR=$(echo dist-newstyle/build/${ARCH}-linux/ghc-${GHC_VER}/simplex-chat-*)
mkdir -p postgres-libs/libs
cp ${BUILD_DIR}/build/libsimplex.so postgres-libs/libs/
cp ${BUILD_DIR}/build/deps/* postgres-libs/libs/
(cd postgres-libs && zip -r simplex-chat-libs-linux-x86_64-postgres.zip libs)
- name: Upload postgres library
uses: softprops/action-gh-release@v2
with:
repository: ${{ github.repository }}-libs
tag_name: ${{ needs.maybe-release.outputs.libs_tag }}
files: postgres-libs/*.zip
token: ${{ secrets.NODEJS_REPO_TOKEN }}
# =========================
# MacOS Build
# =========================
build-macos:
name: "${{ matrix.os }} (CLI,Desktop), GHC: ${{ matrix.ghc }}"
needs: [maybe-release, variables]
runs-on: ${{ matrix.os }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-macos-${{ matrix.os }}-${{ needs.maybe-release.outputs.libs_tag }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
arch: aarch64
ghc: ${{ needs.variables.outputs.GHC_VER }}
cli_asset_name: simplex-chat-macos-aarch64
desktop_asset_name: simplex-desktop-macos-aarch64.dmg
openssl_dir: "/opt/homebrew/opt"
- os: macos-15-intel
arch: x86_64
ghc: ${{ needs.variables.outputs.GHC_VER }}
cli_asset_name: simplex-chat-macos-x86-64
desktop_asset_name: simplex-desktop-macos-x86_64.dmg
openssl_dir: "/usr/local/opt"
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Point Command Line Tools SDK to Xcode SDK
shell: bash
run: sudo ln -sfn "$(xcrun --sdk macosx --show-sdk-path)" /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
- name: Compute toolchain cache key
id: toolchain-key
if: env.release != 'true'
shell: bash
run: echo "key=ghcup-${{ matrix.os }}-${{ matrix.arch }}-ghc${{ matrix.ghc }}-cabal3.10.2.0-$({ sw_vers -productVersion; clang --version; } | shasum -a 256 | cut -c1-16)" >> "$GITHUB_OUTPUT"
- name: Restore toolchain from cache
id: restore-toolchain
if: env.release != 'true'
uses: actions/cache/restore@v4
with:
path: |
~/.ghcup/ghc/${{ matrix.ghc }}
~/.ghcup/bin/*-${{ matrix.ghc }}
~/.ghcup/bin/cabal-3.10.2.0
key: ${{ steps.toolchain-key.outputs.key }}
- name: Warn if toolchain not in cache
if: env.release != 'true' && steps.restore-toolchain.outputs.cache-hit != 'true'
run: echo "::warning title=Cache miss::${{ steps.toolchain-key.outputs.key }}"
- name: Prepare build
id: prepare
uses: ./.github/actions/prepare-build
with:
java_ver: ${{ needs.variables.outputs.JAVA_VER }}
ghc_ver: ${{ matrix.ghc }}
github_ref: ${{ github.ref }}
- name: Save toolchain to cache
if: env.release != 'true' && steps.restore-toolchain.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
~/.ghcup/ghc/${{ matrix.ghc }}
~/.ghcup/bin/*-${{ matrix.ghc }}
~/.ghcup/bin/cabal-3.10.2.0
key: ${{ steps.toolchain-key.outputs.key }}
- name: Install OpenSSL
run: brew install openssl@3.0
- name: Prepare cabal.project.local
shell: bash
run: |
echo "ignore-project: False" >> cabal.project.local
echo "package simplexmq" >> cabal.project.local
echo " extra-include-dirs: ${{ matrix.openssl_dir }}/openssl@3.0/include" >> cabal.project.local
echo " extra-lib-dirs: ${{ matrix.openssl_dir}}/openssl@3.0/lib" >> cabal.project.local
echo "" >> cabal.project.local
echo "package direct-sqlcipher" >> cabal.project.local
echo " extra-include-dirs: ${{ matrix.openssl_dir }}/openssl@3.0/include" >> cabal.project.local
echo " extra-lib-dirs: ${{ matrix.openssl_dir }}/openssl@3.0/lib" >> cabal.project.local
echo " flags: +openssl" >> cabal.project.local
- name: Compute cache key prefixes
id: keys
if: env.release != 'true'
shell: bash
run: |
toolchain=$({ sw_vers -productVersion; clang --version; } | shasum -a 256 | cut -c1-16)
target=${{ matrix.os }}-${{ matrix.arch }}-ghc${{ matrix.ghc }}-$toolchain
echo "deps=deps-$target" >> "$GITHUB_OUTPUT"
echo "dist=dist-$target" >> "$GITHUB_OUTPUT"
- name: Restore dependencies from cache
id: restore-deps
if: env.release != 'true'
uses: actions/cache/restore@v4
with:
path: ${{ steps.prepare.outputs.cabal-store }}
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.deps }}-${{ env.branch }}-
${{ steps.keys.outputs.deps }}-
- name: Warn if dependencies not in cache
if: env.release != 'true' && steps.restore-deps.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.deps }}-${{ env.branch }}"
- name: Restore source repositories from cache
id: restore-src
if: env.release != 'true'
uses: actions/cache/restore@v4
with:
path: dist-newstyle/src
key: src-${{ runner.os }}-${{ hashFiles('cabal.project') }}
restore-keys: src-${{ runner.os }}-
- name: Warn if source repositories not in cache
if: env.release != 'true' && steps.restore-src.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::src-${{ runner.os }}"
- name: Restore build directory from cache
id: restore-build
if: env.release != 'true' && !needs.maybe-release.outputs.libs_tag
uses: actions/cache/restore@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-
${{ steps.keys.outputs.dist }}-${{ env.opt }}-
- name: Warn if build directory not in cache
if: steps.restore-build.outcome == 'success' && steps.restore-build.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}"
- name: Build CLI
id: mac_cli_build
shell: bash
run: |
scripts/ci/prune-old-builds.sh dist-newstyle
cabal build -j --enable-tests ${{ env.ghc_options }}
path=$(cabal list-bin simplex-chat | tail -n 1)
echo "bin_path=$path" >> $GITHUB_OUTPUT
echo "bin_hash=$(echo SHA2-256\(${{ matrix.cli_asset_name }}\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Compute dependency cache key
id: hash-deps
if: env.release != 'true'
shell: bash
run: echo "hash=$(ls '${{ steps.prepare.outputs.cabal-store }}'/ghc-*/ | shasum -a 256 | cut -c1-16)" >> "$GITHUB_OUTPUT"
- name: Save dependencies to cache
if: env.release != 'true' && steps.restore-deps.outputs.cache-matched-key != format('{0}-{1}-{2}', steps.keys.outputs.deps, env.branch, steps.hash-deps.outputs.hash)
uses: actions/cache/save@v4
with:
path: ${{ steps.prepare.outputs.cabal-store }}
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ steps.hash-deps.outputs.hash }}
- name: Save source repositories to cache
if: env.release != 'true' && matrix.arch == 'x86_64' && steps.restore-src.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: dist-newstyle/src
key: src-${{ runner.os }}-${{ hashFiles('cabal.project') }}
- name: Save build directory to cache
if: env.release != 'true' && steps.restore-build.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-${{ github.sha }}
- name: Upload CLI
if: startsWith(github.ref, 'refs/tags/v')
uses: ./.github/actions/prepare-release
with:
bin_path: ${{ steps.mac_cli_build.outputs.bin_path }}
bin_name: ${{ matrix.cli_asset_name }}
bin_hash: ${{ steps.mac_cli_build.outputs.bin_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Desktop
id: mac_desktop_build
if: startsWith(github.ref, 'refs/tags/v')
shell: bash
env:
APPLE_SIMPLEX_SIGNING_KEYCHAIN: ${{ secrets.APPLE_SIMPLEX_SIGNING_KEYCHAIN }}
APPLE_SIMPLEX_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_APPLE_ID }}
APPLE_SIMPLEX_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_PASSWORD }}
run: |
export ASSETS_DIR='../../assets'
scripts/ci/build-desktop-mac.sh
path=$(echo $PWD/apps/multiplatform/release/main/dmg/SimpleX-*.dmg)
echo "package_path=$path" >> $GITHUB_OUTPUT
echo "package_hash=$(echo SHA2-256\(${{ matrix.desktop_asset_name }}\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Upload Desktop
if: startsWith(github.ref, 'refs/tags/v')
uses: ./.github/actions/prepare-release
with:
bin_path: ${{ steps.mac_desktop_build.outputs.package_path }}
bin_name: ${{ matrix.desktop_asset_name }}
bin_hash: ${{ steps.mac_desktop_build.outputs.package_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Run tests
if: matrix.arch == 'aarch64'
timeout-minutes: 120
shell: bash
run: |
i=1
attempts=1
${{ (github.ref == 'refs/heads/stable' || startsWith(github.ref, 'refs/tags/v')) }} && attempts=3
while [ "$i" -le "$attempts" ]; do
if cabal test --test-show-details=direct ${{ env.ghc_options }}; then
break
else
echo "Attempt $i failed, retrying..."
i=$((i + 1))
sleep 1
fi
done
if [ "$i" -gt "$attempts" ]; then
echo "All "$attempts" attempts failed."
exit 1
fi
- name: Build library
id: mac_lib_build
if: ${{ !cancelled() && needs.maybe-release.outputs.libs_tag && steps.mac_cli_build.outcome == 'success' }}
shell: bash
run: |
SKIP_VLC=1 scripts/desktop/build-lib-mac.sh
name=simplex-chat-libs-macos-${{ matrix.arch }}
mkdir -p release-libs/$name/libs
find apps/multiplatform/common/src/commonMain/cpp/desktop/libs/mac-${{ matrix.arch }} -maxdepth 1 -type f -exec cp {} release-libs/$name/libs/ \;
(cd release-libs/$name && zip -r ../$name.zip libs)
- name: Upload library
if: ${{ !cancelled() && steps.mac_lib_build.outcome == 'success' }}
uses: softprops/action-gh-release@v2
with:
repository: ${{ github.repository }}-libs
tag_name: ${{ needs.maybe-release.outputs.libs_tag }}
files: release-libs/*.zip
token: ${{ secrets.NODEJS_REPO_TOKEN }}
- name: Remove -O2 build directory
id: remove-o2
if: env.cache_o0 == 'true' && !cancelled() && steps.mac_cli_build.outcome == 'success'
shell: bash
run: find dist-newstyle -mindepth 1 -maxdepth 1 ! -name src -exec rm -rf {} +
- name: Restore -O0 build directory from cache
id: restore-build-o0
if: ${{ !cancelled() && steps.remove-o2.outcome == 'success' }}
uses: actions/cache/restore@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-
${{ steps.keys.outputs.dist }}-O0-
- name: Build at -O0 for pull request caches
id: build-o0
if: ${{ !cancelled() && steps.remove-o2.outcome == 'success' }}
shell: bash
run: |
scripts/ci/prune-old-builds.sh dist-newstyle
cabal build -j --enable-tests --ghc-options=-O0
- name: Save -O0 build directory to cache
if: ${{ !cancelled() && steps.build-o0.outcome == 'success' && steps.restore-build-o0.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-${{ github.sha }}
# =========================
# Windows Build
# =========================
build-windows:
name: "${{ matrix.os }} (CLI,Desktop), GHC: ${{ matrix.ghc }}"
needs: [maybe-release, variables]
runs-on: ${{ matrix.os }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-windows-${{ matrix.os }}-${{ needs.maybe-release.outputs.libs_tag }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
ghc: ${{ needs.variables.outputs.GHC_VER }}
cli_asset_name: simplex-chat-windows-x86-64
desktop_asset_name: simplex-desktop-windows-x86_64.msi
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Prepare build
id: prepare
uses: ./.github/actions/prepare-build
with:
java_ver: ${{ needs.variables.outputs.JAVA_VER }}
ghc_ver: ${{ matrix.ghc }}
github_ref: ${{ github.ref }}
- name: Configure pagefile (Windows)
uses: simplex-chat/configure-pagefile-action@v1.4
with:
minimum-size: 16GB
maximum-size: 16GB
disk-root: "C:"
- name: 'Setup MSYS2'
uses: simplex-chat/setup-msys2@v2
with:
msystem: ucrt64
update: true
install: >-
git
perl
make
zip
pacboy: >-
toolchain:p
cmake:p
- name: Compute cache key prefixes
id: keys
if: env.release != 'true'
shell: msys2 {0}
run: |
toolchain=$(gcc --version | sha256sum | cut -c1-16)
target=windows-x86_64-ghc${{ matrix.ghc }}-$toolchain
echo "deps=deps-$target" >> "$GITHUB_OUTPUT"
echo "dist=dist-$target" >> "$GITHUB_OUTPUT"
- name: Restore dependencies from cache
id: restore-deps
if: env.release != 'true'
uses: actions/cache/restore@v4
with:
path: ${{ steps.prepare.outputs.cabal-store }}
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.deps }}-${{ env.branch }}-
${{ steps.keys.outputs.deps }}-
- name: Warn if dependencies not in cache
if: env.release != 'true' && steps.restore-deps.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.deps }}-${{ env.branch }}"
- name: Restore source repositories from cache
id: restore-src
if: env.release != 'true'
uses: actions/cache/restore@v4
with:
path: dist-newstyle/src
key: src-${{ runner.os }}-${{ hashFiles('cabal.project') }}
restore-keys: src-${{ runner.os }}-
- name: Warn if source repositories not in cache
if: env.release != 'true' && steps.restore-src.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::src-${{ runner.os }}"
- name: Restore build directory from cache
id: restore-build
if: env.release != 'true' && !needs.maybe-release.outputs.libs_tag
uses: actions/cache/restore@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-
${{ steps.keys.outputs.dist }}-${{ env.opt }}-
- name: Warn if build directory not in cache
if: steps.restore-build.outcome == 'success' && steps.restore-build.outputs.cache-matched-key == ''
run: echo "::warning title=Cache miss::${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}"
# rm -rf dist-newstyle/src/{direct-sq,simplexmq}* is here because of the bug in cabal's dependency which prevents second build from finishing
# (simplexmq is removed because cabal cannot delete its read-only git submodule pack files - blst, libbbs - on Windows)
- name: Build CLI
id: windows_cli_build
shell: msys2 {0}
run: |
export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo)
scripts/desktop/prepare-openssl-windows.sh
openssl_windows_style_path=$(echo `pwd`/dist-newstyle/openssl-3.0.15 | sed 's#/\([a-zA-Z]\)#\1:#' | sed 's#/#\\#g')
rm cabal.project.local 2>/dev/null || true
echo "ignore-project: False" >> cabal.project.local
echo "package direct-sqlcipher" >> cabal.project.local
echo " flags: +openssl" >> cabal.project.local
echo " extra-include-dirs: $openssl_windows_style_path\include" >> cabal.project.local
echo " extra-lib-dirs: $openssl_windows_style_path" >> cabal.project.local
scripts/ci/prune-old-builds.sh dist-newstyle
rm -rf dist-newstyle/src/direct-sq* dist-newstyle/src/simplexmq*
sed -i "s/, unix /--, unix /" simplex-chat.cabal
cabal build -j --enable-tests ${{ env.ghc_options }}
rm -rf dist-newstyle/src/direct-sq* dist-newstyle/src/simplexmq*
path=$(cabal list-bin simplex-chat | tail -n 1)
echo "bin_path=$path" >> $GITHUB_OUTPUT
echo "bin_hash=$(echo SHA2-256\(${{ matrix.cli_asset_name }}\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Compute dependency cache key
id: hash-deps
if: env.release != 'true'
shell: msys2 {0}
run: echo "hash=$(ls "$(cygpath -u '${{ steps.prepare.outputs.cabal-store }}')"/ghc-*/ | sha256sum | cut -c1-16)" >> "$GITHUB_OUTPUT"
- name: Save dependencies to cache
if: env.release != 'true' && steps.restore-deps.outputs.cache-matched-key != format('{0}-{1}-{2}', steps.keys.outputs.deps, env.branch, steps.hash-deps.outputs.hash)
uses: actions/cache/save@v4
with:
path: ${{ steps.prepare.outputs.cabal-store }}
key: ${{ steps.keys.outputs.deps }}-${{ env.branch }}-${{ steps.hash-deps.outputs.hash }}
- name: Save source repositories to cache
if: env.release != 'true' && steps.restore-src.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: dist-newstyle/src
key: src-${{ runner.os }}-${{ hashFiles('cabal.project') }}
- name: Save build directory to cache
if: env.release != 'true' && steps.restore-build.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-${{ env.opt }}-${{ env.branch }}-${{ github.sha }}
- name: Build library
if: needs.maybe-release.outputs.libs_tag
shell: msys2 {0}
run: |
export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo)
SKIP_VLC=1 scripts/desktop/build-lib-windows.sh
dlltool -d libsimplex.dll.def -l libsimplex.lib -D libsimplex.dll
name=simplex-chat-libs-windows-x86_64
mkdir -p release-libs/$name/libs
find apps/multiplatform/common/src/commonMain/cpp/desktop/libs/windows-x86_64 -maxdepth 1 -type f -exec cp {} release-libs/$name/libs/ \;
cp libsimplex.lib release-libs/$name/libs/
(cd release-libs/$name && zip -r ../$name.zip libs)
- name: Upload library
if: needs.maybe-release.outputs.libs_tag
uses: softprops/action-gh-release@v2
with:
repository: ${{ github.repository }}-libs
tag_name: ${{ needs.maybe-release.outputs.libs_tag }}
files: release-libs/*.zip
token: ${{ secrets.NODEJS_REPO_TOKEN }}
- name: Upload CLI
if: startsWith(github.ref, 'refs/tags/v')
uses: ./.github/actions/prepare-release
with:
bin_path: ${{ steps.windows_cli_build.outputs.bin_path }}
bin_name: ${{ matrix.cli_asset_name }}
bin_hash: ${{ steps.windows_cli_build.outputs.bin_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Desktop
id: windows_desktop_build
if: startsWith(github.ref, 'refs/tags/v')
shell: msys2 {0}
run: |
export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo)
scripts/desktop/build-lib-windows.sh
cd apps/multiplatform
./gradlew -Psimplex.assets.dir=../../assets packageMsi
rm -rf dist-newstyle/src/direct-sq* dist-newstyle/src/simplexmq*
path=$(echo $PWD/release/main/msi/*imple*.msi | sed 's#/\([a-z]\)#\1:#' | sed 's#/#\\#g')
echo "package_path=$path" >> $GITHUB_OUTPUT
echo "package_hash=$(echo SHA2-256\(${{ matrix.desktop_asset_name }}\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Upload Desktop
if: startsWith(github.ref, 'refs/tags/v')
uses: ./.github/actions/prepare-release
with:
bin_path: ${{ steps.windows_desktop_build.outputs.package_path }}
bin_name: ${{ matrix.desktop_asset_name }}
bin_hash: ${{ steps.windows_desktop_build.outputs.package_hash }}
github_ref: ${{ github.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Remove -O2 build directory
id: remove-o2
if: env.cache_o0 == 'true' && !needs.maybe-release.outputs.libs_tag && !cancelled() && steps.windows_cli_build.outcome == 'success'
shell: msys2 {0}
run: find dist-newstyle -mindepth 1 -maxdepth 1 ! -name src -exec rm -rf {} +
- name: Restore -O0 build directory from cache
id: restore-build-o0
if: ${{ !cancelled() && steps.remove-o2.outcome == 'success' }}
uses: actions/cache/restore@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-${{ github.sha }}
restore-keys: |
${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-
${{ steps.keys.outputs.dist }}-O0-
- name: Build at -O0 for pull request caches
id: build-o0
if: ${{ !cancelled() && steps.remove-o2.outcome == 'success' }}
shell: msys2 {0}
run: |
export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo)
scripts/desktop/prepare-openssl-windows.sh
scripts/ci/prune-old-builds.sh dist-newstyle
rm -rf dist-newstyle/src/direct-sq* dist-newstyle/src/simplexmq*
cabal build -j --enable-tests --ghc-options=-O0
rm -rf dist-newstyle/src/direct-sq* dist-newstyle/src/simplexmq*
- name: Save -O0 build directory to cache
if: ${{ !cancelled() && steps.build-o0.outcome == 'success' && steps.restore-build-o0.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: |
dist-newstyle/*
!dist-newstyle/src
key: ${{ steps.keys.outputs.dist }}-O0-${{ env.branch }}-${{ github.sha }}
# =========================
# Packages release
# =========================
# A new library release is tested with the Node.js and Python packages and updates them in a release PR.
packages:
needs: [maybe-release, build-linux, build-linux-push, build-linux-postgres, build-macos, build-windows]
if: ${{ !cancelled() && needs.maybe-release.outputs.libs_tag }}
# the called workflow can't be granted more than its caller, and its publish job needs these
permissions:
contents: read
id-token: write
uses: ./.github/workflows/packages.yml
with:
libs_release: ${{ needs.maybe-release.outputs.libs_tag }}
secrets: inherit