Tests

name: Tests

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  workflow_dispatch:

jobs:
  unit-tests:
      name: Unit tests
      runs-on: ubuntu-latest
      timeout-minutes: 10
      steps:
        - uses: fkirc/skip-duplicate-actions@master
        - uses: actions/checkout@v2
        - uses: gradle/wrapper-validation-action@v1
        - uses: actions/setup-java@v1
          with:
            java-version: 11
        - uses: actions/cache@v2
          with:
            path: |
              ~/.gradle/caches
              ~/.gradle/wrapper
            key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
        - name: Unit tests
          run: |
            ./gradlew test --stacktrace
            ./gradlew jacocoTestReport --stacktrace
        - name: API changes check
          run: |
              ./gradlew :sdk:apiCheck --stacktrace
              ./gradlew :sdk-hebe:apiCheck --stacktrace
              ./gradlew :sdk-scrapper:apiCheck --stacktrace
        - uses: codecov/codecov-action@v1

  lint:
      name: Lint check
      runs-on: ubuntu-latest
      timeout-minutes: 10
      steps:
        - uses: fkirc/skip-duplicate-actions@master
        - uses: actions/checkout@v2
        - uses: actions/setup-java@v1
          with:
            java-version: 11
        - uses: actions/cache@v2
          with:
            path: |
              ~/.gradle/caches
              ~/.gradle/wrapper
            key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
        - name: Lint
          run: |
            ./gradlew ktlintCheck --stacktrace
        - uses: codecov/codecov-action@v1


Bump Version

name: Bump Version

on:
  workflow_dispatch:
    inputs:
      newVersion:
        description: "Version name"
        required: true
        type: string

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  bump_version:
    name: Bump version
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Bump version script
        run: |
          perl -i -pe 's/^(templateScriptVersion=(.*))$/"templateScriptVersion=${{ github.event.inputs.newVersion }}"/e' version.properties

      - name: Bump version Compose
        run: |
          perl -i -pe 's/ANDROID_VERSION_NAME =(.*)$/ANDROID_VERSION_NAME = "${{ github.event.inputs.newVersion }}"/g' sample-compose/buildSrc/src/main/java/Versions.kt

      - name: Create pull request
        uses: peter-evans/create-pull-request@v4
        with:
          assignees: ${{ secrets.GITHUB_USER }}
          token: ${{ secrets.WIKI_ACTION_TOKEN }}
          commit-message: '[Chore] Bump version to ${{ github.event.inputs.newVersion }}'
          committer: Nimble Bot <bot@nimblehq.co>
          branch: chore/bump-version-to-${{ github.event.inputs.newVersion }}
          delete-branch: true
          title: '[Chore] Bump version to ${{ github.event.inputs.newVersion }}'
          labels: |
            type : chore
          body: |
            ## What happened 👀

            Bump version to ${{ github.event.inputs.newVersion }}

            ## Insight 📝

            Automatically created by the `Bump Version` workflow.

            ## Proof Of Work 📹

            On the `Files changed` tab


Draft new release

name: Draft new release

on:
  push:
    branches:
      - main

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  draft_new_release:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Install Kscript
        run: |
          curl -s "https://get.sdkman.io" | bash
          source "$HOME/.sdkman/bin/sdkman-init.sh"
          source version.properties
          sdk install kotlin $kotlinVersion
          sdk install kscript $kscriptVersion
          echo $PATH >> $GITHUB_PATH

      - name: Get version from the latest commit message
        working-directory: scripts
        run: |
          COMMIT_MESSAGE="${{ github.event.head_commit.message }}"
          VERSION=$(kscript get_version.kts "$COMMIT_MESSAGE")
          echo "VERSION=$VERSION" >> $GITHUB_ENV

      - name: Draft release
        uses: release-drafter/release-drafter@v5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          config-name: release-drafter-config.yml
          version: ${{ env.VERSION }}


Publish docs to Wiki

name: Publish docs to Wiki

