stages:
  - verify
  - test
  - build
  - source
  - release

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GRADLE_USER_HOME: "$CI_PROJECT_DIR/.gradle"
  FF_USE_FASTZIP: "true"
  CACHE_COMPRESSION_FORMAT: "zipzstd"
  CACHE_COMPRESSION_LEVEL: "fastest"
  HT_ANDROID_NDK_VERSION: "27.3.13750724"
  HT_ANDROID_CMAKE_VERSION: "3.22.1"

.android-job:
  image:
    name: ghcr.io/cirruslabs/android-sdk:36-ndk@sha256:dea0b3ff418657460823682cdc0e1b8af63596645f13f816be2838f7ba41b3cd
    pull_policy: always
  interruptible: true
  cache: &android-gradle-cache
    key:
      files:
        - gradle/wrapper/gradle-wrapper.properties
      prefix: android-gradle-downloads
    paths:
      - .gradle/caches/modules-2/files-2.1
      - .gradle/caches/modules-2/metadata-*
      - .gradle/caches/8.13/generated-gradle-jars
      - .gradle/caches/8.13/kotlin-dsl
      - .gradle/wrapper/dists
      - .gradle/android-toolchain-downloads
    policy: pull-push
  before_script:
    - scripts/ensure-android-toolchain.sh
    - scripts/apply-n3n-patches.sh

verify-source:
  stage: verify
  image: alpine:3.21
  before_script:
    - apk add --no-cache bash git
  script:
    - scripts/apply-n3n-patches.sh
    - scripts/verify-n3n-pin.sh
    - test -f LICENSE
    - test -f THIRD_PARTY_NOTICES.md

core-test:
  stage: test
  image: debian:bookworm-slim
  before_script:
    - apt-get update
    - apt-get install -y --no-install-recommends build-essential cmake perl ca-certificates git
  script:
    - scripts/apply-n3n-patches.sh
    - cmake -S core -B core/.build -DHTP_BUILD_N3N=OFF
    - cmake --build core/.build --parallel
    - ctest --test-dir core/.build --output-on-failure
    - cmake -S core -B core/.build-n3n -DHTP_BUILD_N3N=ON
    - cmake --build core/.build-n3n --parallel

android-test:
  extends: .android-job
  stage: test
  script:
    - ./gradlew --no-daemon testDebugUnitTest lintDebug

