Files
simplex-chat/.github/workflows/build.yml
T
Moritz Angermann e241a9ba95 Merge current master into stable GHC 9.14 migration
Preserve upstream build caching, agent peer type and channel profile fixes. Keep migration CI diagnostics and runner settings, using the upstream Linux CLI step ID for the termination report.
2026-10-18 07:45:40 +09:00

1386 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:
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' && !startsWith(github.ref, 'refs/tags/v') && !needs.maybe-release.outputs.libs_tag }}
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'
- 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:
- 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
- name: Report GHC 8.10 build termination
if: ${{ failure() && matrix.ghc == '8.10.7' && steps.build-cli.outcome == 'failure' }}
timeout-minutes: 1
shell: bash
run: |
# SIGKILL alone does not identify an OOM kill. Keep the failed build
# result and report the container counters and host kernel evidence.
free -h || true
swapon --show || true
docker inspect --format '{{json .State}}' builder || true
docker exec builder sh -c '
for counter in memory.events memory.current memory.peak memory.max memory.swap.current memory.swap.max; do
path=/sys/fs/cgroup/$counter
if [ -r "$path" ]; then
printf "\n%s\n" "$path"
cat "$path"
fi
done
' || true
sudo journalctl -k -b --no-pager | grep -Ei 'out of memory|oom.kill|killed process' || true
# Also for pull requests that change the chat core, for the package tests (packages-pr).
- 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 artifact
if: matrix.libs && needs.maybe-release.outputs.core_changed && matrix.arch == 'x86_64'
uses: actions/upload-artifact@v7
with:
name: simplex-chat-libs-linux-${{ matrix.arch }}
path: release-libs/simplex-chat-libs-linux-${{ matrix.arch }}.zip
if-no-files-found: error
- 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: 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 }}
# =================================
# 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' && !startsWith(github.ref, 'refs/tags/v') && !needs.maybe-release.outputs.libs_tag }}
strategy:
fail-fast: false
matrix:
include:
# The CLT 27 SDK on macos-latest breaks GHC 9.6 hsc2hs linking.
- os: macos-15
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' && !startsWith(github.ref, 'refs/tags/v') && !needs.maybe-release.outputs.libs_tag }}
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-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
# A pull request that changes the chat core is tested with the Node.js and Python packages.
packages-pr:
needs: [maybe-release, build-linux]
# build-linux uploads the library before its chat tests run
if: ${{ !cancelled() && needs.maybe-release.outputs.core_changed }}
permissions:
contents: read
id-token: write
uses: ./.github/workflows/packages.yml
with:
libs_artifact: true