on:
  push:
    paths:
      - .github/wiki/**
    branches:
      - main

jobs:
  publish_docs_to_wiki:
    name: Publish docs to Wiki
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout source code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.head_ref }}

      - name: Publish Github Wiki
        uses: nimblehq/publish-github-wiki-action@v1.0
        with:
          user_name: team-nimblehq
          user_email: dev@nimblehq.co
          user_access_token: ${{ secrets.WIKI_ACTION_TOKEN }}


Review pull request

name: Review pull request

on:
  pull_request:
    types: [ opened, edited, reopened, synchronize ]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  review_pull_request:
    name: Review pull request
    runs-on: ubuntu-latest
    timeout-minutes: 30
    environment: template-compose
    steps:
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Cache Gradle
        uses: actions/cache@v2
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      # template-compose

      - name: Run Detekt on template-compose
        working-directory: ./template-compose
        run: ./gradlew detekt

      - name: Run Android Lint on template-compose
        working-directory: ./template-compose
        run: ./gradlew lint

      - name: Run unit tests with Kover on template-compose
        working-directory: ./template-compose
        run: ./gradlew koverXmlReport

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '2.7'

      - name: Cache gems
        uses: actions/cache@v2
        with:
          path: vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-

      - name: Install Bundle and check environment versions
        run: |
          echo 'Install Bundle'
          bundle config path vendor/bundle
          bundle install
          echo 'Check environment setup versions'
          ruby --version
          gem --version
          bundler --version

      - name: Run Danger
        env:
          DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: bundle exec danger


Run Detekt and unit tests

name: Run Detekt and unit tests

on: push

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  run_detekt_and_unit_tests:
    name: Run Detekt and unit tests
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Cache Gradle
        uses: actions/cache@v2
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      # template-compose

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Run Detekt on template-compose
        working-directory: ./template-compose
        run: ./gradlew detekt

      - name: Archive Detekt reports on template-compose
        uses: actions/upload-artifact@v3
        with:
          name: DetektReportsTemplateCompose
          path: template-compose/build/reports/detekt/

      - name: Run unit tests with Kover on template-compose
        working-directory: ./template-compose
        run: ./gradlew koverHtmlReport

      - name: Archive code coverage reports on template-compose
        uses: actions/upload-artifact@v3
        with:
          name: CodeCoverageReportsTemplateCompose
          path: template-compose/app/build/reports/kover/

      # sample-compose

      - name: Run Detekt on sample-compose
        working-directory: ./sample-compose
        run: ./gradlew detekt

      - name: Archive Detekt reports on sample-compose
        uses: actions/upload-artifact@v3
        with:
          name: DetektReportsTemplateCompose
          path: sample-compose/build/reports/detekt/

      - name: Run unit tests with Kover on sample-compose
        working-directory: ./sample-compose
        run: ./gradlew koverHtmlReport

      - name: Archive code coverage reports on sample-compose
        uses: actions/upload-artifact@v3
        with:
          name: CodeCoverageReportsTemplateCompose
          path: sample-compose/app/build/reports/kover/


Verify newproject script

name: Verify newproject script

on:
  pull_request:
    types: [ opened, reopened, synchronize ]
    branches: [ develop ]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  verify_newproject_script:
    name: Verify newproject script
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Cache Gradle
        uses: actions/cache@v2
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      - name: Install Kscript
        run: |
          curl -s "https://get.sdkman.io" | bash
          source "$HOME/.sdkman/bin/sdkman-init.sh"
          source version.properties
          sdk install kotlin $kotlinVersion
          sdk install kscript $kscriptVersion
          echo $PATH >> $GITHUB_PATH

      - name: Verify generating new project from template-compose
        working-directory: scripts
        run: kscript new_project.kts package-name=co.mycomposeproject.example app-name="My Compose Project" template=compose


Build

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: "Build"

# Controls when the action will run. Triggers the workflow on push or pull request
# events for the `master` branch
on:
  push:
    branches: [master]
    tags: build*
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [master]
  schedule:
    # Run once a week (even if no new code or PRs) to detect random regressions
    - cron: "12 13 * * 2"

env:
  # Allow precise monitoring of the save/restore of Gradle User Home by `gradle-build-action`
  # See https://github.com/marketplace/actions/gradle-build-action?version=v2.1.1#cache-debugging-and-analysis
  GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
  GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: "fhir" # change this to invalidate cache

concurrency:
  # github.head_ref uniquely identifies Pull Requests (but is not available when building branches like main or master)
  # github.ref is the fallback used when building for workflows triggered by push
  # Note that || are fallback values (not "concatenations")
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: true # Use e.g. ${{ github.ref != 'refs/heads/main' }} (or master, until #2180) to only cancel for PRs not on branch

  # A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # Build will compile APK, test APK and run tests, lint, etc.
  build:
    runs-on: ubuntu-22.04-8core
    timeout-minutes: 60
    permissions:
      actions: read
      contents: read
      packages: write

    strategy:
      fail-fast: false

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - name: Checkout Repo
        uses: actions/checkout@v4
        with:
          # Fetch origin/master for spotless ratchet to work
          # https://github.com/diffplug/spotless/issues/1242
          fetch-depth: 0

      - name: Setup machine
        uses: ./.github/actions/commonSetup

      - name: Spotless check
        run: ./gradlew spotlessCheck --scan --full-stacktrace

      - name: Build (full) with Gradle
        run: ./gradlew build --scan --full-stacktrace

      - name: Check with Gradle
        run: ./gradlew check --scan --full-stacktrace

      - name: Publish Maven packages to GitHub Packages
        if: ${{ github.event_name == 'push' }}
        run: ./gradlew publish
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPOSITORY_URL: 'https://maven.pkg.github.com/google/android-fhir'
          # Use SNAPSHOT Prefix to follow Maven convention
          ARTIFACT_VERSION_SUFFIX: SNAPSHOT

      - name: Release artifacts to local repo
        run: ./gradlew publishReleasePublicationToCIRepository --scan
        env:
          ARTIFACT_VERSION_SUFFIX: build_${{ github.run_id }}

      - name: Upload artifact maven-repository.zip
        uses: actions/upload-artifact@v4
        with:
          name: maven-repository
          path: build/ci-repo

      - name: Zip artifact for debugging
        if: ${{ failure() }}
        run: zip build.zip ./*/build -r

      # Upload the build dir for all the modules for diagnosis
      - name: Upload build dir
        if: ${{ failure() }}
        uses: actions/upload-artifact@v4
        with:
          name: build
          path: build.zip

      # Steps that follow are related to the Documentation Web Site
      # This deploys content based on docs/ which ends up in site/
      # to https://google.github.io/android-fhir/ using GitHub Pages.

      - name: Install Python
        uses: actions/setup-python@v5
        with:
          python-version: 3.11
          cache: "pipenv"
      - name: Install PipEnv
        uses: tiagovrtr/actions-pipenv@v1
        with:
          pipenv-version: 2023.12.1

      - name: Build Docs Site
        # This 1st step intentionally runs not just on the main ("master") branch
        # but also for all pull requests. This serves to detect doc breakages.
        # (But the following steps, which do the actual deploy, only run for
        #  the main branch, of course.)
        run: ./build-docs.bash

      - name: Setup GitHub Pages
        if: ${{ github.event_name == 'push' }}
        uses: actions/configure-pages@v5

      - name: Upload site/ directory as GitHub Pages artifact
        if: ${{ github.event_name == 'push' }}
        uses: actions/upload-pages-artifact@v3
        with:
          path: "site/"

  deploy-website:
    needs: build
    if: ${{ github.event_name == 'push' }}
    runs-on: ubuntu-latest
    # https://docs.github.com/en/actions/security-guides/automatic-token-authentication
    # Sets required permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages.
    permissions:
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      # https://github.com/actions/deploy-pages
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4


CodeQL

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: "CodeQL"

# NB: This GitHub Action for https://codeql.github.com seems to be
# a bit "special"; it does not appear to be (easily) possible to just
# integrate and run this as part of the main build.yaml action; see
# https://github.com/google/android-fhir/issues/2310.

on:
  push:
    branches: ["master"]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: ["master"]
  schedule:
    - cron: "32 13 * * 2"

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref || || github.run_id }}
  cancel-in-progress: true

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-22.04-8core
    timeout-minutes: 60
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: ["java"]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Switch to Java 17 from Eclipse Temurin distro
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: temurin

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}

      # TODO: use Autobuild instead of ./gradlew after https://github.com/github/codeql-action/issues/1417 is fixed
      # - name: Autobuild
      #   uses: github/codeql-action/autobuild@v2
      - name: Build with Gradle
        run: ./gradlew --scan --full-stacktrace -Dorg.gradle.dependency.verification=off compileDebugAndroidTestSources

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v3
        with:
          category: "/language:${{matrix.language}}"


Validate Gradle Wrapper

name: "Validate Gradle Wrapper"
on: [push, pull_request]

permissions:
  contents: read #  to fetch code (actions/checkout)

jobs:
  validation:
    name: "Validation"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: gradle/wrapper-validation-action@v1


Build & Test

name: Build & Test

on:
  push:
    branches:
      - '*'
      - '*/*'
  pull_request:
    branches:
      - '*'
      - '*/*'

concurrency:
  group: build-${{ github.ref }}
  cancel-in-progress: true

jobs:

  build-test:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Build & Test
        run: cd projects && ./test.sh

  build-publish-local:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Build & Install
        run: cd projects && ./install.sh

  build-macos:
    runs-on: macos-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Test
        run: cd projects && ./gradlew :core:koin-core:macosX64Test --no-daemon --stacktrace


Weekly Benchmark

name: Weekly Benchmark

on:
  schedule:
    - cron:  '0 0 * * 0'    # sunday weekly

jobs:

  jvm-benchmark:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Install
        run: cd projects && ./install.sh

      - name: Test Examples
        run: cd examples/jvm-perfs && ./benchmark.sh


Test Examples

name: Test Examples

on:
  push:
    branches:
      - '*'
      - '*/*'
  pull_request:
    branches:
      - '*'
      - '*/*'

concurrency:
  group: test-examples-${{ github.ref }}
  cancel-in-progress: true

