name: Zen Release builds

on:
  workflow_dispatch:
    inputs:
      create_release:
        description: 'Create a new release for this build'
        required: false
        default: false
        type: 'boolean'
      update_version:
        description: 'Update the version number'
        required: false
        default: false
        type: 'boolean'
      update_branch:
        description: 'Update branch with new version'
        required: true
        default: 'release'
        type: 'choice'
        options:
          - 'release'
          - 'twilight'
      use-sccache:
        description: 'Use sccache'
        required: true
        type: 'boolean'
        default: false
  workflow_call:
    inputs:
      create_release:
        description: 'Create a new release for this build'
        required: false
        default: false
        type: 'boolean'
      update_version:
        description: 'Update the version number'
        required: false
        default: false
        type: 'boolean'
      update_branch:
        description: 'Update branch with new version'
        required: true
        default: 'release'
        type: 'string'
      use-sccache:
        description: 'Use sccache'
        required: true
        type: 'boolean'
        default: false

jobs:
  debug-inputs:
    name: Debug inputs
    runs-on: ubuntu-latest
    steps:
      - name: Debug
        run: |
          echo "create_release: ${{ inputs.create_release }}"
          echo "update_version: ${{ inputs.update_version }}"
          echo "use sccache: ${{ inputs.use-sccache }}"
          echo "update_branch: ${{ inputs.update_branch }}"
          echo "GITHUB_REPOSITORY: ${{ github.repository }}"
          echo "GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}"
          echo "GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}"

  buildid:
    name: Generate build ID
    runs-on: ubuntu-latest
    outputs:
      buildids: ${{ steps.get.outputs.bid }}
    steps:
      - id: get
        shell: bash -xe {0}
        run: |
          bdat=`date +"%Y%m%d%I%M%S"`
          echo "bid=${bdat}" >> $GITHUB_OUTPUT

  start-self-host:
    runs-on: ubuntu-latest
    needs: debug-inputs
    steps:
      - name: Download aws-cli
        if: ${{ inputs.create_release && inputs.update_branch == 'release' }}
        run: |
          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip awscliv2.zip
          sudo ./aws/install --update

      - name: Start self-hosted runner
        if: ${{ inputs.create_release && inputs.update_branch == 'release' }}
        run: |
          echo "Starting self-hosted runner"
          echo "${{ secrets.SELF_HOSTED_RUNNER_START_SCRIPT }}" | base64 -d > start.sh
          sudo chmod +x start.sh
          bash ./start.sh

      - name: Remove self-hosted runner script
        if: always() && ${{ inputs.create_release && inputs.update_branch == 'release' }}
        run: |
          echo "Removing self-hosted runner script"
          rm start.sh || true

  check-build-is-correct:
    runs-on: ubuntu-latest
    needs: [debug-inputs]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Check if correct branch
        if: ${{ inputs.create_release }}
        run: |
          echo "Checking if we are on the correct branch"
          git branch
          git status
          git branch --show-current
          branch="${{ inputs.update_branch }}"
          if [[ $branch == "twilight" ]]; then
            branch="dev"
          elif [[ $branch == "release" ]]; then
            branch="stable"
          fi
          if [[ $(git branch --show-current) != $branch ]]; then
            echo ">>> Branch mismatch"
          # exit 1
          else
            echo ">>> Branch matches"
          fi

  build-data:
    permissions:
      contents: write
    name: Generate build data
    runs-on: ubuntu-latest
    needs: check-build-is-correct
    outputs:
      build_date: ${{ steps.data.outputs.builddate }}
      version: ${{ steps.data.outputs.version }}
      build_time: ${{ steps.data.outputs.buildtime }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: '.nvmrc'

      - name: Install dependencies
        run: |
          npm install

      - name: Setup Surfer
        run: |
          npm i -g @zen-browser/surfer

      - name: Bump version
        if: ${{ inputs.update_version && inputs.update_branch == 'release' }}
        run: |
          npm run surfer -- ci --brand ${{ inputs.update_branch }} --bump prerelease

      - name: Bump version without new version
        if: ${{ !inputs.update_version || inputs.update_branch == 'twilight' }}
        run: |
          npm run surfer -- ci --brand ${{ inputs.update_branch }}

      - name: Debug
        run: |
          surfer get version
          surfer get version | xargs
          echo "$(surfer get version | xargs)"

      - name: Export release date
        id: data
        shell: bash
        run: |
          echo "builddate=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
          echo "version=$(surfer get version | xargs)" >> $GITHUB_OUTPUT
          echo "buildtime=$(date +"%H:%M:%S")" >> $GITHUB_OUTPUT

      - name: Commit
        uses: stefanzweifel/git-auto-commit-action@v5
        if: ${{ inputs.update_version }}
        with:
          commit_message: 🔖 Update version to ${{ steps.data.outputs.version }}
          commit_user_name: Zen Browser Robot
          commit_user_email: zen-browser-auto@users.noreply.github.com

  lint:
    uses: ./.github/workflows/code-linter.yml
    needs: [build-data]
    name: Lint

  check-release:
    runs-on: ubuntu-latest
    needs: [build-data, lint]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: '.nvmrc'

      - name: Install dependencies
        run: |
          npm install

      - name: Setup Surfer
        run: |
          npm i -g @zen-browser/surfer

      - name: Activate Surfer CLI
        run: |
          npm run surfer -- ci --brand ${{ inputs.update_branch }} --display-version ${{ needs.build-data.outputs.version }}

      - name: Check version
        run: |
          echo "$(pwd)"
          echo $(npm run --silent surfer -- get version | xargs)
          echo "version=$(npm run --silent surfer -- get version | xargs)" >> $GITHUB_OUTPUT
          if [[ $(npm run --silent surfer -- get version | xargs) == ${{ needs.build-data.outputs.version }} ]]; then
            echo ">>> Version matches"
          else
            echo ">>> Version mismatch"
            exit 1
          fi

  source:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    needs: [build-data, check-release]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: '.nvmrc'

      - name: Setup Git
        run: |
          git config --global user.email "mauro-balades@users.noreply.github.com"
          git config --global user.name "mauro-balades"

      - name: Install dependencies
        run: |
          npm install

      - name: Load Surfer CI setup
        run: npm run surfer -- ci --brand ${{ inputs.update_branch }} --display-version ${{ needs.build-data.outputs.version }}

      - name: Download Firefox source and dependencies
        run: npm run download --verbose

      - name: Import
        run: npm run import -- --verbose

      - name: Compress
        run: |
          cd engine
          tar --use-compress-program=zstd -hcf ../zen.source.tar.zst *
          cd ..

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: zen.source.tar.zst
          path: ./zen.source.tar.zst

  windows-step-1:
    name: Windows build step 1 (PGO build)
    uses: ./.github/workflows/windows-release-build.yml
    needs: [build-data, buildid]
    permissions:
      contents: write
    secrets: inherit
    with:
      use-sccache: ${{ inputs.use-sccache }}
      build-version: ${{ needs.build-data.outputs.version }}
      generate-gpo: true
      profile-data-path-archive: zen-windows-profile-data-and-jarlog.zip
      release-branch: ${{ inputs.update_branch }}
      MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}

  windows-step-2:
    name: Windows build step 2 (Generate profile data)
    uses: ./.github/workflows/windows-profile-build.yml
    permissions:
      contents: write
    secrets: inherit
    needs: [windows-step-1, build-data]
    with:
      build-version: ${{ needs.build-data.outputs.version }}
      profile-data-path-archive: zen.win64-pgo-stage-1.zip
      release-branch: ${{ inputs.update_branch }}

  windows-step-3:
    name: Windows build step 3 (build with profile data)
    uses: ./.github/workflows/windows-release-build.yml
    permissions:
      contents: write
    secrets: inherit
    needs: [build-data, windows-step-2, start-self-host, buildid]
    with:
      build-version: ${{ needs.build-data.outputs.version }}
      generate-gpo: false
      release-branch: ${{ inputs.update_branch }}
      MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
      use-sccache: ${{ inputs.use-sccache }}

  linux:
    name: Linux build
    uses: ./.github/workflows/linux-release-build.yml
    permissions:
      contents: write
    secrets: inherit
    needs: [build-data, start-self-host, buildid]
    with:
      build-version: ${{ needs.build-data.outputs.version }}
      release-branch: ${{ inputs.update_branch }}
      MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
      use-sccache: ${{ inputs.use-sccache }}

  mac:
    name: macOS build
    uses: ./.github/workflows/macos-release-build.yml
    permissions:
      contents: write
    secrets: inherit
    needs: [build-data, buildid]
    with:
      build-version: ${{ needs.build-data.outputs.version }}
      release-branch: ${{ inputs.update_branch }}
      MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
      use-sccache: ${{ inputs.use-sccache }}

  mac-uni:
    name: macOS build (Universal)
    uses: ./.github/workflows/macos-universal-release-build.yml
    permissions:
      contents: write
    secrets: inherit
    needs: [build-data, mac]
    with:
      build-version: ${{ needs.build-data.outputs.version }}
      release-branch: ${{ inputs.update_branch }}

  appimage:
    name: AppImage build - Linux ${{ matrix.arch }}
    permissions:
      contents: write
    runs-on: ubuntu-latest
    strategy:
      matrix:
        arch: [x86_64, aarch64]
    needs: [linux]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: '.nvmrc'

      - name: Install dependencies
        run: |
          npm install
          sudo apt-get update
          sudo apt-get -y install libfuse2 desktop-file-utils appstream

      - name: Download Linux build
        uses: actions/download-artifact@v4
        with:
          name: zen.linux-${{ matrix.arch }}.tar.xz

      - name: Execute AppImage build
        run: |
          set -eux
          export ARCH=${{ matrix.arch }}
          UPINFO="gh-releases-zsync|$GITHUB_REPOSITORY_OWNER|desktop|latest|zen-$ARCH.AppImage.zsync"
          rm build/AppDir/.DirIcon || true
          cp configs/branding/${{ inputs.update_branch }}/logo128.png build/AppDir/usr/share/icons/hicolor/128x128/apps/zen.png
          cp configs/branding/${{ inputs.update_branch }}/logo128.png build/AppDir/zen.png && ln -s zen.png build/AppDir/.DirIcon

          if [ "${{ inputs.update_branch }}" = "twilight" ]; then
            sed -i -e 's/Name=Zen Browser/Name=Zen Twilight/g' build/AppDir/zen.desktop
            sed -i -e 's/StartupWMClass=zen/StartupWMClass=zen-twilight/g' build/AppDir/zen.desktop
          fi

          APPDIR=build/AppDir
          tar -xvf *.tar.* && rm -rf *.tar.*
          mv zen/* $APPDIR/
          wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
          wget "https://github.com/VHSgunzo/uruntime/releases/latest/download/uruntime-appimage-squashfs-lite-$ARCH"
          chmod +x *.AppImage
          chmod +x ./uruntime-appimage-squashfs-lite-"$ARCH"
          chmod +x ./build/AppDir/AppRun

          # keep the uruntime mountpoint (massively speeds up launch time)
          sed -i 's|URUNTIME_MOUNT=[0-9]|URUNTIME_MOUNT=0|' ./uruntime-appimage-squashfs-lite-"$ARCH"

          echo "AppDir: $APPDIR"
          ls -al
          find .
          ls -al "$APPDIR"
          ./appimagetool-x86_64.AppImage -u "$UPINFO" "$APPDIR" zen-"$ARCH".AppImage --runtime-file ./uruntime-appimage-squashfs-lite-"$ARCH"
          mkdir dist
          mv zen*AppImage* dist/.
          unset ARCH

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: zen-${{ matrix.arch }}.AppImage
          path: ./dist/zen-${{ matrix.arch }}.AppImage

      - name: Upload artifact (ZSync)
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: zen-${{ matrix.arch }}.AppImage.zsync
          path: ./dist/zen-${{ matrix.arch }}.AppImage.zsync

  stop-self-hosted:
    runs-on: ubuntu-latest
    needs: [windows-step-3, linux]
    if: always()
    steps:
      - name: Download aws-cli
        if: ${{ inputs.create_release && inputs.update_branch == 'release' }}
        run: |
          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip awscliv2.zip
          sudo ./aws/install --update

      - name: Stop self-hosted runner
        if: ${{ inputs.create_release && inputs.update_branch == 'release' }}
        run: |
          echo "Stopping self-hosted runner"
          echo "${{ secrets.SELF_HOSTED_RUNNER_STOP_SCRIPT }}" | base64 -d > stop.sh
          sudo chmod +x stop.sh
          bash ./stop.sh > /dev/null

      - name: Remove self-hosted runner script
        if: always() && ${{ inputs.create_release && inputs.update_branch == 'release' }}
        run: |
          echo "Removing self-hosted runner script"
          rm stop.sh || true

  release:
    if: ${{ inputs.create_release || inputs.update_branch == 'twilight' }}
    permissions: write-all
    name: Release
    needs:
      [
        build-data,
        linux,
        windows-step-3,
        check-release,
        mac-uni,
        appimage,
        source,
        lint,
        stop-self-hosted,
      ]
    runs-on: ubuntu-latest
    environment:
      name: ${{ inputs.update_branch == 'release' && 'Deploy-Release' || 'Deploy-Twilight' }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Download artifact
        uses: actions/download-artifact@v4

      - name: Checkout updates repository
        uses: actions/checkout@v4
        with:
          repository: zen-browser/updates-server
          path: updates-server
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Download object files
        if: ${{ inputs.update_branch == 'release' }}
        run: |
          git clone https://github.com/zen-browser/windows-binaries.git .github/workflows/object --depth 1

      - name: Copy update manifests
        env:
          RELEASE_BRANCH: ${{ inputs.update_branch }}
        run: |
          cd updates-server
          mkdir -p updates
          cp -a ../linux_update_manifest_x86_64/.  updates/
          cp -a ../linux_update_manifest_aarch64/.  updates/

          if [[ $RELEASE_BRANCH == 'release' ]]; then
            cp -a ../.github/workflows/object/windows-x64-signed-x86_64/update_manifest/.  updates/
            cp -a ../.github/workflows/object/windows-x64-signed-arm64/update_manifest/.  updates/
          else
            cp -a ../windows_update_manifest_x86_64/.  updates/
            cp -a ../windows_update_manifest_arm64/.  updates/
          fi

          cp -a ../macos_update_manifest/.  updates/

      - name: Commit
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: 🚀 Update update manifests
          commit_user_name: Zen Browser Robot
          commit_user_email: zen-browser-auto@users.noreply.github.com
          repository: ./updates-server

      - name: Generate Release Notes
        env:
          RELEASE_BRANCH: ${{ inputs.update_branch }}
        run: bash .github/workflows/src/generate_release_notes.sh

        # If we are on Twilight, we want to just update the Twilight tag's release
      - name: Update Twilight tag
        if: ${{ inputs.update_branch == 'twilight' }}
        uses: softprops/action-gh-release@v2.2.2
        with:
          body_path: release_notes.md
          files: |
            ./zen.source.tar.zst/*
            ./zen.linux-x86_64.tar.xz/*
            ./zen.linux-aarch64.tar.xz/*
            ./zen-x86_64.AppImage/*
            ./zen-x86_64.AppImage.zsync/*
            ./zen-aarch64.AppImage/*
            ./zen-aarch64.AppImage.zsync/*
            ./zen.win-x86_64.zip/*
            ./zen.win-arm64.zip/*
            ./linux.mar/*
            ./linux-aarch64.mar/*
            ./windows.mar/*
            ./windows-arm64.mar/*
            ./macos.mar/*
            ./zen.installer.exe/*
            ./zen.installer-arm64.exe/*
            ./zen.macos-universal.dmg/*
          tag_name: 'twilight'
          name: 'Twilight build - ${{ needs.build-data.outputs.version }} (${{ needs.build-data.outputs.build_date }} at ${{ needs.build-data.outputs.build_time }})'
          draft: false
          generate_release_notes: false
          prerelease: true
          token: ${{ secrets.DEPLOY_KEY }}
          fail_on_unmatched_files: false
        env:
          GITHUB_REPOSITORY: ${{ github.repository }}

      - name: Release
        uses: softprops/action-gh-release@v2.2.2
        if: ${{ inputs.update_branch == 'release' }}
        with:
          token: ${{ secrets.DEPLOY_KEY }}
          tag_name: ${{ needs.build-data.outputs.version }}
          prerelease: false
          fail_on_unmatched_files: false
          generate_release_notes: false
          name: 'Release build - ${{ needs.build-data.outputs.version }} (${{ needs.build-data.outputs.build_date }})'
          body_path: release_notes.md
          files: |
            ./zen.source.tar.zst/*
            ./zen.linux-x86_64.tar.xz/*
            ./zen.linux-aarch64.tar.xz/*
            ./zen-x86_64.AppImage/*
            ./zen-x86_64.AppImage.zsync/*
            ./zen-aarch64.AppImage/*
            ./zen-aarch64.AppImage.zsync/*
            ./.github/workflows/object/windows-x64-signed-x86_64/zen.win-x86_64.zip
            ./.github/workflows/object/windows-x64-signed-arm64/zen.win-arm64.zip
            ./linux.mar/*
            ./linux-aarch64.mar/*
            ./.github/workflows/object/windows-x64-signed-x86_64/windows.mar
            ./.github/workflows/object/windows-x64-signed-arm64/windows-arm64.mar
            ./macos.mar/*
            ./.github/workflows/object/windows-x64-signed-x86_64/zen.installer.exe
            ./.github/workflows/object/windows-x64-signed-arm64/zen.installer-arm64.exe
            ./zen.macos-universal.dmg/*

  prepare-flatpak:
    if: ${{ inputs.create_release && inputs.update_branch == 'release' }}
    permissions: write-all
    name: Prepare Flatpak
    needs: [release, linux, build-data]
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Flatpak repository
        uses: actions/checkout@v4
        with:
          repository: zen-browser/release-utils
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Install dependencies
        run: |
          git pull
          sudo apt-get update
          npm install

      - name: Generate new Flatpak release
        run: |
          npm run build-flatpak -- \
            --version ${{ needs.build-data.outputs.version }}

      - name: Commit
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: 🚀 Update releases for Flatpak
          commit_user_name: Zen Browser Robot
          commit_user_email: zen-browser-auto@users.noreply.github.com

      - name: Checkout Flatpak repository
        uses: actions/checkout@v4
        with:
          repository: zen-browser/flatpak
          token: ${{ secrets.DEPLOY_KEY }}
          path: flatpak

      - name: Move releases.xml
        run: |
          pwd
          ls .
          ls ..
          mv releases.xml ./flatpak/app.zen_browser.zen.metainfo.xml
          # output the version to the file
          echo -n ${{ needs.build-data.outputs.version }} > ./flatpak/version

      - name: Commit
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: '[release]: Update Flatpak manifest'
          commit_user_name: Zen Browser Robot
          commit_user_email: zen-browser-auto@users.noreply.github.com
          repository: ./flatpak

      - name: Wait 2 minutes for the Flatpak repo to update
        run: sleep 120

  release-flatpak:
    if: ${{ inputs.create_release && inputs.update_branch == 'release' }}
    permissions: write-all
    name: Release Flatpak
    needs: [prepare-flatpak, build-data]
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Flatpak repository
        uses: actions/checkout@v4
        with:
          repository: flathub/app.zen_browser.zen
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Download Linux x86_64 build
        uses: actions/download-artifact@v4
        with:
          name: zen.linux-x86_64.tar.xz

      - name: Download Linux aarch64 build
        uses: actions/download-artifact@v4
        with:
          name: zen.linux-aarch64.tar.xz

      - name: Update repository
        uses: actions/checkout@v4
        with:
          path: zen-browser
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Download Flatpak archive
        run: |
          wget https://github.com/zen-browser/flatpak/releases/latest/download/archive.tar -O archive.tar

      - name: Setup Git
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"

      - name: Prepare Flatpak manifest
        run: |
          python3 ./zen-browser/scripts/prepare-flatpak-release.py \
            --flatpak-archive archive.tar \
            --version ${{ needs.build-data.outputs.version }} \
            --linux-archive zen.linux-x86_64.tar.xz \
            --linux-aarch64-archive zen.linux-aarch64.tar.xz \
            --output app.zen_browser.zen.yml \
            --template-root ./zen-browser/build/flatpak

      - name: Commit changes
        run: |
          git add app.zen_browser.zen.yml
          git commit -m "Update to version ${{ needs.build-data.outputs.version }}"

      - name: Clean up
        run: |
          rm -rf zen-browser
          rm -rf archive.tar
          rm -rf zen.linux-x86_64.tar.xz
          rm -rf zen.linux-aarch64.tar.xz

      - name: Upload Flatpak manifest
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: app.zen_browser.zen.yml
          path: ./app.zen_browser.zen.yml

      - name: Create pull request
        uses: peter-evans/create-pull-request@v7
        env:
          GIT_TRACE: 1
          GIT_CURL_VERBOSE: 1
        with:
          token: ${{ secrets.DEPLOY_KEY }}
          commit-message: 🚀 Update to version ${{ needs.build-data.outputs.version }}
          title: 🚀 Update to version ${{ needs.build-data.outputs.version }}
          body: |
            This PR updates the Zen Browser Flatpak package to version ${{ needs.build-data.outputs.version }}.

            @${{ github.actor }} please review and merge this PR.
          branch: update-to-${{ needs.build-data.outputs.version }}
          base: master
          git-token: ${{ secrets.DEPLOY_KEY }}
          delete-branch: true