android-debug:
  extends: .android-job
  stage: build
  cache:
    <<: *android-gradle-cache
    policy: pull
  script:
    - ./gradlew --no-daemon assembleDebug
  artifacts:
    expire_in: 14 days
    paths:
      - android/app/build/outputs/apk/debug/*.apk

android-release:
  extends: .android-job
  stage: build
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ && $HT_ANDROID_UPLOAD_KEYSTORE_BASE64'
  cache:
    <<: *android-gradle-cache
    policy: pull
  before_script:
    - scripts/ensure-android-toolchain.sh
    - scripts/apply-n3n-patches.sh
    - test -n "$HT_ANDROID_UPLOAD_KEYSTORE_BASE64"
    - test -n "$HT_ANDROID_KEYSTORE_PASSWORD"
    - test -n "$HT_ANDROID_KEY_ALIAS"
    - test -n "$HT_ANDROID_KEY_PASSWORD"
    - printf '%s' "$HT_ANDROID_UPLOAD_KEYSTORE_BASE64" | base64 -d > "$CI_PROJECT_DIR/.android-upload.jks"
    - export HT_ANDROID_KEYSTORE_FILE="$CI_PROJECT_DIR/.android-upload.jks"
  script:
    - ./gradlew --no-daemon bundleRelease assembleRelease
    - scripts/check-android-16k.sh android/app/build/outputs/bundle/release/app-release.aab
    - apksigner_path="$(find "${ANDROID_SDK_ROOT:-$ANDROID_HOME}/build-tools" -type f -name apksigner -perm -u+x | sort -V | tail -1)"
    - test -n "$apksigner_path"
    - |
      "$apksigner_path" verify --verbose --print-certs android/app/build/outputs/apk/release/app-release.apk
    - release_version="${CI_COMMIT_TAG#v}"
    - mkdir -p dist
    - cp android/app/build/outputs/bundle/release/app-release.aab "dist/HT-Portal-VPN-${release_version}.aab"
    - cp android/app/build/outputs/apk/release/app-release.apk "dist/HT-Portal-VPN-${release_version}.apk"
    - sha256sum "dist/HT-Portal-VPN-${release_version}.aab" > "dist/HT-Portal-VPN-${release_version}.aab.sha256"
    - sha256sum "dist/HT-Portal-VPN-${release_version}.apk" > "dist/HT-Portal-VPN-${release_version}.apk.sha256"
  after_script:
    - rm -f "$CI_PROJECT_DIR/.android-upload.jks"
  artifacts:
    expire_in: 90 days
    paths:
      - android/app/build/outputs/bundle/release/*.aab
      - android/app/build/outputs/apk/release/*.apk
      - android/app/build/outputs/mapping/release/mapping.txt
      - dist/*.aab
      - dist/*.aab.sha256
      - dist/*.apk
      - dist/*.apk.sha256

ios-preview:
  stage: build
  tags: [macos]
  rules:
    - if: '$HT_ENABLE_IOS_CI == "true"'
  script:
    - scripts/apply-n3n-patches.sh
    - xcodegen generate
    - xcodebuild -project HTPortalVPN.xcodeproj -scheme HTPortalVPN -configuration Debug -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO build

ios-release:
  stage: build
  tags: [macos]
  resource_group: o20010-mobile-ios-build
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ && $HT_ENABLE_IOS_RELEASE_CI == "true"'
  script:
    - export HT_MOBILE_RELEASE_VERSION="${CI_COMMIT_TAG#v}"
    - scripts/build-ios-release.sh
  artifacts:
    expire_in: 90 days
    paths:
      - build/ios-release/HTPortalVPN.xcarchive/
      - dist/*.ipa
      - dist/*.ipa.sha256

source-offer:
  stage: source
  image: alpine:3.21
  before_script:
    - apk add --no-cache bash git tar
  script:
    - scripts/apply-n3n-patches.sh
    - source_version="${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
    - source_version="${source_version#v}"
    - scripts/package-source-offer.sh "$source_version" "dist/${source_version}-android-source.tar.gz"
    - ios_version="$(sed -n 's/^[[:space:]]*MARKETING_VERSION:[[:space:]]*"\([^"]*\)"/\1/p' project.yml | head -1)"
    - ios_build="$(sed -n 's/^[[:space:]]*CURRENT_PROJECT_VERSION:[[:space:]]*\([0-9][0-9]*\)/\1/p' project.yml | head -1)"
    - test -n "$ios_version"
    - test -n "$ios_build"
    - scripts/package-source-offer.sh "${ios_version}-build${ios_build}" "dist/${ios_version}-build${ios_build}-source.tar.gz"
  artifacts:
    expire_in: 1 year
    paths:
      - dist/*-source.tar.gz

.mobile-release:
  stage: release
  image: debian:bookworm
  resource_group: o20010-mobile-release
  before_script:
    - apt-get update
    - apt-get install -y --no-install-recommends bash curl jq ca-certificates coreutils
  allow_failure: false
  environment:
    name: mobile-vpn/$RELEASE_PLATFORM/$RELEASE_CHANNEL
    url: https://releases.hivetechnology.net/o20010/06/$RELEASE_PLATFORM/$RELEASE_CHANNEL

.android-release-rules:
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ && $HT_ANDROID_UPLOAD_KEYSTORE_BASE64'
      when: manual

.ios-release-rules:
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ && $HT_ENABLE_IOS_RELEASE_CI == "true"'
      when: manual

release:android:alpha:
  extends: [.mobile-release, .android-release-rules]
  needs:
    - job: android-release
      artifacts: true
    - job: source-offer
      artifacts: true
  variables:
    RELEASE_PLATFORM: android
    RELEASE_CHANNEL: alpha
  script:
    - bash scripts/send.sh "$RELEASE_CHANNEL" "$RELEASE_PLATFORM"

release:android:beta:
  extends: [.mobile-release, .android-release-rules]
  needs:
    - job: android-release
      artifacts: true
    - job: source-offer
      artifacts: true
  variables:
    RELEASE_PLATFORM: android
    RELEASE_CHANNEL: beta
  script:
    - bash scripts/send.sh "$RELEASE_CHANNEL" "$RELEASE_PLATFORM"

release:android:stable:
  extends: [.mobile-release, .android-release-rules]
  needs:
    - job: android-release
      artifacts: true
    - job: source-offer
      artifacts: true
  variables:
    RELEASE_PLATFORM: android
    RELEASE_CHANNEL: stable
  script:
    - bash scripts/send.sh "$RELEASE_CHANNEL" "$RELEASE_PLATFORM"

release:ios:alpha:
  extends: [.mobile-release, .ios-release-rules]
  needs:
    - job: ios-release
      artifacts: true
    - job: source-offer
      artifacts: true
  variables:
    RELEASE_PLATFORM: ios
    RELEASE_CHANNEL: alpha
  script:
    - bash scripts/send.sh "$RELEASE_CHANNEL" "$RELEASE_PLATFORM"

release:ios:beta:
  extends: [.mobile-release, .ios-release-rules]
  needs:
    - job: ios-release
      artifacts: true
    - job: source-offer
      artifacts: true
  variables:
    RELEASE_PLATFORM: ios
    RELEASE_CHANNEL: beta
  script:
    - bash scripts/send.sh "$RELEASE_CHANNEL" "$RELEASE_PLATFORM"

release:ios:stable:
  extends: [.mobile-release, .ios-release-rules]
  needs:
    - job: ios-release
      artifacts: true
    - job: source-offer
      artifacts: true
  variables:
    RELEASE_PLATFORM: ios
    RELEASE_CHANNEL: stable
  script:
    - bash scripts/send.sh "$RELEASE_CHANNEL" "$RELEASE_PLATFORM"