jobs:

  run-tests:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Install
        run: cd projects && ./install.sh

      - name: Test Examples
        run: cd examples && ./test.sh

      - name: Upload test reports
        if: success() || failure()
        uses: actions/upload-artifact@v3
        with:
          name: test-reports
          path: |
            '**/*/examples/android-perfs/build/reports/tests/testDebugUnitTest/'


CodeQL

name: "CodeQL"

on:
  push:
    branches: [ 'main' ]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ 'main' ]
  schedule:
    - cron: '52 13 * * 6'

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'java' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
        # Use only 'java' to analyze code written in Java, Kotlin or both
        # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

    steps:
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        distribution: 'zulu'
        java-version: 11

    - name: Setup Gradle
      uses: gradle/gradle-build-action@v2

    - name: Checkout repository
      uses: actions/checkout@v3

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      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.

        # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
        # queries: security-extended,security-and-quality

    - name: Build and install all
      # working-directory: core
      run: cd projects && ./install.sh

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2
      with:
        category: "/language:${{matrix.language}}"


Release

name: Release

on:
  push:
    tags:
    - '*'

env:
  IS_RELEASE: true
  OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
  OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
  SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
  SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
  SIGNING_KEY: ${{ secrets.SIGNING_KEY }}

jobs:
  release:
    runs-on: macos-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Install
        run: cd projects && ./install.sh

      - name: Release
        run: cd projects && ./release.sh


Crane

name: Crane

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Crane.yaml'
      - 'Crane/**'
  pull_request:
    paths:
      - '.github/workflows/Crane.yaml'
      - 'Crane/**'
  workflow_dispatch:

env:
  SAMPLE_PATH: Crane
  compose_store_password: ${{ secrets.compose_store_password }}
  compose_key_alias: ${{ secrets.compose_key_alias }}
  compose_key_password: ${{ secrets.compose_key_password }}
jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Crane
      path: Crane
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}

  test:
    needs: build
    runs-on: macos-13
    timeout-minutes: 30
    strategy:
      matrix:
        api-level: [23, 26, 29]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh $SAMPLE_PATH checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Inject Maps API Key
        run: |
          # Injecting the key directly into the manifest as secrets-gradle-plugin
          # isn't picking up the key when creating a local.properties file here
          sed -i -e "s,\${googleMapsKey},$GOOGLE_MAPS_KEY,g" ${{ env.SAMPLE_PATH }}/app/src/main/AndroidManifest.xml
        env:
          GOOGLE_MAPS_KEY: ${{ secrets.GOOGLE_MAPS_KEY }}

      - name: Run instrumentation tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          target: google_apis
          arch: x86
          disable-animations: true
          script: ./gradlew app:connectedDebugAndroidTest --stacktrace
          working-directory: ${{ env.SAMPLE_PATH }}

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports-crane-${{ matrix.api-level }}
          path: ${{ env.SAMPLE_PATH }}/app/build/reports


JetLagged

name: JetLagged

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/JetLagged.yaml'
      - 'JetLagged/**'
  pull_request:
    paths:
      - '.github/workflows/JetLagged.yaml'
      - 'JetLagged/**'
  workflow_dispatch:

env:
  SAMPLE_PATH: JetLagged
  compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
  compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
  compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}
jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: JetLagged
      path: JetLagged
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}

  test:
    needs: build
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        api-level: [23, 26, 29]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh $SAMPLE_PATH checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Run instrumentation tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          arch: x86
          disable-animations: true
          script: ./gradlew connectedCheck --stacktrace
          working-directory: ${{ env.SAMPLE_PATH }}

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports-jetlagged-${{ matrix.api-level }}
          path: ${{ env.SAMPLE_PATH }}/app/build/reports


JetNews

name: JetNews

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/JetNews.yaml'
      - 'JetNews/**'
  pull_request:
    paths:
      - '.github/workflows/JetNews.yaml'
      - 'JetNews/**'
  workflow_dispatch:

env:
  SAMPLE_PATH: JetNews
  compose_store_password: ${{ secrets.compose_store_password }}
  compose_key_alias: ${{ secrets.compose_key_alias }}
  compose_key_password: ${{ secrets.compose_key_password }}
jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: JetNews
      path: JetNews
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}

  androidTest:
    needs: build
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        api-level: [23, 26, 29]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh $SAMPLE_PATH checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Run instrumentation tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          arch: x86
          disable-animations: true
          script: ./gradlew connectedCheck --stacktrace
          working-directory: ${{ env.SAMPLE_PATH }}

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports-jetnews-${{ matrix.api-level }}
          path: ${{ env.SAMPLE_PATH }}/app/build/reports/androidTests


Jetcaster

name: Jetcaster

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Jetcaster.yaml'
      - 'Jetcaster/**'
  pull_request:
    paths:
      - '.github/workflows/Jetcaster.yaml'
      - 'Jetcaster/**'
  workflow_dispatch:

jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Jetcaster
      path: Jetcaster
      module: mobile
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}


Jetchat

name: Jetchat

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Jetchat.yaml'
      - 'Jetchat/**'
  pull_request:
    paths:
      - '.github/workflows/Jetchat.yaml'
      - 'Jetchat/**'
  workflow_dispatch:

env:
  SAMPLE_PATH: Jetchat
  compose_store_password: ${{ secrets.compose_store_password }}
  compose_key_alias: ${{ secrets.compose_key_alias }}
  compose_key_password: ${{ secrets.compose_key_password }}
jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Jetchat
      path: Jetchat
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}
  test:
    needs: build
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        api-level: [23, 26, 29]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh $SAMPLE_PATH checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Run instrumentation tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          arch: x86
          disable-animations: true
          script: ./gradlew connectedCheck --stacktrace
          working-directory: ${{ env.SAMPLE_PATH }}

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports-jetchat-${{ matrix.api-level }}
          path: ${{ env.SAMPLE_PATH }}/app/build/reports


Jetsnack

name: Jetsnack

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Jetsnack.yaml'
      - 'Jetsnack/**'
  pull_request:
    paths:
      - '.github/workflows/Jetsnack.yaml'
      - 'Jetsnack/**'
  workflow_dispatch:

jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Jetsnack
      path: Jetsnack
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}


Jetsurvey

name: Jetsurvey

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Jetsurvey.yaml'
      - 'Jetsurvey/**'
  pull_request:
    paths:
      - '.github/workflows/Jetsurvey.yaml'
      - 'Jetsurvey/**'
  workflow_dispatch:

jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Jetsurvey
      path: Jetsurvey
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}


Owl

name: Owl

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Owl.yaml'
      - 'Owl/**'
  pull_request:
    paths:
      - '.github/workflows/Owl.yaml'
      - 'Owl/**'
  workflow_dispatch:

env:
  SAMPLE_PATH: Owl
  compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
  compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
  compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}
jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Owl
      path: Owl
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}

  test:
    needs: build
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      matrix:
        api-level: [23, 26, 29]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh $SAMPLE_PATH checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Run instrumentation tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          arch: x86
          disable-animations: true
          script: ./gradlew connectedCheck --stacktrace
          working-directory: ${{ env.SAMPLE_PATH }}

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports-owl-${{ matrix.api-level }}
          path: ${{ env.SAMPLE_PATH }}/app/build/reports


