name: Flatpak CI

on:
  push:
    branches:
    - main
    - 'flatpak-1.[0-9]+.x'
  pull_request:
    branches:
    - main
    - 'flatpak-1.[0-9]+.x'
  merge_group:
    types:
    - checks_requested

permissions:
  contents: read

jobs:
  check:
    name: Build with gcc and test
    runs-on: ubuntu-24.04
    steps:
    - name: Install Dependencies
      run: |
        head -v -n-0 /etc/apt/sources.list || :
        head -v -n-0 /etc/apt/sources.list.d/* || :
        # Workaround for https://github.com/orgs/community/discussions/120966
        sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
        # Workaround for apparmor breaking bwrap by disabling unpriv userns
        sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
        sudo systemctl reload apparmor
        # Dependencies
        sudo apt-get update
        sudo apt-get install -y libglib2.0-dev attr gettext bison  dbus gtk-doc-tools \
        libfuse3-dev ostree libostree-dev libarchive-dev libzstd-dev libcap-dev libattr1-dev libdw-dev libelf-dev python3-pyparsing \
        libjson-glib-dev shared-mime-info desktop-file-utils libpolkit-agent-1-dev libpolkit-gobject-1-dev \
        libseccomp-dev libcurl4-openssl-dev libsystemd-dev libxml2-utils libgpgme11-dev gobject-introspection \
        libgirepository1.0-dev libappstream-dev libdconf-dev clang socat meson libdbus-1-dev e2fslibs-dev bubblewrap xdg-dbus-proxy \
        meson ninja-build libyaml-dev libstemmer-dev gperf itstool libmalcontent-0-dev libxau-dev libgdk-pixbuf2.0-dev openssl libc6-dev
        # One of the tests wants this
        sudo mkdir /tmp/flatpak-com.example.App-OwnedByRoot
    - name: Check out flatpak
      uses: actions/checkout@v4
      with:
        submodules: true
    - name: Create logs dir
      run: mkdir test-logs
    - name: configure
      # We don't do gtk-doc or GObject-Introspection here, because they can
      # clash with AddressSanitizer. Instead, the clang build enables those.
      run: |
        meson setup \
          -Db_sanitize=address,undefined \
          -Dgir=disabled \
          -Dgtkdoc=disabled \
          -Dinternal_checks=true \
          -Dinternal_tests=true \
          -Dsystem_dbus_proxy=xdg-dbus-proxy \
          _build
      env:
        CFLAGS: -O2 -Wp,-D_FORTIFY_SOURCE=2
    - name: Build flatpak
      run: meson compile -C _build
      env:
        ASAN_OPTIONS: detect_leaks=0 # Right now we're not fully clean, but this gets us use-after-free etc
    - name: Run tests
      run: meson test -C _build
      env:
        ASAN_OPTIONS: detect_leaks=0 # Right now we're not fully clean, but this gets us use-after-free etc
        LC_ALL: en_US.UTF-8
    - name: Collect logs on failure
      if: failure() || cancelled()
      run: mv _build/meson-logs/* test-logs/ || true
    - name: Upload test logs
      uses: actions/upload-artifact@v4
      if: failure() || cancelled()
      with:
        name: test logs
        path: test-logs

  # This is similar to the above, but runs on an older OS with some different configuration:
  # * Soup instead of curl
  # * Use built in bubblewrap instead of external
  # * Use built in xdg-dbus-proxy instead of external
  # * Disable malcontent build-dependency
  check-alt2:
    name: Build with gcc and test (older)
    runs-on: ubuntu-22.04
    steps:
    - name: Install Dependencies
      run: |
        sudo add-apt-repository ppa:flatpak/stable
        sudo apt-get update
        sudo apt-get install -y libglib2.0-dev attr gettext bison dbus gtk-doc-tools \
        libfuse-dev ostree libostree-dev libarchive-dev libzstd-dev libcap-dev libattr1-dev libdw-dev libelf-dev python3-pyparsing \
        libjson-glib-dev shared-mime-info desktop-file-utils libpolkit-agent-1-dev libpolkit-gobject-1-dev \
        libseccomp-dev libcurl4-openssl-dev libsystemd-dev libxml2-utils libgpgme11-dev gobject-introspection \
        libgirepository1.0-dev libappstream-dev libdconf-dev clang socat meson libdbus-1-dev e2fslibs-dev libc6-dev
        # One of the tests wants this
        sudo mkdir /tmp/flatpak-com.example.App-OwnedByRoot
    - name: Check out flatpak
      uses: actions/checkout@v4
      with:
        submodules: true
    - name: Create logs dir
      run: mkdir test-logs
    - name: Configure
      # Sometimes the older sanitizer toolchains will trigger issues that are either
      # false positive or that have been already against in newer versions, so we don't
      # enable them here.
      run: |
        meson setup \
          -Dgir=disabled \
          -Dgtkdoc=disabled \
          -Dinternal_checks=true \
          -Dinternal_tests=true \
          _build
      env:
        CFLAGS: -O2 -Wp,-D_FORTIFY_SOURCE=2
    - name: Build flatpak
      # Can't use `meson compile` here because Ubuntu 20.04 is too old
      run: ninja -C _build
    - name: Run tests
      run: meson test -C _build
      env:
        LC_ALL: en_US.UTF-8
    - name: Collect overall test logs on failure
      if: failure()
      run: mv _build/test-suite.log test-logs/ || true
    - name: Collect individual test logs on cancel
      if: failure() || cancelled()
      run: mv _build/meson-logs/* test-logs/ || true
    - name: Upload test logs
      uses: actions/upload-artifact@v4
      if: failure() || cancelled()
      with:
        name: test logs
        path: test-logs

  clang:
    permissions:
      security-events: write # for codeql
    name: Build with clang and analyze
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        language: [ 'cpp', 'python' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
        # Learn more:
        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
    steps:
    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v3
      with:
        languages: ${{ matrix.language }}
        # If you wish to specify custom queries, you can do so here or in a config file.
        # By default, queries listed here will override any specified in a config file.
        # Prefix the list here with "+" to use these queries and those in the config file.
        # queries: ./path/to/local/query, your-org/your-repo/queries@main
    - name: Install Dependencies
      run: |
        sudo add-apt-repository ppa:flatpak/stable
        sudo apt-get update
        sudo apt-get install -y libglib2.0-dev attr gettext bison dbus gtk-doc-tools \
        libfuse-dev ostree libostree-dev libarchive-dev libzstd-dev libcap-dev libattr1-dev libdw-dev libelf-dev python3-pyparsing \
        libjson-glib-dev shared-mime-info desktop-file-utils libpolkit-agent-1-dev libpolkit-gobject-1-dev \
        libseccomp-dev libcurl4-openssl-dev libsystemd-dev libxml2-utils libgpgme11-dev gobject-introspection \
        libgirepository1.0-dev libappstream-dev libdconf-dev clang e2fslibs-dev meson socat libxau-dev libgdk-pixbuf2.0-dev \
        xmlto libc6-dev
    - name: Check out flatpak
      uses: actions/checkout@v4
      with:
        submodules: true
    - name: Configure
      run: |
        meson setup \
          -Dgir=enabled \
          -Dgtkdoc=enabled \
          _build
      env:
        CC: clang
        CFLAGS: -Werror=unused-variable
    - name: Build flatpak
      # Can't use `meson compile` here because Ubuntu 20.04 is too old
      run: ninja -C _build
    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v3
    - name: Upload docs
      uses: actions/upload-artifact@v4
      with:
        if-no-files-found: error
        overwrite: true
        name: docs
        path: |
          _build/doc/

  valgrind:
    name: Run tests in valgrind
    needs: check # Don't run expensive test if main check fails
    runs-on: ubuntu-24.04 # Might as well test with a different one too
    if: ${{ false }} # Currently Valgrind takes too long and always fails
    steps:
    - name: Install Dependencies
      run: |
        sudo add-apt-repository ppa:flatpak/stable
        sudo apt-get update
        sudo apt-get install -y libglib2.0-dev attr gettext bison dbus gtk-doc-tools \
        libfuse-dev ostree libostree-dev libarchive-dev libzstd-dev libcap-dev libattr1-dev libdw-dev libelf-dev python3-pyparsing \
        libjson-glib-dev shared-mime-info desktop-file-utils libpolkit-agent-1-dev libpolkit-gobject-1-dev \
        libseccomp-dev libcurl4-openssl-dev libsystemd-dev libxml2-utils libgpgme11-dev gobject-introspection \
        libgirepository1.0-dev libappstream-dev libdconf-dev clang socat meson libdbus-1-dev \
        valgrind e2fslibs-dev meson libxau-dev libgdk-pixbuf2.0-dev libc6-dev
    - name: Check out flatpak
      uses: actions/checkout@v4
      with:
        submodules: true
    - name: Create logs dir
      run: mkdir test-logs
    - name: Configure
      run: |
        meson setup \
          -Dgir=enabled \
          -Dgtkdoc=enabled \
          _build
      env:
        CFLAGS: -O2
    - name: Build flatpak
      run: meson compile -C _build
    - name: Run tests under valgrind
      run: meson test -C _build
      env:
        FLATPAK_TESTS_VALGRIND: true
    - name: Collect overall test logs on failure
      if: failure()
      run: mv _build/meson-logs/* test-logs/ || true
    - name: Collect individual test logs on cancel
      if: failure() || cancelled()
      run: mv _build/tests/*.log test-logs/ || true
    - name: Upload test logs
      uses: actions/upload-artifact@v4
      if: failure() || cancelled()
      with:
        name: test logs
        path: test-logs

  # This is a workaround to CodeQL not reporting status to the
  # merge queue.
  check_codeql_status:
    name: Check CodeQL Status
    needs: clang
    permissions:
      contents: read
      checks: read
      pull-requests: read
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'pull_request' }}
    steps:
    - name: Check CodeQL Status
      uses: eldrick19/code-scanning-status-checker@v2
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        pr_number: ${{ github.event.pull_request.number }}
        repo: ${{ github.repository }}