GitHub Release with APKs

name: GitHub Release with APKs

on:
  push:
    tags:
    - 'v*'
env:
  compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
  compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
  compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 45

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Build all projects
        run: ./scripts/gradlew_recursive.sh assembleDebug

      - name: Create Release
        id: create_release
        uses: actions/create-release@v4
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          draft: true
          prerelease: false

      - name: Upload Crane
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: Crane/app/build/outputs/apk/debug/app-debug.apk
          asset_name: crane-debug.apk
          asset_content_type: application/vnd.android.package-archive

      - name: Upload Owl
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: Owl/app/build/outputs/apk/debug/app-debug.apk
          asset_name: owl-debug.apk
          asset_content_type: application/vnd.android.package-archive

      - name: Upload Jetcaster
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: Jetcaster/app/build/outputs/apk/debug/app-debug.apk
          asset_name: jetcaster-debug.apk
          asset_content_type: application/vnd.android.package-archive

      - name: Upload Jetchat
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: Jetchat/app/build/outputs/apk/debug/app-debug.apk
          asset_name: jetchat-debug.apk
          asset_content_type: application/vnd.android.package-archive

      - name: Upload Jetnews
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: JetNews/app/build/outputs/apk/debug/app-debug.apk
          asset_name: jetnews-debug.apk
          asset_content_type: application/vnd.android.package-archive

      - name: Upload Jetsnack
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: Jetsnack/app/build/outputs/apk/debug/app-debug.apk
          asset_name: jetsnack-debug.apk
          asset_content_type: application/vnd.android.package-archive

      - name: Upload Jetsurvey
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: Jetsurvey/app/build/outputs/apk/debug/app-debug.apk
          asset_name: jetsurvey-debug.apk
          asset_content_type: application/vnd.android.package-archive


Reply

name: Reply

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/Reply.yaml'
      - 'Reply/**'
  pull_request:
    paths:
      - '.github/workflows/Reply.yaml'
      - 'Reply/**'
  workflow_dispatch:

env:
  SAMPLE_PATH: Reply
  compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
  compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
  compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}
jobs:
  build:
    uses: ./.github/workflows/build-sample.yml
    with:
      name: Reply
      path: Reply
    secrets:
      compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
      compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
      compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}

  test:
    needs: build
    runs-on: ubuntu-latest # enables hardware acceleration in the virtual machine
    timeout-minutes: 30
    strategy:
      matrix:
        api-level: [23, 26, 29]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh $SAMPLE_PATH checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Run instrumentation tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          arch: x86
          disable-animations: true
          script: ./gradlew connectedCheck --stacktrace
          working-directory: ${{ env.SAMPLE_PATH }}

      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports-reply-${{ matrix.api-level }}
          path: ${{ env.SAMPLE_PATH }}/app/build/reports


Build and Test Sample

name: Build and Test Sample

on:
  workflow_call:
    inputs:
      name:
        required: true
        type: string
      path:
        required: true
        type: string
      module:
        default: "app"
        type: string
    secrets:
      compose_store_password:
        description: 'password for the keystore'
        required: true
      compose_key_alias:
        description: 'alias for the keystore'
        required: true
      compose_key_password:
        description: 'password for the key'
        required: true
concurrency:
  group: ${{ inputs.name }}-build-${{ github.ref }}
  cancel-in-progress: true
env:
  compose_store_password: ${{ secrets.compose_store_password }}
  compose_key_alias: ${{ secrets.compose_key_alias }}
  compose_key_password: ${{ secrets.compose_key_password }}
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Generate cache key
        run: ./scripts/checksum.sh ${{ inputs.path }} checksum.txt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches/modules-*
            ~/.gradle/caches/jars-*
            ~/.gradle/caches/build-cache-*
          key: gradle-${{ hashFiles('checksum.txt') }}

      - name: Check formatting
        working-directory: ${{ inputs.path }}
        run: ./gradlew --init-script buildscripts/init.gradle.kts spotlessCheck --stacktrace

      - name: Check lint
        working-directory: ${{ inputs.path }}
        run: ./gradlew lintDebug --stacktrace

      - name: Build debug
        working-directory: ${{ inputs.path }}
        run: ./gradlew assembleDebug --stacktrace

      - name: Run local tests
        working-directory: ${{ inputs.path }}
        run: ./gradlew testDebug --stacktrace

      - name: Upload build outputs (APKs)
        uses: actions/upload-artifact@v4
        with:
          name: build-outputs
          path: ${{ inputs.path }}/${{ inputs.module }}/build/outputs

      - name: Upload build reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: build-reports
          path: ${{ inputs.path }}/${{ inputs.module }}/build/reports


Duplicates main to old master branch

# Duplicates default main branch to the old master branch

name: Duplicates main to old master branch

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the main branch
on:
  push:
    branches: [ main ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "copy-branch"
  copy-branch:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it,
    # but specifies master branch (old default).
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
        ref: master

    - run: |
        git config user.name github-actions
        git config user.email github-actions@github.com
        git merge origin/main
        git push


Apply Spotless

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Apply Spotless

on:
  pull_request:
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  spotlessApply:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
    - uses: actions/checkout@v4

    - name: set up Java 17
      uses: actions/setup-java@v4
      with:
        distribution: 'zulu'
        java-version: 17

    - name: Apply spotless formatting
      run: ./scripts/format.sh

    - uses: stefanzweifel/git-auto-commit-action@v5
      with:
        commit_message: 🤖 Apply Spotless


Build and Test a Compose snapshot

name: Build and Test a Compose snapshot

on:
  workflow_dispatch:
    inputs:
      snapshotID:
        required: true
        type: string
      composeVersion:
        required: true
        type: string
env:
  compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
  compose_key_alias: $${{ secrets.COMPOSE_KEY_ALIAS }}
  compose_key_password: $${{ secrets.COMPOSE_KEY_PASSWORD }}
concurrency:
  group: ${{ inputs.name }}-build-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copy CI gradle.properties
        run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: 'zulu'

      - name: Check snapshot
        working-directory: ${{ inputs.path }}
        run: ./scripts/test_snapshot.sh $CI_COMPOSE_VERSION $CI_COMPOSE_SNAPSHOT
        env:
          CI_COMPOSE_VERSION: ${{ inputs.composeVersion }}
          CI_COMPOSE_SNAPSHOT: ${{ inputs.snapshotID }}

      - name: Upload build reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: build-reports
          path: ${{ inputs.path }}/app/build/reports


Update Versions / Dependencies

name: Update Versions / Dependencies

on:
  workflow_dispatch:
env:
  compose_store_password: ${{ secrets.COMPOSE_STORE_PASSWORD }}
  compose_key_alias: ${{ secrets.COMPOSE_KEY_ALIAS }}
  compose_key_password: ${{ secrets.COMPOSE_KEY_PASSWORD }}
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Copy CI gradle.properties
      run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties
    - name: set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: 17
        distribution: 'zulu'
        cache: gradle

    - name: Update dependencies
      run: ./scripts/updateDeps.sh
    - name: Duplicate version configuration
      run: ./scripts/duplicate_version_config.sh
    - name: Create pull request
      id: cpr
      uses: peter-evans/create-pull-request@v6
      with:
        token: ${{ secrets.PAT }}
        commit-message: 🤖 Update Dependencies
        committer: compose-devrel-github-bot <compose-devrel-github-bot@google.com>
        author: compose-devrel-github-bot <compose-devrel-github-bot@google.com>
        signoff: false
        branch: bot-update-deps
        delete-branch: true
        title: '🤖 Update Dependencies'
        body: Updated depedencies
        reviewers: ${{ github.actor }}


Baseline profile generation

name: Baseline profile generation

on:
  # Every Sunday at 00:43
  schedule:
    - cron: '43 0 * * 0'
  workflow_dispatch:
  pull_request:
    paths:
      - 'benchmark/**'
      - '.github/workflows/baseline-profile.yml'

jobs:
  baseline-profile:
    runs-on: ubuntu-latest
    timeout-minutes: 45
    env:
      TERM: dumb
      ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TVDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TVDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD }}

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
        with:
          # We need to use a Personal Access Token from an admin to be able to commit to main,
          # as it is a protected branch.
          # https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-fine-grained-personal-access-token
          token: ${{ secrets.TIVI_OWNER_PAT }}

      - name: Enable KVM
        run: |
          echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
          sudo udevadm control --reload-rules
          sudo udevadm trigger --name-match=kvm

      - name: Setup JDK for build
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Accept Android SDK licenses
        run: yes | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses

      - name: Decrypt secrets
        run: ./release/decrypt-secrets.sh
        env:
          ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}

      - uses: gradle/actions/setup-gradle@v3
        with:
          cache-disabled: true

      # This allows us to build most of what we need without the emulator running
      # and using resources
      - name: Build app and benchmark
        run: ./gradlew assembleNonMinifiedRelease

      - name: Clear Gradle Managed Devices
        run: ./gradlew cleanManagedDevices

      - name: Run benchmark on Gradle Managed Device
        run: |
          ./gradlew generateBaselineProfile \
            -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" \
            -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile \
            -Pandroid.experimental.testOptions.managedDevices.setupTimeoutMinutes=10 \
            --no-configuration-cache

      # If we're on main branch, copy over the baseline profile and
      # commit it to the repository (if changed)
      - name: Commit baseline profile into main
        if: github.ref == 'refs/heads/main'
        run: |
          # If the baseline profile has changed, commit it
          if [[ $(git diff --stat android-app/app/src) != '' ]]; then
            git config user.name github-actions
            git config user.email github-actions@github.com
            git add android-app/app/src
            git commit -m "Update app baseline profile"
            git pull --rebase
            git push
          fi

      - name: Upload reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: reports
          path: |
            **/build/reports/*

      - name: Clean secrets
        if: always()
        run: ./release/clean-secrets.sh


CI

name: CI

on:
  push:
    branches:
      - main
    tags:
      - v*
  pull_request:
  workflow_dispatch:

jobs:
  android:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    env:
      ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD }}
      ORG_GRADLE_PROJECT_TIVI_RELEASE_KEYSTORE_PWD: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_RELEASE_KEYSTORE_PWD }}
      ORG_GRADLE_PROJECT_TIVI_RELEASE_KEY_PWD: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_RELEASE_KEY_PWD }}

    steps:
      - name: Generate build number
        shell: bash
        run: echo "ORG_GRADLE_PROJECT_TIVI_VERSIONCODE=$(( (GITHUB_RUN_NUMBER * 2) + 10000 ))" >> $GITHUB_ENV

      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: set up JDK
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: gradle/actions/setup-gradle@v3
        with:
          cache-disabled: true

      - name: Decrypt secrets
        run: ./release/decrypt-secrets.sh
        env:
          ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}

      - name: Build Android App (skipping benchmark variant)
        run: |
          ./gradlew check \
            :android-app:app:assemble \
            :android-app:app:bundle \
            -x assembleNonMinifiedRelease \
            -x bundleNonMinifiedRelease \
            -Pandroidx.baselineprofile.skipgeneration=true \
            --no-configuration-cache

      - name: Clean secrets
        if: always()
        run: ./release/clean-secrets.sh

      - name: Upload build outputs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: android-build-outputs
          path: android-app/app/build/outputs

      - name: Upload reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: android-reports
          path: |
            **/build/reports/*

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: android-test-results
          path: |
            **/build/test-results/*

  desktop:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    env:
      ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD }}

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v3

      - name: set up JDK
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: gradle/actions/setup-gradle@v3
        with:
          cache-disabled: true

      - name: Build Desktop App
        run: ./gradlew jvmTest :desktop-app:packageDistributionForCurrentOS

      - name: Upload build outputs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: desktop-build-binaries
          path: desktop-app/build/compose/binaries

      - name: Upload reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: desktop-reports
          path: |
            **/build/reports/*

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: desktop-test-results
          path: |
            **/build/test-results/*

  ios-qa-app:
    runs-on: macos-14
    timeout-minutes: 60
    env:
      ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD }}
      FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 60

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: set up JDK
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true

      - run: brew install swiftlint

      - uses: gradle/actions/setup-gradle@v3
        with:
          cache-disabled: true

      - name: Decrypt secrets
        run: ./release/decrypt-secrets.sh
        env:
          ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}

      - name: Run Fastlane Lint lane
        run: bundle exec fastlane ios lint

      - name: Build iOS application
        run: bundle exec fastlane ios build_qa
        env:
          API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
          API_KEY_CONTENTS: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENTS }}
          ISSUER_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
          MATCH_PASSWORD: ${{ secrets.FASTLANE_MATCH_PASSWORD }}
          MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.FASTLANE_MATCH_GH_PAT }}
          TIVI_BUILD_NUMBER: ${{ github.run_number }}

      - name: Upload build outputs
        if: always()
        continue-on-error: true
        uses: actions/upload-artifact@v4
        with:
          name: ios-qa-build-outputs
          path: |
            *.ipa
            *.dSYM.zip

      - name: Upload build logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: ios-qa-logs
          path: |
            **/fastlane-buildlog

  ios-prod-app:
    runs-on: macos-14
    timeout-minutes: 60
    env:
      ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD }}
      FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 60

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: set up JDK
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true

      - run: brew install swiftlint

      - uses: gradle/actions/setup-gradle@v3
        with:
          cache-disabled: true

      - name: Decrypt secrets
        run: ./release/decrypt-secrets.sh
        env:
          ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}

      - name: Build iOS application
        run: bundle exec fastlane ios build_prod
        env:
          API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
          API_KEY_CONTENTS: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENTS }}
          ISSUER_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
          MATCH_PASSWORD: ${{ secrets.FASTLANE_MATCH_PASSWORD }}
          MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.FASTLANE_MATCH_GH_PAT }}
          TIVI_BUILD_NUMBER: ${{ github.run_number }}

      - name: Upload build outputs
        if: always()
        continue-on-error: true
        uses: actions/upload-artifact@v4
        with:
          name: ios-prod-build-outputs
          path: |
            *.ipa
            *.dSYM.zip

      - name: Upload build logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: ios-prod-logs
          path: |
            **/fastlane-buildlog

  ios-test:
    runs-on: macos-14
    timeout-minutes: 60
    env:
      ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TMDB_API_KEY }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_ID }}
      ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET: ${{ secrets.ORG_GRADLE_PROJECT_TIVI_TRAKT_CLIENT_SECRET }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_URL }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_USERNAME }}
      ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_REMOTE_BUILD_CACHE_PASSWORD }}

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: set up JDK
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: gradle/actions/setup-gradle@v3
        with:
          cache-disabled: true

      # Set Xcode version
      - run: sudo xcodes select

      - name: iOS tests
        # Disable CC due to https://github.com/google/ksp/issues/1463
        run: ./gradlew iosSimulatorArm64Test --no-configuration-cache

      - name: Upload reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: ios-reports
          path: |
            **/build/reports/*

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: ios-test-results
          path: |
            **/build/test-results/*

  publish-testflight:
    if: github.ref == 'refs/heads/main'
    needs: [ios-qa-app, ios-prod-app, ios-test]
    runs-on: macos-latest
    timeout-minutes: 20
    env:
      API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
      API_KEY_CONTENTS: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENTS }}
      ISSUER_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
      MATCH_PASSWORD: ${{ secrets.FASTLANE_MATCH_PASSWORD }}
      MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.FASTLANE_MATCH_GH_PAT }}

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true

      - name: Decrypt secrets
        run: ./release/decrypt-secrets.sh
        env:
          ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}

      - uses: actions/download-artifact@v4
        with:
          name: ios-qa-build-outputs

      - name: Publish QA to TestFlight
        run: bundle exec fastlane ios publish_qa

      - name: Delete QA IPA
        run: |
          rm *.ipa
          rm *.dSYM.zip

      - uses: actions/download-artifact@v4
        with:
          name: ios-prod-build-outputs

      - name: Publish prod to TestFlight
        run: bundle exec fastlane ios publish_prod

  publish-playstore:
    if: github.ref == 'refs/heads/main'
    needs: [android]
    runs-on: ubuntu-latest
    timeout-minutes: 20

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true

      - name: Decrypt secrets
        run: ./release/decrypt-secrets.sh
        env:
          ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}

      - uses: actions/download-artifact@v4
        with:
          name: android-build-outputs
          path: android-app/app/build/outputs

      - name: Publish QA to Google Play
        run: bundle exec fastlane android publish_qa

      - name: Publish prod to Google Play
        run: bundle exec fastlane android publish_prod


gradle-wrapper

name: gradle-wrapper

on:
  pull_request:
    paths:
      - 'gradlew'
      - 'gradlew.bat'
      - 'gradle/wrapper/'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: gradle/wrapper-validation-action@v3


TODO <> Issues

name: TODO <> Issues

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
      - uses: alstr/todo-to-issue-action@v4


Code Coverage

name: Code Coverage

on:
  push:
    branches:
      - main
  pull_request:

env:
  ORG_GRADLE_PROJECT_enablePTS: false

permissions:
  contents: read

jobs:
  publish-code-coverage:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Generate Coverage Report
        run: ./gradlew jacocoMergedReport
        env:
          DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

      - name: Publish Coverage
        if: success()
        uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4
        with:
          files: ./code-coverage-report/build/reports/jacoco/jacocoMergedReport/jacocoMergedReport.xml
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}


Danger

name: "Danger"

on:
  pull_request_target:
    types: [ assigned, closed, opened, synchronize, reopened ]

permissions:
  actions: write
  checks: write
  contents: write
  issues: write
  pull-requests: write
  statuses: write

jobs:
  danger:
    if: github.event.sender != 'codecov' && github.repository == 'detekt/detekt'
    name: Danger JS
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Node
        uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
        with:
          node-version: "18"
          cache: "yarn"
          cache-dependency-path: "website/yarn.lock"

      - name: Install Yarn Dependencies
        working-directory: bots/
        run: yarn install --frozen-lockfile

      - name: Run Danger
        working-directory: bots/
        run: yarn danger ci
        env:
          DANGER_GITHUB_API_TOKEN: ${{ secrets.DETEKT_CI_GITHUB_USER_TOKEN }}


Deploy Snapshot

name: Deploy Snapshot

on:
  push:
    branches:
      - main

env:
  DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
  ORG_GRADLE_PROJECT_enablePTS: false

permissions:
  contents: read

jobs:
  gradle:
    runs-on: ubuntu-latest
    if: github.repository == 'detekt/detekt'
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: "temurin"

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Assemble and publish artifacts to Maven Local
        run: ./gradlew publishToMavenLocal

      - name: Build detekt
        run: ./gradlew build

      - name: Deploy Snapshot
        env:
          ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
          ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
          ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
          ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
        run: ./gradlew publishAllToSonatypeSnapshot -Dsnapshot=true --stacktrace


detekt with type resolution

name: detekt with type resolution

on:
  push:
    branches:
      - main
  pull_request:

env:
  DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

permissions:
  contents: read

jobs:
  plain:
    permissions:
      contents: read  # for actions/checkout to fetch code
      security-events: write  # for github/codeql-action/upload-sarif to upload SARIF results
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Run detekt-cli with argsfile
        run: ./gradlew :detekt-cli:runWithArgsFile

      - name: Upload SARIF to GitHub using the upload-sarif action
        uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3
        if: success() || failure()
        with:
          sarif_file: build/detekt-report.sarif

  gradle:
    permissions:
      contents: read  # for actions/checkout to fetch code
      security-events: write  # for github/codeql-action/upload-sarif to upload SARIF results
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Run analysis
        run: ./gradlew detektMain detektTest detektFunctionalTest detektTestFixtures detektFunctionalTestMinSupportedGradle detektReportMergeSarif --continue

      - name: Upload SARIF to GitHub using the upload-sarif action
        uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3
        if: success() || failure()
        with:
          sarif_file: build/reports/detekt/merge.sarif


FOSSA License Scan

name: FOSSA License Scan

on:
  push:
    branches:
      - main

permissions:
  contents: read

jobs:
  fossa-scan:
    if: github.repository == 'detekt/detekt'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Run FOSSA Scan
        uses: fossas/fossa-action@f61a4c0c263690f2ddb54b9822a719c25a7b608f # tag=v1
        with:
          api-key: ${{ secrets.FOSSA_API_KEY }}


Dependency Submission

name: Dependency Submission

on:
  push:
    branches:
      - main

permissions:
  contents: write

jobs:
  dependency-submission:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
      - name: Generate and submit dependency graph
        uses: gradle/actions/dependency-submission@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3


Pull Request Labeler

name: "Pull Request Labeler"
on:
  - pull_request_target

jobs:
  label-pr:
    if: github.event.sender != 'codecov' && github.repository == 'detekt/detekt'
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
        with:
          repo-token: "${{ secrets.DETEKT_CI_GITHUB_USER_TOKEN }}"


Pre Merge Checks

name: Pre Merge Checks

on:
  push:
    branches:
      - main
  pull_request:
  workflow_dispatch:

env:
  DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
  ORG_GRADLE_PROJECT_enablePTS: ${{ github.ref_name != 'main' }}

permissions:
  contents: read

jobs:
  gradle:
    strategy:
      fail-fast: false
      matrix:
        os: [ ubuntu-latest ]
        jdk: [ 8, 11, 17, 21 ]
        include:
          - os: windows-latest
            jdk: 21
          - os: macos-latest
            jdk: 21
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: ${{ matrix.jdk }}
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Assemble and publish artifacts to Maven Local
        run: ./gradlew publishToMavenLocal

      - name: Build detekt
        run: ./gradlew build -x detekt

      - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
        with:
          name: heap-dump
          path: '**.hprof'
          if-no-files-found: ignore

  verify-generated-config-file:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Verify Generated Detekt Config File
        run: ./gradlew verifyGeneratorOutput

  compile-test-snippets:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Build and compile test snippets
        run: ./gradlew test -Pcompile-test-snippets=true

  warnings-as-errors:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Run with allWarningsAsErrors
        run: ./gradlew compileKotlin compileTestKotlin compileTestFixturesKotlin -PwarningsAsErrors=true


Mark stale issues and pull requests

name: Mark stale issues and pull requests
on:
  schedule:
    - cron: "30 1 * * *"

jobs:
  stale:
    runs-on: ubuntu-latest
    if: github.repository == 'detekt/detekt'
    permissions:
      issues: write
      pull-requests: write
    steps:
      - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9
        with:
          repo-token: ${{ secrets.DETEKT_CI_GITHUB_USER_TOKEN }}
          days-before-stale: 90
          stale-issue-message: "This issue is stale because it has been open 90 days with no activity. Please comment or this will be closed in 7 days."
          stale-pr-message: "This PR is stale because it has been open 90 days with no activity. Please comment or this will be closed in 7 days."
          close-issue-message: "This issue was closed because it has been stalled for 7 days with no activity."
          close-pr-message: "This PR was closed because it has been stalled for 7 days with no activity."
          stale-issue-label: stale
          stale-pr-label: stale
          exempt-issue-labels: help wanted, good first issue, never gets stale, blocked
          exempt-pr-labels: help wanted, good first issue, never gets stale, blocked
          exempt-milestones: 2.0.0
      - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9
        with:
          repo-token: ${{ secrets.DETEKT_CI_GITHUB_USER_TOKEN }}
          days-before-stale: 30
          stale-issue-message: "This issue is waiting for authors feedback since 30 days. Please comment providing the requested feedback or this issue will be closed in 7 days."
          stale-pr-message: "This PR is waiting for authors feedback since 30 days. Please comment providing the requested feedback or this PR will be closed in 7 days."
          close-issue-message: "This issue was closed because its author has not followed up after 7 days."
          close-pr-message: "This PR was closed because its author has not followed up after 7 days."
          stale-issue-label: stale
          stale-pr-label: stale
          any-of-labels: waiting for feedback, support
          exempt-issue-labels: never gets stale
          exempt-pr-labels: never gets stale


Build and Deploy Website

name: Build and Deploy Website

on:
  push:
    branches:
      - main
  pull_request:

env:
  DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}

permissions:
  contents: write  # for JamesIves/github-pages-deploy-action to push changes in repo

jobs:
  build-detekt-docs:
    if: github.repository == 'detekt/detekt'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

      - name: Setup Java
        uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
        with:
          java-version: 21
          distribution: 'temurin'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda # v3
        with:
          cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

      - name: Setup Node
        uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
        with:
          node-version: '18'
          cache: 'yarn'
          cache-dependency-path: 'website/yarn.lock'

      - name: Run generateWebsite
        run: ./gradlew :detekt-generator:generateWebsite

      - name: Install Yarn Dependencies
        working-directory: website/
        run: yarn install --frozen-lockfile

      - name: Build the Detekt Website
        working-directory: website/
        run: yarn build

      - name: Deploy GitHub Pages (only on main)
        uses: JamesIves/github-pages-deploy-action@5c6e9e9f3672ce8fd37b9856193d2a537941e66c # v4
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        with:
          branch: gh-pages
          folder: website/build/


Asana Integration after Issue opened

name: Asana Integration after Issue opened

on:
  issues:
    types: [opened, reopened]

jobs:
  create-asana-task:
    runs-on: ubuntu-latest
    steps:
      - name: Create Asana task
        uses: duckduckgo/native-github-asana-sync@v1.1
        with:
          asana-pat: ${{ secrets.GH_ASANA_SECRET }}
          asana-project: '414730916066338'
          action: 'create-asana-issue-task'
  add-comment:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Render template
        id: render_template
        uses: chuhlomin/render-template@v1.7
        with:
          template: .github/issue-reply-template.md

      - name: Add comment
        uses: peter-evans/create-or-update-comment@v3.0.2
        with:
          issue-number: ${{ github.event.issue.number }}
          body-path: '.github/issue-reply-template.md'


Pull Request Reviewed

name: Pull Request Reviewed

on:
  pull_request_review:
    types: [submitted]

jobs:
  pr-reviewed:
    if: github.event.review.state == 'approved'
    runs-on: ubuntu-latest
    steps:
      - name: Update Asana task -> PR approved
        uses: duckduckgo/native-github-asana-sync@v1.1
        with:
          asana-pat: ${{ secrets.GH_ASANA_SECRET }}
          trigger-phrase: "Task/Issue URL:"
          action: 'notify-pr-approved'


Mark task as complete on merge

name: Mark task as complete on merge

on:
  pull_request:
    types: [closed]

jobs:
  add-pr-merged-comment:
    runs-on: ubuntu-latest
    steps:
      - uses: duckduckgo/native-github-asana-sync@v1.1
        if: github.event.pull_request.merged
        with:
          asana-pat: ${{ secrets.GH_ASANA_SECRET }}
          trigger-phrase: "Task/Issue URL:"
          action: 'notify-pr-merged'
          is-complete: true


name: Asana Integration after Pull Request submitted

on:
  pull_request:
    types: [opened, reopened]

jobs:
  process-internal-pr:
    name: Process internal Pull Request, adding PR link to Asana task if present
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Add comment in Asana task
        uses: duckduckgo/native-github-asana-sync@v1.1
        with:
          asana-pat: ${{ secrets.GH_ASANA_SECRET }}
          trigger-phrase: "Task/Issue URL:"
          action: 'add-asana-comment'
          is-pinned: true


Android Design System End-to-End tests

name: Android Design System End-to-End tests

on:
  schedule:
    - cron: '0 5 * * *' # run at 5 AM UTC
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  instrumentation_tests:
    runs-on: ubuntu-latest
    name: End-to-End tests

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Create folder
        if: always()
        run: mkdir apk

      - name: Decode keys
        uses: davidSchuppa/base64Secret-toFile-action@v2
        with:
          secret: ${{ secrets.FAKE_RELEASE_PROPERTIES }}
          fileName: ddg_android_build.properties
          destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/

      - name: Decode key file
        uses: davidSchuppa/base64Secret-toFile-action@v2
        with:
          secret: ${{ secrets.FAKE_RELEASE_KEY }}
          fileName: android
          destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/

      - name: Assemble release APK
        uses: gradle/gradle-build-action@v2
        with:
          arguments: assembleInternalRelease -Pforce-default-variant

      - name: Move APK to new folder
        if: always()
        run: find . -name "*.apk"  -exec mv '{}' apk/release.apk \;

      - name: ADS Preview Flows
        uses: mobile-dev-inc/action-maestro-cloud@v1.8.1
        with:
          api-key: ${{ secrets.MOBILE_DEV_API_KEY }}
          name: ${{ github.sha }}
          app-file: apk/release.apk
          workspace: .maestro
          include-tags: androidDesignSystemTest

      - name: Create Asana task when workflow failed
        if: ${{ failure() }}
        uses: honeycombio/gha-create-asana-task@main
        with:
          asana-secret: ${{ secrets.GH_ASANA_SECRET }}
          asana-workspace-id: ${{ secrets.GH_ASANA_WORKSPACE_ID }}
          asana-project-id: ${{ secrets.GH_ASANA_AOR_PROJECT_ID }}
          asana-section-id: ${{ secrets.GH_ASANA_INCOMING_ID }}
          asana-task-name: GH Workflow Failure - ADS Preview test
          asana-task-description: The ADS Preview end to end workflow has failed. See https://github.com/duckduckgo/Android/actions/runs/${{ github.run_id }}


Build debug apk

name: Build debug apk

on:
  pull_request:
    branches:
      - develop
    paths-ignore:
      - '**.md'
      - '.github/**'
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build_debug_apk:
    name: Build debug apk
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: '1.18.3'

      - name: Build
        uses: gradle/gradle-build-action@v2
        with:
          arguments: assembleInternalDebug -Pforce-default-variant

      - name: Obtain debug apk
        if: always()
        run: cp $(find . -regex '.*outputs/apk/.*internal-debug.apk') pr-ddg-debug.apk

      - name: Upload debug apk
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: pr-ddg-debug
          path: pr-ddg-debug.apk


CI Checks

name: CI Checks

on:
  push:
    branches:
      - main
      - develop
    paths-ignore:
      - '**.md'
      - '.github/**'
  pull_request:
    paths-ignore:
      - '**.md'
      - '.github/**'

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  code_formatting:
    name: Code Formatting
    runs-on: ubuntu-20.04

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Run Code Formatting Checks
        uses: gradle/gradle-build-action@v2
        with:
          arguments: code_format_checks

  unit_tests:
    name: Unit tests
    runs-on: android-large-runner

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: JVM tests
        uses: gradle/gradle-build-action@v2
        with:
          arguments: jvm_tests

      - name: Bundle the JVM checks report
        if: always()
        run: find . -type d -name 'reports' | zip -@ -r unit-tests-report.zip

      - name: Upload the JVM checks report
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: unit-tests-report
          path: unit-tests-report.zip

  lint:
    name: Lint
    runs-on: android-large-runner

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: '1.18.3'

      - name: Lint
        uses: gradle/gradle-build-action@v2
        with:
          arguments: lint

      - name: Bundle the lint report
        if: always()
        run: find . -name lint-results\* | zip -@ -r lint-report.zip

      - name: Upload the JVM lint report
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: lint-report
          path: lint-report.zip

  android_tests:
    runs-on: android-large-runner
    name: Android CI tests

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Setup jq
        uses: dcarbone/install-jq-action@v1.0.1
        with:
          force: true

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: '1.18.3'

      - name: Decode secret
        env:
          FLANK: ${{ secrets.FLANK }}
        run: echo $FLANK > flank.json

      - name: Build
        uses: gradle/gradle-build-action@v2
        with:
          arguments: androidTestsBuild

      - name: Run Android Tests
        uses: gradle/gradle-build-action@v2
        with:
          arguments: runFlankAndroidTests

      - name: Bundle the Android CI tests report
        if: always()
        run: find . -type d -name 'fladleResults' | zip -@ -r android-tests-report.zip

      - name: Generate json file with failures
        if: ${{ failure() }}
        run: cat build/fladle/fladleResults/HtmlErrorReport.html | cut -d\`  -f2 >> results.json

      - name: Print failure report
        if: ${{ failure() }}
        run: |
          jq -r '.[] | .label as $id | .items[] | "Test:", $id, "Failure:", .label, "URL:", .url, "\n"' results.json

      - name: Upload the Android CI tests report
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: android-tests-report
          path: android-tests-report.zip


Custom Tabs nightly tests

name: Custom Tabs nightly tests

on:
  schedule:
    - cron: '0 5 * * *' # run at 5 AM UTC
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  instrumentation_tests:
    runs-on: ubuntu-latest
    name: Custom Tabs nightly tests

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Create folder
        if: always()
        run: mkdir apk

      - name: Decode keys
        uses: davidSchuppa/base64Secret-toFile-action@v2
        with:
          secret: ${{ secrets.FAKE_RELEASE_PROPERTIES }}
          fileName: ddg_android_build.properties
          destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/

      - name: Decode key file
        uses: davidSchuppa/base64Secret-toFile-action@v2
        with:
          secret: ${{ secrets.FAKE_RELEASE_KEY }}
          fileName: android
          destination-path: $HOME/jenkins_static/com.duckduckgo.mobile.android/

      - name: Assemble internal release APK
        uses: gradle/gradle-build-action@v2
        with:
          arguments: assembleInternalRelease -Pforce-default-variant -x lint

      - name: Move APK to new folder
        if: always()
        run: find . -name "*.apk"  -exec mv '{}' apk/release.apk \;

      - name: Custom Tabs Flows
        uses: mobile-dev-inc/action-maestro-cloud@v1.8.1
        with:
          api-key: ${{ secrets.MOBILE_DEV_API_KEY }}
          name: ${{ github.sha }}
          app-file: apk/release.apk
          android-api-level: 30
          workspace: .maestro
          include-tags: customTabsTest

      - name: Create Asana task when workflow failed
        if: ${{ failure() }}
        id: create-failure-task
        uses: duckduckgo/native-github-asana-sync@v1.1
        with:
          asana-pat: ${{ secrets.GH_ASANA_SECRET }}
          asana-project: ${{ vars.GH_ANDROID_APP_PROJECT_ID }}
          asana-section: ${{ vars.GH_ANDROID_APP_INCOMING_SECTION_ID }}
          asana-task-name: GH Workflow Failure - Custom Tabs Flows
          asana-task-description: The Custom Tabs nightly workflow has failed. See https://github.com/duckduckgo/Android/actions/runs/${{ github.run_id }}
          action: 'create-asana-task'


Docs

name: Docs

on:
  push:
    branches: ["develop"]

  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  # Single deploy job since we're just deploying
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Execute Gradle build
        run: ./gradlew dokkaHtmlMultiModule

      - name: Copy files
        run: |
          mkdir -p docs
          mv build/dokka/htmlMultiModule/* docs

      - name: Setup Pages
        uses: actions/configure-pages@v3

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          path: 'docs'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2